r5314 - in branches/nexuiz-2.0: . Docs/server Docs/server/rcon2irc data data/env data/env/desert data/gfx data/gfx/menu/default data/gfx/menu/silver data/gfx/menu/simplygray data/gfx/menu/wickedblack data/gfx/menu/wickedblue data/gfx/menu/wickedgreen data/gfx/menu/wickedred data/gfx/menu/wickedwhite data/gfx/menu/wickedyellow data/gfx/menu/wickedz data/gfx/menu/xaw data/models/ctf data/models/sprites data/models/weapons data/qcsrc/client data/qcsrc/common data/qcsrc/menu data/qcsrc/menu/item data/qcsrc/menu/nexuiz data/qcsrc/server data/scripts data/sound/weapons data/textures misc misc/ttf2conchars

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri Dec 26 09:39:00 EST 2008


Author: div0
Date: 2008-12-26 09:38:59 -0500 (Fri, 26 Dec 2008)
New Revision: 5314

Added:
   branches/nexuiz-2.0/data/env/desert/desert_bk.tga
   branches/nexuiz-2.0/data/env/desert/desert_dn.tga
   branches/nexuiz-2.0/data/env/desert/desert_ft.tga
   branches/nexuiz-2.0/data/env/desert/desert_lf.tga
   branches/nexuiz-2.0/data/env/desert/desert_rt.tga
   branches/nexuiz-2.0/data/env/desert/desert_up.tga
   branches/nexuiz-2.0/data/env/mandelbrot/
   branches/nexuiz-2.0/data/gfx/crosshair13.tga
   branches/nexuiz-2.0/data/gfx/crosshair14.tga
   branches/nexuiz-2.0/data/gfx/crosshair15.tga
   branches/nexuiz-2.0/data/gfx/crosshair16.tga
   branches/nexuiz-2.0/data/gfx/crosshair17.tga
   branches/nexuiz-2.0/data/gfx/crosshair18.tga
   branches/nexuiz-2.0/data/gfx/crosshair19.tga
   branches/nexuiz-2.0/data/gfx/crosshair20.tga
   branches/nexuiz-2.0/data/gfx/crosshair21.tga
   branches/nexuiz-2.0/data/gfx/hslimage.tga
   branches/nexuiz-2.0/data/gfx/inv_weapon14.tga
   branches/nexuiz-2.0/data/gfx/inv_weapon_hlacmod_renameit.tga
   branches/nexuiz-2.0/data/gfx/menu/default/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/silver/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/simplygray/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedblack/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedblue/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedgreen/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedred/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedwhite/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedyellow/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedz/colorpicker.tga
   branches/nexuiz-2.0/data/gfx/menu/xaw/colorpicker.tga
   branches/nexuiz-2.0/data/models/ctf/flags.md3
   branches/nexuiz-2.0/data/models/ctf/flags.md3_0.skin
   branches/nexuiz-2.0/data/models/ctf/flags.md3_1.skin
   branches/nexuiz-2.0/data/models/sprites/wpn-campingrifle_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-crylink_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-electro_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-gl_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-hagar_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-hlac_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-hookgun_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-laser_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-minstanex_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-nex_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-porto_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-rl_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-seeker_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-shotgun_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/wpn-uzi_frame0.tga
   branches/nexuiz-2.0/data/models/weapons/g_campingrifle.md3
   branches/nexuiz-2.0/data/models/weapons/g_hlacmod.md3
   branches/nexuiz-2.0/data/models/weapons/v_campingrifle.md3
   branches/nexuiz-2.0/data/models/weapons/v_hlacmod.md3
   branches/nexuiz-2.0/data/models/weapons/w_campingrifle.zym
   branches/nexuiz-2.0/data/models/weapons/w_hlacmod.zym
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/colorpicker.c
   branches/nexuiz-2.0/data/qcsrc/server/w_campingrifle.qc
   branches/nexuiz-2.0/data/scripts/flags.shader
   branches/nexuiz-2.0/data/scripts/hlac.shader
   branches/nexuiz-2.0/data/scripts/mandelbrotsky.shader
   branches/nexuiz-2.0/data/sound/weapons/campingrifle_fire.ogg
   branches/nexuiz-2.0/data/sound/weapons/campingrifle_reload.ogg
   branches/nexuiz-2.0/data/textures/campingrifle.tga
   branches/nexuiz-2.0/data/textures/campingrifle_bump.tga
   branches/nexuiz-2.0/data/textures/campingrifle_gloss.tga
   branches/nexuiz-2.0/data/textures/campingrifle_glow.tga
   branches/nexuiz-2.0/data/textures/campingrifle_pants.tga
   branches/nexuiz-2.0/data/textures/campingrifle_shirt.tga
   branches/nexuiz-2.0/data/textures/flags/
   branches/nexuiz-2.0/data/textures/hlac_accessory.tga
   branches/nexuiz-2.0/data/textures/hlac_accessory_gloss.tga
   branches/nexuiz-2.0/data/textures/hlac_accessory_norm.tga
   branches/nexuiz-2.0/data/textures/hlac_accessory_pants.tga
   branches/nexuiz-2.0/data/textures/hlac_accessory_shirt.tga
   branches/nexuiz-2.0/data/textures/hlac_body.tga
   branches/nexuiz-2.0/data/textures/hlac_body_gloss.tga
   branches/nexuiz-2.0/data/textures/hlac_body_glow.tga
   branches/nexuiz-2.0/data/textures/hlac_body_norm.tga
   branches/nexuiz-2.0/data/textures/hlac_body_pants.tga
   branches/nexuiz-2.0/data/textures/hlac_body_shirt.tga
   branches/nexuiz-2.0/data/textures/hlac_glass.tga
   branches/nexuiz-2.0/data/textures/hlac_metal.tga
   branches/nexuiz-2.0/data/textures/hlac_plasma.tga
   branches/nexuiz-2.0/misc/hslimage.c
Removed:
   branches/nexuiz-2.0/data/env/desert/desert_bk.jpg
   branches/nexuiz-2.0/data/env/desert/desert_dn.jpg
   branches/nexuiz-2.0/data/env/desert/desert_ft.jpg
   branches/nexuiz-2.0/data/env/desert/desert_lf.jpg
   branches/nexuiz-2.0/data/env/desert/desert_rt.jpg
   branches/nexuiz-2.0/data/env/desert/desert_up.jpg
Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/Docs/server/rcon.pl
   branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc-example.conf
   branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl
   branches/nexuiz-2.0/data/build-compat-pack.sh
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   branches/nexuiz-2.0/data/gfx/crosshair7.tga
   branches/nexuiz-2.0/data/gfx/inv_weapon12.tga
   branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/silver/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/simplygray/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/wickedz/skinvalues.txt
   branches/nexuiz-2.0/data/gfx/menu/xaw/skinvalues.txt
   branches/nexuiz-2.0/data/models/sprites/make-sprites.sh
   branches/nexuiz-2.0/data/models/weapons/g_hlac.md3
   branches/nexuiz-2.0/data/models/weapons/v_hlac.md3
   branches/nexuiz-2.0/data/models/weapons/w_hlac.zym
   branches/nexuiz-2.0/data/qcsrc/client/View.qc
   branches/nexuiz-2.0/data/qcsrc/client/hook.qc
   branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc
   branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc
   branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc
   branches/nexuiz-2.0/data/qcsrc/common/items.qc
   branches/nexuiz-2.0/data/qcsrc/common/items.qh
   branches/nexuiz-2.0/data/qcsrc/common/util.qc
   branches/nexuiz-2.0/data/qcsrc/common/util.qh
   branches/nexuiz-2.0/data/qcsrc/menu/classes.c
   branches/nexuiz-2.0/data/qcsrc/menu/draw.qc
   branches/nexuiz-2.0/data/qcsrc/menu/item/inputbox.c
   branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup.c
   branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc
   branches/nexuiz-2.0/data/qcsrc/server/bots.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc
   branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
   branches/nexuiz-2.0/data/qcsrc/server/constants.qh
   branches/nexuiz-2.0/data/qcsrc/server/ctf.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
   branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
   branches/nexuiz-2.0/data/qcsrc/server/ipban.qc
   branches/nexuiz-2.0/data/qcsrc/server/ipban.qh
   branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/server/progs.src
   branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_common.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc
   branches/nexuiz-2.0/data/scripts/entities.def
   branches/nexuiz-2.0/data/scripts/shaderlist.txt
   branches/nexuiz-2.0/data/weapons.cfg
   branches/nexuiz-2.0/data/weaponsPro.cfg
   branches/nexuiz-2.0/misc/demotc.pl
   branches/nexuiz-2.0/misc/jpeg-if-not-alpha.sh
   branches/nexuiz-2.0/misc/ttf2conchars/foo.sh
   branches/nexuiz-2.0/misc/ttf2conchars/ttf2conchars.c
Log:
r5229 | morphed | 2008-12-15 18:46:47 +0100 (Mon, 15 Dec 2008) | 1 line
new hlac model in 2 versions + textures and stuff
r5230 | div0 | 2008-12-16 08:28:00 +0100 (Tue, 16 Dec 2008) | 2 lines
ipban update
r5231 | div0 | 2008-12-16 09:45:57 +0100 (Tue, 16 Dec 2008) | 2 lines
less MD and FF
r5232 | div0 | 2008-12-16 10:28:08 +0100 (Tue, 16 Dec 2008) | 2 lines
new parameter use
r5233 | div0 | 2008-12-16 10:31:26 +0100 (Tue, 16 Dec 2008) | 2 lines
refire for hook now working
r5234 | div0 | 2008-12-16 10:42:34 +0100 (Tue, 16 Dec 2008) | 2 lines
hook: separate refire timers for primary/secondary (probably a bit buggy)
r5235 | div0 | 2008-12-16 10:54:06 +0100 (Tue, 16 Dec 2008) | 2 lines
fix some C++ warnings
r5236 | div0 | 2008-12-16 13:06:21 +0100 (Tue, 16 Dec 2008) | 2 lines
visual studio BS... but it should at least work now.
r5237 | div0 | 2008-12-16 13:11:02 +0100 (Tue, 16 Dec 2008) | 2 lines
less spam
r5238 | div0 | 2008-12-16 13:21:55 +0100 (Tue, 16 Dec 2008) | 2 lines
fix blur
r5239 | div0 | 2008-12-16 13:32:22 +0100 (Tue, 16 Dec 2008) | 2 lines
make display of hook less weird
r5240 | div0 | 2008-12-16 14:34:27 +0100 (Tue, 16 Dec 2008) | 2 lines
fix hook again
r5241 | div0 | 2008-12-16 14:43:41 +0100 (Tue, 16 Dec 2008) | 2 lines
bots: combos; custom weapon priorities
r5242 | div0 | 2008-12-16 15:13:26 +0100 (Tue, 16 Dec 2008) | 2 lines
more distance before it switches to nex whore mode
r5243 | div0 | 2008-12-17 08:05:49 +0100 (Wed, 17 Dec 2008) | 2 lines
fixed env/desert by sev
r5244 | div0 | 2008-12-17 09:09:20 +0100 (Wed, 17 Dec 2008) | 2 lines
get rid of RETURN VALUE ALREADY IN USE bug
r5245 | div0 | 2008-12-17 10:56:26 +0100 (Wed, 17 Dec 2008) | 2 lines
ttf2conchars: add "scale 1" directive
r5246 | div0 | 2008-12-17 14:13:12 +0100 (Wed, 17 Dec 2008) | 2 lines
weapon sprites
r5247 | div0 | 2008-12-17 14:29:35 +0100 (Wed, 17 Dec 2008) | 3 lines
weapon sprites, this time right
r5248 | div0 | 2008-12-17 14:29:45 +0100 (Wed, 17 Dec 2008) | 2 lines
delete the old ones
r5249 | div0 | 2008-12-17 14:34:06 +0100 (Wed, 17 Dec 2008) | 3 lines
- only complain about ONE missing weapon;
- g_showweaponspawns (feature you know from the OTLD servers)
r5250 | div0 | 2008-12-17 14:36:57 +0100 (Wed, 17 Dec 2008) | 2 lines
compat pack: HLAC texture, wpn- tga files
r5251 | div0 | 2008-12-17 14:55:41 +0100 (Wed, 17 Dec 2008) | 2 lines
bigger head shot area, hope this helps
r5252 | div0 | 2008-12-17 15:08:51 +0100 (Wed, 17 Dec 2008) | 2 lines
specop needhelp2 missing
r5253 | div0 | 2008-12-17 15:27:16 +0100 (Wed, 17 Dec 2008) | 2 lines
make hook switch also when trying to use the hook button
r5254 | div0 | 2008-12-17 21:52:49 +0100 (Wed, 17 Dec 2008) | 2 lines
admin interface beginning
r5255 | div0 | 2008-12-18 07:38:58 +0100 (Thu, 18 Dec 2008) | 2 lines
rcon2irc: more stuff :P
r5256 | div0 | 2008-12-18 07:57:51 +0100 (Thu, 18 Dec 2008) | 2 lines
add support for managing bans
r5257 | div0 | 2008-12-18 08:01:39 +0100 (Thu, 18 Dec 2008) | 2 lines
add irc admin to the cofnig file
r5258 | div0 | 2008-12-18 08:39:10 +0100 (Thu, 18 Dec 2008) | 2 lines
fix showweaponspawns
r5259 | div0 | 2008-12-18 08:48:05 +0100 (Thu, 18 Dec 2008) | 2 lines
now the weapon icon showing REALLY works
r5260 | div0 | 2008-12-18 08:54:39 +0100 (Thu, 18 Dec 2008) | 2 lines
fix typo in unban command
r5261 | div0 | 2008-12-18 08:56:21 +0100 (Thu, 18 Dec 2008) | 2 lines
next typo
r5262 | div0 | 2008-12-18 09:01:28 +0100 (Thu, 18 Dec 2008) | 2 lines
ipban: enforce always
r5263 | div0 | 2008-12-18 09:02:25 +0100 (Thu, 18 Dec 2008) | 2 lines
removed next typo
r5264 | div0 | 2008-12-18 09:07:53 +0100 (Thu, 18 Dec 2008) | 2 lines
don't crash if no status received yet
r5265 | div0 | 2008-12-18 09:12:23 +0100 (Thu, 18 Dec 2008) | 2 lines
move the # to the place where it belongs :P (just weird output otherwise)
r5266 | div0 | 2008-12-18 09:13:24 +0100 (Thu, 18 Dec 2008) | 2 lines
kick should also say #2, not 2
r5267 | div0 | 2008-12-18 15:09:41 +0100 (Thu, 18 Dec 2008) | 2 lines
bug fix
r5268 | m0rfar | 2008-12-18 15:20:19 +0100 (Thu, 18 Dec 2008) | 5 lines
A preliminary commit until tzork flag modification is done.
* New flag model by ai (with laser beams always visible).
* New cvar g_ctf_dynamiclights (default: 1) which adds a red/blue dynamic light on flag origin.
* Changed g_ctf_fullbrights to 0, or else normal maps wont work. Cloths are fullbright anyway.
* Old flag models still exists for compability reasons (if some maps are still referring to them).
r5269 | m0rfar | 2008-12-18 18:23:36 +0100 (Thu, 18 Dec 2008) | 1 line
I forgot this file. Dunno what it is. :D
r5270 | div0 | 2008-12-19 11:19:14 +0100 (Fri, 19 Dec 2008) | 2 lines
flag model -> compat pack
r5271 | div0 | 2008-12-19 11:23:07 +0100 (Fri, 19 Dec 2008) | 2 lines
build script now reducing texture quality to make smaller pack
r5272 | div0 | 2008-12-19 11:24:34 +0100 (Fri, 19 Dec 2008) | 2 lines
more quality reduction
r5273 | div0 | 2008-12-19 11:27:00 +0100 (Fri, 19 Dec 2008) | 2 lines
tghere is no specop needhelp2
r5274 | div0 | 2008-12-19 11:32:47 +0100 (Fri, 19 Dec 2008) | 2 lines
fix...
r5275 | div0 | 2008-12-19 11:58:19 +0100 (Fri, 19 Dec 2008) | 2 lines
fix doors with origin brush
r5276 | div0 | 2008-12-19 13:10:45 +0100 (Fri, 19 Dec 2008) | 2 lines
scaledown option
r5277 | div0 | 2008-12-19 13:11:48 +0100 (Fri, 19 Dec 2008) | 2 lines
scale down textures in the compat pack to 256x256 if possible
r5278 | div0 | 2008-12-20 18:03:31 +0100 (Sat, 20 Dec 2008) | 2 lines
fix maplist shuffling when set to ""
r5279 | div0 | 2008-12-20 19:49:34 +0100 (Sat, 20 Dec 2008) | 2 lines
verify clientcomamnds again
r5280 | div0 | 2008-12-20 19:51:50 +0100 (Sat, 20 Dec 2008) | 2 lines
typo, argh
r5281 | div0 | 2008-12-20 20:23:50 +0100 (Sat, 20 Dec 2008) | 2 lines
hook: clear waiting for release flag
r5282 | div0 | 2008-12-21 18:01:43 +0100 (Sun, 21 Dec 2008) | 2 lines
remove "frags left" for ctf
r5283 | div0 | 2008-12-22 16:56:42 +0100 (Mon, 22 Dec 2008) | 8 lines
Weapon rebalancing according to stats:
Crylink: -10% damage
Nex: -7% damage
Hagar: -12% damage
RL: sameg damage, less edge damage, slightly less radius
HLAC: -8% damage
r5284 | div0 | 2008-12-22 17:47:23 +0100 (Mon, 22 Dec 2008) | 3 lines
new crosshairs by mikeeusa as posted on the NN forum, but fixtrans'd ;)
crosshair19 isn't in the menu as it doesn't make a good preview anyway, use "crosshair 19" to load it
r5285 | div0 | 2008-12-22 17:56:05 +0100 (Mon, 22 Dec 2008) | 2 lines
CH 15 updated
r5286 | div0 | 2008-12-22 18:06:06 +0100 (Mon, 22 Dec 2008) | 2 lines
even more CHs
r5287 | div0 | 2008-12-22 20:44:31 +0100 (Mon, 22 Dec 2008) | 2 lines
uzi: small tuning of spread and damage
r5288 | div0 | 2008-12-23 11:26:15 +0100 (Tue, 23 Dec 2008) | 3 lines
electro: rebalance it by making primary and secondary have less damage, but increase combo damage
hagar: undo half of the last damage reduction, it was too much
r5289 | div0 | 2008-12-23 23:24:46 +0100 (Tue, 23 Dec 2008) | 7 lines
New stuff:
- Camping Rifle (with a preliminary model, should really be exchanged before release, and do not use it in maps yet)
- Ballistics mode (g_ballistics_force 1), makes Uzi and Shotgun bullets use the ballistics code from the camping rifle too so they are no longer hitscan (for SG this does not matter and is just less ugly, for MG it might actually fix its balance)
- A Mandelbrot set-based skybox made by the skybox generator I had posted
- Rocket launcher tuned to 120 damage units (before: 130)
r5290 | div0 | 2008-12-23 23:30:41 +0100 (Tue, 23 Dec 2008) | 2 lines
ballistics: also show bullet mark where the bullet came out
r5291 | div0 | 2008-12-23 23:38:21 +0100 (Tue, 23 Dec 2008) | 2 lines
fix cvar checks
r5292 | div0 | 2008-12-23 23:45:23 +0100 (Tue, 23 Dec 2008) | 2 lines
fix extra casings :P
r5293 | m0rfar | 2008-12-24 14:16:14 +0100 (Wed, 24 Dec 2008) | 2 lines
Use "Two cloth" version of the flags.
I think they look better, are still visible and use fewer polygons :)
r5294 | div0 | 2008-12-24 14:57:07 +0100 (Wed, 24 Dec 2008) | 2 lines
updated ballistics code and data, matches physics better now
r5295 | div0 | 2008-12-24 15:00:02 +0100 (Wed, 24 Dec 2008) | 2 lines
remove debug output
r5296 | div0 | 2008-12-24 15:42:58 +0100 (Wed, 24 Dec 2008) | 2 lines
hopefulyl fix decals of ballistic bullets
r5297 | div0 | 2008-12-24 16:27:27 +0100 (Wed, 24 Dec 2008) | 2 lines
now bots can use the CR too
r5298 | div0 | 2008-12-24 18:21:34 +0100 (Wed, 24 Dec 2008) | 2 lines
hook patch from Roffnan
r5299 | div0 | 2008-12-24 18:23:40 +0100 (Wed, 24 Dec 2008) | 2 lines
remove other unnecessary check
r5300 | div0 | 2008-12-24 20:05:18 +0100 (Wed, 24 Dec 2008) | 2 lines
remove some spam
r5301 | div0 | 2008-12-24 20:33:38 +0100 (Wed, 24 Dec 2008) | 2 lines
camping rifle: DO use trueaim. Better for head shots. MUCH better.
r5302 | div0 | 2008-12-24 20:38:44 +0100 (Wed, 24 Dec 2008) | 2 lines
no, do this: shoot CR from the eye when zoomed, to avoid trueaim problems; when not zoomed, shoot with trueaim
r5303 | div0 | 2008-12-24 23:48:53 +0100 (Wed, 24 Dec 2008) | 2 lines
csqc: fix position of waypoints in intermission
r5304 | div0 | 2008-12-25 00:10:38 +0100 (Thu, 25 Dec 2008) | 2 lines
fix size of minimap
r5305 | div0 | 2008-12-25 14:25:06 +0100 (Thu, 25 Dec 2008) | 2 lines
factor the ballistic bullet tracing into a separate inverted traceline function
r5306 | div0 | 2008-12-25 14:40:22 +0100 (Thu, 25 Dec 2008) | 2 lines
avoid calling dropclient from cl_movement frames
r5307 | div0 | 2008-12-25 15:09:32 +0100 (Thu, 25 Dec 2008) | 2 lines
recalculate bullet parameters
r5308 | div0 | 2008-12-25 18:43:41 +0100 (Thu, 25 Dec 2008) | 2 lines
rcon, rcon2irc: support terrencehill's colors
r5309 | div0 | 2008-12-25 19:03:28 +0100 (Thu, 25 Dec 2008) | 2 lines
terrencehill's color codes patch. Please test thoroughly!
r5310 | morphed | 2008-12-25 23:20:39 +0100 (Thu, 25 Dec 2008) | 1 line
hlac fix: proper size for textures, smaller scope, reposition of 1st person view
r5311 | morphed | 2008-12-25 23:28:47 +0100 (Thu, 25 Dec 2008) | 1 line
I changed hlac_mod into hlacmod by accident, sry :)
r5312 | div0 | 2008-12-26 15:25:58 +0100 (Fri, 26 Dec 2008) | 2 lines
hsl color space generator script
r5313 | div0 | 2008-12-26 15:29:00 +0100 (Fri, 26 Dec 2008) | 2 lines
menu: add a color picker for player names

Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/.patchsets	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-5227
+revisions_applied = 1-5313

Modified: branches/nexuiz-2.0/Docs/server/rcon.pl
===================================================================
--- branches/nexuiz-2.0/Docs/server/rcon.pl	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/Docs/server/rcon.pl	2008-12-26 14:38:59 UTC (rev 5314)
@@ -23,8 +23,8 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 # OTHER DEALINGS IN THE SOFTWARE.
 
-
 # parts copied from rcon2irc
+# MISC STRING UTILITY ROUTINES to convert between DarkPlaces and IRC conventions
 
 # convert mIRC color codes to DP color codes
 our @color_irc2dp_table = (7, 0, 4, 2, 1, 1, 6, 1, 3, 2, 5, 5, 4, 6, 7, 7);
@@ -95,60 +95,149 @@
 	$message = join '', map { $text_qfont_table[ord $_] } split //, $message;
 }
 
+sub color_dp_transform(&$)
+{
+	my ($block, $message) = @_;
+
+	$message =~ s{(?:(\^\^)|\^x([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])|\^([0-9])|(.))(?=([0-9,]?))}{
+		defined $1 ? $block->(char => '^', $7) :
+		defined $2 ? $block->(rgb => [hex $2, hex $3, hex $4], $7) :
+		defined $5 ? $block->(color => $5, $7) :
+		defined $6 ? $block->(char => $6, $7) :
+			die "Invalid match";
+	}esg;
+
+	return $message;
+}
+
 sub color_dp2none($)
 {
 	my ($message) = @_;
-	my $color = -1;
-	$message =~ s{\^(.)(?=([0-9,]?))}{
-		my $c = $1;
-		$c eq '^' ? '^' :
-		$c =~ /^[0-9]$/ ? '' : "^$c";
-	}esg;
-	return text_dp2ascii $message;
+
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+		print "$type $data\n";
+		$type eq 'char'
+			? $text_qfont_table[ord $data]
+			: "";
+	}
+	$message;
 }
 
+sub color_rgb2basic($)
+{
+	my ($data) = @_;
+	my ($r, $g, $b) = @$data;
+	my $min = [sort ($r, $g, $b)]->[0];
+	my $max = [sort ($r, $g, $b)]->[-1];
+
+	my $v = $max / 15;
+	my $s = ($max == $min) ? 0 : 1 - $min/$max;
+
+	if($s < 0.2)
+	{
+		return 0 if $v < 0.5;
+		return 7;
+	}
+
+	my $h;
+	if($max == $min)
+	{
+		$h = 0;
+	}
+	elsif($max == $r)
+	{
+		$h = (60 * ($g - $b) / ($max - $min)) % 360;
+	}
+	elsif($max == $g)
+	{
+		$h = (60 * ($b - $r) / ($max - $min)) + 120;
+	}
+	elsif($max == $b)
+	{
+		$h = (60 * ($r - $g) / ($max - $min)) + 240;
+	}
+
+	return 1 if $h < 36;
+	return 3 if $h < 80;
+	return 2 if $h < 150;
+	return 5 if $h < 200;
+	return 4 if $h < 270;
+	return 6 if $h < 330;
+	return 1;
+}
+
+sub color_dp_rgb2basic($)
+{
+	my ($message) = @_;
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+		print "$type $data\n";
+		$type eq 'char'  ? ($data eq '^' ? '^^' : $data) :
+		$type eq 'color' ? "^$data" :
+		$type eq 'rgb'   ? "^" . color_rgb2basic $data :
+			die "Invalid type";
+	}
+	$message;
+}
+
 sub color_dp2irc($)
 {
 	my ($message) = @_;
 	my $color = -1;
-	$message =~ s{\^(.)(?=([0-9,]?))}{
-		my $c = $1;
-		my $f = $2;
-		$c eq '^' ? '^' :
-		$c =~ /^[0-9]$/ ? do {
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+
+		if($type eq 'rgb')
+		{
+			$type = 'color';
+			$data = color_rgb2basic $data;
+		}
+
+		$type eq 'char'  ? $text_qfont_table[ord $data] :
+		$type eq 'color' ? do {
 			my $oldcolor = $color;
-			$c = 0 if $c >= 7; # map 0, 7, 8, 9 to default (no bright white or such stuff)
-			$color = $color_dp2irc_table[$c];
-			($color == $oldcolor) ? '' :
-			$c == 0 ? "\0001" :
-			$f eq ',' ? "\0003$color\0002\0002" :
-			$f ne ''  ? sprintf "\0003%02d", $color : "\0003$color";
-		} : "^$c";
-	}esg;
-	$message = text_dp2ascii $message;
-	$message =~ s/\0001/\017/g;
-	$message =~ s/\0002/\002/g;
-	$message =~ s/\0003/\003/g;
-	return $message;
+			$data = 0 if $data >= 7; # map 0, 7, 8, 9 to default (no bright white or such stuff)
+			$color = $color_dp2irc_table[$data];
+
+			$color == $oldcolor ? '' :
+			$color == 0         ? "\017" :
+			$next eq ','        ? "\003$color\002\002" :
+			                      sprintf "\003%02d", $color;
+		} :
+			die "Invalid type";
+	}
+	$message;
 }
 
 sub color_dp2ansi($)
 {
 	my ($message) = @_;
 	my $color = -1;
-	$message =~ s{\^(.)}{
-		my $c = $1;
-		$c eq '^' ? '^' :
-		$c =~ /^[0-9]$/ ? do {
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+
+		if($type eq 'rgb')
+		{
+			$type = 'color';
+			$data = color_rgb2basic $data;
+		}
+
+		$type eq 'char'  ? $text_qfont_table[ord $data] :
+		$type eq 'color' ? do {
 			my $oldcolor = $color;
-			$color = $color_dp2ansi_table[$c];
-			($color eq $oldcolor) ? '' :
-			"\000[${color}" # "
-		} : "^$c";
-	}esg;
-	$message = text_dp2ascii $message;
-	$message =~ s/\000/\033/g;
-	return $message;
+			$color = $color_dp2ansi_table[$data];
+
+			$color eq $oldcolor ? '' :
+			                      "\033[${color}"
+		} :
+			die "Invalid type";
+	}
+	$message;
 }
 
 sub color_dpfix($)
@@ -161,6 +250,7 @@
 
 
 
+
 # Interfaces:
 #   Connection:
 #     $conn->sockname() returns a connection type specific representation
@@ -258,8 +348,18 @@
 {
 	my ($self) = @_;
 	my $data = "";
-	$self->{sock}->recv($data, 32768, 0);
-	return $data;
+	if(defined $self->{sock}->recv($data, 32768, 0))
+	{
+		return $data;
+	}
+	elsif($!{EAGAIN})
+	{
+		return "";
+	}
+	else
+	{
+		return undef;
+	}
 }
 
 # $sock->fds() returns the socket file descriptor.
@@ -325,7 +425,10 @@
 	my ($self) = @_;
 	for(;;)
 	{
-		length(my $s = $self->{connector}->recv())
+		my $s = $self->{connector}->recv();
+		die "read error\n"
+			if not defined $s;
+		length $s
 			or last;
 		next
 			if $s !~ /^\377\377\377\377n(.*)$/s;

Modified: branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc-example.conf
===================================================================
--- branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc-example.conf	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc-example.conf	2008-12-26 14:38:59 UTC (rev 5314)
@@ -8,6 +8,9 @@
 irc_user = banme
 irc_channel = #Nexuiz-Pwayers
 
+# uncomment for server administration via IRC
+#irc_admin_password = hackme
+
 # IRC NickServ authentication (optional)
 #irc_nickserv_password = hackme
 
@@ -25,6 +28,7 @@
 #dp_server_from_wan =
 #dp_listen = 141.2.16.23:27771
 #dp_status_delay = 30
+#irc_admin_timeout = 3600
 #irc_local = 141.2.16.23
 #irc_ping_delay = 120
 #irc_nickserv_identify = PRIVMSG NickServ :IDENTIFY %2$s

Modified: branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl
===================================================================
--- branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl	2008-12-26 14:38:59 UTC (rev 5314)
@@ -25,6 +25,233 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 # OTHER DEALINGS IN THE SOFTWARE.
 
+# MISC STRING UTILITY ROUTINES to convert between DarkPlaces and IRC conventions
+
+# convert mIRC color codes to DP color codes
+our @color_irc2dp_table = (7, 0, 4, 2, 1, 1, 6, 1, 3, 2, 5, 5, 4, 6, 7, 7);
+our @color_dp2irc_table = (14, 4, 9, 8, 12, 11, 13, 14, 15, 15); # not accurate, but legible
+our @color_dp2ansi_table = ("m", "1;31m", "1;32m", "1;33m", "1;34m", "1;36m", "1;35m", "m", "1m", "1m"); # not accurate, but legible
+our %color_team2dp_table = (5 => 1, 14 => 4, 13 => 3, 10 => 6);
+our %color_team2irc_table = (5 => 4, 14 => 12, 13 => 8, 10 => 13);
+sub color_irc2dp($)
+{
+	my ($message) = @_;
+	$message =~ s/\^/^^/g;
+	my $color = 7;
+	$message =~ s{\003(\d\d?)(?:,(\d?\d?))?|(\017)}{
+		# $1 is FG, $2 is BG, but let's ignore BG
+		my $oldcolor = $color;
+		if($3)
+		{
+			$color = 7;
+		}
+		else
+		{
+			$color = $color_irc2dp_table[$1];
+			$color = $oldcolor if not defined $color;
+		}
+		($color == $oldcolor) ? '' : '^' . $color;
+	}esg;
+	$message =~ s{[\000-\037]}{}gs; # kill bold etc. for now
+	return $message;
+}
+
+our @text_qfont_table = ( # ripped from DP console.c qfont_table
+    "\0", '#',  '#',  '#',  '#',  '.',  '#',  '#',
+    '#',  9,    10,   '#',  ' ',  13,   '.',  '.',
+    '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
+    '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
+    ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
+    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
+    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+    '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
+    '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
+    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
+    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
+    'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_',
+    '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<',
+    '<',  '=',  '>',  '#',  '#',  '.',  '#',  '#',
+    '#',  '#',  ' ',  '#',  ' ',  '>',  '.',  '.',
+    '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
+    '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
+    ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
+    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
+    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+    '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
+    '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
+    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
+    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
+    'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_',
+    '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<'
+);
+sub text_dp2ascii($)
+{
+	my ($message) = @_;
+	$message = join '', map { $text_qfont_table[ord $_] } split //, $message;
+}
+
+sub color_dp_transform(&$)
+{
+	my ($block, $message) = @_;
+
+	$message =~ s{(?:(\^\^)|\^x([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])|\^([0-9])|(.))(?=([0-9,]?))}{
+		defined $1 ? $block->(char => '^', $7) :
+		defined $2 ? $block->(rgb => [hex $2, hex $3, hex $4], $7) :
+		defined $5 ? $block->(color => $5, $7) :
+		defined $6 ? $block->(char => $6, $7) :
+			die "Invalid match";
+	}esg;
+
+	return $message;
+}
+
+sub color_dp2none($)
+{
+	my ($message) = @_;
+
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+		print "$type $data\n";
+		$type eq 'char'
+			? $text_qfont_table[ord $data]
+			: "";
+	}
+	$message;
+}
+
+sub color_rgb2basic($)
+{
+	my ($data) = @_;
+	my ($r, $g, $b) = @$data;
+	my $min = [sort ($r, $g, $b)]->[0];
+	my $max = [sort ($r, $g, $b)]->[-1];
+
+	my $v = $max / 15;
+	my $s = ($max == $min) ? 0 : 1 - $min/$max;
+
+	if($s < 0.2)
+	{
+		return 0 if $v < 0.5;
+		return 7;
+	}
+
+	my $h;
+	if($max == $min)
+	{
+		$h = 0;
+	}
+	elsif($max == $r)
+	{
+		$h = (60 * ($g - $b) / ($max - $min)) % 360;
+	}
+	elsif($max == $g)
+	{
+		$h = (60 * ($b - $r) / ($max - $min)) + 120;
+	}
+	elsif($max == $b)
+	{
+		$h = (60 * ($r - $g) / ($max - $min)) + 240;
+	}
+
+	return 1 if $h < 36;
+	return 3 if $h < 80;
+	return 2 if $h < 150;
+	return 5 if $h < 200;
+	return 4 if $h < 270;
+	return 6 if $h < 330;
+	return 1;
+}
+
+sub color_dp_rgb2basic($)
+{
+	my ($message) = @_;
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+		print "$type $data\n";
+		$type eq 'char'  ? ($data eq '^' ? '^^' : $data) :
+		$type eq 'color' ? "^$data" :
+		$type eq 'rgb'   ? "^" . color_rgb2basic $data :
+			die "Invalid type";
+	}
+	$message;
+}
+
+sub color_dp2irc($)
+{
+	my ($message) = @_;
+	my $color = -1;
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+
+		if($type eq 'rgb')
+		{
+			$type = 'color';
+			$data = color_rgb2basic $data;
+		}
+
+		$type eq 'char'  ? $text_qfont_table[ord $data] :
+		$type eq 'color' ? do {
+			my $oldcolor = $color;
+			$data = 0 if $data >= 7; # map 0, 7, 8, 9 to default (no bright white or such stuff)
+			$color = $color_dp2irc_table[$data];
+
+			$color == $oldcolor ? '' :
+			$color == 0         ? "\017" :
+			$next eq ','        ? "\003$color\002\002" :
+			                      sprintf "\003%02d", $color;
+		} :
+			die "Invalid type";
+	}
+	$message;
+}
+
+sub color_dp2ansi($)
+{
+	my ($message) = @_;
+	my $color = -1;
+	return color_dp_transform
+	{
+		my ($type, $data, $next) = @_;
+
+		if($type eq 'rgb')
+		{
+			$type = 'color';
+			$data = color_rgb2basic $data;
+		}
+
+		$type eq 'char'  ? $text_qfont_table[ord $data] :
+		$type eq 'color' ? do {
+			my $oldcolor = $color;
+			$color = $color_dp2ansi_table[$data];
+
+			$color eq $oldcolor ? '' :
+			                      "\033[${color}"
+		} :
+			die "Invalid type";
+	}
+	$message;
+}
+
+sub color_dpfix($)
+{
+	my ($message) = @_;
+	# if the message ends with an odd number of ^, kill one
+	chop $message if $message =~ /(?:^|[^\^])\^(\^\^)*$/;
+	return $message;
+}
+
+
+
+
 # Interfaces:
 #   Connection:
 #     $conn->sockname() returns a connection type specific representation
@@ -433,148 +660,14 @@
 	dp_server_from_wan => "",
 	irc_local => "",
 
+	irc_admin_password => "",
+	irc_admin_timeout => 3600,
+
 	plugins => "",
 );
 
 
 
-# MISC STRING UTILITY ROUTINES to convert between DarkPlaces and IRC conventions
-
-# convert mIRC color codes to DP color codes
-our @color_irc2dp_table = (7, 0, 4, 2, 1, 1, 6, 1, 3, 2, 5, 5, 4, 6, 7, 7);
-our @color_dp2irc_table = (14, 4, 9, 8, 12, 11, 13, 14, 15, 15); # not accurate, but legible
-our @color_dp2ansi_table = ("m", "1;31m", "1;32m", "1;33m", "1;34m", "1;36m", "1;35m", "m", "1m", "1m"); # not accurate, but legible
-our %color_team2dp_table = (5 => 1, 14 => 4, 13 => 3, 10 => 6);
-our %color_team2irc_table = (5 => 4, 14 => 12, 13 => 8, 10 => 13);
-sub color_irc2dp($)
-{
-	my ($message) = @_;
-	$message =~ s/\^/^^/g;
-	my $color = 7;
-	$message =~ s{\003(\d\d?)(?:,(\d?\d?))?|(\017)}{
-		# $1 is FG, $2 is BG, but let's ignore BG
-		my $oldcolor = $color;
-		if($3)
-		{
-			$color = 7;
-		}
-		else
-		{
-			$color = $color_irc2dp_table[$1];
-			$color = $oldcolor if not defined $color;
-		}
-		($color == $oldcolor) ? '' : '^' . $color;
-	}esg;
-	$message =~ s{[\000-\037]}{}gs; # kill bold etc. for now
-	return $message;
-}
-
-our @text_qfont_table = ( # ripped from DP console.c qfont_table
-    "\0", '#',  '#',  '#',  '#',  '.',  '#',  '#',
-    '#',  9,    10,   '#',  ' ',  13,   '.',  '.',
-    '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
-    '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
-    ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
-    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
-    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
-    '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
-    '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
-    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
-    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
-    'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_',
-    '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
-    'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-    'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-    'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<',
-    '<',  '=',  '>',  '#',  '#',  '.',  '#',  '#',
-    '#',  '#',  ' ',  '#',  ' ',  '>',  '.',  '.',
-    '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
-    '6',  '7',  '8',  '9',  '.',  '<',  '=',  '>',
-    ' ',  '!',  '"',  '#',  '$',  '%',  '&',  '\'',
-    '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
-    '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
-    '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
-    '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
-    'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
-    'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
-    'X',  'Y',  'Z',  '[',  '\\', ']',  '^',  '_',
-    '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
-    'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-    'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-    'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<'
-);
-sub text_dp2ascii($)
-{
-	my ($message) = @_;
-	$message = join '', map { $text_qfont_table[ord $_] } split //, $message;
-}
-
-sub color_dp2none($)
-{
-	my ($message) = @_;
-	my $color = -1;
-	$message =~ s{\^(.)(?=([0-9,]?))}{
-		my $c = $1;
-		$c eq '^' ? '^' :
-		$c =~ /^[0-9]$/ ? '' : "^$c";
-	}esg;
-	return text_dp2ascii $message;
-}
-
-sub color_dp2irc($)
-{
-	my ($message) = @_;
-	my $color = -1;
-	$message =~ s{\^(.)(?=([0-9,]?))}{
-		my $c = $1;
-		my $f = $2;
-		$c eq '^' ? '^' :
-		$c =~ /^[0-9]$/ ? do {
-			my $oldcolor = $color;
-			$c = 0 if $c >= 7; # map 0, 7, 8, 9 to default (no bright white or such stuff)
-			$color = $color_dp2irc_table[$c];
-			($color == $oldcolor) ? '' :
-			$c == 0 ? "\0001" :
-			$f eq ',' ? "\0003$color\0002\0002" :
-			$f ne ''  ? sprintf "\0003%02d", $color : "\0003$color";
-		} : "^$c";
-	}esg;
-	$message = text_dp2ascii $message;
-	$message =~ s/\0001/\017/g;
-	$message =~ s/\0002/\002/g;
-	$message =~ s/\0003/\003/g;
-	return $message;
-}
-
-sub color_dp2ansi($)
-{
-	my ($message) = @_;
-	my $color = -1;
-	$message =~ s{\^(.)}{
-		my $c = $1;
-		$c eq '^' ? '^' :
-		$c =~ /^[0-9]$/ ? do {
-			my $oldcolor = $color;
-			$color = $color_dp2ansi_table[$c];
-			($color eq $oldcolor) ? '' :
-			"\000[${color}" # "
-		} : "^$c";
-	}esg;
-	$message = text_dp2ascii $message;
-	$message =~ s/\000/\033/g;
-	return $message;
-}
-
-sub color_dpfix($)
-{
-	my ($message) = @_;
-	# if the message ends with an odd number of ^, kill one
-	chop $message if $message =~ /(?:^|[^\^])\^(\^\^)*$/;
-	return $message;
-}
-
-
-
 # Nexuiz specific parsing of some server messages
 
 sub nex_is_teamplay($)
@@ -719,7 +812,8 @@
 		$store{irc_nick} = "";
 		schedule sub {
 			my ($timer) = @_;
-			out dp => 0, 'status', 'log_dest_udp';
+			out dp => 0, 'sv_cmd bans', 'status 1', 'log_dest_udp';
+			$store{status_waiting} = -1;
 		} => 1;
 		# this will clear irc_error_active
 	} => 30;
@@ -829,6 +923,12 @@
 	return 0;
 }
 
+my $RE_FAIL = qr/$ $/;
+my $RE_SUCCEED = qr//;
+sub cond($)
+{
+	return $_[0] ? $RE_FAIL : $RE_SUCCEED;
+}
 
 
 # List of all handlers on the various sockets. Additional handlers can be added by a plugin.
@@ -857,26 +957,41 @@
 		return 0;
 	} ],
 
+	# retrieve list of banned hosts
+	[ dp => q{#(\d+): (\S+) is still banned for (\S+) seconds} => sub {
+		return 0 unless $store{status_waiting} < 0;
+		my ($id, $ip, $time) = @_;
+		$store{bans_new} = [] if $id == 0;
+		$store{bans_new}[$id] = { ip => $ip, 'time' => $time };
+		return 0;
+	} ],
+
 	# retrieve hostname from status replies
 	[ dp => q{host:     (.*)} => sub {
+		return 0 unless $store{status_waiting} < 0;
 		my ($name) = @_;
 		$store{dp_hostname} = $name;
+		$store{bans} = $store{bans_new};
 		return 0;
 	} ],
 
 	# retrieve version from status replies
 	[ dp => q{version:  (.*)} => sub {
+		return 0 unless $store{status_waiting} < 0;
 		my ($version) = @_;
 		$store{dp_version} = $version;
 		return 0;
 	} ],
 
-	# retrieve number of open player slots
+	# retrieve player names
 	[ dp => q{players:  (\d+) active \((\d+) max\)} => sub {
+		return 0 unless $store{status_waiting} < 0;
 		my ($active, $max) = @_;
 		my $full = ($active >= $max);
 		$store{slots_max} = $max;
 		$store{slots_active} = $active;
+		$store{status_waiting} = $active;
+		$store{playerslots_active_new} = [];
 		if($full != ($store{slots_full} || 0))
 		{
 			$store{slots_full} = $full;
@@ -895,6 +1010,124 @@
 		return 0;
 	} ],
 
+	# retrieve player names
+	[ dp => q{\^\d(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(-?\d+)\s+\#(\d+)\s+\^\d(.*)} => sub {
+		return 0 unless $store{status_waiting} > 0;
+		my ($ip, $pl, $ping, $time, $frags, $no, $name) = ($1, $2, $3, $4, $5, $6, $7);
+		$store{"playerslot_$no"} = { ip => $ip, pl => $pl, ping => $ping, 'time' => $time, frags => $frags, no => $no, name => $name };
+		push @{$store{playerslots_active_new}}, $no;
+		if(--$store{status_waiting} == 0)
+		{
+			$store{playerslots_active} = $store{playerslots_active_new};
+		}
+		return 0;
+	} ],
+
+	# IRC admin commands
+	[ irc => q{:(([^! ]*)![^ ]*) (?i:PRIVMSG) [^&#%]\S* :(.*)} => sub {
+		return 0 unless $config{irc_admin_password} ne '';
+
+		my ($hostmask, $nick, $command) = @_;
+		my $dpnick = color_dpfix $nick;
+
+		if($command eq "login $config{irc_admin_password}")
+		{
+			$store{logins}{$hostmask} = time() + $config{irc_admin_timeout};
+			out irc => 0, "PRIVMSG $nick :my wish is your command";
+			return -1;
+		}
+
+		if($command =~ /^login /)
+		{
+			out irc => 0, "PRIVMSG $nick :invalid password";
+			return -1;
+		}
+
+		if(($store{logins}{$hostmask} || 0) < time())
+		{
+			out irc => 0, "PRIVMSG $nick :authentication required";
+			return -1;
+		}
+
+		if($command =~ /^status(?: (.*))?$/)
+		{
+			my ($match) = $1;
+			my $found = 0;
+			my $foundany = 0;
+			for my $slot(@{$store{playerslots_active} || []})
+			{
+				my $s = $store{"playerslot_$slot"};
+				next unless $s;
+				if(not defined $match or index(color_dp2none($s->{name}), $match) >= 0)
+				{
+					out irc => 0, sprintf 'PRIVMSG %s :%-21s %2i %4i %8s %4i #%-3u %s', $nick, $s->{ip}, $s->{pl}, $s->{ping}, $s->{time}, $s->{frags}, $slot, color_dp2irc $s->{name};
+					++$found;
+				}
+				++$foundany;
+			}
+			if(!$found)
+			{
+				if(!$foundany)
+				{
+					out irc => 0, "PRIVMSG $nick :the server is empty";
+				}
+				else
+				{
+					out irc => 0, "PRIVMSG $nick :no nicknames match";
+				}
+			}
+			return 0;
+		}
+
+		if($command =~ /^kick # (\d+) (.*)$/)
+		{
+			my ($id, $reason) = ($1, $2);
+			my $dpreason = color_irc2dp $reason;
+			$dpreason =~ s/^(~?)(.*)/$1irc $dpnick: $2/g;
+			$dpreason =~ s/(["\\])/\\$1/g;
+			out dp => 0, "kick # $id $dpreason";
+			my $slotnik = "playerslot_$id";
+			out irc => 0, "PRIVMSG $nick :kicked #$id (@{[color_dp2irc $store{$slotnik}{name}]} @ $store{$slotnik}{ip}) ($reason)";
+			return 0;
+		}
+
+		if($command =~ /^kickban # (\d+) (\d+) (\d+) (.*)$/)
+		{
+			my ($id, $bantime, $mask, $reason) = ($1, $2, $3, $4);
+			my $dpreason = color_irc2dp $reason;
+			$dpreason =~ s/^(~?)(.*)/$1irc $dpnick: $2/g;
+			$dpreason =~ s/(["\\])/\\$1/g;
+			out dp => 0, "kickban # $id $bantime $mask $dpreason";
+			my $slotnik = "playerslot_$id";
+			out irc => 0, "PRIVMSG $nick :kickbanned #$id (@{[color_dp2irc $store{$slotnik}{name}]} @ $store{$slotnik}{ip}), netmask $mask, for $bantime seconds ($reason)";
+			return 0;
+		}
+
+		if($command eq "bans")
+		{
+			my $banlist =
+				join ", ",
+				map { "$_ ($store{bans}[$_]{ip}, $store{bans}[$_]{time}s)" }
+				0..@{$store{bans} || []}-1;
+			$banlist = "no bans"
+				if $banlist eq "";
+			out irc => 0, "PRIVMSG $nick :$banlist";
+			return 0;
+		}
+
+		if($command =~ /^unban (\d+)$/)
+		{
+			my ($id) = ($1);
+			out dp => 0, "unban $id";
+			out irc => 0, "PRIVMSG $nick :removed ban $id ($store{bans}[$id]{ip})";
+			return 0;
+		}
+
+		out irc => 0, "PRIVMSG $nick :unknown command (supported: status [substring], kick # id reason, kickban # id bantime mask reason, bans, unban banid)";
+
+		return -1;
+	} ],
+
 	# LMS: detect "no more lives" message
 	[ dp => q{\^4.*\^4 has no more lives left} => sub {
 		if(!$store{lms_blocked})
@@ -1290,7 +1523,8 @@
 # not containing our own IP:port, or by rcon2irc_eval not being a defined command).
 schedule sub {
 	my ($timer) = @_;
-	out dp => 0, 'status', 'log_dest_udp', 'rcon2irc_eval set dummy 1';
+	out dp => 0, 'sv_cmd bans', 'status 1', 'log_dest_udp', 'rcon2irc_eval set dummy 1';
+	$store{status_waiting} = -1;
 	schedule $timer => (exists $store{dp_hostname} ? $config{dp_status_delay} : 1);;
 } => 1;
 
@@ -1381,6 +1615,7 @@
 				# found one! Check if it matches the regular expression of one of
 				# our handlers...
 				my $handled = 0;
+				my $private = 0;
 				for my $h(@handlers)
 				{
 					my ($chanstr_wanted, $re, $sub) = @$h;
@@ -1394,12 +1629,18 @@
 					# and if it is a match, handle it.
 					++$handled;
 					my $result = $sub->(@matches);
+					$private = 1
+						if $result < 0;
 					last
 						if $result;
 				}
 				# print the message, together with info on whether it has been handled or not
-				if($handled)
+				if($private)
 				{
+					print "           $chanstr >> (private)\n";
+				}
+				elsif($handled)
+				{
 					print "           $chanstr >> $line\n";
 				}
 				else

Modified: branches/nexuiz-2.0/data/build-compat-pack.sh
===================================================================
--- branches/nexuiz-2.0/data/build-compat-pack.sh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/build-compat-pack.sh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -18,6 +18,7 @@
 	gfx/inv_weapon11.tga
 	gfx/inv_weapon12.tga
 	gfx/inv_weapon13.tga
+	gfx/inv_weapon14.tga
 	gfx/inv_weapon9.tga
 	gfx/reslimed_mini.tga
 	gfx/runningman_1on1remix_mini.tga
@@ -38,6 +39,9 @@
 	gfx/teamradar_ping.tga
 	gfx/toxic_mini.tga
 	gfx/warfare_mini.tga
+	models/ctf/flags.md3
+	models/ctf/flags.md3_0.skin
+	models/ctf/flags.md3_1.skin
 	models/player/carni.zym.sounds
 	models/player/headhunter.zym.sounds
 	models/player/insurrectionist.zym.sounds
@@ -95,6 +99,21 @@
 	models/sprites/race-finish.tga
 	models/sprites/redbase.tga
 	models/sprites/waypoint.tga
+	models/sprites/wpn-campingrifle_frame0.tga
+	models/sprites/wpn-crylink_frame0.tga
+	models/sprites/wpn-electro_frame0.tga
+	models/sprites/wpn-gl_frame0.tga
+	models/sprites/wpn-hagar_frame0.tga
+	models/sprites/wpn-hlac_frame0.tga
+	models/sprites/wpn-hookgun_frame0.tga
+	models/sprites/wpn-laser_frame0.tga
+	models/sprites/wpn-minstanex_frame0.tga
+	models/sprites/wpn-nex_frame0.tga
+	models/sprites/wpn-porto_frame0.tga
+	models/sprites/wpn-rl_frame0.tga
+	models/sprites/wpn-seeker_frame0.tga
+	models/sprites/wpn-shotgun_frame0.tga
+	models/sprites/wpn-uzi_frame0.tga
     models/tagrocket.md3
     models/tagrocket.tga
 	models/turrets/base-gib1.md3
@@ -132,22 +151,26 @@
 	models/turrets/walker_mghead.md3
 	models/turrets/walker_props.md3
 	models/turrets/walker_spawn.md3
+	models/weapons/g_campingrifle.md3
     models/weapons/g_hlac.md3
 	models/weapons/g_hookgun.md3
 	models/weapons/g_minstanex.md3
 	models/weapons/g_porto.md3
     models/weapons/g_seeker.md3
+	models/weapons/v_campingrifle.md3
     models/weapons/v_hlac.md3
 	models/weapons/v_hookgun.md3
 	models/weapons/v_minstanex.md3
 	models/weapons/v_porto.md3
     models/weapons/v_seeker.md3
+	models/weapons/w_campingrifle.zym
     models/weapons/w_hlac.zym
 	models/weapons/w_hookgun.zym
 	models/weapons/w_minstanex.zym
 	models/weapons/w_porto.zym
     models/weapons/w_seeker.zym
 	particles/particlefont.tga
+	scripts/flags.shader
 	scripts/portals.shader
 	sound/announcer/male/airshot.ogg
 	sound/announcer/male/electrobitch.ogg
@@ -206,7 +229,6 @@
 	sound/player/carni-lycan/coms/incoming.ogg
 	sound/player/carni-lycan/coms/meet.ogg
 	sound/player/carni-lycan/coms/needhelp1.ogg
-	sound/player/carni-lycan/coms/needhelp2.ogg
 	sound/player/carni-lycan/coms/seenflag.ogg
 	sound/player/carni-lycan/coms/taunt1.ogg
 	sound/player/carni-lycan/coms/taunt2.ogg
@@ -418,7 +440,6 @@
 	sound/player/specop/coms/incoming.ogg
 	sound/player/specop/coms/meet.ogg
 	sound/player/specop/coms/needhelp1.ogg
-	sound/player/specop/coms/needhelp2.ogg
 	sound/player/specop/coms/seenflag.ogg
 	sound/player/specop/coms/taunt1.ogg
 	sound/player/specop/coms/taunt2.ogg
@@ -468,6 +489,8 @@
 	sound/weapons/brass1.ogg
 	sound/weapons/brass2.ogg
 	sound/weapons/brass3.ogg
+	sound/weapons/campingrifle_fire.ogg
+	sound/weapons/campingrifle_reload.ogg
 	sound/weapons/casings1.ogg
 	sound/weapons/casings2.ogg
 	sound/weapons/casings3.ogg
@@ -496,10 +519,10 @@
 	sound/weapons/hagexp1.ogg
 	sound/weapons/hagexp2.ogg
 	sound/weapons/hagexp3.ogg
+	sound/weapons/hookbomb_fire.ogg
+	sound/weapons/hookbomb_impact.ogg
 	sound/weapons/hook_fire.ogg
 	sound/weapons/hook_impact.ogg
-	sound/weapons/hookbomb_fire.ogg
-	sound/weapons/hookbomb_impact.ogg
 	sound/weapons/lasergun_fire.ogg
 	sound/weapons/laserimpact.ogg
 	sound/weapons/minstanexfire.ogg
@@ -525,6 +548,38 @@
 	sound/weapons/uzi_fire.ogg
 	sound/weapons/weaponpickup.ogg
 	sound/weapons/weapon_switch.ogg
+	textures/campingrifle_bump.tga
+	textures/campingrifle_gloss.tga
+	textures/campingrifle_glow.tga
+	textures/campingrifle_pants.tga
+	textures/campingrifle_shirt.tga
+	textures/campingrifle.tga
+	textures/flags/flag_blue_cloth.tga
+	textures/flags/flag_blue_gloss.tga
+	textures/flags/flag_blue_glow.tga
+	textures/flags/flag_blue_laser.tga
+	textures/flags/flag_blue_norm.tga
+	textures/flags/flag_blue.tga
+	textures/flags/flag_red_cloth.tga
+	textures/flags/flag_red_gloss.tga
+	textures/flags/flag_red_glow.tga
+	textures/flags/flag_red_laser.tga
+	textures/flags/flag_red_norm.tga
+	textures/flags/flag_red.tga
+	textures/hlac_accessory_gloss.tga
+	textures/hlac_accessory_norm.tga
+	textures/hlac_accessory_pants.tga
+	textures/hlac_accessory_shirt.tga
+	textures/hlac_accessory.tga
+	textures/hlac_body_gloss.tga
+	textures/hlac_body_glow.tga
+	textures/hlac_body_norm.tga
+	textures/hlac_body_pants.tga
+	textures/hlac_body_shirt.tga
+	textures/hlac_body.tga
+	textures/hlac_glass.tga
+	textures/hlac_metal.tga
+	textures/hlac_plasma.tga
 	textures/hlac.tga
 	textures/hookgun_gloss.tga
 	textures/hookgun_norm.tga
@@ -559,8 +614,28 @@
 	textures/seeker.tga
 "
 
-rev=`svnversion`
+rm -rf pack
+mkdir pack
+for F in $COMPAT_FILES; do
+	mkdir -p pack/${F%/*}
+	cp "$F" pack/"$F"
+done
+
+cd pack
+
+find . -type f -print0 | qual=85 scaledown=256x256 xargs -0 ../../misc/jpeg-if-not-alpha.sh
+
+find . -name \*.ogg | while IFS= read -r NAME; do
+	oggdec -o "$NAME.wav" "$NAME"
+	oggenc -q 0 -o "$NAME" "$NAME.wav"
+	rm -f "$NAME.wav"
+done
+
+rev=`svnversion ..`
 pack="zzz_svn-compat-$rev"
 echo "Support files to play on svn servers of revision $rev" > "$pack.txt"
-7za a -tzip -mx=9 "$pack.pk3" $COMPAT_FILES "$pack.txt"
+7za a -tzip -mx=9 "../$pack.pk3" .
 rm -f "$pack.txt"
+
+cd ..
+rm -rf pack

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-12-26 14:38:59 UTC (rev 5314)
@@ -16,7 +16,7 @@
 seta g_configversion 0
 
 // default.cfg versioning (update using update-cvarcount.sh; run that every time after adding a new cvar)
-set cvar_check_default 3e222928f6156061e54639483d8961f0
+set cvar_check_default 3a4552d8adffd3ad69fec3f0c15c62d8
 
 // Nexuiz version (formatted for machines)
 // used to determine if a client version is compatible
@@ -256,6 +256,12 @@
 set bot_ai_aimskill_order_filter_3th 0.05
 set bot_ai_aimskill_order_filter_4th 0.25
 set bot_ai_aimskill_order_filter_5th 0.3
+set bot_ai_custom_weapon_priority_distances "200 1000" // Define close and far distances in any order, the bots will detect middle distances automatically. 
+set bot_ai_custom_weapon_priority_far   "11 7 15 14 4 5 8 13 6 1 3 9 2" // Desired weapons in any order. Up to the max ammount of weapons available in the system 
+set bot_ai_custom_weapon_priority_mid   "11 9 4 5 3 7 15 14 6 13 8 2 1" // same as previous 
+set bot_ai_custom_weapon_priority_close "11 3 9 13 14 8 6 4 2 5 7 15 1" // same as previous
+set bot_ai_weapon_combo 1 // Enable weapon combos 
+set bot_ai_weapon_combo_threshold 0.3 // Try to make a combo N seconds after the last attack
 
 // waypoint editor enable
 set g_waypointeditor 0
@@ -371,8 +377,8 @@
   // 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.5              // for teamplay 4: mirror damage factor
-seta g_friendlyfire 0.2              // for teamplay 4: fiendly fire factor
+seta g_mirrordamage 0.3              // for teamplay 4: mirror damage factor
+seta g_friendlyfire 0.1              // 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
 
@@ -394,7 +400,8 @@
 set g_ctf_flag_returntime 30
 set g_ctf_flagcarrier_selfdamage 1
 set g_ctf_flagcarrier_selfforce 1
-set g_ctf_fullbrightflags 1
+set g_ctf_fullbrightflags 0
+set g_ctf_dynamiclights 1
 set g_ctf_allow_drop 0 // 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_balance_ctf_delay_collect 1.0
@@ -1124,16 +1131,16 @@
 alias allready "sv_cmd allready"
 
 // note: these cvars use weapon NUMBERS. Use the menu to edit this cvar, or look the numbers up in qcsrc/common/constants.qh.
-seta cl_weaponpriority "14 13 9 8 11 7 6 5 4 3 2 1 10 12" // default porto and hook as LOW priority, use the weapon key numbers otherwise
+seta cl_weaponpriority "14 13 9 8 11 7 6 5 4 15 3 2 1 10 12" // default porto and hook as LOW priority, use the weapon key numbers otherwise
 seta cl_weaponpriority_useforcycling 0
 // impulse 200, 210, 220:
-seta cl_weaponpriority0 "14 9 8 4"   // explosives    (RL Hagar Mortar)
+seta cl_weaponpriority0 "14 9 8 4"    // explosives    (RL Hagar Mortar)
 // impulse 201, 211, 221:
-seta cl_weaponpriority1 "13 7 6 5 1" // energy        (Nex Crylink Electro Laser)
-seta cl_weaponpriority2 "7 3"        // hitscan exact (Nex MG)
-seta cl_weaponpriority3 "7 3 2"      // hitscan all   (Nex MG Shotgun)
-seta cl_weaponpriority4 "13 8 6 5 2" // spam          (Hagar Crylink Electro Shotgun)
-seta cl_weaponpriority5 "1 12 10"    // for moving    (Laser Hook Port-O-Launch)
+seta cl_weaponpriority1 "13 7 6 5 1"  // energy        (Nex Crylink Electro Laser)
+seta cl_weaponpriority2 "15 11 7 3"   // hitscan exact (Nex MG)
+seta cl_weaponpriority3 "15 11 7 3 2" // hitscan all   (Nex MG Shotgun)
+seta cl_weaponpriority4 "13 8 6 5 2"  // spam          (Hagar Crylink Electro Shotgun)
+seta cl_weaponpriority5 "1 12 10"     // for moving    (Laser Hook Port-O-Launch)
 seta cl_weaponpriority6 ""
 seta cl_weaponpriority7 ""
 seta cl_weaponpriority8 ""
@@ -1158,6 +1165,7 @@
 set g_weaponreplace_hook ""
 set g_weaponreplace_seeker ""
 set g_weaponreplace_hlac ""
+set g_weaponreplace_campingrifle ""
 
 seta sv_status_privacy 1 // hide IP addresses from "status" replies shown to clients
 
@@ -1232,6 +1240,44 @@
 set g_ban_sync_uri "" // sync using this ban list provider (empty string to disable)
 set g_ban_sync_interval 5 // sync every 5 minutes
 set g_ban_sync_trusted_servers "" // request ban lists from these nexuiz servers (do not include your own server there, or unbanning may fail)
+set g_ban_sync_timeout 45 // time out in seconds for the ban sync requests
 set g_ban_sync_trusted_servers_verify 0 // when set to 1, additional bans sent by the servers are ignored, and only bans for the requested IP are used
 
+set g_showweaponspawns 0 // 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"
+
+// ballistics use physical units, but qu based
+//   Quake-Newton: 1 qN  = 1 qu * 1 g / 1 s^2
+//   Quake-Joule:  1 qJ  = 1 qN * 1 qu
+//   Quake-Pascal: 1 qPa = 1 qN / 1 qu^2
+
+set g_ballistics_materialconstant 1414213562
+// unit: qJ / qu^3 (energy needed per volume unit of solid to push/burn away
+// parameter: bullet constant: mass / area in g/qu^2
+// = mass / (pi/4 * caliber^2)
+// with caliber in inches, mass in grams:
+// = 1.273239544735163 * mass / caliber^2
+// with caliber in inches, mass in grains:
+// = 0.082633246453312 * mass / caliber^2
+
+// bullet max travel distance inside solid:
+//   0.5 * v^2 * bulletconstant / g_ballistics_materialconstant
+
+// some bullet constants:
+//   http://hypertextbook.com/facts/2000/ShantayArmstrong.shtml
+//     second bullet: caliber .45, mass 16.2g, bullet constant 101.859163578813
+//     third bullet: caliber .338, mass 16.2g, bullet constant 180.5476053421592
+//     fourth bullet: caliber .25, mass 2.3g, bullet constant 46.85521524625399
+//   http://en.wikipedia.org/wiki/.50_BMG
+//     caliber .5, 360 grains, bullet constant 118.9918748927693
+//   AK-47:
+//     caliber .3, 62 grains, bullet constant 56.92512533450383
+//   .3 winchester magnum:
+//     caliber .3, 150 grains, bullet constant 137.7220774221867
+
+set g_ballistics_force 0 // 1: make all bullets use the ballistics code instead of hitscan
+set g_ballistics_force_uzi_speed 12000 // speed of uzi bullets if g_ballistics_force is 1
+set g_ballistics_force_uzi_bulletconstant 115 // 5.8qu
+set g_ballistics_force_shotgun_speed 15000 // speed of shotgun bullets if g_ballistics_force is 1
+set g_ballistics_force_shotgun_bulletconstant 50 // 3.9qu

Deleted: branches/nexuiz-2.0/data/env/desert/desert_bk.jpg
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/desert/desert_bk.tga (from rev 5313, trunk/data/env/desert/desert_bk.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/env/desert/desert_dn.jpg
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/desert/desert_dn.tga (from rev 5313, trunk/data/env/desert/desert_dn.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/env/desert/desert_ft.jpg
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/desert/desert_ft.tga (from rev 5313, trunk/data/env/desert/desert_ft.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/env/desert/desert_lf.jpg
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/desert/desert_lf.tga (from rev 5313, trunk/data/env/desert/desert_lf.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/env/desert/desert_rt.jpg
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/desert/desert_rt.tga (from rev 5313, trunk/data/env/desert/desert_rt.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/env/desert/desert_up.jpg
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/desert/desert_up.tga (from rev 5313, trunk/data/env/desert/desert_up.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/env/mandelbrot (from rev 5313, trunk/data/env/mandelbrot)

Copied: branches/nexuiz-2.0/data/gfx/crosshair13.tga (from rev 5313, trunk/data/gfx/crosshair13.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair14.tga (from rev 5313, trunk/data/gfx/crosshair14.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair15.tga (from rev 5313, trunk/data/gfx/crosshair15.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair16.tga (from rev 5313, trunk/data/gfx/crosshair16.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair17.tga (from rev 5313, trunk/data/gfx/crosshair17.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair18.tga (from rev 5313, trunk/data/gfx/crosshair18.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair19.tga (from rev 5313, trunk/data/gfx/crosshair19.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair20.tga (from rev 5313, trunk/data/gfx/crosshair20.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/crosshair21.tga (from rev 5313, trunk/data/gfx/crosshair21.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/crosshair7.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/hslimage.tga (from rev 5313, trunk/data/gfx/hslimage.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/inv_weapon12.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/inv_weapon14.tga (from rev 5313, trunk/data/gfx/inv_weapon14.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/inv_weapon_hlacmod_renameit.tga (from rev 5313, trunk/data/gfx/inv_weapon_hlacmod_renameit.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/gfx/menu/default/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/default/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '1 1 1'
 COLOR_CHECKBOX_D                '1 1 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/silver/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/silver/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/silver/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/silver/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/silver/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '1 1 1'
 COLOR_CHECKBOX_D                '1 1 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/simplygray/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/simplygray/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/simplygray/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/simplygray/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/simplygray/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '1 1 1'
 COLOR_CHECKBOX_D                '1 1 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedblack/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedblack/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '0.75 0.75 0.75'
 COLOR_CHECKBOX_D                '1 1 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedblue/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedblue/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '0.25 0.5 0.75'
 COLOR_CHECKBOX_D                '0.5 0.75 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedgreen/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedgreen/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '0.25 0.75 0'
 COLOR_CHECKBOX_D                '0.5 1 0'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedred/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedred/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '0.75 0 0'
 COLOR_CHECKBOX_D                '1 0 0'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedwhite/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedwhite/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '0.75 0.75 0.75'
 COLOR_CHECKBOX_D                '1 1 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedyellow/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedyellow/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '1 0.75 0'
 COLOR_CHECKBOX_D                '1 0.875 0'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedz/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/wickedz/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedz/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedz/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedz/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -84,6 +84,10 @@
 COLOR_CHECKBOX_F                '0.6 0.4 0'
 COLOR_CHECKBOX_D                '0 0.75 0.75'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/gfx/menu/xaw/colorpicker.tga (from rev 5313, trunk/data/gfx/menu/xaw/colorpicker.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/gfx/menu/xaw/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/xaw/skinvalues.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/gfx/menu/xaw/skinvalues.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -70,6 +70,10 @@
 COLOR_CHECKBOX_F                '1 1 1'
 COLOR_CHECKBOX_D                '1 1 1'
 
+// item: color picker
+//   uses "colorpicker" images
+MARGIN_COLORPICKER              '0 0 0'
+
 // item: credits list
 COLOR_CREDITS_TITLE             '1 1 1'
 ALPHA_CREDITS_TITLE             1

Copied: branches/nexuiz-2.0/data/models/ctf/flags.md3 (from rev 5313, trunk/data/models/ctf/flags.md3)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/ctf/flags.md3_0.skin (from rev 5313, trunk/data/models/ctf/flags.md3_0.skin)
===================================================================
--- branches/nexuiz-2.0/data/models/ctf/flags.md3_0.skin	                        (rev 0)
+++ branches/nexuiz-2.0/data/models/ctf/flags.md3_0.skin	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,3 @@
+replace "flag_red" "textures/flags/flag_red.tga"
+replace "flag_red_cloth" "flag_red_cloth"
+replace "flag_red_laser" "flag_red_laser"

Copied: branches/nexuiz-2.0/data/models/ctf/flags.md3_1.skin (from rev 5313, trunk/data/models/ctf/flags.md3_1.skin)
===================================================================
--- branches/nexuiz-2.0/data/models/ctf/flags.md3_1.skin	                        (rev 0)
+++ branches/nexuiz-2.0/data/models/ctf/flags.md3_1.skin	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,3 @@
+replace "flag_red" "textures/flags/flag_blue.tga"
+replace "flag_red_cloth" "flag_blue_cloth"
+replace "flag_red_laser" "flag_blue_laser"

Modified: branches/nexuiz-2.0/data/models/sprites/make-sprites.sh
===================================================================
--- branches/nexuiz-2.0/data/models/sprites/make-sprites.sh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/models/sprites/make-sprites.sh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -169,3 +169,18 @@
 sprite ons-cp-dfnd-blue   "CONTROL POINT" 0000ff 000000 0.5 0000ff ffffff 0.5
 sprite race-checkpoint    "CHECKPOINT"    ff8000 000000 0.0
 sprite race-finish        "FINISH"        ff8000 000000 0.0
+
+sprite wpn-laser          "LASER"         ff8080 000000 0.0 # bright red
+sprite wpn-shotgun        "SG"            804000 000000 0.0 # brown
+sprite wpn-uzi            "MG"            ffff00 000000 0.0 # yellow
+sprite wpn-gl             "GL"            ff0000 000000 0.0 # red
+sprite wpn-electro        "ELECTRO"       0080ff 000000 0.0 # bluish cyan
+sprite wpn-crylink        "CRYLINK"       ff80ff 000000 0.0 # bright pink
+sprite wpn-nex            "NEX"           00ffff 000000 0.0 # cyan
+sprite wpn-hagar          "HAGAR"         ffff80 000000 0.0 # bright yellow
+sprite wpn-rl             "RL"            ffff00 000000 0.0 # yellow
+sprite wpn-porto          "PORTO"         808080 000000 0.0 # grey
+sprite wpn-minstanex      "MINSTANEX"     80ffff 000000 0.0 # bright cyan
+sprite wpn-hookgun        "HOOK"          008000 000000 0.0 # dark green
+sprite wpn-seeker         "SEEKER"        ff8000 000000 0.0 # orange
+sprite wpn-hlac           "HLAC"          00ff00 000000 0.0 # green

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-campingrifle_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-campingrifle_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-crylink_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-crylink_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-electro_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-electro_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-gl_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-gl_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-hagar_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-hagar_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-hlac_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-hlac_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-hookgun_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-hookgun_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-laser_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-laser_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-minstanex_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-minstanex_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-nex_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-nex_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-porto_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-porto_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-rl_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-rl_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-seeker_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-seeker_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-shotgun_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-shotgun_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/wpn-uzi_frame0.tga (from rev 5313, trunk/data/models/sprites/wpn-uzi_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/weapons/g_campingrifle.md3 (from rev 5313, trunk/data/models/weapons/g_campingrifle.md3)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/models/weapons/g_hlac.md3
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/weapons/g_hlacmod.md3 (from rev 5313, trunk/data/models/weapons/g_hlacmod.md3)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/weapons/v_campingrifle.md3 (from rev 5313, trunk/data/models/weapons/v_campingrifle.md3)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/models/weapons/v_hlac.md3
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/weapons/v_hlacmod.md3 (from rev 5313, trunk/data/models/weapons/v_hlacmod.md3)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/weapons/w_campingrifle.zym (from rev 5313, trunk/data/models/weapons/w_campingrifle.zym)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/models/weapons/w_hlac.zym
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/weapons/w_hlacmod.zym (from rev 5313, trunk/data/models/weapons/w_hlacmod.zym)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/qcsrc/client/View.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -189,6 +189,7 @@
 void PostInit(void);
 float Sbar_WouldDrawScoreboard ();
 float zoomscript_caught;
+float view_set;
 void CSQC_UpdateView(float w, float h)
 {
 	entity e;
@@ -200,12 +201,16 @@
 	WaypointSprite_Load();
 
 	// Render the Scene
-	view_origin = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
-	view_angles = input_angles;
-	makevectors(view_angles);
-	view_forward = v_forward;
-	view_right = v_right;
-	view_up = v_up;
+	if(!intermission || !view_set)
+	{
+		view_origin = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
+		view_angles = input_angles;
+		makevectors(view_angles);
+		view_forward = v_forward;
+		view_right = v_right;
+		view_up = v_up;
+		view_set = 1;
+	}
 
 	f = floor(cvar("v_flipped"));
 	cvar_set("v_flipped", ftos(!f));

Modified: branches/nexuiz-2.0/data/qcsrc/client/hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/hook.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/client/hook.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -34,6 +34,7 @@
 	vector a, b;
 	string tex;
 	vector rgb;
+	float t;
 
 	if(time >= self.HookKillTime)
 		return;
@@ -42,22 +43,25 @@
 	else
 		a = self.HookStart;
 	b = self.HookEnd;
-	if(self.team == COLOR_TEAM1)
+
+	t = GetPlayerColorForce(self.sv_entnum);
+
+	if(t == COLOR_TEAM1)
 	{
 		tex = "particles/hook_red";
 		rgb = '1 .3 .3';
 	}
-	else if(self.team == COLOR_TEAM2)
+	else if(t == COLOR_TEAM2)
 	{
 		tex = "particles/hook_blue";
 		rgb = '.3 .3 1';
 	}
-	else if(self.team == COLOR_TEAM3)
+	else if(t == COLOR_TEAM3)
 	{
 		tex = "particles/hook_yellow";
 		rgb = '1 1 .3';
 	}
-	else if(self.team == COLOR_TEAM4)
+	else if(t == COLOR_TEAM4)
 	{
 		tex = "particles/hook_pink";
 		rgb = '1 .3 1';

Modified: branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -136,11 +136,22 @@
 			ch = str2chr(text, i+1);
 			if(ch >= '0' && ch <= '9')
 				++i;
-			else
-				++width;
-		}
-		else
-			++width;
+			else if(i+4 < len && ch == 'x')
+			{
+				ch = str2chr(text, i+2);
+				if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') )
+				{
+					ch = str2chr(text, i+3);
+					if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') )
+					{
+						ch = str2chr(text, i+4);
+						if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') )
+							i+=4;
+						else ++width;
+					} else ++width;
+				} else ++width;
+			} else ++width;
+		} else ++width;
 	}
 	return width;
 }

Modified: branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -14,16 +14,22 @@
 	}
 }
 
+float GetPlayerColorForce(float i)
+{
+	if(!teamplay)
+		return 0;
+	else
+		return stof(getplayerkey(i, "colors")) & 15;
+}
+
 float GetPlayerColor(float i)
 {
 	if not(playerslots[i].gotscores) // unconnected
 		return COLOR_SPECTATOR;
 	else if(getplayerkey(i, "frags") == "-666")
 		return COLOR_SPECTATOR;
-	else if(!teamplay)
-		return 0;
 	else
-		return stof(getplayerkey(i, "colors")) & 15;
+		return GetPlayerColorForce(i);
 }
 
 vector GetTeamRGB(float color)

Modified: branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -6,6 +6,11 @@
 float cl_teamradar_scale; // window size = ...qu
 float v_flipped;
 
+float vlen2d(vector v)
+{
+	return sqrt(v_x * v_x + v_y * v_y);
+}
+
 float vlen_maxnorm2d(vector v)
 {
 	return max4(v_x, v_y, -v_x, -v_y);
@@ -248,7 +253,7 @@
 	switch(cl_teamradar_rotation)
 	{
 		case 0:
-			teamradar_angle = input_angles_y - 90;
+			teamradar_angle = view_angles_y - 90;
 			break;
 		default:
 			teamradar_angle = 90 * cl_teamradar_rotation;
@@ -265,7 +270,7 @@
 	if(cl_teamradar_rotation == 0)
 	{
 		// max-min distance must fit the radar in any rotation
-		bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen(mi_max - mi_min));
+		bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen2d(mi_max - mi_min));
 	}
 	else
 	{
@@ -294,7 +299,7 @@
 		+ (1 - f) * normalsize;
 	teamradar_origin3d_in_texcoord = teamradar_3dcoord_to_texcoord(
 		  f * (mi_min + mi_max) * 0.5
-		+ (1 - f) * pmove_org);
+		+ (1 - f) * view_origin);
 
 	color = GetPlayerColor(player_localentnum-1);
 	rgb = GetTeamRGB(color);
@@ -340,7 +345,7 @@
 		//if(color == COLOR_SPECTATOR || color == color2)
 			draw_teamradar_player(tm.origin, tm.angles, GetTeamRGB(color2));
 	}
-	draw_teamradar_player(pmove_org, input_angles, '1 1 1');
+	draw_teamradar_player(view_origin, view_angles, '1 1 1');
 
 	drawresetcliparea();
 };

Modified: branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/common/gamecommand.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -48,7 +48,8 @@
 {
 	float argc;
 	float i, j, f, n;
-	string s, s2;
+	vector rgb;
+	string s, s2, c;
 	argc = tokenize_sane(command);
 	if(argv(0) == "help")
 	{
@@ -140,6 +141,33 @@
 			return TRUE;
 		}
 	}
+	else if(argv(0) == "BRLOGENSHFEGLE" && argc >= 2)
+	{
+		// test case for terrencehill's color codes
+		s = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2));
+		s2 = "";
+		n = strlen(s);
+		
+		j = random() * 0.1 + 0.05;
+		f = random();
+
+		for(i = 0; i < n; ++i)
+		{
+			c = substring(s, i, 1);
+			if(c == ";")
+				c = ":";
+			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)

Modified: branches/nexuiz-2.0/data/qcsrc/common/items.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/items.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/common/items.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -16,6 +16,7 @@
 	e.mdl = modelname;
 	e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
 	e.spawnflags = 0;
+	e.model2 = strzone(strcat("wpn-", e.mdl));
 	if(normalweapon)
 		e.spawnflags |= WEPSPAWNFLAG_NORMAL;
 	if(canclimb)
@@ -43,6 +44,7 @@
 	dummy_weapon_info.spawnflags = 0;
 	dummy_weapon_info.impulse = -1;
 	dummy_weapon_info.bot_pickupbasevalue = 0;
+	dummy_weapon_info.model2 = "";
 
 	float i;
 	weaponpriority_hudselector_0 = "";
@@ -110,6 +112,7 @@
 	register_weapon(WEP_HOOK,             w_hook,      IT_CELLS,       0, 0, 1,     0, "hookgun",   "hook",            "Grappling Hook");
 	register_weapon(WEP_SEEKER,           w_seeker,    IT_ROCKETS,     8, 1, 0,     0, "seeker",    "seeker",          "T.A.G. Seeker");
 	register_weapon(WEP_HLAC,             w_hlac,      IT_CELLS,       6, 1, 0,     0, "hlac",      "hlac",            "Heavy Laser Assault Cannon");
+	register_weapon(WEP_CAMPINGRIFLE,              w_campingrifle,       IT_NAILS,       3, 1, 0,  5000, "campingrifle",       "campingrifle",             "Camping Rifle");
 
 	register_weapons_done();
 }

Modified: branches/nexuiz-2.0/data/qcsrc/common/items.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/items.qh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/common/items.qh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -15,8 +15,9 @@
 float WEP_HOOK     			= 12; float WEPBIT_HOOK     		= 2048;
 float WEP_HLAC			    = 13; float WEPBIT_HLAC		        = 4096;
 float WEP_SEEKER			= 14; float WEPBIT_SEEKER		    = 8192;
-float WEP_LAST				= 14; float WEPBIT_ALL              = 16383;
-float WEP_COUNT             = 15;
+float WEP_CAMPINGRIFLE	    = 15; float WEPBIT_CAMPINGRIFLE     = 16384;
+float WEP_LAST				= 15; float WEPBIT_ALL              = 32767;
+float WEP_COUNT             = 16;
 
 float	IT_UNLIMITED_WEAPON_AMMO  = 1;
 // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
@@ -75,3 +76,4 @@
 .float spawnflags; // WEPSPAWNFLAG_... combined
 .float impulse; // weapon impulse
 .float bot_pickupbasevalue; // bot weapon priority
+.string model2; // wpn- sprite name

Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1140,3 +1140,110 @@
 					else
 						return 0;
 }
+
+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);
+
+	if(mi == ma)
+		hsl_x = 0;
+	else if(ma == rgb_x)
+		hsl_x = (rgb_y - rgb_z) / (ma - mi);
+	else if(ma == rgb_y)
+		hsl_x = (rgb_z - rgb_x) / (ma - mi) + 2;
+	else // if(ma == rgb_z)
+		hsl_x = (rgb_x - rgb_y) / (ma - mi) + 4;
+	if(hsl_x < 0)
+		hsl_x += 6;
+	
+	hsl_z = 0.5 * (mi + ma);
+
+	if(mi == ma)
+		hsl_y = 0;
+	else if(hsl_z <= 0.5)
+		hsl_y = (ma - mi) / (2*hsl_z);
+	else // if(hsl_z > 0.5)
+		hsl_y = (ma - mi) / (2 - 2*hsl_z);
+	
+	return hsl;
+}
+
+vector hsl_to_rgb(vector hsl)
+{
+	float mi, ma, maminusmi, h;
+	vector rgb;
+
+	if(hsl_z <= 0.5)
+		maminusmi = hsl_y * 2 * hsl_z;
+	else
+		maminusmi = hsl_y * (2 - 2 * hsl_z);
+	
+	// hsl_z     = 0.5 * mi + 0.5 * ma
+	// maminusmi =     - mi +       ma
+	mi = hsl_z - 0.5 * maminusmi;
+	ma = hsl_z + 0.5 * maminusmi;
+
+	h = hsl_x - 6 * floor(hsl_x / 6);
+
+	//else if(ma == rgb_x)
+	//	h = 60 * (rgb_y - rgb_z) / (ma - mi);
+	if(h <= 1)
+	{
+		rgb_x = ma;
+		rgb_y = h * (ma - mi) + mi;
+		rgb_z = mi;
+	}
+	//else if(ma == rgb_y)
+	//	h = 60 * (rgb_z - rgb_x) / (ma - mi) + 120;
+	else if(h <= 2)
+	{
+		rgb_x = (2 - h) * (ma - mi) + mi;
+		rgb_y = ma;
+		rgb_z = mi;
+	}
+	else if(h <= 3)
+	{
+		rgb_x = mi;
+		rgb_y = ma;
+		rgb_z = (h - 2) * (ma - mi) + mi;
+	}
+	//else // if(ma == rgb_z)
+	//	h = 60 * (rgb_x - rgb_y) / (ma - mi) + 240;
+	else if(h <= 4)
+	{
+		rgb_x = mi;
+		rgb_y = (4 - h) * (ma - mi) + mi;
+		rgb_z = ma;
+	}
+	else if(h <= 5)
+	{
+		rgb_x = (h - 4) * (ma - mi) + mi;
+		rgb_y = mi;
+		rgb_z = ma;
+	}
+	//else if(ma == rgb_x)
+	//	h = 60 * (rgb_y - rgb_z) / (ma - mi);
+	else // if(h <= 6)
+	{
+		rgb_x = ma;
+		rgb_y = mi;
+		rgb_z = (6 - h) * (ma - mi) + mi;
+	}
+
+	return rgb;
+}
+
+string rgb_to_hexcolor(vector rgb)
+{
+	return
+		strcat(
+			"^x",
+			DEC_TO_HEXDIGIT(floor(rgb_x * 15 + 0.5)),
+			DEC_TO_HEXDIGIT(floor(rgb_y * 15 + 0.5)),
+			DEC_TO_HEXDIGIT(floor(rgb_z * 15 + 0.5))
+		);
+}

Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -119,3 +119,12 @@
 
 float power2of(float e);
 float log2of(float x);
+
+string HEXDIGITS = "0123456789ABCDEF0123456789abcdef";
+#define HEXDIGIT_TO_DEC_RAW(d) (strstrofs(HEXDIGITS, (d), 0))
+#define HEXDIGIT_TO_DEC(d) ((HEXDIGIT_TO_DEC_RAW(d) | 0x10) - 0x10)
+#define DEC_TO_HEXDIGIT(d) (substring(HEXDIGITS, (d), 1))
+
+vector rgb_to_hsl(vector rgb);
+vector hsl_to_rgb(vector hsl);
+string rgb_to_hexcolor(vector rgb);

Modified: branches/nexuiz-2.0/data/qcsrc/menu/classes.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/classes.c	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/menu/classes.c	2008-12-26 14:38:59 UTC (rev 5314)
@@ -74,3 +74,4 @@
 #include "nexuiz/dialog_multiplayer_playersetup_radar.c"
 #include "nexuiz/dialog_settings_demo.c"
 #include "nexuiz/demolist.c"
+#include "nexuiz/colorpicker.c"

Modified: branches/nexuiz-2.0/data/qcsrc/menu/draw.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/draw.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/menu/draw.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -295,6 +295,7 @@
 		return strlen(theText); // yeah!
 
 	// binary search for right place to cut string
+	float ch;
 	float left, right, middle; // this always works
 	left = 0;
 	right = strlen(theText); // this always fails
@@ -313,6 +314,32 @@
 	// terminate, as the range still halves each time - but nevertheless, it is
 	// guaranteed that it finds ONE valid cutoff place (where "left" is in
 	// range, and "right" is outside).
-
+	
+	// terencehill: the following code detects truncated ^xrgb tags (e.g. ^x or ^x4)
+	// and decrease left on the basis of the chars detected of the truncated tag
+	// Even if the ^xrgb tag is not complete/correct, left is decreased
+	// (sometimes too much but with a correct result)
+	// it fixes also ^[0-9]
+	if (left >= 1 && substring(theText, left-1, 1) == "^") // * it doesn't consider one or more ^ before the current ^
+		left-=1;
+	else if (left >= 2 && substring(theText, left-2, 2) == "^x") // ^x/
+		left-=2;
+	else if (left >= 3 && substring(theText, left-3, 2) == "^x")
+		{
+			ch = str2chr(theText, left-1);
+			if( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') ) // ^xr/
+				left-=3;
+		}
+	else if (left >= 4 && substring(theText, left-4, 2) == "^x")
+		{
+			ch = str2chr(theText, left-2);
+			if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') )
+			{
+				ch = str2chr(theText, left-1);
+				if ( (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') ) // ^xrg/
+					left-=4;
+			}
+		}
+	
 	return left;
 }

Modified: branches/nexuiz-2.0/data/qcsrc/menu/item/inputbox.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/item/inputbox.c	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/menu/item/inputbox.c	2008-12-26 14:38:59 UTC (rev 5314)
@@ -163,13 +163,17 @@
 		string ch, ch2;
 		float i;
 		vector theColor;
-		float theAlpha;
+		float theAlpha;    //float theVariableAlpha;
 		vector p;
 		float brightness;
+		vector theTempColor;
+		float component;
+		
 		brightness = cvar("r_textbrightness");
 		p = me.realOrigin - eX * me.scrollPos;
 		theColor = '1 1 1';
-		theAlpha = 1;
+		theAlpha = 1;    //theVariableAlpha = 1; // changes when ^ax found
+		
 		for(i = 0; i < strlen(me.text); ++i)
 		{
 			ch = substring(me.text, i, 1);
@@ -180,7 +184,7 @@
 				w = draw_TextWidth(strcat(ch, ch2), 0) * me.realFontSize_x;
 				if(ch2 == "^")
 				{
-					draw_Fill(p, eX * w + eY * me.realFontSize_y, '0 0 1', 0.5);
+					draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
 					draw_Text(p + eX * 0.25 * w, "^", me.realFontSize, theColor, theAlpha, 0);
 				}
 				else if(ch2 == "0" || stof(ch2)) // digit?
@@ -201,19 +205,99 @@
 					theColor = theColor * (1 - brightness) + brightness * '1 1 1';
 					draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
 					draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
-					draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
 				}
+				else if(ch2 == "x") // ^x found
+				{
+					theColor = '1 1 1' * (1 - brightness) + brightness * '1 1 1';
+					theTempColor = '0 0 0';
+					
+					component = HEXDIGIT_TO_DEC(substring(me.text, i+2, 1));
+					if (component >= 0) // ^xr found
+					{
+						theTempColor_x = component/15;
+						
+						component = HEXDIGIT_TO_DEC(substring(me.text, i+3, 1));
+						if (component >= 0) // ^xrg found
+						{
+							theTempColor_y = component/15;
+							
+							component = HEXDIGIT_TO_DEC(substring(me.text, i+4, 1));
+							if (component >= 0) // ^xrgb found
+							{
+								theTempColor_z = component/15;
+								theColor = '0 0 0' + theTempColor;
+								w = draw_TextWidth(substring(me.text, i, 5), 0) * me.realFontSize_x;
+								
+								draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
+								draw_Text(p, substring(me.text, i, 5), me.realFontSize, theColor, 1, 0);    // theVariableAlpha instead of 1 using alpha tags ^ax
+								i += 3;
+							}
+							else
+							{
+								// blue missing
+								w = draw_TextWidth(substring(me.text, i, 4), 0) * me.realFontSize_x;
+								draw_Fill(p, eX * w + eY * me.realFontSize_y, eZ, 0.5);
+								draw_Text(p, substring(me.text, i, 4), me.realFontSize, '1 1 1', theAlpha, 0);
+								i += 2;
+							}
+						}
+						else
+						{
+							// green missing
+							w = draw_TextWidth(substring(me.text, i, 3), 0) * me.realFontSize_x;
+							draw_Fill(p, eX * w + eY * me.realFontSize_y, eY, 0.5);
+							draw_Text(p, substring(me.text, i, 3), me.realFontSize, '1 1 1', theAlpha, 0);
+							i += 1;
+						}
+					}
+					else
+					{
+						// red missing
+						//w = draw_TextWidth(substring(me.text, i, 2), 0) * me.realFontSize_x;
+						draw_Fill(p, eX * w + eY * me.realFontSize_y, eX, 0.5);
+						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_x + 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 0 0', 0.5);
+					draw_Fill(p, eX * w + eY * me.realFontSize_y, '1 1 1', 0.5);
 					draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
-					draw_Text(p, strcat(ch, ch2), me.realFontSize, theColor, theAlpha, 0);
 				}
 				p += w * eX;
 				++i;
 				continue;
 			}
-			draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); p += eX * draw_TextWidth(ch, 0) * me.realFontSize_x;
+			draw_Text(p, ch, me.realFontSize, theColor, theAlpha, 0); // TODO theVariableAlpha
+			p += eX * draw_TextWidth(ch, 0) * me.realFontSize_x;
 		}
 	}
 	else

Modified: branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -83,7 +83,19 @@
 
 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;

Copied: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/colorpicker.c (from rev 5313, trunk/data/qcsrc/menu/nexuiz/colorpicker.c)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/colorpicker.c	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/colorpicker.c	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,113 @@
+#ifdef INTERFACE
+CLASS(NexuizColorpicker) EXTENDS(Image)
+	METHOD(NexuizColorpicker, configureNexuizColorpicker, void(entity, entity))
+	METHOD(NexuizColorpicker, mousePress, float(entity, vector))
+	METHOD(NexuizColorpicker, mouseRelease, float(entity, vector))
+	METHOD(NexuizColorpicker, mouseDrag, float(entity, vector))
+	ATTRIB(NexuizColorpicker, controlledTextbox, entity, NULL)
+	ATTRIB(NexuizColorpicker, image, string, SKINGFX_COLORPICKER)
+	ATTRIB(NexuizColorpicker, imagemargin, vector, SKINMARGIN_COLORPICKER)
+	ATTRIB(NexuizColorpicker, focusable, float, 1)
+	METHOD(NexuizColorpicker, focusLeave, void(entity))
+	METHOD(NexuizColorpicker, keyDown, float(entity, float, float, float))
+ENDCLASS(NexuizColorpicker)
+entity makeNexuizColorpicker(entity theTextbox);
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeNexuizColorpicker(entity theTextbox)
+{
+	entity me;
+	me = spawnNexuizColorpicker();
+	me.configureNexuizColorpicker(me, theTextbox);
+	return me;
+}
+
+void configureNexuizColorpickerNexuizColorpicker(entity me, entity theTextbox)
+{
+	me.controlledTextbox = theTextbox;
+	me.configureImage(me, me.image);
+}
+
+float mousePressNexuizColorpicker(entity me, vector coords)
+{
+	me.mouseDrag(me, coords);
+	return 1;
+}
+
+// must match hslimage.c
+vector hslimage_color(vector v, vector margin)
+{
+    v_x = (v_x - margin_x) / (1 - 2 * margin_x);
+    v_y = (v_y - margin_y) / (1 - 2 * margin_y);
+    if(v_x < 0) v_x = 0;
+    if(v_y < 0) v_y = 0;
+    if(v_x > 1) v_x = 1;
+    if(v_y > 1) v_y = 1;
+    if(v_y > 0.875) // grey bar
+        return hsl_to_rgb(eZ * v_x);
+    else
+        return hsl_to_rgb(v_x * 6 * eX + eY + v_y / 0.875 * eZ);
+}
+
+float mouseDragNexuizColorpicker(entity me, vector coords)
+{
+	float i;
+	for(;;)
+	{
+		i = me.controlledTextbox.cursorPos;
+		if(i >= 2)
+		{
+			if(substring(me.controlledTextbox.text, i-2, 1) == "^")
+				if(strstrofs("0123456789", substring(me.controlledTextbox.text, i-1, 1), 0) >= 0)
+				{
+					me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+					me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+					continue;
+				}
+		}
+
+		if(i >= 5)
+		{
+			if(substring(me.controlledTextbox.text, i-5, 2) == "^x")
+				if(strstrofs("0123456789abcdefABCDEF", substring(me.controlledTextbox.text, i-3, 1), 0) >= 0)
+					if(strstrofs("0123456789abcdefABCDEF", substring(me.controlledTextbox.text, i-2, 1), 0) >= 0)
+						if(strstrofs("0123456789abcdefABCDEF", substring(me.controlledTextbox.text, i-1, 1), 0) >= 0)
+						{
+							me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+							me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+							me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+							me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+							me.controlledTextbox.keyDown(me.controlledTextbox, K_BACKSPACE, 8, 0);
+							continue;
+						}
+		}
+		break;
+	}
+
+	vector margin;
+	margin = me.imagemargin;
+	if(coords_x >= margin_x)
+	if(coords_y >= margin_y)
+	if(coords_x <= 1 - margin_x)
+	if(coords_y <= 1 - margin_y)
+		me.controlledTextbox.enterText(me.controlledTextbox, rgb_to_hexcolor(hslimage_color(coords, margin)));
+
+	return 1;
+}
+
+float mouseReleaseNexuizColorpicker(entity me, vector coords)
+{
+	me.mouseDrag(me, coords);
+	return 1;
+}
+
+void focusLeaveNexuizColorpicker(entity me)
+{
+	me.controlledTextbox.saveCvars(me.controlledTextbox);
+}
+float keyDownNexuizColorpicker(entity me, float key, float ascii, float shift)
+{
+	return me.controlledTextbox.keyDown(me.controlledTextbox, key, ascii, shift);
+}
+#endif

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup.c	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup.c	2008-12-26 14:38:59 UTC (rev 5314)
@@ -30,17 +30,17 @@
 }
 void fillNexuizPlayerSettingsTab(entity me)
 {
-	entity e, pms, sl, e0;
+	entity e, pms, sl, e0, box;
 	float i, n;
 
 	me.TR(me);
 		me.TD(me, 1, 1, me.playerNameLabel = makeNexuizTextLabel(0, "Player Name:"));
 			me.playerNameLabelAlpha = me.playerNameLabel.alpha;
-		me.TD(me, 1, 2, e = makeNexuizInputBox(1, "_cl_name"));
-			e.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved
+		me.TD(me, 1, 2, box = makeNexuizInputBox(1, "_cl_name"));
+			box.forbiddenCharacters = "\r\n\\\"$"; // don't care, isn't getting saved
 	me.TR(me);
-		me.TDempty(me, 1);
-		me.TD(me, 5, 2, e = makeNexuizCharmap(e));
+		me.TD(me, 5, 1, e = makeNexuizColorpicker(box));
+		me.TD(me, 5, 2, e = makeNexuizCharmap(box));
 	me.TR(me);
 	me.TR(me);
 	me.TR(me);
@@ -92,10 +92,13 @@
 	me.TR(me);
 	me.TR(me);
 		me.TD(me, 1, 1, e = makeNexuizTextLabel(0, "Crosshair:"));
-		n = 12;
-		for(i = 1; i <= n; ++i)
-			me.TDNoMargin(me, 1, 2 / n, e = makeNexuizCrosshairButton(3, i), '0 0 0');
+		for(i = 1; i <= 10; ++i)
+			me.TDNoMargin(me, 1, 2 / 10, e = makeNexuizCrosshairButton(3, i), '0 0 0');
 	me.TR(me);
+		me.TDempty(me, 1);
+		for(i = 11; i <= 20; ++i)
+			me.TDNoMargin(me, 1, 2 / 10, e = makeNexuizCrosshairButton(3, i), '0 0 0');
+	me.TR(me);
 		me.TD(me, 1, 1, e = makeNexuizTextLabel(0, "Crosshair Size:"));
 		me.TD(me, 1, 2, e = makeNexuizSlider(0.40, 2, 0.05, "crosshair_size"));
 	me.TR(me);
@@ -111,6 +114,8 @@
 		me.TD(me, 1, 1, e = makeNexuizTextLabel(0, "Crosshair Blue:"));
 		me.TD(me, 1, 2, e = makeNexuizSlider(0, 1, 0.01, "crosshair_color_blue"));
 	me.TR(me);
+	/*
+	 * not supported by the current csqc code
 	me.TR(me);
 		me.TD(me, 1, 1, e = makeNexuizTextLabel(0, "HUD size:"));
 		me.TD(me, 1, 2, e = makeNexuizTextSlider("viewsize"));
@@ -118,6 +123,7 @@
 			e.addValue(e, "Reduced", "110");
 			e.addValue(e, "Full", "100");
 			e.configureNexuizTextSliderValues(e);
+	*/
 	me.TR(me);
 		me.TDempty(me, 0.2);
 		me.TD(me, 1, 2.8, e = makeNexuizCheckBox(1, "sbar_hudselector", "Use old-style HUD layout"));

Modified: branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -102,6 +102,10 @@
 	SKINVECTOR(COLOR_CHECKBOX_F, '1 1 1');
 	SKINVECTOR(COLOR_CHECKBOX_D, '1 1 1');
 
+	// item: color picker
+	SKINSTRING(GFX_COLORPICKER, "colorpicker");
+	SKINVECTOR(MARGIN_COLORPICKER, '0 0 0');
+
 	// item: credits list
 	SKINVECTOR(COLOR_CREDITS_TITLE, '1 1 1');
 	SKINFLOAT(ALPHA_CREDITS_TITLE, 1);

Modified: branches/nexuiz-2.0/data/qcsrc/server/bots.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/bots.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/bots.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1499,6 +1499,89 @@
  		self.netname = name;
 };
 
+float bot_custom_weapon;
+float bot_distance_far;
+float bot_distance_close;
+
+float bot_weapons_far[WEP_LAST];
+float bot_weapons_mid[WEP_LAST];
+float bot_weapons_close[WEP_LAST];
+
+void bot_custom_weapon_priority_setup()
+{
+	local float tokens, i, c, w;
+
+	bot_custom_weapon = FALSE;
+
+	if(	cvar_string("bot_ai_custom_weapon_priority_far") == "" ||
+		cvar_string("bot_ai_custom_weapon_priority_mid") == "" ||
+		cvar_string("bot_ai_custom_weapon_priority_close") == "" ||
+ 		cvar_string("bot_ai_custom_weapon_priority_distances") == ""
+	)
+		return;
+
+	// Parse distances
+	tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_distances")," ");
+
+	if (tokens!=2)
+		return;
+
+	bot_distance_far = stof(argv(0));
+	bot_distance_close = stof(argv(1));
+	
+	if(bot_distance_far < bot_distance_close){
+		bot_distance_far = stof(argv(1));
+		bot_distance_close = stof(argv(0));	
+	}
+
+	// Initialize list of weapons
+	bot_weapons_far[0] = -1;
+	bot_weapons_mid[0] = -1;
+	bot_weapons_close[0] = -1;
+
+	// Parse far distance weapon priorities
+	tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_far")," ");
+
+	c = 0;
+	for(i=0; i < tokens && i < WEP_LAST; ++i){
+		w = stof(argv(i));
+		if ( w >= WEP_FIRST && w <= WEP_LAST) {
+			bot_weapons_far[c] = w;
+			++c;
+		}
+	}
+	bot_weapons_far[c] = -1;
+
+	// Parse mid distance weapon priorities
+	tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_mid")," ");
+
+	c = 0;
+	for(i=0; i < tokens && i < WEP_LAST; ++i){
+		w = stof(argv(i));
+		if ( w >= WEP_FIRST && w <= WEP_LAST) {
+			bot_weapons_mid[c] = w;
+			++c;
+		}
+	}
+	bot_weapons_mid[c] = -1;
+
+	// Parse close distance weapon priorities
+	tokens = tokenizebyseparator(cvar_string("bot_ai_custom_weapon_priority_close")," ");
+
+	c = 0;
+	for(i=0; i < tokens && i < WEP_LAST; ++i){
+		w = stof(argv(i));
+		if ( w >= WEP_FIRST && w <= WEP_LAST) {
+			bot_weapons_close[c] = w;
+			++c;
+		}
+	}
+	bot_weapons_close[c] = -1;
+
+	bot_custom_weapon = TRUE;
+};
+
+
 void bot_endgame()
 {
 	local entity e;
@@ -2169,6 +2252,7 @@
 		head.totalfrags_lastcheck = head.totalfrags;
 }
 
+float bot_cvar_nextthink;
 void bot_serverframe()
 {
 	float realplayers, bots, activerealplayers;
@@ -2288,4 +2372,11 @@
 
 	if (cvar("g_waypointeditor"))
 		botframe_showwaypointlinks();
+
+	if(time > bot_cvar_nextthink)
+	{
+		if(currentbots>1)
+			bot_custom_weapon_priority_setup();
+		bot_cvar_nextthink = time + 5;
+	}
 };

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -2027,7 +2027,8 @@
 	self.stat_sys_ticrate = cvar("sys_ticrate");
 	self.stat_game_starttime = game_starttime;
 
-	if(blockSpectators)
+	if(blockSpectators && frametime)
+		// WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
 		checkSpectatorBlock();
 	
 	zoomstate_set = 0;
@@ -2325,8 +2326,9 @@
 		stuffcmd(self, "seta _cl_name Player\n");
 	}
 
-	if(sv_maxidle)
+	if(sv_maxidle && frametime)
 	{
+		// 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)

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -6,9 +6,10 @@
 		W_SwitchWeapon_Force(self, imp);
 };
 
+.float weaponcomplainindex;
 float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain)
 {
-	float n, i, weaponwant, first_valid, prev_valid, switchtonext, switchtolast;
+	float n, i, weaponwant, first_valid, prev_valid, switchtonext, switchtolast, c;
 	n = tokenize_sane(weaponorder);
 	switchtonext = switchtolast = 0;
 	first_valid = prev_valid = 0;
@@ -16,14 +17,17 @@
 	if(dir == 0)
 		switchtonext = 1;
 
+	c = 0;
+
 	for(i = 0; i < n; ++i)
 	{
 		weaponwant = stof(argv(i));
-
 		if(imp >= 0)
 			if((get_weaponinfo(weaponwant)).impulse != imp)
 				continue;
 
+		++c;
+
 		if(client_hasweapon(pl, weaponwant, TRUE, FALSE))
 		{
 			if(switchtonext)
@@ -49,16 +53,24 @@
 		else
 			return first_valid;
 	}
-	// complain
+	// complain (but only for one weapon on the button that has been pressed)
 	if(complain)
 	{
+		self.weaponcomplainindex += 1;
+		c = mod(self.weaponcomplainindex, c) + 1;
 		for(i = 0; i < n; ++i)
 		{
 			weaponwant = stof(argv(i));
 			if(imp >= 0)
 				if((get_weaponinfo(weaponwant)).impulse != imp)
 					continue;
-			client_hasweapon(pl, weaponwant, TRUE, TRUE);
+
+			--c;
+			if(c == 0)
+			{
+				client_hasweapon(pl, weaponwant, TRUE, TRUE);
+				break;
+			}
 		}
 	}
 	return 0;

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -373,11 +373,18 @@
 	self.exteriorweaponentity.nextthink = time;
 };
 
+.float hasweapon_complain_spam;
+
 float client_hasweapon(entity cl, float wpn, float andammo, float complain)
 {
 	local float weaponbit, f;
 	local entity oldself;
 
+	if(time < self.hasweapon_complain_spam)
+		complain = 0;
+	if(complain)
+		self.hasweapon_complain_spam = time + 0.2;
+
 	if (wpn < WEP_FIRST || wpn > WEP_LAST)
 	{
 		if (complain)
@@ -415,7 +422,34 @@
 		// DRESK - 3/16/07
 		// Report Proper Weapon Status / Modified Weapon Ownership Message
 		if(weaponsInMap & weaponbit)
+		{
 			sprint(cl, strcat("You do not have the ^2", W_Name(wpn), "\n") );
+
+			if(cvar("g_showweaponspawns"))
+			{
+				entity e;
+				string s;
+
+				e = get_weaponinfo(wpn);
+				s = e.model2;
+
+				for(e = world; (e = findfloat(e, weapons, weaponbit)); )
+				{
+					if(e.classname == "droppedweapon")
+						continue;
+					if not(e.flags & FL_ITEM)
+						continue;
+					WaypointSprite_Spawn(
+						s,
+						1, 0,
+						world, e.origin,
+						self, 0,
+						world, enemy,
+						0
+					);
+				}
+			}
+		}
 		else
 			sprint(cl, strcat("The ^2", W_Name(wpn), "^7 is ^1NOT AVAILABLE^7 in this map\n") );
 	}
@@ -482,19 +516,23 @@
 		return FALSE;
 
 	// don't fire if previous attack is not finished
-	if (ATTACK_FINISHED(self) > time + frametime * 0.5)
-		return FALSE;
+	if(attacktime >= 0)
+		if (ATTACK_FINISHED(self) > time + frametime * 0.5)
+			return FALSE;
 	// don't fire while changing weapon
 	if (self.weaponentity.state != WS_READY)
 		return FALSE;
 	self.weaponentity.state = WS_INUSE;
 	// if the weapon hasn't been firing continuously, reset the timer
-	if (ATTACK_FINISHED(self) < time - frametime * 1.5)
+	if(attacktime >= 0)
 	{
-		ATTACK_FINISHED(self) = time;
-		//dprint("resetting attack finished to ", ftos(time), "\n");
+		if (ATTACK_FINISHED(self) < time - frametime * 1.5)
+		{
+			ATTACK_FINISHED(self) = time;
+			//dprint("resetting attack finished to ", ftos(time), "\n");
+		}
+		ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime;
 	}
-	ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime;
 	self.bulletcounter += 1;
 	//dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
 	return TRUE;

Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -425,29 +425,40 @@
 		//if(ctf_clientcommand())
 		//	return;
 		cmd = argv(0);
-		/* checks not needed any more since DP has separated clientcommands and regular commands
+		// grep for Cmd_AddCommand_WithClientCommand to find them all
 		if(cmd != "status")
-		if(cmd != "name")
+		if(cmd != "max")
+		if(cmd != "monster")
+		if(cmd != "scrag")
+		if(cmd != "wraith")
+		if(cmd != "gimme")
+		if(cmd != "god")
+		if(cmd != "notarget")
+		if(cmd != "fly")
+		if(cmd != "noclip")
+		if(cmd != "give")
 		//if(cmd != "say") // handled above
 		//if(cmd != "say_team") // handled above
 		if(cmd != "tell")
-		if(cmd != "color")
 		if(cmd != "kill")
 		if(cmd != "pause")
-		if(cmd != "kick")
 		if(cmd != "ping")
-		if(cmd != "pings")
-		if(cmd != "ban")
+		if(cmd != "name")
+		if(cmd != "color")
+		if(cmd != "rate")
 		if(cmd != "pmodel")
-		if(cmd != "rate")
 		if(cmd != "playermodel")
 		if(cmd != "playerskin")
-		if(cmd != "god") if(cmd != "notarget") if(cmd != "fly") if(cmd != "give") if(cmd != "noclip")
+		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;
 		}
-		*/
 		clientcommand(self,s);
 	}
 }

Modified: branches/nexuiz-2.0/data/qcsrc/server/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/constants.qh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/constants.qh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1,6 +1,5 @@
-string CVAR_CHECK_DEFAULT = "3e222928f6156061e54639483d8961f0";
-string CVAR_CHECK_WEAPONS = "bf8a055d6b6b090133b248bccf916024";
-
+string CVAR_CHECK_DEFAULT = "3a4552d8adffd3ad69fec3f0c15c62d8";
+string CVAR_CHECK_WEAPONS = "0ce586134eb7097440e850031829efe6";
 float	FALSE					= 0;
 float	TRUE					= 1;
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/ctf.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/ctf.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/ctf.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -150,7 +150,7 @@
 	if(!self.t_width)
 		self.t_width = 0.1; // frame animation rate
 	if(!self.t_length)
-		self.t_length = 119; // maximum frame
+		self.t_length = 58; // maximum frame
 
 	setattachment(self, world, "");
 	self.mdl = self.model;
@@ -700,7 +700,7 @@
 	if(self.spawnflags & 1)
 		self.noalign = 1;
 	if (!self.model)
-		self.model = "models/ctf/flag_red.md3";
+		self.model = "models/ctf/flags.md3";
 	if (!self.noise)
 		self.noise = "ctf/take.wav";
 	if (!self.noise1)
@@ -729,6 +729,8 @@
 	self.effects = self.effects | EF_LOWPRECISION;
 	if(cvar("g_ctf_fullbrightflags"))
 		self.effects |= EF_FULLBRIGHT;
+	if(cvar("g_ctf_dynamiclights"))
+		self.effects |= EF_RED;
 
 	waypoint_spawnforitem(self);
 
@@ -790,11 +792,11 @@
 	}
 	self.netname = "^4BLUE^7 flag";
 	self.target = "###item###";
-	self.skin = 0;
+	self.skin = 1;
 	if(self.spawnflags & 1)
 		self.noalign = 1;
 	if (!self.model)
-		self.model = "models/ctf/flag_blue.md3";
+		self.model = "models/ctf/flags.md3";
 	if (!self.noise)
 		self.noise = "ctf/take.wav";
 	if (!self.noise1)
@@ -823,6 +825,8 @@
 	self.effects = self.effects | EF_LOWPRECISION;
 	if(cvar("g_ctf_fullbrightflags"))
 		self.effects |= EF_FULLBRIGHT;
+	if(cvar("g_ctf_dynamiclights"))
+		self.effects |= EF_BLUE;
 
 	waypoint_spawnforitem(self);
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -738,8 +738,8 @@
 						// 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 + '0.5 0 0' * targ.mins_x + '0 0.5 0' * targ.mins_y + '0 0 1' * targ.view_ofs_z;
-						headmaxs = org + '0.5 0 0' * targ.maxs_x + '0 0.5 0' * targ.maxs_y + '0 0 1' * targ.maxs_z;
+						headmins = org + '0.7 0 0' * targ.mins_x + '0 0.7 0' * targ.mins_y + '0 0 1' * targ.view_ofs_z;
+						headmaxs = org + '0.7 0 0' * targ.maxs_x + '0 0.7 0' * targ.maxs_y + '0 0 1' * targ.maxs_z;
 						if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs))
 						{
 							damage *= 1 + damage_headshotbonus;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -84,6 +84,7 @@
 }
 
 .float hook_length;
+.float hook_switchweapon;
 
 void RemoveGrapplingHook(entity pl)
 {
@@ -407,6 +408,12 @@
 			//self.hook_state &~= HOOK_RELEASING;
 		}
 	}
+	else if(!g_grappling_hook && self.switchweapon != WEP_HOOK)
+	{
+		if(self.BUTTON_HOOK && !self.hook_switchweapon)
+			W_SwitchWeapon(WEP_HOOK);
+	}
+	self.hook_switchweapon = self.BUTTON_HOOK;
 
 	if(!g_grappling_hook && self.weapon != WEP_HOOK)
 	{
@@ -427,6 +434,7 @@
 			RemoveGrapplingHook(self);
 		self.hook_state &~= HOOK_REMOVING;
 	}
+
 	/*
 	// if I have no hook or it's not pulling yet, make sure I'm not flying!
 	if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -280,6 +280,58 @@
 	traceline_antilag_force(source, v1, v2, nomonst, forent, lag);
 }
 
+void traceline_inverted (vector v1, vector v2, float nomonsters, entity forent)
+{
+	vector pos, dir, t;
+	float nudge;
+
+	//nudge = 2 * cvar("collision_impactnudge"); // why not?
+	nudge = 0.5;
+
+	dir = normalize(v2 - v1);
+
+	pos = v1 + dir * nudge;
+
+	for(;;)
+	{
+		if((pos - v1) * dir >= (v2 - v1) * dir)
+		{
+			// went too far
+			trace_fraction = 1;
+			return;
+		}
+
+		traceline(pos, v2, nomonsters, forent);
+
+		if(trace_startsolid)
+		{
+			// we started inside solid.
+			// then trace from endpos to pos
+			t = trace_endpos;
+			traceline(t, pos, nomonsters, forent);
+			if(trace_startsolid)
+			{
+				// t is inside solid? bad
+				// force advance, then
+				pos = pos + dir * nudge;
+			}
+			else
+			{
+				// we actually LEFT solid!
+				trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
+				return;
+			}
+		}
+		else
+		{
+			// pos is outside solid?!? but why?!? never mind, just return it.
+			trace_endpos = pos;
+			trace_fraction = ((trace_endpos - v1) * dir) / ((v2 - v1) * dir);
+			return;
+		}
+	}
+}
+
 /*
 ==================
 findbetterlocation

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -196,6 +196,7 @@
 
 void detect_maptype()
 {
+#if 0
 	vector o, v;
 	float i;
 
@@ -222,6 +223,7 @@
 
 		break;
 	}
+#endif
 }
 
 float world_already_spawned;
@@ -751,15 +753,14 @@
 
 void Maplist_Init()
 {
-	string temp;
-	temp = cvar_string("g_maplist");
-	Map_Count = tokenizebyseparator(temp, " ");
+	Map_Count = tokenizebyseparator(cvar_string("g_maplist"), " ");
 	if(Map_Count == 0)
 	{
 		bprint( "Maplist is empty!  Resetting it to default map list.\n" );
-		cvar_set("g_maplist", temp = MapInfo_ListAllowedMaps(0, MAPINFO_FLAG_HIDDEN));
+		cvar_set("g_maplist", MapInfo_ListAllowedMaps(0, MAPINFO_FLAG_HIDDEN));
+		ShuffleMaplist();
 		localcmd("\nmenu_cmd sync\n");
-		Map_Count = tokenizebyseparator(temp, " ");
+		Map_Count = tokenizebyseparator(cvar_string("g_maplist"), " ");
 	}
 	if(Map_Count == 0)
 		error("empty maplist, cannot select a new map");
@@ -876,6 +877,7 @@
 			{
 				bprint( "Maplist contains no single playable map!  Resetting it to default map list.\n" );
 				cvar_set("g_maplist", MapInfo_ListAllowedMaps(0, MAPINFO_FLAG_HIDDEN));
+				ShuffleMaplist();
 				localcmd("\nmenu_cmd sync\n");
 			}
 			else
@@ -1510,7 +1512,7 @@
 		limit = -limit;
 	}
 
-	if(g_dm || (g_ctf && g_ctf_win_mode != 2) || g_tdm || g_arena || (g_race && !g_race_qualifying))
+	if(g_dm || g_tdm || g_arena || (g_race && !g_race_qualifying))
 	// these modes always score in increments of 1, thus this makes sense
 	{
 		if(leaderfrags != WinningConditionHelper_topscore)
@@ -1896,6 +1898,7 @@
 	{
 		bprint( "Maplist contains no single playable map!  Resetting it to default map list.\n" );
 		cvar_set("g_maplist", MapInfo_ListAllowedMaps(0, MAPINFO_FLAG_HIDDEN));
+		ShuffleMaplist();
 		localcmd("\nmenu_cmd sync\n");
 		for(i = 0; i < 100 && mapvote_count < nmax; ++i)
 			MapVote_AddVotable(GetNextMap(), FALSE);

Modified: branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -320,6 +320,7 @@
 	self.havocbot_stickenemy = 1;
 };
 
+.float bot_chooseweapontime;
 float(entity e) w_getbestweapon;
 void havocbot_chooseweapon()
 {
@@ -339,6 +340,7 @@
 	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 currentscore;
@@ -348,8 +350,69 @@
 	local float maxdelaytime=0.5;
 	local float spreadpenalty=10;
 	local float distancefromfloor;
+
+	local float af;
+
 	traceline(self.enemy.origin,self.enemy.origin-'0 0 1000',TRUE,world);
 	distancefromfloor = self.enemy.origin_z - trace_endpos_z;
+	
+	af = ATTACK_FINISHED(self);
+
+	// Custom weapon list based on distance to the enemy
+	local float i; i = 0;
+	if(bot_custom_weapon){
+
+		// Choose weapons for far distance
+		if ( distance > bot_distance_far ) {
+			for(i=0; i < WEP_LAST && bot_weapons_far[i] != -1 ; ++i){
+				w = bot_weapons_far[i];
+				if ( client_hasweapon(self, w, TRUE, FALSE) ){
+					if ( self.weapon == w){
+						if( cvar("bot_ai_weapon_combo") && 
+							af > time + cvar("bot_ai_weapon_combo_threshold"))
+							continue;
+					} else {
+						self.switchweapon = w;
+					}
+					return;
+				}
+			}
+		}
+
+		// Choose weapons for mid distance
+		if ( distance > bot_distance_close ) {
+			for(i=0; i < WEP_LAST && bot_weapons_mid[i] != -1 ; ++i){
+				w = bot_weapons_mid[i];
+				if ( client_hasweapon(self, w, TRUE, FALSE) ){
+					if ( self.weapon == w){
+						if( cvar("bot_ai_weapon_combo") && 
+							af > time + cvar("bot_ai_weapon_combo_threshold"))
+							continue;
+					} else {
+						self.switchweapon = w;
+					}
+					return;
+				}
+			}
+		}
+
+		// Choose weapons for close distance
+		for(i=0; i < WEP_LAST && bot_weapons_close[i] != -1 ; ++i){
+			w = bot_weapons_close[i];
+			if ( client_hasweapon(self, w, TRUE, FALSE) ){
+				if ( self.weapon == w){
+					if( cvar("bot_ai_weapon_combo") && 
+						af > time + cvar("bot_ai_weapon_combo_threshold"))
+						continue;
+				} else {
+					self.switchweapon = w;
+				}
+				return;
+			}
+		}
+		// If now weapon was chosen by this system fall back to the previous one
+	}
+
 	// Formula:
 	//	(Damage/Sec * Weapon spefic change to get that damage)
 	//	*(Time to get to target * weapon specfic hitchange bonus) / (in a time of maxdelaytime)
@@ -359,33 +422,71 @@
 	if (client_hasweapon(self, WEP_MINSTANEX, TRUE, FALSE))
 		minstanex = (1000/cvar("g_balance_minstanex_refire")*1.0)
 			* (0.5);
-	if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
+
+	if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE)  && 
+		!(	cvar("bot_ai_weapon_combo") && self.weapon == WEP_ROCKET_LAUNCHER && 
+			af > time + cvar("bot_ai_weapon_combo_threshold") 
+		)
+	)
 		rocket = (cvar("g_balance_rocketlauncher_damage")/cvar("g_balance_rocketlauncher_refire")*0.75)
 			* bound(0,(cvar("g_balance_rocketlauncher_speed")/distance*maxdelaytime),1)*1.5;
-	if (client_hasweapon(self, WEP_NEX, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_NEX, TRUE, FALSE)  && 
+		!( 	cvar("bot_ai_weapon_combo") && self.weapon == WEP_NEX && 
+			af > time + cvar("bot_ai_weapon_combo_threshold") 
+		)
+	)
 		nex = (cvar("g_balance_nex_damage")/cvar("g_balance_nex_refire")*1.0)
 			* (0.5);
-	if (client_hasweapon(self, WEP_HAGAR, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_HAGAR, TRUE, FALSE) ) // && 
+	//	!( cvar("bot_ai_weapon_combo") && self.weapon == WEP_HAGAR &&  time < self.bot_lastshot + cvar("g_balance_hagar_primary_refire") ))
 		hagar = (cvar("g_balance_hagar_primary_damage")/cvar("g_balance_hagar_primary_refire")*1.0)
 			* bound(0,(cvar("g_balance_hagar_primary_speed")/distance*maxdelaytime),1)*0.2;
-	if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE, FALSE) && 
+		!( 
+			cvar("bot_ai_weapon_combo") && self.weapon == WEP_GRENADE_LAUNCHER && 
+			af > time + cvar("bot_ai_weapon_combo_threshold") 
+		)
+	)
 		grenade = (cvar("g_balance_grenadelauncher_primary_damage")/cvar("g_balance_grenadelauncher_primary_refire")*1.0)
 			* bound(0,(cvar("g_balance_grenadelauncher_primary_speed")/distance*maxdelaytime),1)*1.1;
-	if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE) && 
+		!( 	cvar("bot_ai_weapon_combo") && self.weapon == WEP_ELECTRO && 
+			af > time + cvar("bot_ai_weapon_combo_threshold") 
+		)
+	)
 		electro = (cvar("g_balance_electro_primary_damage")/cvar("g_balance_electro_primary_refire")*0.75)
 			* bound(0,(cvar("g_balance_electro_primary_speed")/distance*maxdelaytime),1)*1.0;
-	if (client_hasweapon(self, WEP_CRYLINK, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_CRYLINK, TRUE, FALSE) ) // && 
+	//	!( self.weapon == WEP_CRYLINK &&  time < self.bot_lastshot + cvar("g_balance_crylink_primary_refire") ))
 		crylink = (cvar("g_balance_crylink_primary_damage")/cvar("g_balance_crylink_primary_refire")*1.0)
 			* bound(0,(cvar("g_balance_crylink_primary_speed")/distance*maxdelaytime),1)*(64/(32+cvar("g_balance_crylink_primary_spread")*distance))*1.0;
-	if (client_hasweapon(self, WEP_UZI, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_UZI, TRUE, FALSE) ) // && 
+	//	!( self.weapon == WEP_UZI &&  time < self.bot_lastshot + cvar("g_balance_uzi_sustained_refire") ))
 		uzi = (cvar("g_balance_uzi_sustained_damage")/cvar("g_balance_uzi_sustained_refire")*1.0)
 			* bound(0,32/(32+cvar("g_balance_uzi_sustained_spread")*distance),1);
-	if (client_hasweapon(self, WEP_SHOTGUN, TRUE, FALSE))
+			
+	if (client_hasweapon(self, WEP_SHOTGUN, TRUE, FALSE) && 
+		!(	cvar("bot_ai_weapon_combo") && self.weapon == WEP_SHOTGUN && 
+			af > time + cvar("bot_ai_weapon_combo_threshold") 
+		)
+	)
 		shotgun = (cvar("g_balance_shotgun_primary_damage")*cvar("g_balance_shotgun_primary_bullets")/cvar("g_balance_shotgun_primary_refire")*1.0)
 			* bound(0,32/(32+cvar("g_balance_shotgun_primary_spread")*distance),1);
-	if (client_hasweapon(self, WEP_LASER, FALSE, FALSE))
+			
+	if (client_hasweapon(self, WEP_LASER, FALSE, FALSE) && 
+		!(	cvar("bot_ai_weapon_combo") && self.weapon == WEP_LASER && 
+			af > time + cvar("bot_ai_weapon_combo_threshold") 
+		)
+	)
 		laser = (cvar("g_balance_laser_primary_damage")/cvar("g_balance_laser_primary_refire")*1.0)
 			* bound(0,cvar("g_balance_laser_primary_speed")/distance*maxdelaytime,1);
+			
 	if((self.enemy.flags & FL_ONGROUND)==FALSE){
 		rocket = rocket   * (1.5-bound(0, distancefromfloor/cvar("g_balance_rocketlauncher_radius"         ),0.9)); //slight bigger change
 		grenade = grenade * (1.5-bound(0,distancefromfloor/cvar("g_balance_grenadelauncher_primary_radius"),0.95));
@@ -417,8 +518,13 @@
 	w = WEP_LASER            ;s = laser    ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
 
 	// switch if the best weapon would provide a significant damage increase
-	if (bestscore > currentscore*1.5)
+	if (bestscore > currentscore*1.5){
 		self.switchweapon = bestweapon;
+		
+		// buys time for detonating the rocket. not tested yet
+		if ( cvar("bot_ai_weapon_combo") && bestweapon == WEP_ROCKET_LAUNCHER )
+			self.bot_chooseweapontime += (distance  / cvar("g_balance_rocketlauncher_speed"));
+	}
 };
 
 .float nextaim;
@@ -442,7 +548,6 @@
 		lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, self.goalcurrent.origin, '0 0 0');
 };
 
-.float bot_chooseweapontime;
 void havocbot_ai()
 {
 	if (bot_strategytoken == self)
@@ -453,7 +558,7 @@
 		bot_strategytoken_taken = TRUE;
 	}
 	havocbot_chooseenemy();
-	if (self.bot_chooseweapontime < time)
+	if (self.bot_chooseweapontime < time )
 	{
 		self.bot_chooseweapontime = time + cvar("bot_ai_chooseweaponinterval");
 		havocbot_chooseweapon();

Modified: branches/nexuiz-2.0/data/qcsrc/server/ipban.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/ipban.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/ipban.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -32,8 +32,10 @@
 	uri = strcat(uri, "&reason=", uri_escape(reason));
 
 	n = tokenize_sane(cvar_string("g_ban_sync_uri"));
+	if(n >= MAX_IPBAN_URIS)
+		n = MAX_IPBAN_URIS;
 	for(i = 0; i < n; ++i)
-		uri_get(strcat(argv(i), uri), 0); // 0 = "discard" callback target
+		uri_get(strcat(argv(i), uri), URI_GET_DISCARD); // 0 = "discard" callback target
 }
 
 void OnlineBanList_SendUnban(string ip)
@@ -45,15 +47,17 @@
 	uri = strcat(uri, "&ip=", uri_escape(ip));
 
 	n = tokenize_sane(cvar_string("g_ban_sync_uri"));
+	if(n >= MAX_IPBAN_URIS)
+		n = MAX_IPBAN_URIS;
 	for(i = 0; i < n; ++i)
-		uri_get(strcat(argv(i), uri), 0); // 0 = "discard" callback target
+		uri_get(strcat(argv(i), uri), URI_GET_DISCARD); // 0 = "discard" callback target
 }
 
 string OnlineBanList_Servers;
 float OnlineBanList_Timeout;
-float OnlineBanList_Requests;
+float OnlineBanList_RequestWaiting[MAX_IPBAN_URIS];
 
-void OnlineBanList_URI_Get_Callback(float status, string data)
+void OnlineBanList_URI_Get_Callback(float id, float status, string data)
 {
 	float n, i, j, l;
 	string ip;
@@ -61,46 +65,71 @@
 	string reason;
 	string serverip;
 	float syncinterval;
+	string uri;
 
-	if(OnlineBanList_Requests <= 0)
+	id -= URI_GET_IPBAN;
+
+	if(id >= MAX_IPBAN_URIS)
+	{
+		print("Received ban list for invalid ID\n");
 		return;
+	}
 
-	--OnlineBanList_Requests;
+	tokenize_sane(cvar_string("g_ban_sync_uri"));
+	uri = argv(id);
 
+	print("Received ban list from ", uri, ": ");
+
+	if(OnlineBanList_RequestWaiting[id] == 0)
+	{
+		print("rejected (unexpected)\n");
+		return;
+	}
+
+	OnlineBanList_RequestWaiting[id] = 0;
+
 	if(time > OnlineBanList_Timeout)
+	{
+		print("rejected (too late)\n");
 		return;
+	}
 
 	syncinterval = cvar("g_ban_sync_interval");
 	if(syncinterval == 0)
+	{
+		print("rejected (syncing disabled)\n");
 		return;
+	}
 	if(syncinterval > 0)
 		syncinterval *= 60;
-
+	
 	if(status != 0)
 	{
-		print("Error receiving the online ban list: Status is ", ftos(status), "\n");
+		print("error: status is ", ftos(status), "\n");
 		return;
 	}
 
 	if(substring(data, 0, 1) == "<")
 	{
-		print("Error receiving the online ban list: Received HTML instead of a ban list: ");
+		print("error: received HTML instead of a ban list: ");
 		return;
 	}
 
 	if(strstrofs(data, "\r", 0) != -1)
 	{
-		print("Error receiving the online ban list: Received carriage returns: ");
+		print("error: received carriage returns: ");
 		return;
 	}
 
 	n = tokenizebyseparator(data, "\n");
 	if(mod(n, 4) != 0)
 	{
-		print("Error receiving the online ban list: Received invalid item count: ");
+		print("error: eceived invalid item count: ");
 		return;
 	}
 
+	print("OK\n");
+
 	for(i = 0; i < n; i += 4)
 	{
 		ip = argv(i);
@@ -108,7 +137,7 @@
 		reason = argv(i + 2);
 		serverip = argv(i + 3);
 
-		timeleft -= 15;
+		timeleft -= 1.5 * cvar("g_ban_sync_timeout");
 		if(timeleft < 0)
 			continue;
 
@@ -125,11 +154,12 @@
 				goto skip;
 
 		if(syncinterval > 0)
-			timeleft = min(syncinterval + 15, timeleft);
-			// 15 seconds for safety
+			timeleft = min(syncinterval + (OnlineBanList_Timeout - time) + 5, timeleft);
 			// the ban will be prolonged on the next sync
-		Ban_Insert(ip, timeleft, strcat("ban synced from ", serverip), 0);
-		print("Ban list syncing: accepted ban of ", ip, " by ", serverip, ": ", reason, "\n");
+			// or expire 5 seconds after the next timeout
+		Ban_Insert(ip, timeleft, strcat("ban synced from ", serverip, " at ", uri), 0);
+		print("Ban list syncing: accepted ban of ", ip, " by ", serverip, " at ", uri, ": ");
+		print(reason, "\n");
 
 		continue;
 :skip
@@ -150,26 +180,27 @@
 	if(argc == 0)
 		return;
 
-	if(OnlineBanList_Requests == 0) // only if there is no ongoing request!
-	{
-		if(OnlineBanList_Servers)
-			strunzone(OnlineBanList_Servers);
-		OnlineBanList_Servers = argv(0);
-		for(i = 1; i < argc; ++i)
-			OnlineBanList_Servers = strcat(OnlineBanList_Servers, ";", argv(i));
-		OnlineBanList_Servers = strzone(OnlineBanList_Servers);
-		
-		uri = strcat(     "?action=list&hostname=", uri_escape(cvar_string("hostname")));
-		uri = strcat(uri, "&servers=", uri_escape(OnlineBanList_Servers));
+	if(OnlineBanList_Servers)
+		strunzone(OnlineBanList_Servers);
+	OnlineBanList_Servers = argv(0);
+	for(i = 1; i < argc; ++i)
+		OnlineBanList_Servers = strcat(OnlineBanList_Servers, ";", argv(i));
+	OnlineBanList_Servers = strzone(OnlineBanList_Servers);
+	
+	uri = strcat(     "?action=list&hostname=", uri_escape(cvar_string("hostname")));
+	uri = strcat(uri, "&servers=", uri_escape(OnlineBanList_Servers));
 
-		OnlineBanList_Timeout = time + 10;
+	OnlineBanList_Timeout = time + cvar("g_ban_sync_timeout");
 
-		n = tokenize_sane(cvar_string("g_ban_sync_uri"));
-		for(i = 0; i < n; ++i)
-		{
-			++OnlineBanList_Requests;
-			uri_get(strcat(argv(i), uri), 1); // 1 = "banlist" callback target
-		}
+	n = tokenize_sane(cvar_string("g_ban_sync_uri"));
+	if(n >= MAX_IPBAN_URIS)
+		n = MAX_IPBAN_URIS;
+	for(i = 0; i < n; ++i)
+	{
+		if(OnlineBanList_RequestWaiting[i])
+			continue;
+		OnlineBanList_RequestWaiting[i] = 1;
+		uri_get(strcat(argv(i), uri), URI_GET_IPBAN + i); // 1000 = "banlist" callback target
 	}
 	
 	if(cvar("g_ban_sync_interval") > 0)
@@ -326,13 +357,37 @@
 	return FALSE;
 }
 
+string Ban_Enforce(float i, string reason)
+{
+	string s;
+	entity e;
+
+	// Enforce our new ban
+	s = "";
+	FOR_EACH_REALCLIENT(e)
+		if(Ban_IsClientBanned(e, i))
+		{
+			if(reason != "")
+			{
+				if(s == "")
+					reason = strcat(reason, ": affects ");
+				else
+					reason = strcat(reason, ", ");
+				reason = strcat(reason, e.netname);
+			}
+			s = strcat(s, "^1NOTE:^7 banned client ", e.netname, "^7 has to go\n");
+			dropclient(e);
+		}
+	bprint(s);
+
+	return reason;
+}
+
 float Ban_Insert(string ip, float bantime, string reason, float dosync)
 {
 	float i;
 	float j;
 	float bestscore;
-	entity e;
-	string s;
 
 	// already banned?
 	for(i = 0; i < ban_count; ++i)
@@ -345,6 +400,9 @@
 				print(ip, "'s ban has been prolonged to ", ftos(bantime), " seconds from now\n");
 			}
 
+			// and enforce
+			reason = Ban_Enforce(i, reason);
+
 			// and abort
 			if(dosync)
 				if(reason != "")
@@ -353,6 +411,7 @@
 
 			return FALSE;
 		}
+
 	// do we have a free slot?
 	for(i = 0; i < ban_count; ++i)
 		if(time > ban_expire[i])
@@ -384,23 +443,7 @@
 
 	Ban_SaveBans();
 
-	// Enforce our new ban
-	s = "";
-	FOR_EACH_REALCLIENT(e)
-		if(Ban_IsClientBanned(e, i))
-		{
-			if(reason != "")
-			{
-				if(s == "")
-					reason = strcat(reason, ": affects ");
-				else
-					reason = strcat(reason, ", ");
-				reason = strcat(reason, e.netname);
-			}
-			s = strcat(s, "^1NOTE:^7 banned client ", e.netname, "^7 has to go\n");
-			dropclient(e);
-		}
-	bprint(s);
+	reason = Ban_Enforce(i, reason);
 
 	// and abort
 	if(dosync)

Modified: branches/nexuiz-2.0/data/qcsrc/server/ipban.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/ipban.qh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/ipban.qh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -3,4 +3,4 @@
 float Ban_MaybeEnforceBan(entity client);
 float GameCommand_Ban(string command);
 
-void OnlineBanList_URI_Get_Callback(float status, string data);
+void OnlineBanList_URI_Get_Callback(float id, float status, string data);

Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1515,7 +1515,7 @@
 			remove_builtin(self);
 			self = e_old;
 		}
-		dprint("Delayed initialization: ", self.classname, "\n");
+		//dprint("Delayed initialization: ", self.classname, "\n");
 		func();
 		self = e;
 	}
@@ -1663,25 +1663,31 @@
 const string STR_MISC_NULL_WAV = "misc/null.wav";
 #define PROJECTILE_TOUCH_NOSOUND do { if(SUB_OwnerCheck()) return; if(SUB_NoImpactCheck()) { sound (self, CHAN_PROJECTILE, STR_MISC_NULL_WAV, VOL_BASE, ATTN_NORM); remove(self); return; } } while(0)
 
+float MAX_IPBAN_URIS = 16;
+
+float URI_GET_DISCARD   = 0;
+float URI_GET_IPBAN     = 1;
+float URI_GET_IPBAN_END = 16;
+
 void URI_Get_Callback(float id, float status, string data)
 {
 	dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is\n:");
 	dprint(data);
 	dprint("\nEnd of data.\n");
 
-	switch(id)
+	if(id == URI_GET_DISCARD)
 	{
-		case 0:
-			// 0 is the ID for discarding
-			break;
-		case 1:
-			// 1 is the ID for online ban list
-			OnlineBanList_URI_Get_Callback(status, data);
-			break;
-		default:
-			print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
-			break;
+		// discard
 	}
+	else if(id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
+	{
+		// online ban list
+		OnlineBanList_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)

Modified: branches/nexuiz-2.0/data/qcsrc/server/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/progs.src	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/progs.src	2008-12-26 14:38:59 UTC (rev 5314)
@@ -96,6 +96,7 @@
 w_hook.qc
 w_hlac.qc
 w_seeker.qc
+w_campingrifle.qc
 
 t_items.qc
 cl_weapons.qc

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -27,8 +27,8 @@
 	trigger.solid = SOLID_TRIGGER;
 	trigger.enemy = self;
 
-	tmin = self.mins + '25 25 0';
-	tmax = self.maxs - '25 25 -8';
+	tmin = self.absmin + '25 25 0';
+	tmax = self.absmax - '25 25 -8';
 	tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
 	if (self.spawnflags & PLAT_LOW_TRIGGER)
 		tmax_z = tmin_z + 8;
@@ -895,13 +895,13 @@
 		if (self.items)
 			return;
 
-		self.trigger_field = spawn_field(self.mins, self.maxs);
+		self.trigger_field = spawn_field(self.absmin, self.absmax);
 
 		return;		// don't want to link this door
 	}
 
-	cmins = self.mins;
-	cmaxs = self.maxs;
+	cmins = self.absmin;
+	cmaxs = self.absmax;
 
 	starte = self;
 	t = self;
@@ -947,18 +947,18 @@
 			self.enemy = t;
 			self = t;
 
-			if (t.mins_x < cmins_x)
-				cmins_x = t.mins_x;
-			if (t.mins_y < cmins_y)
-				cmins_y = t.mins_y;
-			if (t.mins_z < cmins_z)
-				cmins_z = t.mins_z;
-			if (t.maxs_x > cmaxs_x)
-				cmaxs_x = t.maxs_x;
-			if (t.maxs_y > cmaxs_y)
-				cmaxs_y = t.maxs_y;
-			if (t.maxs_z > cmaxs_z)
-				cmaxs_z = t.maxs_z;
+			if (t.absmin_x < cmins_x)
+				cmins_x = t.absmin_x;
+			if (t.absmin_y < cmins_y)
+				cmins_y = t.absmin_y;
+			if (t.absmin_z < cmins_z)
+				cmins_z = t.absmin_z;
+			if (t.absmax_x > cmaxs_x)
+				cmaxs_x = t.absmax_x;
+			if (t.absmax_y > cmaxs_y)
+				cmaxs_y = t.absmax_y;
+			if (t.absmax_z > cmaxs_z)
+				cmaxs_z = t.absmax_z;
 		}
 	} while (1 );
 

Copied: branches/nexuiz-2.0/data/qcsrc/server/w_campingrifle.qc (from rev 5313, trunk/data/qcsrc/server/w_campingrifle.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_campingrifle.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_campingrifle.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,163 @@
+//Camping rifle Primary mode: manually operated bolt*, Secondary: full automatic** --MikeeUSA--
+//* 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_bulletcounter;
+
+void W_Campingrifle_Reload()
+{
+	if (self.campingrifle_bulletcounter <= 0)
+		return;
+	
+	sound (self, CHAN_WEAPON2, "weapons/campingrifle_reload.wav", VOL_BASE, ATTN_NORM);
+	ATTACK_FINISHED(self) = time + cvar("g_balance_campingrifle_reloadtime");
+	self.campingrifle_bulletcounter = 0;
+}
+
+void W_Campingrifle_CheckReload()
+{
+	if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
+		W_Campingrifle_Reload();
+}
+
+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;
+
+	W_SetupShot (self, '25 8 -8', FALSE, 2, "weapons/campingrifle_fire.wav");
+	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;
+	}
+
+	fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, EF_RED, 1, pBulletConstant);
+
+	if (cvar("g_casings") >= 2)
+		SpawnCasing (w_shotorg + v_forward * 10, ((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.campingrifle_bulletcounter = self.campingrifle_bulletcounter + 1;
+	W_Campingrifle_CheckReload();
+}
+
+void W_Campingrifle_Attack()
+{
+	W_CampingRifle_FireBullet(cvar("g_balance_campingrifle_primary_spread"), cvar("g_balance_campingrifle_primary_damage"), cvar("g_balance_campingrifle_primary_headshotaddeddamage"), cvar("g_balance_campingrifle_primary_force"), cvar("g_balance_campingrifle_primary_speed"), cvar("g_balance_campingrifle_primary_lifetime"), cvar("g_balance_campingrifle_primary_ammo"), WEP_CAMPINGRIFLE, cvar("g_balance_campingrifle_primary_bulletconstant"));
+}
+
+void W_Campingrifle_Attack2()
+{
+	W_CampingRifle_FireBullet(cvar("g_balance_campingrifle_secondary_spread"), cvar("g_balance_campingrifle_secondary_damage"), cvar("g_balance_campingrifle_secondary_headshotaddeddamage"), cvar("g_balance_campingrifle_secondary_force"), cvar("g_balance_campingrifle_secondary_speed"), cvar("g_balance_campingrifle_secondary_lifetime"), cvar("g_balance_campingrifle_secondary_ammo"), WEP_CAMPINGRIFLE | HITTYPE_SECONDARY, cvar("g_balance_campingrifle_secondary_bulletconstant"));
+}
+
+void spawnfunc_weapon_campingrifle (void)
+{
+	weapon_defaultspawnfunc(WEP_CAMPINGRIFLE);
+}
+
+.float bot_secondary_campingriflemooth;
+float w_campingrifle(float req)
+{
+	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(cvar("g_balance_campingrifle_primary_speed"), 0, cvar("g_balance_campingrifle_primary_lifetime"), TRUE))
+			{
+				self.BUTTON_ATCK = TRUE;
+				if(random() < 0.01) self.bot_secondary_campingriflemooth = 1;
+			}
+		}
+		else
+		{
+			if(bot_aim(cvar("g_balance_campingrifle_secondary_speed"), 0, cvar("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.BUTTON_ATCK)
+		if (weapon_prepareattack(0, cvar("g_balance_campingrifle_primary_refire")))
+		{
+			W_Campingrifle_Attack();
+			weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), w_ready);
+		}
+		if (self.BUTTON_ATCK2)
+		if (weapon_prepareattack(1, cvar("g_balance_campingrifle_secondary_refire")))
+		{
+			W_Campingrifle_Attack2();
+			weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_campingrifle_secondary_animtime"), w_ready);
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{		
+		precache_model ("models/tracer.mdl");
+		precache_model ("models/weapons/g_campingrifle.md3");
+		precache_model ("models/weapons/v_campingrifle.md3");
+		precache_model ("models/weapons/w_campingrifle.zym");
+		precache_sound ("weapons/campingrifle_reload.wav");
+		precache_sound ("weapons/ric1.wav");
+		precache_sound ("weapons/ric2.wav");
+		precache_sound ("weapons/ric3.wav");
+		precache_sound ("weapons/campingrifle_fire.wav");
+		if (cvar("g_casings") >= 2)
+		{
+			precache_sound ("weapons/brass1.wav");
+			precache_sound ("weapons/brass2.wav");
+			precache_sound ("weapons/brass3.wav");
+			precache_model ("models/casing_bronze.mdl");
+		}
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_CAMPINGRIFLE);
+		W_Campingrifle_Reload();
+	}
+	else if (req == WR_CHECKAMMO1)
+		return self.ammo_nails >= cvar("g_balance_campingrifle_primary_ammo");
+	else if (req == WR_CHECKAMMO2)
+		return self.ammo_nails >= cvar("g_balance_campingrifle_secondary_ammo");
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			w_deathtypestring = "shot himself automatically";
+		else
+			w_deathtypestring = "sniped himself somehow";
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+				w_deathtypestring = "failed to hide from #'s bullet hail";
+			else
+				w_deathtypestring = "died in #'s bullet hail";
+		}
+		else
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+			{
+				// TODO special headshot message here too?
+				w_deathtypestring = "failed to hide from #'s rifle";
+			}
+			else
+			{
+				if(w_deathtype & HITTYPE_HEADSHOT)
+					w_deathtypestring = "got hit in the head by #";
+				else
+					w_deathtypestring = "was sniped by #";
+			}
+		}
+	}
+	return TRUE;
+};

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_common.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_common.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_common.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -111,11 +111,201 @@
 	trace_dphitq3surfaceflags = endq3surfaceflags;
 }
 
+.float dmg_edge;
+.float dmg_force;
+.float dmg_radius;
+void W_BallisticBullet_Hit (void)
+{
+	float f;
+
+	if (DEATH_ISWEAPON(self.projectiledeathtype, WEP_SHOTGUN))
+		pointparticles(particleeffectnum("shotgun_impact"), self.origin, normalize(self.velocity) * 1000, 1);
+	else
+		pointparticles(particleeffectnum("machinegun_impact"), self.origin, normalize(self.velocity) * 1000, 1);
+
+	if(other && other != self.enemy)
+	{
+		self.enemy = other; // don't hit the same player twice with the same bullet
+
+		f = pow(bound(0, vlen(self.velocity) / vlen(self.oldvelocity), 1), 2); // energy multiplier
+
+		headshot = 0;
+		yoda = 0;
+		damage_headshotbonus = self.dmg_edge;
+		railgun_start = self.origin - 2 * frametime * self.oldvelocity;
+		railgun_end = self.origin + 2 * frametime * self.oldvelocity;
+		Damage(other, self, self.owner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f);
+		damage_headshotbonus = 0;
+
+		if(self.dmg_edge != 0)
+		{
+			if(headshot)
+				announce(self.owner, "announcer/male/headshot.wav");
+			if(yoda)
+				announce(self.owner, "announcer/male/yoda.wav");
+		}
+
+		//sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
+	}
+}
+
+.void(void) W_BallisticBullet_LeaveSolid_think_save;
+.float W_BallisticBullet_LeaveSolid_nextthink_save;
+.vector W_BallisticBullet_LeaveSolid_origin;
+.vector W_BallisticBullet_LeaveSolid_velocity;
+
+void W_BallisticBullet_LeaveSolid_think()
+{
+	setorigin(self, self.W_BallisticBullet_LeaveSolid_origin);
+	self.velocity = self.W_BallisticBullet_LeaveSolid_velocity;
+
+	self.think = self.W_BallisticBullet_LeaveSolid_think_save;
+	self.nextthink = max(time, self.W_BallisticBullet_LeaveSolid_nextthink_save) + 1;
+	self.W_BallisticBullet_LeaveSolid_think_save = SUB_Null;
+
+	self.flags &~= FL_ONGROUND;
+	self.effects &~= EF_NODRAW;
+
+	if (DEATH_ISWEAPON(self.projectiledeathtype, WEP_SHOTGUN))
+		pointparticles(particleeffectnum("shotgun_impact"), self.origin, normalize(self.velocity) * 1000, 1);
+	else
+		pointparticles(particleeffectnum("machinegun_impact"), self.origin, normalize(self.velocity) * 1000, 1);
+}
+
+// a fake logarithm function
+float log(float x)
+{
+	if(x < 0.0001)
+		return 0;
+	if(x > 0.9 && x < 1.1)
+		return x - 1;
+	return 2 * log(sqrt(x));
+}
+
+float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant)
+{
+	// move the entity along its velocity until it's out of solid, then let it resume
+	
+	float dt, dst, velfactor, v0, vs;
+	float maxdist;
+	float E0_m, Es_m;
+
+	// E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass
+	v0 = vlen(vel);
+
+	E0_m = 0.5 * v0 * v0;
+	maxdist = E0_m / constant;
+	// maxdist = 0.5 * v0 * v0 / constant
+	// dprint("max dist = ", ftos(maxdist), "\n");
+
+	if(maxdist <= 0.5)
+		return 0;
+
+	traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self);
+
+	if(trace_fraction == 1) // 1: we never got out of solid
+		return 0;
+
+	self.W_BallisticBullet_LeaveSolid_origin = trace_endpos;
+
+	dst = vlen(trace_endpos - self.origin);
+	// E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass
+	Es_m = E0_m - constant * dst;
+	if(Es_m <= 0)
+	{
+		// roundoff errors got us
+		return 0;
+	}
+	vs = sqrt(2 * Es_m);
+	velfactor = vs / v0;
+
+	dt = dst / (0.5 * (v0 + vs));
+	// this is not correct, but the differential equations have no analytic
+	// solution - and these times are very small anyway
+	//print("dt = ", ftos(dt), "\n");
+
+	self.W_BallisticBullet_LeaveSolid_think_save = self.think;
+	self.W_BallisticBullet_LeaveSolid_nextthink_save = self.nextthink;
+	self.think = W_BallisticBullet_LeaveSolid_think;
+	self.nextthink = time + dt;
+
+	vel = vel * velfactor;
+
+	self.velocity = '0 0 0';
+	self.flags |= FL_ONGROUND; // prevent moving
+	self.effects |= EF_NODRAW;
+	self.W_BallisticBullet_LeaveSolid_velocity = vel;
+
+	return 1;
+}
+
+void W_BallisticBullet_Touch (void)
+{
+	if(self.think == W_BallisticBullet_LeaveSolid_think) // skip this!
+		return;
+
+	PROJECTILE_TOUCH;
+	W_BallisticBullet_Hit ();
+
+	// go through solid!
+	if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius))
+	{
+		remove(self);
+		return;
+	}
+
+	self.projectiledeathtype |= HITTYPE_BOUNCE;
+}
+
+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)
+{
+	entity proj;
+	proj = spawn();
+	proj.owner = self;
+	proj.solid = SOLID_BBOX;
+	if(gravityfactor > 0)
+	{
+		proj.movetype = MOVETYPE_TOSS;
+		proj.gravity = gravityfactor;
+	}
+	else
+		proj.movetype = MOVETYPE_FLY;
+	proj.think = SUB_Remove;
+	proj.nextthink = time + lifetime; // min(pLifetime, vlen(world.maxs - world.mins) / pSpeed);
+	proj.velocity = (dir + randomvec() * spread) * pSpeed;
+	W_SetupProjectileVelocity(proj);
+	proj.angles = vectoangles(proj.velocity);
+	proj.dmg_radius = cvar("g_ballistics_materialconstant") / bulletconstant;
+	// so: bulletconstant = bullet mass / area of bullet circle
+	setmodel(proj, "models/tracer.mdl");
+	setsize(proj, '0 0 0', '0 0 0');
+	setorigin(proj, start);
+	proj.effects = EF_LOWPRECISION | tracereffects;
+	proj.flags = FL_PROJECTILE;
+
+	proj.touch = W_BallisticBullet_Touch;
+	proj.dmg = damage;
+	proj.dmg_edge = headshotbonus;
+	proj.dmg_force = force;
+	proj.projectiledeathtype = dtype;
+
+	proj.oldvelocity = proj.velocity;
+}
+
 void fireBullet (vector start, vector dir, float spread, float damage, float force, float dtype, float tracer)
 {
 	vector  end;
 	local entity e;
 
+	if(cvar("g_ballistics_force"))
+	{
+		if (DEATH_ISWEAPON(dtype, WEP_SHOTGUN))
+			fireBallisticBullet(start, dir, spread, cvar("g_ballistics_force_shotgun_speed"), 5, damage, 0, force, dtype, 0, 1, cvar("g_ballistics_force_shotgun_bulletconstant"));
+		else
+			fireBallisticBullet(start, dir, spread, cvar("g_ballistics_force_uzi_speed"), 5, damage, 0, force, dtype, 0, 1, cvar("g_ballistics_force_shotgun_bulletconstant"));
+		return;
+	}
+
 	dir = dir + randomvec() * spread;
 	end = start + dir * MAX_SHOT_DISTANCE;
 	if(self.antilag_debug)

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc	2008-12-26 14:38:59 UTC (rev 5314)
@@ -5,6 +5,9 @@
 .float dmg_power;
 .float dmg_duration;
 .float dmg_last;
+.float hook_refire;
+.float hook_datehooked;
+.float hook_datehooked_delay;
 
 void W_Hook_ExplodeThink (void)
 {
@@ -106,6 +109,8 @@
 
 float w_hook(float req)
 {
+	float hooked_time_max, hooked_ammodecrease_delay;
+		
 	if (req == WR_AIM)
 	{
 		// ... sorry ...
@@ -116,12 +121,13 @@
 		{
 			if(!self.hook)
 			if not(self.hook_state & HOOK_WAITING_FOR_RELEASE)
-			if (weapon_prepareattack(0, cvar("g_balance_hook_primary_refire")))
+			if (time > self.hook_refire)
+			if (weapon_prepareattack(0, -1))
 			{
 				if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
 					self.ammo_cells = self.ammo_cells - cvar("g_balance_hook_primary_ammo");
 				self.hook_state |= HOOK_FIRING;
-				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hook_primary_animtime"), w_ready);
+				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hook_primary_animtime"), w_ready);				
 			}
 		}
 
@@ -134,6 +140,42 @@
 			}
 		}
 
+		if(self.hook)
+		{
+			// if hooked, no bombs, and increase the timer
+			self.hook_refire = max(self.hook_refire, time + cvar("g_balance_hook_primary_refire"));
+		}
+
+		if(self.hook && self.hook.state == 1)
+		{
+			hooked_time_max = cvar("g_balance_hook_primary_hooked_time_max");			
+			if (hooked_time_max > 0)
+			{
+				if ( time > self.hook_datehooked + hooked_time_max )
+					self.hook_state |= HOOK_REMOVING;
+			}
+			
+			hooked_ammodecrease_delay = cvar("g_balance_hook_primary_hooked_ammodecrease_delay");
+			if (hooked_ammodecrease_delay > 0)
+			{
+				if ( time > self.hook_datehooked_delay + hooked_ammodecrease_delay )
+				{
+					if ( self.ammo_cells >= 1 )
+					{
+						self.ammo_cells -= 1;
+						self.hook_datehooked_delay = time;
+					}
+					else
+					{
+						self.hook_state |= HOOK_REMOVING;
+						W_SwitchWeapon_Force(self, w_getbestweapon(self));
+					}
+				}
+			}
+		}
+		else
+			self.hook_datehooked = self.hook_datehooked_delay = time;				
+
 		if (self.BUTTON_CROUCH)
 		{
 			self.hook_state &~= HOOK_PULLING;
@@ -173,10 +215,11 @@
 	else if (req == WR_SETUP)
 	{
 		weapon_setup(WEP_HOOK);
+		self.hook_state &~= HOOK_WAITING_FOR_RELEASE;
 	}
 	else if (req == WR_CHECKAMMO1)
 	{
-		return self.ammo_cells >= cvar("g_balance_hook_primary_ammo");
+		return self.ammo_cells >= cvar("g_balance_hook_primary_ammo");			
 	}
 	else if (req == WR_CHECKAMMO2)
 	{

Modified: branches/nexuiz-2.0/data/scripts/entities.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/entities.def	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/scripts/entities.def	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1216,6 +1216,7 @@
 /*QUAKED weapon_hlac (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
 the Heavy Laser Assault Cannon.
 -------- KEYS --------
+ammo_cells: initial cells of the weapon (if unset, g_pickup_cells is used)
 respawntime: time till it respawns (default: 30)
 team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
 cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
@@ -1228,6 +1229,7 @@
 /*QUAKED weapon_seeker (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
 the T.A.G. Seeker.
 -------- KEYS --------
+ammo_rockets: initial rockets of the weapon (if unset, g_pickup_rockets is used)
 respawntime: time till it respawns (default: 30)
 team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
 cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
@@ -1240,6 +1242,7 @@
 /*QUAKED weapon_hook (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
 the on-hand Grappling Hook.
 -------- KEYS --------
+ammo_cells: initial cells of the weapon (if unset, g_pickup_cells is used)
 respawntime: time till it respawns (default: 30)
 team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
 cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
@@ -1256,3 +1259,19 @@
 max_health: max health this trigger will give (default 200)
 noise: sound file to play (use misc/null.wav to make it silent), default = item_health_medium sound
 */
+
+/*QUAKED weapon_campingrifle (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
+the Camping Rifle.
+WARNING: DO NOT PLACE THIS ON MAPS YET.
+The weapon is subject to change in behaviour and appearance, and such a change may break weapon balance on your map. So don't place it yet, use it as server weapon replacement option ONLY.
+-------- KEYS --------
+ammo_nails: initial bullets of the weapon (if unset, g_pickup_nails is used)
+respawntime: time till it respawns (default: 30)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
+cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/weapons/g_campingrifle.md3"
+*/
+

Copied: branches/nexuiz-2.0/data/scripts/flags.shader (from rev 5313, trunk/data/scripts/flags.shader)
===================================================================
--- branches/nexuiz-2.0/data/scripts/flags.shader	                        (rev 0)
+++ branches/nexuiz-2.0/data/scripts/flags.shader	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,33 @@
+flag_red_cloth {
+	cull none
+	deformVertexes wave 100 sin 0 0.4 0 2.5
+	{
+		map textures/flags/flag_red_cloth.tga
+	}
+}
+
+flag_red_laser {
+	{
+		map textures/flags/flag_red_laser.tga
+		tcMod scroll 0.2 -1
+		blendfunc add
+	}
+}
+
+
+flag_blue_cloth {
+	cull none
+	deformVertexes wave 100 sin 0 0.4 0 2.5
+	{
+		map textures/flags/flag_blue_cloth.tga
+	}
+}
+
+flag_blue_laser {
+	{
+		map textures/flags/flag_blue_laser.tga
+		tcMod scroll 0.2 -1
+		blendfunc add
+	}
+}
+

Copied: branches/nexuiz-2.0/data/scripts/hlac.shader (from rev 5313, trunk/data/scripts/hlac.shader)
===================================================================
--- branches/nexuiz-2.0/data/scripts/hlac.shader	                        (rev 0)
+++ branches/nexuiz-2.0/data/scripts/hlac.shader	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,31 @@
+hlac_plasma
+{
+ {
+	map textures/hlac_plasma.tga
+	tcMod scroll 22.5 0.2
+	tcmod scale 0.01 0.01
+ }
+}
+
+hlac_metal
+{
+        cull none
+        {
+                map textures/hlac_metal.tga
+                rgbgen vertex
+        }
+}
+hlac_glass
+{
+	qer_editorimage textures/hlac_glass.tga
+	surfaceparm trans
+	cull disable
+	qer_trans 0.5
+	{
+		map textures/hlac_glass.tga
+		blendfunc add
+		//rgbGen vertex
+		tcgen environment
+		tcmod scale 4 4
+	}	
+}
\ No newline at end of file

Copied: branches/nexuiz-2.0/data/scripts/mandelbrotsky.shader (from rev 5313, trunk/data/scripts/mandelbrotsky.shader)
===================================================================
--- branches/nexuiz-2.0/data/scripts/mandelbrotsky.shader	                        (rev 0)
+++ branches/nexuiz-2.0/data/scripts/mandelbrotsky.shader	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,14 @@
+//   nebula skybox
+//   =============
+
+textures/skies/mandelbrot
+{
+	qer_editorimage env/mandelbrot/mandel_up.tga
+	surfaceparm sky
+	surfaceparm noimpact
+	surfaceparm nolightmap
+	surfaceparm nomarks
+	q3map_skylight 200 3
+	q3map_sun 1 .98 .9 0 0 90
+	skyparms env/mandelbrot/mandel - -
+}

Modified: branches/nexuiz-2.0/data/scripts/shaderlist.txt
===================================================================
--- branches/nexuiz-2.0/data/scripts/shaderlist.txt	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/scripts/shaderlist.txt	2008-12-26 14:38:59 UTC (rev 5314)
@@ -14,8 +14,9 @@
 evil6_trims
 evil6_walls
 evil8_base
-eX
-final_rage
+eX
+final_rage
+flags
 harlequin_sky
 kaznexctf2
 leiprojectile

Copied: branches/nexuiz-2.0/data/sound/weapons/campingrifle_fire.ogg (from rev 5313, trunk/data/sound/weapons/campingrifle_fire.ogg)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/sound/weapons/campingrifle_reload.ogg (from rev 5313, trunk/data/sound/weapons/campingrifle_reload.ogg)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/campingrifle.tga (from rev 5313, trunk/data/textures/campingrifle.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/campingrifle_bump.tga (from rev 5313, trunk/data/textures/campingrifle_bump.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/campingrifle_gloss.tga (from rev 5313, trunk/data/textures/campingrifle_gloss.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/campingrifle_glow.tga (from rev 5313, trunk/data/textures/campingrifle_glow.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/campingrifle_pants.tga (from rev 5313, trunk/data/textures/campingrifle_pants.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/campingrifle_shirt.tga (from rev 5313, trunk/data/textures/campingrifle_shirt.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/flags (from rev 5313, trunk/data/textures/flags)

Copied: branches/nexuiz-2.0/data/textures/hlac_accessory.tga (from rev 5313, trunk/data/textures/hlac_accessory.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_accessory_gloss.tga (from rev 5313, trunk/data/textures/hlac_accessory_gloss.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_accessory_norm.tga (from rev 5313, trunk/data/textures/hlac_accessory_norm.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_accessory_pants.tga (from rev 5313, trunk/data/textures/hlac_accessory_pants.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_accessory_shirt.tga (from rev 5313, trunk/data/textures/hlac_accessory_shirt.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_body.tga (from rev 5313, trunk/data/textures/hlac_body.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_body_gloss.tga (from rev 5313, trunk/data/textures/hlac_body_gloss.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_body_glow.tga (from rev 5313, trunk/data/textures/hlac_body_glow.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_body_norm.tga (from rev 5313, trunk/data/textures/hlac_body_norm.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_body_pants.tga (from rev 5313, trunk/data/textures/hlac_body_pants.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_body_shirt.tga (from rev 5313, trunk/data/textures/hlac_body_shirt.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_glass.tga (from rev 5313, trunk/data/textures/hlac_glass.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_metal.tga (from rev 5313, trunk/data/textures/hlac_metal.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/textures/hlac_plasma.tga (from rev 5313, trunk/data/textures/hlac_plasma.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/weapons.cfg
===================================================================
--- branches/nexuiz-2.0/data/weapons.cfg	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/weapons.cfg	2008-12-26 14:38:59 UTC (rev 5314)
@@ -3,7 +3,7 @@
 //
 // And... don't forget to edit weaponsPro.cfg too.
 
-set cvar_check_weapons bf8a055d6b6b090133b248bccf916024
+set cvar_check_weapons 0ce586134eb7097440e850031829efe6
 
 set g_start_weapon_laser 1
 set g_start_weapon_shotgun 1
@@ -19,6 +19,7 @@
 set g_start_weapon_hook 0
 set g_start_weapon_hlac 0
 set g_start_weapon_seeker 0
+set g_start_weapon_campingrifle 0
 set g_start_ammo_shells 50
 set g_start_ammo_nails 0
 set g_start_ammo_rockets 0
@@ -87,10 +88,10 @@
 
 set g_balance_uzi_first_damage 30
 set g_balance_uzi_first_force 50
-set g_balance_uzi_first_spread 0.01
+set g_balance_uzi_first_spread 0.02
 set g_balance_uzi_first_refire 0.2
 set g_balance_uzi_first_ammo 1
-set g_balance_uzi_sustained_damage 16
+set g_balance_uzi_sustained_damage 15
 set g_balance_uzi_sustained_force 27
 set g_balance_uzi_sustained_spread 0.05
 set g_balance_uzi_sustained_refire 0.1
@@ -118,7 +119,7 @@
 set g_balance_grenadelauncher_secondary_ammo 2
 set g_balance_grenadelauncher_secondary_health 10
 
-set g_balance_electro_primary_damage 80
+set g_balance_electro_primary_damage 60
 set g_balance_electro_primary_edgedamage 0
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_radius 150
@@ -127,7 +128,7 @@
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_animtime 0.3
 set g_balance_electro_primary_ammo 2
-set g_balance_electro_secondary_damage 60
+set g_balance_electro_secondary_damage 50
 set g_balance_electro_secondary_spread 0.05
 set g_balance_electro_secondary_edgedamage 0
 set g_balance_electro_secondary_force 200
@@ -139,13 +140,13 @@
 set g_balance_electro_secondary_animtime 0.3
 set g_balance_electro_secondary_ammo 2
 set g_balance_electro_secondary_health 5
-set g_balance_electro_combo_damage 70
+set g_balance_electro_combo_damage 80
 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_speed 2000
 
-set g_balance_crylink_primary_damage 20
+set g_balance_crylink_primary_damage 18
 set g_balance_crylink_primary_edgedamage 0
 set g_balance_crylink_primary_force -55
 set g_balance_crylink_primary_radius 80
@@ -165,7 +166,7 @@
 set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2100
 set g_balance_crylink_primary_other_fadetime 0.2
 
-set g_balance_crylink_secondary_damage 20
+set g_balance_crylink_secondary_damage 18
 set g_balance_crylink_secondary_edgedamage 0
 set g_balance_crylink_secondary_force -55
 set g_balance_crylink_secondary_radius 3
@@ -183,7 +184,7 @@
 set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000
 set g_balance_crylink_secondary_line_fadetime 2
 
-set g_balance_nex_damage 140
+set g_balance_nex_damage 130
 set g_balance_nex_force 600
 set g_balance_nex_refire 1.5
 set g_balance_nex_animtime 0.3
@@ -193,7 +194,7 @@
 set g_balance_minstanex_animtime 0.3
 set g_balance_minstanex_ammo 10
 
-set g_balance_hagar_primary_damage 40
+set g_balance_hagar_primary_damage 38
 set g_balance_hagar_primary_edgedamage 15
 set g_balance_hagar_primary_force 100
 set g_balance_hagar_primary_radius 70
@@ -202,7 +203,7 @@
 set g_balance_hagar_primary_lifetime 30
 set g_balance_hagar_primary_refire 0.15
 set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_secondary_damage 40
+set g_balance_hagar_secondary_damage 38
 set g_balance_hagar_secondary_edgedamage 15
 set g_balance_hagar_secondary_force 100
 set g_balance_hagar_secondary_radius 70
@@ -212,10 +213,10 @@
 set g_balance_hagar_secondary_refire 0.15
 set g_balance_hagar_secondary_ammo 1
 
-set g_balance_rocketlauncher_damage 130
-set g_balance_rocketlauncher_edgedamage 50
+set g_balance_rocketlauncher_damage 120
+set g_balance_rocketlauncher_edgedamage 35
 set g_balance_rocketlauncher_force 600
-set g_balance_rocketlauncher_radius 170
+set g_balance_rocketlauncher_radius 150
 set g_balance_rocketlauncher_speed 850
 set g_balance_rocketlauncher_speedaccel 0
 set g_balance_rocketlauncher_speedstart 850
@@ -240,9 +241,11 @@
 set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
 
 // TESTING: on-hand hook with bomb
-set g_balance_hook_primary_ammo 0 // hook monkeys
+set g_balance_hook_primary_ammo 1 // hook monkeys
 set g_balance_hook_primary_refire 0 // hook monkeys
 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_ammodecrease_delay 2.5 // no ammo used if nagative or 0
 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
@@ -262,7 +265,7 @@
 set g_balance_hlac_primary_spread_add 0.0045
 set g_balance_hlac_primary_spread_crouchmod 0.25
 
-set g_balance_hlac_primary_damage 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
@@ -276,7 +279,7 @@
 set g_balance_hlac_secondary_spread 0.15
 set g_balance_hlac_secondary_spread_crouchmod 0.5
 
-set g_balance_hlac_secondary_damage 25
+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
@@ -342,4 +345,27 @@
 set g_balance_seeker_flac_animtime     0.1
 set g_balance_seeker_flac_ammo         0.5
 
-
+// NOTE: maps should not use this weapon yet
+set g_balance_campingrifle_magazinecapacity 12
+set g_balance_campingrifle_reloadtime 1.4
+set g_balance_campingrifle_primary_damage 90
+set g_balance_campingrifle_primary_headshotaddeddamage 160
+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 120 // 51.9qu
+set g_balance_campingrifle_secondary_damage 60
+set g_balance_campingrifle_secondary_headshotaddeddamage 0
+set g_balance_campingrifle_secondary_spread 0.01
+set g_balance_campingrifle_secondary_force 1
+set g_balance_campingrifle_secondary_speed 18000
+set g_balance_campingrifle_secondary_lifetime 5
+set g_balance_campingrifle_secondary_refire 0.12
+set g_balance_campingrifle_secondary_animtime 0.06
+set g_balance_campingrifle_secondary_ammo 10
+set g_balance_campingrifle_secondary_health 5
+set g_balance_campingrifle_secondary_bulletconstant 120 // 13.7qu

Modified: branches/nexuiz-2.0/data/weaponsPro.cfg
===================================================================
--- branches/nexuiz-2.0/data/weaponsPro.cfg	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/data/weaponsPro.cfg	2008-12-26 14:38:59 UTC (rev 5314)
@@ -1,4 +1,4 @@
-set cvar_check_weapons bf8a055d6b6b090133b248bccf916024
+set cvar_check_weapons 0ce586134eb7097440e850031829efe6
 
 set g_start_weapon_laser 1
 set g_start_weapon_shotgun 1
@@ -14,6 +14,7 @@
 set g_start_weapon_hook 0
 set g_start_weapon_hlac 0
 set g_start_weapon_seeker 0
+set g_start_weapon_campingrifle 0
 set g_start_ammo_shells 40
 set g_start_ammo_nails 0
 set g_start_ammo_rockets 0
@@ -235,9 +236,11 @@
 set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
 
 // TESTING: on-hand hook with bomb
-set g_balance_hook_primary_ammo 0 // hook monkeys
+set g_balance_hook_primary_ammo 1 // hook monkeys
 set g_balance_hook_primary_refire 0 // hook monkeys
 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_ammodecrease_delay 2.5 // no ammo used if nagative or 0
 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
@@ -337,4 +340,27 @@
 set g_balance_seeker_flac_animtime     0.1
 set g_balance_seeker_flac_ammo         0.5
 
-
+// NOTE: maps should not use this weapon yet
+set g_balance_campingrifle_magazinecapacity 12
+set g_balance_campingrifle_reloadtime 1.4
+set g_balance_campingrifle_primary_damage 90
+set g_balance_campingrifle_primary_headshotaddeddamage 160
+set g_balance_campingrifle_primary_spread 0
+set g_balance_campingrifle_primary_force 2
+set g_balance_campingrifle_primary_speed 30000
+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 // 97.5 qu
+set g_balance_campingrifle_secondary_damage 60
+set g_balance_campingrifle_secondary_headshotaddeddamage 0
+set g_balance_campingrifle_secondary_spread 0.02
+set g_balance_campingrifle_secondary_force 1
+set g_balance_campingrifle_secondary_speed 8000
+set g_balance_campingrifle_secondary_lifetime 5
+set g_balance_campingrifle_secondary_refire 0.12
+set g_balance_campingrifle_secondary_animtime 0.06
+set g_balance_campingrifle_secondary_ammo 10
+set g_balance_campingrifle_secondary_health 5
+set g_balance_campingrifle_secondary_bulletconstant 130 // 6.9 qu

Modified: branches/nexuiz-2.0/misc/demotc.pl
===================================================================
--- branches/nexuiz-2.0/misc/demotc.pl	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/misc/demotc.pl	2008-12-26 14:38:59 UTC (rev 5314)
@@ -141,7 +141,14 @@
 	{
 		if(my @l = ($data =~ /$pattern/))
 		{
-			print "$tc:";
+			if(defined $tc)
+			{
+				print "$tc:";
+			}
+			else
+			{
+				print "start:";
+			}
 			for(@l)
 			{
 				print " \"", sanitize($_), "\"";

Copied: branches/nexuiz-2.0/misc/hslimage.c (from rev 5313, trunk/misc/hslimage.c)
===================================================================
--- branches/nexuiz-2.0/misc/hslimage.c	                        (rev 0)
+++ branches/nexuiz-2.0/misc/hslimage.c	2008-12-26 14:38:59 UTC (rev 5314)
@@ -0,0 +1,104 @@
+#include <math.h>
+#include <stdio.h>
+
+#define MARGIN_X 0
+#define MARGIN_Y 0
+
+void hsl_to_rgb(float hsl_x, float hsl_y, float hsl_z, float *rgb_x, float *rgb_y, float *rgb_z)
+{
+	float mi, ma, maminusmi, h;
+
+	if(hsl_z <= 0.5)
+		maminusmi = hsl_y * 2 * hsl_z;
+	else
+		maminusmi = hsl_y * (2 - 2 * hsl_z);
+	
+	// hsl_z     = 0.5 * mi + 0.5 * ma
+	// maminusmi =     - mi +       ma
+	mi = hsl_z - 0.5 * maminusmi;
+	ma = hsl_z + 0.5 * maminusmi;
+
+	h = hsl_x - 6 * floor(hsl_x / 6);
+
+	//else if(ma == rgb_x)
+	//	h = 60 * (rgb_y - rgb_z) / (ma - mi);
+	if(h <= 1)
+	{
+		*rgb_x = ma;
+		*rgb_y = h * (ma - mi) + mi;
+		*rgb_z = mi;
+	}
+	//else if(ma == rgb_y)
+	//	h = 60 * (rgb_z - rgb_x) / (ma - mi) + 120;
+	else if(h <= 2)
+	{
+		*rgb_x = (2 - h) * (ma - mi) + mi;
+		*rgb_y = ma;
+		*rgb_z = mi;
+	}
+	else if(h <= 3)
+	{
+		*rgb_x = mi;
+		*rgb_y = ma;
+		*rgb_z = (h - 2) * (ma - mi) + mi;
+	}
+	//else // if(ma == rgb_z)
+	//	h = 60 * (rgb_x - rgb_y) / (ma - mi) + 240;
+	else if(h <= 4)
+	{
+		*rgb_x = mi;
+		*rgb_y = (4 - h) * (ma - mi) + mi;
+		*rgb_z = ma;
+	}
+	else if(h <= 5)
+	{
+		*rgb_x = (h - 4) * (ma - mi) + mi;
+		*rgb_y = mi;
+		*rgb_z = ma;
+	}
+	//else if(ma == rgb_x)
+	//	h = 60 * (rgb_y - rgb_z) / (ma - mi);
+	else // if(h <= 6)
+	{
+		*rgb_x = ma;
+		*rgb_y = mi;
+		*rgb_z = (6 - h) * (ma - mi) + mi;
+	}
+}
+
+void hslimage_color(float v_x, float v_y, float margin_x, float margin_y, float *rgb_x, float *rgb_y, float *rgb_z)
+{
+	v_x = (v_x - margin_x) / (1 - 2 * margin_x);
+	v_y = (v_y - margin_y) / (1 - 2 * margin_y);
+	if(v_x < 0) v_x = 0;
+	if(v_y < 0) v_y = 0;
+	if(v_x > 1) v_x = 1;
+	if(v_y > 1) v_y = 1;
+	if(v_y > 0.875) // grey bar
+		hsl_to_rgb(0, 0, v_x, rgb_x, rgb_y, rgb_z);
+	else
+		hsl_to_rgb(v_x * 6, 1, (v_y / 0.875), rgb_x, rgb_y, rgb_z);
+}
+
+int main()
+{
+	int x, y;
+	float r, g, b;
+
+	for(y = 0; y < 512; ++y)
+	{
+		for(x = 0; x < 512; ++x)
+		{
+			hslimage_color(x / 512.0, y / 512.0, MARGIN_X, MARGIN_Y, &r, &g, &b);
+			/*
+			putc(floor(r * 15 + 0.5) * 17, stdout);
+			putc(floor(g * 15 + 0.5) * 17, stdout);
+			putc(floor(b * 15 + 0.5) * 17, stdout);
+			*/
+			putc(floor(r * 255 + 0.5), stdout);
+			putc(floor(g * 255 + 0.5), stdout);
+			putc(floor(b * 255 + 0.5), stdout);
+		}
+	}
+	return 0;
+}

Modified: branches/nexuiz-2.0/misc/jpeg-if-not-alpha.sh
===================================================================
--- branches/nexuiz-2.0/misc/jpeg-if-not-alpha.sh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/misc/jpeg-if-not-alpha.sh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -7,10 +7,16 @@
 for X in "$@"; do
 	case "$X" in
 		*.jpg)
+			if [ -n "$scaledown" ]; then
+				mogrify "$X" -geometry "$scaledown<" -quality 100
+			fi
 			jpegoptim --strip-all -m$qual "$X"
 			;;
 		*.png|*.tga)
-			if convert "$X" -depth 16 RGBA:- | perl -e 'local $/ = \8; while(<>) { substr($_, 6, 2) eq "\xFF\xFF" or exit 1; ++$pix; } END { exit not $pix; }'; then
+			if [ -n "$scaledown" ]; then
+				mogrify "$X" -geometry "$scaledown<" -quality 100
+			fi
+			if convert "$X" -depth 16 RGBA:- | perl -e 'while(read STDIN, $_, 8) { substr($_, 6, 2) eq "\xFF\xFF" or exit 1; ++$pix; } exit not $pix;'; then
 				echo "$X has no alpha, converting"
 				convert "$X" -quality 100 "${X%.*}.jpg"
 				jpegoptim --strip-all -m$qual "${X%.*}.jpg"

Modified: branches/nexuiz-2.0/misc/ttf2conchars/foo.sh
===================================================================
--- branches/nexuiz-2.0/misc/ttf2conchars/foo.sh	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/misc/ttf2conchars/foo.sh	2008-12-26 14:38:59 UTC (rev 5314)
@@ -9,6 +9,6 @@
 
 set -ex
 gcc -Wall -Wextra ttf2conchars.c `sdl-config --cflags --libs` -lSDL_ttf -lSDL_image -ggdb3
-./a.out gfx/conchars.tga 0 56 64 gfx/vera-sans.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf "" "" 0.05 0.004 0.000000000000001
-./a.out gfx/conchars.tga 0 56 64 gfx/vera-sans-big.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf "" "" 0.18 0.05  0.000000000000001
+./a.out gfx/conchars.tga 0 56 64 gfx/vera-sans.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf "" "" 1 0.08 0.000000000000001
+./a.out gfx/conchars.tga 0 56 64 gfx/vera-sans-big.tga /usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf "" "" 1 0.28  0.000000000000001
 display gfx/vera-sans-big.tga

Modified: branches/nexuiz-2.0/misc/ttf2conchars/ttf2conchars.c
===================================================================
--- branches/nexuiz-2.0/misc/ttf2conchars/ttf2conchars.c	2008-12-26 14:29:00 UTC (rev 5313)
+++ branches/nexuiz-2.0/misc/ttf2conchars/ttf2conchars.c	2008-12-26 14:38:59 UTC (rev 5314)
@@ -6,7 +6,12 @@
 #include "SDL/SDL_ttf.h" 
 #include "SDL/SDL_image.h" 
 
-void warn(char *fmt, ...)
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#pragma message("You are using a broken and outdated compiler. Do not expect this to work.")
+#endif
+
+void warn(const char *fmt, ...)
 {
 	va_list list;
 	int e = errno;
@@ -17,7 +22,7 @@
 	fputs("\n", stderr);
 }
 
-void warnx(char *fmt, ...)
+void warnx(const char *fmt, ...)
 {
 	va_list list;
 	va_start(list, fmt);
@@ -25,7 +30,7 @@
 	fputs("\n", stderr);
 }
 
-void err(int ex, char *fmt, ...)
+void err(int ex, const char *fmt, ...)
 {
 	va_list list;
 	int e = errno;
@@ -37,7 +42,7 @@
 	exit(ex);
 }
 
-void errx(int ex, char *fmt, ...)
+void errx(int ex, const char *fmt, ...)
 {
 	va_list list;
 	va_start(list, fmt);
@@ -56,7 +61,7 @@
     buffer = (unsigned char *)malloc(width*height*4 + 18);
 
     memset (buffer, 0, 18);
-    buffer[2] = 2;      // uncompressed type
+    buffer[2] = 2;      /*  uncompressed type */
     buffer[12] = (width >> 0) & 0xFF;
     buffer[13] = (width >> 8) & 0xFF;
     buffer[14] = (height >> 0) & 0xFF;
@@ -68,11 +73,11 @@
 
     if (y < width*height*4)
     {   
-        // save the alpha channel
-        buffer[16] = 32;    // pixel size
-        buffer[17] = 8; // 8 bits of alpha
+        /*  save the alpha channel */
+        buffer[16] = 32;    /*  pixel size */
+        buffer[17] = 8; /*  8 bits of alpha */
 
-        // flip upside down
+        /*  flip upside down */
         out = buffer + 18;
         for (y = height - 1;y >= 0;y--)
         {   
@@ -82,11 +87,11 @@
     }
     else
     {   
-        // save only the color channels
-        buffer[16] = 24;    // pixel size
-        buffer[17] = 0; // 8 bits of alpha
+        /*  save only the color channels */
+        buffer[16] = 24;    /*  pixel size */
+        buffer[17] = 0; /*  8 bits of alpha */
 
-        // truncate bgra to bgr and flip upside down
+        /*  truncate bgra to bgr and flip upside down */
         out = buffer + 18;
         for (y = height - 1;y >= 0;y--)
         {
@@ -193,7 +198,7 @@
 	int i, j;
 	int imax = (int) BLURFUNCIMAX(A,B);
 
-	// 1. calculate blackened blurred image
+	/*  1. calculate blackened blurred image */
 	a = 0;
 	for(i=-imax; i<=imax; ++i)
 		if(y+i >= 0 && y+i < src->h)
@@ -213,7 +218,7 @@
 
 	if(C == 0)
 	{
-		// 2. overlap it with the actual image again
+		/*  2. overlap it with the actual image again */
 		if(y >= 0 && y < src->h && x >= 0 && x < src->w)
 		{
 			SDL_GetRGBA(getpixel(src, x, y), src->format, &pr, &pg, &pb, &pa);
@@ -244,10 +249,10 @@
 
 void blitfilter(SDL_Surface *src, SDL_Surface *dest, int x0, int y0, double A, double B, double C)
 {
-	// note: x0, y0 is the origin of the UNFILTERED image; it is "transparently" expanded by a BLURFUNCIMAX.
+	/*  note: x0, y0 is the origin of the UNFILTERED image; it is "transparently" expanded by a BLURFUNCIMAX. */
 	int x, y, d, xa, ya, xb, yb;
+	d = (int) BLURFUNCIMAX(A, B);
 
-	d = (int) BLURFUNCIMAX(A,B);
 	SDL_LockSurface(src);
 	SDL_LockSurface(dest);
 
@@ -287,12 +292,12 @@
 	if(*c >= 0xBA && *c <= 0xDF)
 	{
 		*c &= 0x7F;
-		return 1; // cool
+		return 1; /*  cool */
 	}
 	if(*c >= 0xE0 && *c <= 0xFE)
 	{
 		*c &= 0x5F;
-		return 2; // lcd
+		return 2; /*  lcd */
 	}
 	return -1;
 }
@@ -309,12 +314,18 @@
  */
 void StretchBlit(SDL_Surface *dst, SDL_Surface *src, SDL_Rect *drec, SDL_Rect *srec)
 {
+	unsigned int freeSource;
+	int x, y;
+	double scaleX;
+	double scaleY;
+	
+
 	if(!src)
 		src = dst;
 
-	unsigned int freeSource = 0;
+	freeSource = 0;
 	if(src == dst) {
-		// To avoid copying copied pixels, that would suck :)
+		/*  To avoid copying copied pixels, that would suck :) */
 		src = SDL_ConvertSurface(dst, dst->format, dst->flags);
 		freeSource = 1;
 	}
@@ -327,36 +338,40 @@
 	SDL_LockSurface(dst);
 	SDL_LockSurface(src);
 
-	double scaleX = (double)srec->w / (double)drec->w;
-	double scaleY = (double)srec->h / (double)drec->h;
+	scaleX = (double)srec->w / (double)drec->w;
+	scaleY = (double)srec->h / (double)drec->h;
 	
-	int x, y;
-
 	for(y = drec->y; y < (drec->y + drec->h); ++y)
 	{
+		int dy;
 		if(y >= dst->h)
 			break;
-		int dy = y - drec->y;
+		dy = y - drec->y;
 		for(x = drec->x; x < (drec->x + drec->w); ++x)
 		{
+			int dx;
+			double dfromX, dfromY, dtoX, dtoY;
+			int fromX, fromY, toX, toY;
+			int i, j;
+			unsigned int r, g, b, a, ar, ag, ab;
+			unsigned int count;
+
 			if(x >= dst->w)
 				break;
-			// dx, dy relative to the drec start
-			int dx = x - drec->x;
+			/*  dx, dy relative to the drec start */
+			dx = x - drec->x;
 
-			double dfromX, dfromY, dtoX, dtoY;
-			int fromX, fromY, toX, toY;
-			// Get the pixel range which represents the current pixel
-			// When scaling down this should be a rectangle :)
-			// Otherwise it's just 1 pixel anyway, from==to then
+			/*  Get the pixel range which represents the current pixel */
+			/*  When scaling down this should be a rectangle :) */
+			/*  Otherwise it's just 1 pixel anyway, from==to then */
 			dfromX = dx * scaleX;
 			dfromY = dy * scaleY;
 			dtoX = (dx+1) * scaleX;
 			dtoY = (dy+1) * scaleY;
-			// The first and last one usually aren't 100% within this space
-			fromX = (int)dfromX; dfromX = 1.0 - (dfromX - fromX); // invert the from percentage
+			/*  The first and last one usually aren't 100% within this space */
+			fromX = (int)dfromX; dfromX = 1.0 - (dfromX - fromX); /*  invert the from percentage */
 			fromY = (int)dfromY; dfromY = 1.0 - (dfromY - fromY);
-			toX = (int)dtoX; dtoX -= toX; // this one is ok
+			toX = (int)dtoX; dtoX -= toX; /*  this one is ok */
 			toY = (int)dtoY; dtoY -= toY;
 						
 			/* Short explanation:
@@ -364,20 +379,18 @@
 			 * TO is where it ENDS, so if it's 8.4, then 40% of the 9th pixel is to be used!
 			 */
 						
-			// Now get all the pixels and merge them together...
-			int i, j;
-			unsigned int r, g, b, a, ar, ag, ab;
-			unsigned int count = 0;
+			/*  Now get all the pixels and merge them together... */
+			count = 0;
 			r = g = b = a = ar = ag = ab = 0;
 			/*if(drec->w > 1024)
 			  printf("%i %i - %f %f\n", fromX, toX, dfromX, dtoX);*/
 
-			// when going from one to the next there's usually one
-			// situation where the left pixel has a value of 0.1something and
-			// the right one of 0
-			// so adjust the values here
-			// otherwise we get lines in the image with the original color
-			// of the left pixel
+			/*  when going from one to the next there's usually one */
+			/*  situation where the left pixel has a value of 0.1something and */
+			/*  the right one of 0 */
+			/*  so adjust the values here */
+			/*  otherwise we get lines in the image with the original color */
+			/*  of the left pixel */
 			if(toX - fromX == 1 && drec->w > srec->w) {
 				dfromX = 1.0 - dtoX;
 				++fromX;
@@ -419,6 +432,7 @@
 					Uint8 pr, pg, pb, pa;
 					Uint16 par, pag, pab;
 					double inc = 1;
+					int iinc;
 					if(x < 0)
 						continue;
 					if((i+srec->x) >= src->w)
@@ -438,7 +452,7 @@
 					if(j == (toY))
 						inc *= dtoY;
 
-					int iinc = (int) (inc * 256);
+					iinc = (int) (inc * 256);
 
 					r += (pr * iinc);
 					g += (pg * iinc);
@@ -447,11 +461,11 @@
 					ag += (pag * iinc);
 					ab += (pab * iinc);
 					a += (pa * iinc);
-					//++count;
+					/* ++count; */
 					count += iinc;
 				}
 			}
-			//printf("COLOR VALUE: %i, %i, %i, %i \t COUNT: %f\n", r, g, b, a, count);
+			/* printf("COLOR VALUE: %i, %i, %i, %i \t COUNT: %f\n", r, g, b, a, count); */
 			if(a)
 			{
 				r = ar / a;
@@ -480,17 +494,17 @@
 
 void StretchDown(SDL_Surface *srfc, int x, int y, int w, int h, int wtarget)
 {
-	// @"#$ SDL has no StretchBlit
-	// this one is slow, but at least I know how it works
+	/*  @"#$ SDL has no StretchBlit */
+	/*  this one is slow, but at least I know how it works */
 	int r, c;
-	unsigned int stretchedline[8 * wtarget]; // ra ga ba r g b a n
+	unsigned int *stretchedline = (unsigned int *) alloca(8 * wtarget * sizeof(unsigned int)); /*  ra ga ba r g b a n */
 	SDL_LockSurface(srfc);
 
 	for(r = y; r < y + h; ++r)
 	{
-		// each input pixel is wtarget pixels "worth"
-		//memset(stretchedline, sizeof(stretchedline), 0);
-		memset(stretchedline, 0, sizeof(stretchedline));
+		/*  each input pixel is wtarget pixels "worth" */
+		/* memset(stretchedline, sizeof(stretchedline), 0); */
+		memset(stretchedline, 0, 8 * wtarget * sizeof(unsigned int));
 		for(c = 0; c < w * wtarget; ++c)
 		{
 			Uint8 pr, pg, pb, pa;
@@ -522,9 +536,9 @@
 
 int GetBoundingBox(SDL_Surface *surf, const SDL_Rect *inbox, SDL_Rect *outbox)
 {
-	int bx = -1, by = -1; // start
-	//int bw = 0, bh = 0;
-	int ex = -1, ey = -1; // end
+	int bx = -1, by = -1; /*  start */
+	/* int bw = 0, bh = 0; */
+	int ex = -1, ey = -1; /*  end */
 	int cx, cy;
 	for(cx = inbox->x; cx < inbox->x + inbox->w; ++cx)
 	{
@@ -532,7 +546,7 @@
 		{
 			Uint8 pr, pg, pb, pa;
 			SDL_GetRGBA(getpixel(surf, cx, cy), surf->format, &pr, &pg, &pb, &pa);
-			// include colors, or only care about pa?
+			/*  include colors, or only care about pa? */
 			if(!pa)
 				continue;
 
@@ -542,13 +556,13 @@
 				continue;
 			}
 			
-			if(cx < bx) // a pixel more on the left
+			if(cx < bx) /*  a pixel more on the left */
 				bx = cx;
-			/*if(cy < by) // a pixel more above... wait... this cannot happen actually
-			  by = cy;*/
-			if(cx > ex) // a pixel on the right
+			if(cy < by) /*  a pixel more above... */
+			    by = cy;
+			if(cx > ex) /*  a pixel on the right */
 				ex = cx;
-			if(cy > ey) // a pixel on the bottom :)
+			if(cy > ey) /*  a pixel on the bottom :) */
 				ey = cy;
 		}
 	}
@@ -572,33 +586,71 @@
 	SDL_Color white = {255, 255, 255, 255};
 	Uint32 transparent;
 	int maxAscent, maxDescent, maxWidth;
-	int i;
+	int i, j;
 	int currentSize;
 	int isfixed;
+	const char *infilename;
+	int referenceTop;
+	int referenceBottom;
+	int cell;
+	const char *outfilename;
+	const char *font0;
+	const char *font1;
+	const char *font2;
+	double A;
+	double B;
+	double C;
+	int differentFonts;
+	int d;
+	double f = 0, a = 0;
+	char widthfilename[512];
+	int border;
+	FILE *widthfile;
 
 	if(argc != 12)
 		errx(1, "Usage: %s infile.tga topref bottomref cellheight outfile.tga font.ttf fontCOOL.ttf fontLCD.ttf blurA blurB blurColors\n", argv[0]);
 
-	const char *infilename = argv[1];
-	int referenceTop = atoi(argv[2]);
-	int referenceBottom = atoi(argv[3]);
-	int cell = atoi(argv[4]);
-	const char *outfilename = argv[5];
-	const char *font0 = argv[6];
-	const char *font1 = argv[7];
-	const char *font2 = argv[8];
-	double A = atof(argv[9]);
-	double B = atof(argv[10]);
-	double C = atof(argv[11]);
-	int differentFonts;
+	infilename = argv[1];
+	referenceTop = atoi(argv[2]);
+	referenceBottom = atoi(argv[3]);
+	cell = atoi(argv[4]);
+	outfilename = argv[5];
+	font0 = argv[6];
+	font1 = argv[7];
+	font2 = argv[8];
+	A = atof(argv[9]);
+	B = atof(argv[10]);
+	C = atof(argv[11]);
 
-	char widthfilename[512];
+	d = (int) BLURFUNCIMAX(1, B);
+	fprintf(stderr, "Translating parameters:\nA=%f B=%f (using %d pixels)\n", A, B, (int) BLURFUNCIMAX(1, B));
+	if(C == 0)
+	{
+		B = A * B;
+		A = A * 1;
+	}
+	else
+	{
+		for(i=-d; i<=d; ++i)
+			for(j=-d; j<=d; ++j)
+			{
+				f = BLURFUNC(i*i+j*j, 1, B);
+				f = MAX(0, f);
+
+				if(C == 0)
+					a = MAX(a, f);
+				else
+					a = a + f;
+			}
+		B = A/a * B;
+		A = A/a * 1;
+	}
+	fprintf(stderr, "A=%f B=%f (using %d pixels)\n", A, B, (int) BLURFUNCIMAX(A, B));
+
 	snprintf(widthfilename, sizeof(widthfilename), "%.*s.width", (int)strlen(outfilename) - 4, outfilename);
 
-	int border=(int) BLURFUNCIMAX(A, B);
+	border=(int) BLURFUNCIMAX(A, B);
 
-	fprintf(stderr, "Using %d border pixels\n", border);
-
 	if(SDL_Init(0) < 0)
 		errx(1, "SDL_Init failed");
 
@@ -655,15 +707,16 @@
 			differentFonts = 0;
 		}
 
-		//maxAscent = MAX(MAX(TTF_FontAscent(fonts[0]), fonts[1] ? TTF_FontAscent(fonts[1]) : 0), fonts[2] ? TTF_FontAscent(fonts[2]) : 0);
-		//maxDescent = -MIN(MIN(TTF_FontDescent(fonts[0]), fonts[1] ? TTF_FontDescent(fonts[1]) : 0), fonts[2] ? TTF_FontDescent(fonts[2]) : 0);
+		/* maxAscent = MAX(MAX(TTF_FontAscent(fonts[0]), fonts[1] ? TTF_FontAscent(fonts[1]) : 0), fonts[2] ? TTF_FontAscent(fonts[2]) : 0); */
+		/* maxDescent = -MIN(MIN(TTF_FontDescent(fonts[0]), fonts[1] ? TTF_FontDescent(fonts[1]) : 0), fonts[2] ? TTF_FontDescent(fonts[2]) : 0); */
 		maxAscent = 0;
 		maxDescent = 0;
 		maxWidth = 0;
 		for(i = 0; i < 256; ++i)
 		{
-			char str[2]; str[0] = i; str[1] = 0;
+			char str[2];
 			int fntid = mapFont(differentFonts, &str[0]);
+			str[0] = i; str[1] = 0;
 			if(fntid < 0)
 				continue;
 			if(!fonts[fntid])
@@ -683,6 +736,8 @@
 				int baseline = TTF_FontAscent(fonts[fntid]);
 				int asc = baseline - out.y;
 				int desc = (out.y + out.h - 1) - baseline;
+				//fprintf(stderr, "%c: rect %d %d %d %d baseline %d\n", (int)i, out.x, out.y, out.w, out.h, baseline);
+				//fprintf(stderr, "%c: ascent %d descent %d\n", (int)i, asc, desc);
 				if(asc > maxAscent)
 					maxAscent = asc;
 				if(desc > maxDescent)
@@ -692,9 +747,12 @@
 			SDL_FreeSurface(glyph);
 		}
 
+		maxAscent += 10;
+		maxDescent += 10;
+
 		if(border + maxAscent + 1 + maxDescent + border <= cell)
 			if(border + maxWidth + border <= cell)
-				break; // YEAH
+				break; /*  YEAH */
 
 		if(differentFonts)
 		{
@@ -713,14 +771,15 @@
 	if(getenv("FORCE_FIXED"))
 		isfixed = 1;
 
-	// TODO convert conchars to BGRA (so the TGA writer can reliably use it)
+	/*  TODO convert conchars to BGRA (so the TGA writer can reliably use it) */
 
 	transparent = SDL_MapRGBA(conchars->format, 255, 0, 255, 0);
 
-	FILE *widthfile = fopen(widthfilename, "w");
+	widthfile = fopen(widthfilename, "w");
 	if(!widthfile)
 		err(1, "fopen widthfile");
-	fprintf(widthfile, "extraspacing %f ", 0.0);
+	fprintf(widthfile, "extraspacing %f\n", 0.0);
+	fprintf(widthfile, "scale %f\n", 1.0);
 
 	for(i = 0; i < 256; ++i)
 	{
@@ -729,13 +788,15 @@
 		SDL_Rect dest;
 		char str[2]; str[0] = i; str[1] = 0;
 
-		if(!(i % 16))
+		if(i && !(i % 16))
 			fprintf(widthfile, "\n");
 
 		fntid = mapFont(differentFonts, &str[0]);
 		if(fntid < 0 || !fonts[fntid])
 		{
 			SDL_Rect src, src2;
+			int destTop, destBottom;
+
 			src.x = cell * (i % 16);
 			src.y = cell * (i / 16);
 			src.w = cell;
@@ -747,18 +808,18 @@
 			glyph = SDL_CreateRGBSurface(SDL_SWSURFACE, cell, cell, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
 			SDL_FillRect(glyph, &src2, transparent);
 
-			// map:
-			//   referenceTop    -> (cell - (maxAscent + 1 + maxDescent)) / 2
-			//   referenceBottom -> (cell - (maxAscent + 1 + maxDescent)) / 2 + maxAscent
+			/*  map: */
+			/*    referenceTop    -> (cell - (maxAscent + 1 + maxDescent)) / 2 */
+			/*    referenceBottom -> (cell - (maxAscent + 1 + maxDescent)) / 2 + maxAscent */
 
-			int destTop = (cell - (maxAscent + 1 + maxDescent)) / 2;
-			int destBottom = (cell - (maxAscent + 1 + maxDescent)) / 2 + maxAscent;
+			destTop = (cell - (maxAscent + 1 + maxDescent)) / 2;
+			destBottom = (cell - (maxAscent + 1 + maxDescent)) / 2 + maxAscent;
 
-			// map is:
-			//   x' = x / cell * h + y
-			// solve:
-			//   destTop = referenceTop / cell * h + y
-			//   destBottom = referenceBottom / cell * h + y
+			/*  map is: */
+			/*    x' = x / cell * h + y */
+			/*  solve: */
+			/*    destTop = referenceTop / cell * h + y */
+			/*    destBottom = referenceBottom / cell * h + y */
 
 			dest.x = 0;
 			dest.y = (int) ((double) (destBottom * referenceTop - destTop * referenceBottom) / (double) (referenceTop - referenceBottom));
@@ -777,8 +838,8 @@
 			if(isfixed)
 				dest.w = border + maxWidth + border;
 			StretchBlit(glyph, conchars, &dest, &src);
-			//SDL_FillRect(conchars, &src, transparent);
-			//SDL_BlitSurface(glyph, &src2, conchars, &src);
+			/* SDL_FillRect(conchars, &src, transparent); */
+			/* SDL_BlitSurface(glyph, &src2, conchars, &src); */
 			StretchBlit(conchars, glyph, &src, &src2);
 			SDL_FreeSurface(glyph);
 			fprintf(widthfile, "%f ", dest.w / (double) cell);




More information about the nexuiz-commits mailing list