r4176 - in branches/nexuiz-2.0: . Docs Docs/server data 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/maps data/particles data/qcsrc/client data/qcsrc/common data/qcsrc/server data/sound data/sound/player misc

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sun Aug 24 13:48:40 EDT 2008


Author: div0
Date: 2008-08-24 13:48:37 -0400 (Sun, 24 Aug 2008)
New Revision: 4176

Added:
   branches/nexuiz-2.0/data/particles/hook_blue.tga
   branches/nexuiz-2.0/data/particles/hook_green.tga
   branches/nexuiz-2.0/data/particles/hook_pink.tga
   branches/nexuiz-2.0/data/particles/hook_red.tga
   branches/nexuiz-2.0/data/particles/hook_yellow.tga
   branches/nexuiz-2.0/data/qcsrc/client/hook.qc
   branches/nexuiz-2.0/data/sound/player/torus/
Removed:
   branches/nexuiz-2.0/data/maps/aggressor.cfg
   branches/nexuiz-2.0/data/maps/aneurysm.cfg
   branches/nexuiz-2.0/data/maps/basement.cfg
   branches/nexuiz-2.0/data/maps/basementctf.cfg
   branches/nexuiz-2.0/data/maps/bleach.cfg
   branches/nexuiz-2.0/data/maps/bloodprison.cfg
   branches/nexuiz-2.0/data/maps/bloodprisonctf.cfg
   branches/nexuiz-2.0/data/maps/bluesky.cfg
   branches/nexuiz-2.0/data/maps/ctf_basementctf_exit.cfg
   branches/nexuiz-2.0/data/maps/darkzone.cfg
   branches/nexuiz-2.0/data/maps/dieselpower.cfg
   branches/nexuiz-2.0/data/maps/dismal.cfg
   branches/nexuiz-2.0/data/maps/downer.cfg
   branches/nexuiz-2.0/data/maps/evilspace.cfg
   branches/nexuiz-2.0/data/maps/farewell.cfg
   branches/nexuiz-2.0/data/maps/final_rage.cfg
   branches/nexuiz-2.0/data/maps/ons-reborn.cfg
   branches/nexuiz-2.0/data/maps/reslimed.cfg
   branches/nexuiz-2.0/data/maps/ruiner.cfg
   branches/nexuiz-2.0/data/maps/ruiner_exit.cfg
   branches/nexuiz-2.0/data/maps/rune_aneurysm_exit.cfg
   branches/nexuiz-2.0/data/maps/runningman.cfg
   branches/nexuiz-2.0/data/maps/runningman_1on1remix.cfg
   branches/nexuiz-2.0/data/maps/runningmanctf.cfg
   branches/nexuiz-2.0/data/maps/silvercity.cfg
   branches/nexuiz-2.0/data/maps/skyway.cfg
   branches/nexuiz-2.0/data/maps/slimepit.cfg
   branches/nexuiz-2.0/data/maps/soylent.cfg
   branches/nexuiz-2.0/data/maps/starship.cfg
   branches/nexuiz-2.0/data/maps/stormkeep.cfg
   branches/nexuiz-2.0/data/maps/strength.cfg
   branches/nexuiz-2.0/data/maps/toxic.cfg
   branches/nexuiz-2.0/data/maps/warfare.cfg
   branches/nexuiz-2.0/data/sound/debug/
Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/Docs/mapping.txt
   branches/nexuiz-2.0/Docs/server/server.cfg
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   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/maps/aggressor.mapinfo
   branches/nexuiz-2.0/data/maps/aneurysm.mapinfo
   branches/nexuiz-2.0/data/maps/basement.mapinfo
   branches/nexuiz-2.0/data/maps/basementctf.mapinfo
   branches/nexuiz-2.0/data/maps/bleach.mapinfo
   branches/nexuiz-2.0/data/maps/bloodprison.mapinfo
   branches/nexuiz-2.0/data/maps/bloodprisonctf.mapinfo
   branches/nexuiz-2.0/data/maps/bluesky.mapinfo
   branches/nexuiz-2.0/data/maps/darkzone.mapinfo
   branches/nexuiz-2.0/data/maps/dieselpower.mapinfo
   branches/nexuiz-2.0/data/maps/dismal.mapinfo
   branches/nexuiz-2.0/data/maps/downer.mapinfo
   branches/nexuiz-2.0/data/maps/evilspace.mapinfo
   branches/nexuiz-2.0/data/maps/farewell.mapinfo
   branches/nexuiz-2.0/data/maps/final_rage.mapinfo
   branches/nexuiz-2.0/data/maps/ons-reborn.mapinfo
   branches/nexuiz-2.0/data/maps/reslimed.mapinfo
   branches/nexuiz-2.0/data/maps/ruiner.mapinfo
   branches/nexuiz-2.0/data/maps/runningman.mapinfo
   branches/nexuiz-2.0/data/maps/runningman_1on1remix.mapinfo
   branches/nexuiz-2.0/data/maps/runningmanctf.mapinfo
   branches/nexuiz-2.0/data/maps/silvercity.mapinfo
   branches/nexuiz-2.0/data/maps/skyway.mapinfo
   branches/nexuiz-2.0/data/maps/slimepit.mapinfo
   branches/nexuiz-2.0/data/maps/soylent.mapinfo
   branches/nexuiz-2.0/data/maps/starship.mapinfo
   branches/nexuiz-2.0/data/maps/stormkeep.mapinfo
   branches/nexuiz-2.0/data/maps/strength.mapinfo
   branches/nexuiz-2.0/data/maps/toxic.mapinfo
   branches/nexuiz-2.0/data/maps/warfare.mapinfo
   branches/nexuiz-2.0/data/newhook.cfg
   branches/nexuiz-2.0/data/nexuiz-credits.txt
   branches/nexuiz-2.0/data/qcsrc/client/Defs.qc
   branches/nexuiz-2.0/data/qcsrc/client/Main.qc
   branches/nexuiz-2.0/data/qcsrc/client/View.qc
   branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/client/progs.src
   branches/nexuiz-2.0/data/qcsrc/client/sbar.qc
   branches/nexuiz-2.0/data/qcsrc/common/constants.qh
   branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc
   branches/nexuiz-2.0/data/qcsrc/common/mapinfo.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/server/arena.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_physics.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc
   branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
   branches/nexuiz-2.0/data/qcsrc/server/defs.qh
   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_triggers.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
   branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
   branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/server/race.qc
   branches/nexuiz-2.0/data/qcsrc/server/race.qh
   branches/nexuiz-2.0/data/qcsrc/server/scores.qc
   branches/nexuiz-2.0/data/qcsrc/server/scores.qh
   branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_halflife.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_jumppads.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_swamp.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc
   branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
   branches/nexuiz-2.0/data/sound/player/default.sounds
   branches/nexuiz-2.0/misc/autoshader.sh
Log:
- refactor common setmodel calls for moving brushes and triggers; ALWAYS support .mins/.maxs explicitly set instead of using an actual model (good for ent files)
- nodetail 1 as default for map voting
- hook: allow hooking to moving stuff, including players
- hook: tarzan 2 mode: one can pull other players
- hook: no more jitter; better graphics
- add torus' player sounds; remove the debug sounds
- exact triggers: hurt, ladder, impulse, multiple, jumppads, teleporters, swamp and race checkpoints now work EXACTLY as made in the map editor (not as bbox any more). This change might be desirable on other entity types too.
- don't draw that stupid spawn shield effect when waiting for the restart countdown
- Depcreate mapname.cfg files. From now on, these are only for the user to customize stuff like the CD track, but NOT for the mapper.
- Add a "cdtrack" command to mapinfo files.
- Add a "clientsettemp_for_type" command to mapinfo files (sets a cvar on the client for just this one round).
- Change all existing maps to this.
- Compatibility issue: playing on old servers will be without background music. I think we can live with that.


Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/.patchsets	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-4126
+revisions_applied = 1-4175

Modified: branches/nexuiz-2.0/Docs/mapping.txt
===================================================================
--- branches/nexuiz-2.0/Docs/mapping.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/Docs/mapping.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -30,22 +30,20 @@
 Appendix B - Helpful extras
   i.     Team Colors
   ii.    Text Colors
-
+
 Appendix C - Advanced Darkplaces shaders
 
 ========================
 =I. Map Lists & Scripts=
 ========================
 
-There are actually 2 script/cfg options available to you, each serving a
-different purpose and being executed at a different time during the map's life
-cycle:
+There now is just a single script/cfg file available to you, containing all map
+specific settings:
 
-1. mapname.mapinfo
-2. mapname.cfg
+mapname.mapinfo
 
-Of these, the mapinfo is the only one that's truely required - and the game is
-even so nice that it automatically generates a draft of it for you.
+The mapinfo is actually required - however, the game is so nice that it
+automatically generates a draft of it for you.
 
 ------------------
 -The mapinfo file-
@@ -73,6 +71,7 @@
     _diameter 1966.839355
     _spawnpoints 5
     has weapons
+	cdtrack 5
     type dm 30 20
     type dom 200 20
     type rune 200 20
@@ -113,24 +112,6 @@
 limit (if g_ctf_win_mode is 0 or 1).
 
 
--------------
--mapname.cfg-
--------------
-
-Unlike the mapinfo, which is processed by the server, the mapname.cfg file is
-processed by the client, and therefore is used for client settings like fog or
-the music to play.
-
-To make the mapname.cfg, make a file with the same name as your map's .bsp
-file, except with a .cfg extension instead of .bsp. For example, my
-"wazat1.bsp" map would use "wazat1.cfg". It uses the same name as your map,
-thus the term mapname.cfg. It will typically only contain a single line:
-
-    cd loop 6
-
-where 6 is the number or name of a track in sound/cdtracks/
-
-
 ===============
 =II. Map Image=
 ===============
@@ -271,9 +252,9 @@
 file - or simply edit it to add the "type dom" line.
 
 
-==========
-=III. CTF=
-==========
+=========
+=IV. CTF=
+=========
 
 Capture the flag needs at least 1 CTF flag per team, and can also make use of
 team spawnpoints.
@@ -301,9 +282,9 @@
 such entities, delete the data/data/mapname.mapinfo file - or simply edit it to
 add the "type ctf" line.
 
-================
-=III. Runematch=
-================
+==============
+=V. Runematch=
+==============
 
 Runematch needs only one type of entity to work: rune spawn points. You will
 need at least one for each rune (5 minimum at the time of this writing), though
@@ -319,7 +300,59 @@
 such entities, delete the data/data/mapname.mapinfo file - or simply edit it to
 add the "type rune" line.
 
+==========
+=VI. Race=
+==========
 
+Making a race map is not hard: you need some special spawnpoints, and some checkpoints.
+
+Spawnpoints
+-----------
+classname  info_player_race
+target     targetname of the controlpoint
+race_place for finish line control points, the place of the point
+
+Checkpoints
+-----------
+classname  trigger_race_checkpoint
+targetname some name to target the checkpoint with
+cnt        number of the checkpoint (or 0 for finish line)
+
+Note that checkpoints are brush entities, and they should be somewhat thick and
+cover the full volume the player could use to get past them.
+
+Example of entity placement:
+
+                         ###
+    ---------------------###---
+   /    >>>>  7  5  3  1 ###   \
+  /     >>>> 8  6  4  2  ###    \
+ |     ------------------###     |
+%%%%%%%%                 ###|    |
+%%%%%%%%                 $$$|    |
+ | ^ ^ ------------------$$$     |
+ \                       $$$ <  /
+  \                      $$$ < /
+   ----------------------$$$---
+                         $$$
+
+###:  classname = trigger_race_checkpoint, cnt = 0, targetname = finish
+$$$:  classname = trigger_race_checkpoint, cnt = 1, targetname = cp1
+%%%:  classname = trigger_race_checkpoint, cnt = 2, targetname = cp2
+>:    classname = info_player_race,                 target = finish, angle = 0
+1:    classname = info_player_race,                 target = finish, angle = 0, race_place = 1
+2:    classname = info_player_race,                 target = finish, angle = 0, race_place = 2
+....
+8:    classname = info_player_race,                 target = finish, angle = 0, race_place = 8
+<:    classname = info_player_race,                 target = cp1,    angle = 180
+^:    classname = info_player_race,                 target = cp2,    angle = 90
+
+If your map contains the required entities for Race, the menu will automatically
+detect it for supporting Race. To force the map to get re-detected after you add
+such entities, delete the data/data/mapname.mapinfo file - or simply edit it to
+add the "type race" line.
+
+
 ===============================
 =Appendix A - Advanced mapinfo=
 ===============================
@@ -348,7 +381,11 @@
 another is loaded. As you can see, it is possible to make per-mode temporary
 settings, and global ones.
 
+Similar settings are also possible for the client:
 
+    clientsettemp_for_type all r_shadow_glossexponent 96
+
+
 =============================
 =Appendix B - Helpful Extras=
 =============================
@@ -394,30 +431,30 @@
 8  Grey (transparent)
 9  Grey (solid)
 0  Black
-
+
 ==========================================
 =Appendix C - Advanced Darkplaces shaders=
-==========================================
-
-Shader parameters for DP's own features:
-- dp_reflect <distort> <r> <g> <b> <a>
-  Makes surfaces of this shader reflective with r_water. The reflection is
-  alpha blended on the texture with the given alpha, and modulated by the given
-  color. distort is used in conjunction with the normalmap to simulate a
-  nonplanar water surface.
-- dp_refract <distort> <r> <g> <b>
-  Makes surfaces of this shader refractive with r_water. The refraction
-  replaces the transparency of the texture. distort is used in conjunction with
-  the normalmap to simulate a nonplanar water surface.
-- dp_water <reflectmin> <reflectmax> <refractdistort> <reflectdistort> <refractr> <refractg> <refractb> <reflectr> <reflectg> <reflectb> <alpha>
-  This combines the effects of dp_reflect and dp_refract to simulate a water
-  surface. However, the refraction and the reflection are mixed using a Fresnel
-  equation that makes the amount of reflection slide from reflectmin when
-  looking parallel to the water to reflectmax when looking directly into the
-  water. The result of this reflection/refraction mix is then layered BELOW the
-  texture of the shader, so basically, it "fills up" the alpha values of the
-  water. The alpha value is a multiplicator for the alpha value on the texture
-  - set this to a small value like 0.1 to emphasize the reflection and make
-  the water transparent; but if r_water is 0, alpha isn't used, so the water can
-  be very visible then too.
-
+==========================================
+
+Shader parameters for DP's own features:
+- dp_reflect <distort> <r> <g> <b> <a>
+  Makes surfaces of this shader reflective with r_water. The reflection is
+  alpha blended on the texture with the given alpha, and modulated by the given
+  color. distort is used in conjunction with the normalmap to simulate a
+  nonplanar water surface.
+- dp_refract <distort> <r> <g> <b>
+  Makes surfaces of this shader refractive with r_water. The refraction
+  replaces the transparency of the texture. distort is used in conjunction with
+  the normalmap to simulate a nonplanar water surface.
+- dp_water <reflectmin> <reflectmax> <refractdistort> <reflectdistort> <refractr> <refractg> <refractb> <reflectr> <reflectg> <reflectb> <alpha>
+  This combines the effects of dp_reflect and dp_refract to simulate a water
+  surface. However, the refraction and the reflection are mixed using a Fresnel
+  equation that makes the amount of reflection slide from reflectmin when
+  looking parallel to the water to reflectmax when looking directly into the
+  water. The result of this reflection/refraction mix is then layered BELOW the
+  texture of the shader, so basically, it "fills up" the alpha values of the
+  water. The alpha value is a multiplicator for the alpha value on the texture
+  - set this to a small value like 0.1 to emphasize the reflection and make
+  the water transparent; but if r_water is 0, alpha isn't used, so the water can
+  be very visible then too.
+

Modified: branches/nexuiz-2.0/Docs/server/server.cfg
===================================================================
--- branches/nexuiz-2.0/Docs/server/server.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/Docs/server/server.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -38,6 +38,7 @@
 //g_lms 1         // last man standing
 //g_arena 1       // arena
 //g_keyhunt 1     // key hunt
+//g_race 1        // Race
 
 // enable some mutators you'd like
 //g_cloaked 0              // set to 1 for transparent hard to see players
@@ -73,7 +74,7 @@
 //g_maplist_votable 5 // number of maps to vote between.  set to 0 to disable the map voting screen (please enable g_maplist_shuffle above when this is enabled, or votes will be repetitive)
 //g_maplist_votable_suggestions 2 // number of suggestions to accept using the suggestmap command
 //g_maplist_votable_abstain 0 // when 1, people get a "don't care" selection in the vote screen
-//g_maplist_votable_nodetail 0 // when 1, people can't see how many voted for what (to thwart abusive "influential" first votes)
+//g_maplist_votable_nodetail 1 // when 1, people can't see how many voted for what (to thwart abusive "influential" first votes)
 
 //sv_vote_commands "restart timelimit fraglimit chmap gotomap g_grappling_hook sv_defaultplayer_fbskin_green sv_defaultplayer_fbskin_red sv_defaultplayer_fbskin_orange sv_defaultplayer_fbskin_off" // players can vote for those commands or use them if they are masters
 //sv_vote_call 1 // 0 will disable the normal voting

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -822,7 +822,7 @@
 seta g_maplist_votable_timeout 30 // note: must be below 50 seconds!
 seta g_maplist_votable_suggestions 2
 seta g_maplist_votable_suggestions_override_mostrecent 0
-seta g_maplist_votable_nodetail 0 // nodetail only shows total count instead of all vote counts per map, so votes don't influence others that much
+seta g_maplist_votable_nodetail 1 // nodetail only shows total count instead of all vote counts per map, so votes don't influence others that much
 seta g_maplist_votable_abstain 0 // when 1, you can abstain from your vote
 seta g_maplist_votable_screenshot_dir "maps" // where to look for map screenshots
 seta g_maplist_textonly 0 // use old style centerprint
@@ -865,7 +865,7 @@
 // command extension
 alias qc_cmd               "sv_cmd $*" // menu QC will override this to menu_cmd
 alias adminmsg             "sv_cmd adminmsg $*"
-alias teamstatus           "sv_cmd teamstatus"
+alias teamstatus           "cmd teamstatus; sv_cmd teamstatus" // yes, it is broken on listen servers that way, but well, who cares :P
 alias printstats           "sv_cmd printstats" // print status on demand
 alias g_maplist_add        "qc_cmd maplist add $*"
 alias g_maplist_remove     "qc_cmd maplist remove $*"

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedblack/skinvalues.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -43,6 +43,8 @@
 // item: button
 //   uses "button" images
 //   uses "buttongray" images
+//   uses "bigbutton" images
+//   uses "bigbuttongray" images
 COLOR_BUTTON_N                  '1 1 1'
 COLOR_BUTTON_C                  '1 1 1'
 COLOR_BUTTON_F                  '1 1 1'
@@ -91,7 +93,7 @@
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '1 1 1'
 COLOR_INPUTBOX_F                '1 1 1'
-MARGIN_INPUTBOX                 0.02
+MARGIN_INPUTBOX_CHARS           1
 
 // item: key grabber
 COLOR_KEYGRABBER_TITLES         '1 1 1'

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedblue/skinvalues.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -43,6 +43,8 @@
 // item: button
 //   uses "button" images
 //   uses "buttongray" images
+//   uses "bigbutton" images
+//   uses "bigbuttongray" images
 COLOR_BUTTON_N                  '0.5 0.75 1'
 COLOR_BUTTON_C                  '0.5 0.75 1'
 COLOR_BUTTON_F                  '0.5 0.75 1'
@@ -91,7 +93,7 @@
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '0.5 0.75 1'
 COLOR_INPUTBOX_F                '0.5 0.75 1'
-MARGIN_INPUTBOX                 0.02
+MARGIN_INPUTBOX_CHARS           1
 
 // item: key grabber
 COLOR_KEYGRABBER_TITLES         '1 1 1'

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedgreen/skinvalues.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -43,6 +43,8 @@
 // item: button
 //   uses "button" images
 //   uses "buttongray" images
+//   uses "bigbutton" images
+//   uses "bigbuttongray" images
 COLOR_BUTTON_N                  '0.5 1 0'
 COLOR_BUTTON_C                  '0.5 1 0'
 COLOR_BUTTON_F                  '0.5 1 0'
@@ -91,7 +93,7 @@
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '0.5 1 0'
 COLOR_INPUTBOX_F                '0.5 1 0'
-MARGIN_INPUTBOX                 0.02
+MARGIN_INPUTBOX_CHARS           1
 
 // item: key grabber
 COLOR_KEYGRABBER_TITLES         '1 1 1'

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedred/skinvalues.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -43,6 +43,8 @@
 // item: button
 //   uses "button" images
 //   uses "buttongray" images
+//   uses "bigbutton" images
+//   uses "bigbuttongray" images
 COLOR_BUTTON_N                  '1 0 0'
 COLOR_BUTTON_C                  '1 0 0'
 COLOR_BUTTON_F                  '1 0 0'
@@ -91,7 +93,7 @@
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '1 0 0'
 COLOR_INPUTBOX_F                '1 0 0'
-MARGIN_INPUTBOX                 0.02
+MARGIN_INPUTBOX_CHARS           1
 
 // item: key grabber
 COLOR_KEYGRABBER_TITLES         '1 1 1'

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedwhite/skinvalues.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -43,6 +43,8 @@
 // item: button
 //   uses "button" images
 //   uses "buttongray" images
+//   uses "bigbutton" images
+//   uses "bigbuttongray" images
 COLOR_BUTTON_N                  '1 1 1'
 COLOR_BUTTON_C                  '1 1 1'
 COLOR_BUTTON_F                  '1 1 1'
@@ -91,7 +93,7 @@
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '1 1 1'
 COLOR_INPUTBOX_F                '1 1 1'
-MARGIN_INPUTBOX                 0.02
+MARGIN_INPUTBOX_CHARS           1
 
 // item: key grabber
 COLOR_KEYGRABBER_TITLES         '1 1 1'

Modified: branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/gfx/menu/wickedyellow/skinvalues.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -43,6 +43,8 @@
 // item: button
 //   uses "button" images
 //   uses "buttongray" images
+//   uses "bigbutton" images
+//   uses "bigbuttongray" images
 COLOR_BUTTON_N                  '1 0.875 0'
 COLOR_BUTTON_C                  '1 0.875 0'
 COLOR_BUTTON_F                  '1 0.875 0'
@@ -91,7 +93,7 @@
 //   uses "inputbox" images
 COLOR_INPUTBOX_N                '1 0.875 0'
 COLOR_INPUTBOX_F                '1 0.875 0'
-MARGIN_INPUTBOX                 0.02
+MARGIN_INPUTBOX_CHARS           1
 
 // item: key grabber
 COLOR_KEYGRABBER_TITLES         '1 1 1'

Deleted: branches/nexuiz-2.0/data/maps/aggressor.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/aggressor.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/aggressor.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "4"

Modified: branches/nexuiz-2.0/data/maps/aggressor.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/aggressor.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/aggressor.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -11,3 +11,4 @@
 type lms 9 20
 type arena 10 20
 type kh 1000 20 3
+cdtrack 4

Deleted: branches/nexuiz-2.0/data/maps/aneurysm.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/aneurysm.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/aneurysm.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "6"

Modified: branches/nexuiz-2.0/data/maps/aneurysm.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/aneurysm.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/aneurysm.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -11,3 +11,4 @@
 type arena 10 20
 type kh 1000 30 2
 type tdm 50 20 2
+cdtrack 6

Deleted: branches/nexuiz-2.0/data/maps/basement.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/basement.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/basement.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "4"

Modified: branches/nexuiz-2.0/data/maps/basement.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/basement.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/basement.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 4

Deleted: branches/nexuiz-2.0/data/maps/basementctf.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/basementctf.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/basementctf.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "4"

Modified: branches/nexuiz-2.0/data/maps/basementctf.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/basementctf.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/basementctf.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -5,3 +5,4 @@
 _spawnpoints 15
 has weapons
 type ctf 300 20
+cdtrack 4

Deleted: branches/nexuiz-2.0/data/maps/bleach.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/bleach.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bleach.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "8"

Modified: branches/nexuiz-2.0/data/maps/bleach.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/bleach.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bleach.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,3 +10,4 @@
 type rune 200 20
 type lms 9 20
 type kh 1000 20 3
+cdtrack 8

Deleted: branches/nexuiz-2.0/data/maps/bloodprison.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/bloodprison.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bloodprison.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "2"
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/bloodprison.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/bloodprison.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bloodprison.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -7,3 +7,4 @@
 type dm 30 20
 type tdm 50 20 2
 type lms 9 20
+cdtrack 2

Deleted: branches/nexuiz-2.0/data/maps/bloodprisonctf.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/bloodprisonctf.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bloodprisonctf.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "7"

Modified: branches/nexuiz-2.0/data/maps/bloodprisonctf.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/bloodprisonctf.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bloodprisonctf.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -5,3 +5,4 @@
 _spawnpoints 28
 has weapons
 type ctf 300 20
+cdtrack 7

Deleted: branches/nexuiz-2.0/data/maps/bluesky.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/bluesky.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bluesky.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "3"
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/bluesky.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/bluesky.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/bluesky.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -7,3 +7,4 @@
 type dm 30 20
 type tdm 50 20 2
 type lms 9 20
+cdtrack 3

Deleted: branches/nexuiz-2.0/data/maps/ctf_basementctf_exit.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/ctf_basementctf_exit.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/ctf_basementctf_exit.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,4 +0,0 @@
-// reset laser damage
-//set g_balance_laser_primary_force $BACKUP_g_balance_laser_primary_force
-// reset fog?
-//fog 0

Deleted: branches/nexuiz-2.0/data/maps/darkzone.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/darkzone.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/darkzone.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "8"

Modified: branches/nexuiz-2.0/data/maps/darkzone.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/darkzone.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/darkzone.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 8

Deleted: branches/nexuiz-2.0/data/maps/dieselpower.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/dieselpower.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/dieselpower.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "8"

Modified: branches/nexuiz-2.0/data/maps/dieselpower.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/dieselpower.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/dieselpower.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,3 +10,4 @@
 type rune 200 20
 type lms 9 20
 type kh 1000 20 3
+cdtrack 8

Deleted: branches/nexuiz-2.0/data/maps/dismal.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/dismal.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/dismal.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "7"

Modified: branches/nexuiz-2.0/data/maps/dismal.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/dismal.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/dismal.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,3 +10,4 @@
 type ctf 300 20
 type rune 200 20
 type lms 9 20
+cdtrack 7

Deleted: branches/nexuiz-2.0/data/maps/downer.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/downer.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/downer.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "8"

Modified: branches/nexuiz-2.0/data/maps/downer.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/downer.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/downer.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 8

Deleted: branches/nexuiz-2.0/data/maps/evilspace.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/evilspace.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/evilspace.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "7"

Modified: branches/nexuiz-2.0/data/maps/evilspace.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/evilspace.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/evilspace.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -7,3 +7,4 @@
 type dm 30 20
 type lms 9 20
 type arena 10 20
+cdtrack 7

Deleted: branches/nexuiz-2.0/data/maps/farewell.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/farewell.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/farewell.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "5"

Modified: branches/nexuiz-2.0/data/maps/farewell.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/farewell.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/farewell.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type dm 30 20
 type lms 9 20
 type arena 10 20
+cdtrack 5

Deleted: branches/nexuiz-2.0/data/maps/final_rage.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/final_rage.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/final_rage.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "7"

Modified: branches/nexuiz-2.0/data/maps/final_rage.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/final_rage.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/final_rage.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,4 +10,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
-
+cdtrack 7

Deleted: branches/nexuiz-2.0/data/maps/ons-reborn.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/ons-reborn.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/ons-reborn.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop 8
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/ons-reborn.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/ons-reborn.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/ons-reborn.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -5,3 +5,4 @@
 _spawnpoints 54
 has weapons
 type ons 20
+cdtrack 8

Deleted: branches/nexuiz-2.0/data/maps/reslimed.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/reslimed.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/reslimed.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "4"

Modified: branches/nexuiz-2.0/data/maps/reslimed.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/reslimed.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/reslimed.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type dom 200 20
 type rune 200 20
 type lms 9 20
+cdtrack 4

Deleted: branches/nexuiz-2.0/data/maps/ruiner.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/ruiner.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/ruiner.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,6 +0,0 @@
-set exit_cfg "maps/ruiner_exit.cfg"
-set BACKUP_r_shadow_glossexponent $r_shadow_glossexponent
-set r_shadow_glossexponent 96
-set BACKUP_r_shadow_glossintensity $r_shadow_glossintensity
-set r_shadow_glossintensity 2
-cd loop "thunder"

Modified: branches/nexuiz-2.0/data/maps/ruiner.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/ruiner.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/ruiner.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,6 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack thunder
+clientsettemp_for_type all r_shadow_glossexponent 96
+clientsettemp_for_type all r_shadow_glossintensity 2

Deleted: branches/nexuiz-2.0/data/maps/ruiner_exit.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/ruiner_exit.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/ruiner_exit.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,2 +0,0 @@
-set r_shadow_glossexponent $BACKUP_r_shadow_glossexponent
-set r_shadow_glossintensity $BACKUP_r_shadow_glossintensity
\ No newline at end of file

Deleted: branches/nexuiz-2.0/data/maps/rune_aneurysm_exit.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/rune_aneurysm_exit.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/rune_aneurysm_exit.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,2 +0,0 @@
-// reset laser damage
-//set g_balance_laser_primary_force $BACKUP_g_balance_laser_primary_force

Deleted: branches/nexuiz-2.0/data/maps/runningman.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/runningman.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/runningman.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "2"
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/runningman.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/runningman.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/runningman.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,4 +10,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
-
+cdtrack 2

Deleted: branches/nexuiz-2.0/data/maps/runningman_1on1remix.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/runningman_1on1remix.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/runningman_1on1remix.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "2"
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/runningman_1on1remix.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/runningman_1on1remix.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/runningman_1on1remix.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -11,4 +11,4 @@
 type lms 9 20
 type arena 10 20
 type kh 1000 20 3
-
+cdtrack 2

Deleted: branches/nexuiz-2.0/data/maps/runningmanctf.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/runningmanctf.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/runningmanctf.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "2"
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/runningmanctf.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/runningmanctf.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/runningmanctf.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -11,3 +11,4 @@
 type rune 200 20
 type lms 9 20
 type kh 1000 20 3
+cdtrack 2

Deleted: branches/nexuiz-2.0/data/maps/silvercity.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/silvercity.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/silvercity.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "10"

Modified: branches/nexuiz-2.0/data/maps/silvercity.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/silvercity.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/silvercity.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,3 +10,4 @@
 type rune 200 20
 type lms 9 20
 type kh 1000 20 3
+cdtrack 10

Deleted: branches/nexuiz-2.0/data/maps/skyway.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/skyway.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/skyway.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "9"

Modified: branches/nexuiz-2.0/data/maps/skyway.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/skyway.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/skyway.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 9

Deleted: branches/nexuiz-2.0/data/maps/slimepit.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/slimepit.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/slimepit.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "4"

Modified: branches/nexuiz-2.0/data/maps/slimepit.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/slimepit.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/slimepit.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 4

Deleted: branches/nexuiz-2.0/data/maps/soylent.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/soylent.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/soylent.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "6"

Modified: branches/nexuiz-2.0/data/maps/soylent.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/soylent.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/soylent.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,4 +10,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
-
+cdtrack 6

Deleted: branches/nexuiz-2.0/data/maps/starship.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/starship.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/starship.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "10"

Modified: branches/nexuiz-2.0/data/maps/starship.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/starship.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/starship.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,3 +9,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 10

Deleted: branches/nexuiz-2.0/data/maps/stormkeep.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/stormkeep.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/stormkeep.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "6"

Modified: branches/nexuiz-2.0/data/maps/stormkeep.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/stormkeep.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/stormkeep.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -11,3 +11,4 @@
 type arena 10 20
 type kh 1000 20 3
 type tdm 50 20 2
+cdtrack 6

Deleted: branches/nexuiz-2.0/data/maps/strength.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/strength.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/strength.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "5"

Modified: branches/nexuiz-2.0/data/maps/strength.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/strength.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/strength.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,3 +10,4 @@
 type lms 9 20
 type arena 10 20
 type tdm 50 20 2
+cdtrack 5

Deleted: branches/nexuiz-2.0/data/maps/toxic.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/toxic.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/toxic.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "3"
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/toxic.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/toxic.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/toxic.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,3 +10,4 @@
 type rune 200 20
 type lms 9 20
 type arena 10 20
+cdtrack 3

Deleted: branches/nexuiz-2.0/data/maps/warfare.cfg
===================================================================
--- branches/nexuiz-2.0/data/maps/warfare.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/warfare.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1 +0,0 @@
-cd loop "6"

Modified: branches/nexuiz-2.0/data/maps/warfare.mapinfo
===================================================================
--- branches/nexuiz-2.0/data/maps/warfare.mapinfo	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/maps/warfare.mapinfo	2008-08-24 17:48:37 UTC (rev 4176)
@@ -10,4 +10,4 @@
 type tdm 50 20 2
 type lms 9 20
 type arena 10 20
-
+cdtrack 6

Modified: branches/nexuiz-2.0/data/newhook.cfg
===================================================================
--- branches/nexuiz-2.0/data/newhook.cfg	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/newhook.cfg	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,4 +1,4 @@
-set g_grappling_hook_tarzan 1
+set g_grappling_hook_tarzan 2 // 2: can also pull players
 set g_balance_grapplehook_speed_fly 1800
 set g_balance_grapplehook_speed_pull 2000
 set g_balance_grapplehook_force_rubber 2000

Modified: branches/nexuiz-2.0/data/nexuiz-credits.txt
===================================================================
--- branches/nexuiz-2.0/data/nexuiz-credits.txt	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/nexuiz-credits.txt	2008-08-24 17:48:37 UTC (rev 4176)
@@ -76,6 +76,7 @@
 Amos "torus" Dudley - Announcer voices
 William "Willis" Weilep - Master server host
 Tyler "-z-" Mulligan - Site Design
+"sev" - "Wicked" menu skins
 
 Qantourisc
 Tymo

Copied: branches/nexuiz-2.0/data/particles/hook_blue.tga (from rev 4174, trunk/data/particles/hook_blue.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/particles/hook_green.tga (from rev 4175, trunk/data/particles/hook_green.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/particles/hook_pink.tga (from rev 4174, trunk/data/particles/hook_pink.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/particles/hook_red.tga (from rev 4174, trunk/data/particles/hook_red.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/particles/hook_yellow.tga (from rev 4174, trunk/data/particles/hook_yellow.tga)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/qcsrc/client/Defs.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Defs.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/client/Defs.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -199,3 +199,6 @@
 float race_othercheckpointlapsdelta;
 string race_othercheckpointenemy;
 float sb_showscores_force;
+
+// Spectating
+float spectatee_status;

Modified: branches/nexuiz-2.0/data/qcsrc/client/Main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -2,6 +2,8 @@
 // BEGIN REQUIRED CSQC FUNCTIONS
 //include "main.qh"
 
+#define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+
 void() menu_show_error =
 {
 	drawstring('0 200 0', "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!", '8 8 0', '1 0 0', 1, 0);
@@ -96,6 +98,10 @@
 	remove(teams);
 	remove(players);
 	db_close(configdb);
+
+	entity e;
+	for(e = world; (e = find(e, classname, "saved_cvar_value")); )
+			cvar_set(e.netname, e.message);
 }
 
 .float has_team;
@@ -237,6 +243,18 @@
 		Cmd_MapVote_MapDownload(argc);
 		return true;
 	}
+	else if(cmd == "settemp") {
+		entity e;
+		for(e = world; (e = find(e, classname, "saved_cvar_value")); )
+			if(e.netname == argv(1))
+				goto saved;
+		e = spawn();
+		e.classname = "saved_cvar_value";
+		e.netname = strzone(argv(1));
+		e.message = strzone(cvar_string(argv(1)));
+:saved
+		cvar_set(argv(1), argv(2));
+	}
 	
 	return false;
 }
@@ -301,16 +319,29 @@
 	}
 }
 
+void Ent_Remove();
 void Ent_ReadPlayerScore()
 {
-	float i, Team;
+	float i, Team, n;
 	float isNew;
 	entity o;
 
 	// damnit -.- don't want to go change every single .sv_entnum in sbar.qc AGAIN
 	// (no I've never heard of M-x replace-string, sed, or anything like that)
 	isNew = !self.owner; // workaround for DP bug
-	self.sv_entnum = ReadByte()-1;
+	n = ReadByte()-1;
+
+#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+	if(!isNew && n != self.sv_entnum)
+	{
+		print("A CSQC entity changed its owner!\n");
+		isNew = true;
+		Ent_Remove();
+		self.enttype = ENT_CLIENT_SCORES;
+	}
+#endif
+
+	self.sv_entnum = n;
 	Team = GetPlayerColor(self.sv_entnum);
 
 	if not(playerslots[self.sv_entnum])
@@ -323,8 +354,21 @@
 
 	SetTeam(o, Team);
 
+#if MAX_SCORE <= 3
 	for(i = 0; i < MAX_SCORE; ++i)
 		o.(scores[i]) = ReadShort();
+#else
+	float sf;
+#if MAX_SCORE <= 8
+	sf = ReadByte();
+#else
+	sf = ReadShort();
+#endif
+	float p;
+	for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
+		if(sf & p)
+			o.(scores[i]) = ReadShort();
+#endif
 
 	Sbar_UpdatePlayerPos(o);
 }
@@ -337,22 +381,39 @@
 	self.team = ReadByte();
 	o = self.owner = GetTeam(self.team, true);
 
+#if MAX_TEAMSCORE <= 3
 	for(i = 0; i < MAX_TEAMSCORE; ++i)
 		o.(teamscores[i]) = ReadShort();
+#else
+	float sf;
+#if MAX_TEAMSCORE <= 8
+	sf = ReadByte();
+#else
+	sf = ReadShort();
+#endif
+	float p;
+	for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
+		if(sf & p)
+			o.(teamscores[i]) = ReadShort();
+#endif
 
 	Sbar_UpdateTeamPos(o);
 }
 
 // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
 // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
-void Ent_Remove();
 void(float bIsNewEntity) CSQC_Ent_Update =
 {
 	float msg, t;
 	t = ReadByte();
+#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
 	if(self.enttype)
 		if(t != self.enttype)
+		{
+			print("A CSQC entity changed its type!\n");
 			Ent_Remove();
+		}
+#endif
 	self.enttype = t;
 	if(self.enttype == ENT_CLIENT_ENTCS)
 	{
@@ -590,6 +651,10 @@
 			race_checkpointtime = 0;
 			break;
 
+		case RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING:
+			race_laptime = ReadCoord();
+			race_checkpointtime = -99999;
+			// fall through
 		case RACE_NET_CHECKPOINT_NEXT_QUALIFYING:
 			race_nextcheckpoint = ReadByte();
 
@@ -625,6 +690,28 @@
 	}
 }
 
+void Net_ReadForceScoreboard()
+{
+	sb_showscores_force = ReadByte();
+}
+
+void Net_Reset()
+{
+	race_laptime = 0;
+	race_checkpointtime = 0;
+}
+
+void Net_ReadSpectating()
+{
+	float newspectatee_status;
+	newspectatee_status = ReadByte();
+	if(newspectatee_status == player_localentnum)
+		newspectatee_status = -1; // observing
+	if(newspectatee_status != spectatee_status)
+		Net_Reset();
+	spectatee_status = newspectatee_status;
+}
+
 // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
 // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
 // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
@@ -660,9 +747,17 @@
 			bHandled = true;
 			break;
 		case TE_CSQC_FORCESCOREBOARD:
-			sb_showscores_force = true;
+			Net_ReadForceScoreboard();
 			bHandled = true;
 			break;
+		case TE_CSQC_SPECTATING:
+			Net_ReadSpectating();
+			bHandled = true;
+			break;
+		case 13: // TE_BEAM
+			Net_GrapplingHook();
+			bHandled = true;
+			break;
 		default:
 			// No special logic for this temporary entity; return 0 so the engine can handle it
 			bHandled = false;

Modified: branches/nexuiz-2.0/data/qcsrc/client/View.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -52,6 +52,7 @@
 	R_AddEntities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
 
 	// Render the Scene
+	Draw_GrapplingHook();
 	R_RenderScene();
 
 	// Draw the mouse cursor

Copied: branches/nexuiz-2.0/data/qcsrc/client/hook.qc (from rev 4174, trunk/data/qcsrc/client/hook.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/hook.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/client/hook.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -0,0 +1,99 @@
+.vector HookStart;
+.vector HookEnd;
+.float HookKillTime;
+void Net_GrapplingHook()
+{
+	float i;
+	vector start, end;
+	entity p;
+
+	i = ReadShort();
+	end_x = ReadCoord();
+	end_y = ReadCoord();
+	end_z = ReadCoord();
+	start_x = ReadCoord();
+	start_y = ReadCoord();
+	start_z = ReadCoord();
+
+	if(i <= 0 || i >= 256) // not owned by a client
+		return;
+	--i;
+
+	p = playerslots[i];
+	if(!p)
+		return;
+
+	p.HookKillTime = time + 0.1;
+	p.HookStart = start;
+	p.HookEnd = end;
+}
+
+void Draw_GrapplingHookLine(vector from, vector to, float thickness, vector org, vector view_forward, string texture, float aspect, vector rgb)
+{
+	// I want to draw a quad...
+	// from and to are MIDPOINTS.
+	
+	float t;
+	vector axis, thickdir, A, B, C, D;
+	float length_tex;
+
+	t = -2 * time;
+	t = random();
+
+	axis = normalize(to - from);
+	length_tex = aspect * vlen(to - from) / thickness;
+
+	// direction is perpendicular to the view normal, and perpendicular to the axis
+	thickdir = normalize(cross(axis, org - from));
+
+	A = from - thickdir * (thickness / 2);
+	B = from + thickdir * (thickness / 2);
+	C = to + thickdir * (thickness / 2);
+	D = to - thickdir * (thickness / 2);
+
+	if(checkextension("DP_SV_WRITEPICTURE"))
+		R_BeginPolygon(texture, 0);
+	else
+		R_BeginPolygon("", 0);
+	R_PolygonVertex(A, '0 0 0' + t * '1 0 0', rgb, 1);
+	R_PolygonVertex(B, '0 1 0' + t * '1 0 0', rgb, 1);
+	R_PolygonVertex(C, '0 1 0' + (t + length_tex) * '1 0 0', rgb, 1);
+	R_PolygonVertex(D, '0 0 0' + (t + length_tex) * '1 0 0', rgb, 1);
+	R_EndPolygon();
+}
+
+void Draw_GrapplingHook()
+{
+	float i;
+	vector a, b, o;
+	entity e;
+	string tex;
+
+	o = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
+	makevectors(input_angles);
+
+	for(i = 0; i < 255; ++i)
+	{
+		e = playerslots[i];
+		if(!e)
+			continue;
+		if(time >= e.HookKillTime)
+			continue;
+		if(i == player_localentnum - 1)
+			a = o + v_forward * 8 - v_right * 8 + v_up * -12;
+		else
+			a = e.HookStart;
+		b = e.HookEnd;
+		if(e.team == COLOR_TEAM1)
+			tex = "particles/hook_red";
+		else if(e.team == COLOR_TEAM2)
+			tex = "particles/hook_blue";
+		else if(e.team == COLOR_TEAM3)
+			tex = "particles/hook_yellow";
+		else if(e.team == COLOR_TEAM4)
+			tex = "particles/hook_pink";
+		else
+			tex = "particles/hook_green";
+		Draw_GrapplingHookLine(b, a, 8, o, v_forward, tex, 0.25, '1 1 1');
+	}
+}

Modified: branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -141,7 +141,16 @@
 vector Sbar_GetFontsize()
 {
 	if(csqc_flags & CSQC_FLAG_READPICTURE)
-		return stov(cvar_string("sbar_fontsize"));
+	{
+		vector v;
+		v = stov(cvar_string("sbar_fontsize"));
+		if(v_x == 0)
+			v = '8 8 0';
+		if(v_y == 0)
+			v_y = v_x;
+		v_z = 0;
+		return v;
+	}
 	return '8 8 0' ;
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/client/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/progs.src	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/client/progs.src	2008-08-24 17:48:37 UTC (rev 4176)
@@ -21,6 +21,8 @@
 sbar.qc
 mapvoting.qc
 
+hook.qc
+
 Main.qc
 View.qc
 

Modified: branches/nexuiz-2.0/data/qcsrc/client/sbar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/sbar.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/client/sbar.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -561,29 +561,7 @@
 				sbar_field_rgb = '0 1 1';
 			else
 				sbar_field_rgb = '1 1 1';
-			if(!tmp)
-				if(f & (SFL_HIDE_ZERO | SFL_RANK | SFL_TIME))
-					return "";
-			if(f & SFL_RANK)
-			{
-				str = ftos(floor(tmp + 0.5));
-				num = strlen(str);
-				if((num >= 2) && (substring(str, num - 2, 1) == "1"))
-					return strcat(str, "th");
-				else if(substring(str, num - 1, 1) == "1")
-					return strcat(str, "st");
-				else if(substring(str, num - 1, 1) == "2")
-					return strcat(str, "nd");
-				else if(substring(str, num - 1, 1) == "3")
-					return strcat(str, "rd");
-				else
-					return strcat(str, "th");
-			}
-			else if(f & SFL_TIME)
-			{
-				return mmsss(tmp);
-			}
-			return ftos(tmp);
+			return ScoreString(f, tmp);
 	}
 	//return "error";
 }
@@ -742,12 +720,6 @@
 		lastpingstime = time;
 	}
 
-	sbar_fontsize = Sbar_GetFontsize();
-	if(sbar_fontsize_x == 0)
-		sbar_fontsize = '8 8 0';
-	if(sbar_fontsize_y == 0)
-		sbar_fontsize_y = sbar_fontsize_x;
-	
 	xmin = vid_conwidth / 5;
 	ymin = 20;
 
@@ -1106,7 +1078,7 @@
 		drawfont = sbar_bigfont;
 		float a;
 		vector m;
-		string s;
+		string s, forcetime;
 
 		m = '0.5 0 0' * vid_conwidth + '0 0.25 0' * vid_conheight;
 
@@ -1115,12 +1087,15 @@
 
 			a = bound(0, 2 - (time - race_checkpointtime), 1);
 			s = "";
+			forcetime = "";
 			if(a > 0) // just hit a checkpoint?
 			{
 				if(race_time && race_previousbesttime)
 					s = MakeRaceString(race_checkpoint, race_time / 10 - race_previousbesttime / 10, 0, 0, race_previousbestname);
 				else
 					s = MakeRaceString(race_checkpoint, 0, -1, 0, race_previousbestname);
+				if(race_time)
+					forcetime = mmsss(race_time);
 			}
 			else
 			{
@@ -1134,17 +1109,27 @@
 				}
 			}
 
-			if(s != "")
-			if(a > 0)
+			if(s != "" && a > 0)
 			{
 				dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
 				drawcolorcodedstring(m - '0 16 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', sbar_alpha_fg * a, 0);
 			}
 
+			if(forcetime != "")
+			{
+				float sz;
+				a = bound(0, 1 - 2 * (time - race_checkpointtime), 1);
+				sz = 1.2 / (a + 0.2);
+				drawstring(m - '0 0 0' - '0 16 0' * (sz - 1) - '16 0 0' * sz * stringwidth(forcetime, FALSE), forcetime, '32 32 0' * sz, '1 1 1', sbar_alpha_fg * a, 0);
+				a = 1 - a;
+			}
+			else
+				a = 1;
+
 			if(race_laptime)
 			{
 				s = mmsss(10*(time - race_laptime));
-				drawstring(m - '0 0 0' - '16 0 0' * stringwidth(s, FALSE), s, '32 32 0', '1 1 1', sbar_alpha_fg, 0);
+				drawstring(m - '0 0 0' - '16 0 0' * stringwidth(s, FALSE), s, '32 32 0', '1 1 1', sbar_alpha_fg * a, 0);
 			}
 		}
 		else
@@ -1312,11 +1297,86 @@
 	float x, fade;
 	float stat_items;
 
+	sbar_fontsize = Sbar_GetFontsize();
+
+	if(spectatee_status)
+	{
+		string s;
+		vector o;
+		o = '1 0 0' * vid_conwidth;
+		if(spectatee_status == -1)
+			s = "^1Observing";
+		else
+			s = strcat("^1Spectating ^7", getplayerkey(spectatee_status - 1, "name"));
+		dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+		drawcolorcodedstring(
+			o - sbar_fontsize_x * '1 0 0' * stringwidth(s, TRUE),
+			s,
+			sbar_fontsize,
+			sbar_alpha_fg,
+			0
+		);
+		o += sbar_fontsize_y * '0 1 0';
+
+		if(spectatee_status == -1)
+			s = "^1Press ^3primary fire^1 to spectate";
+		else
+			s = "^1Press ^3primary fire^1 for another player";
+		dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+		drawcolorcodedstring(
+			o - sbar_fontsize_x * '1 0 0' * stringwidth(s, TRUE),
+			s,
+			sbar_fontsize,
+			sbar_alpha_fg,
+			0
+		);
+		o += sbar_fontsize_y * '0 1 0';
+
+		if(spectatee_status == -1)
+			s = "^1Use ^3weapon switching^1 to change the speed";
+		else
+			s = "^1Press ^3secondary fire^1 to observe";
+		dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+		drawcolorcodedstring(
+			o - sbar_fontsize_x * '1 0 0' * stringwidth(s, TRUE),
+			s,
+			sbar_fontsize,
+			sbar_alpha_fg,
+			0
+		);
+		o += sbar_fontsize_y * '0 1 0';
+
+		if(gametype == GAME_ARENA)
+			s = "^1Wait for your turn to join";
+		else if(gametype == GAME_LMS)
+		{
+			entity sk;
+			sk = playerslots[player_localentnum - 1];
+			if(sk.(scores[ps_primary]) >= 666)
+				s = "^1Match has already begun";
+			else if(sk.(scores[ps_primary]) > 0)
+				s = "^1You have no more lives left";
+			else
+				s = "^1Press ^7jump^1 to join";
+		}
+		else
+			s = "^1Press ^7jump^1 to join";
+		dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+		drawcolorcodedstring(
+			o - sbar_fontsize_x * '1 0 0' * stringwidth(s, TRUE),
+			s,
+			sbar_fontsize,
+			sbar_alpha_fg,
+			0
+		);
+		o += sbar_fontsize_y * '0 1 0';
+	}
+	
 	//Sbar_SortFrags();
 	Sbar_UpdatePlayerTeams();
 
 	sb_lines = 24;
-	
+
 	if (sb_showscores)
 		Sbar_DrawScoreboard();
 	else if (intermission == 1)

Modified: branches/nexuiz-2.0/data/qcsrc/common/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -9,7 +9,9 @@
 // Revision 8: race
 // Revision 9: race delta
 // Revision 10: scoreboard force
-#define CSQC_REVISION 9
+// Revision 11: scoreboard unforce; spectator support beginning
+// Revision 12: smaller scores updates (SERVER: requires new engine)
+#define CSQC_REVISION 12
 
 // probably put these in common/
 // so server/ and client/ can be synced better
@@ -189,6 +191,7 @@
 const float TE_CSQC_SCORESINFO = 108;
 const float TE_CSQC_RACE = 109;
 const float TE_CSQC_FORCESCOREBOARD = 110;
+const float TE_CSQC_SPECTATING = 111;
 
 const float STAT_KH_KEYS = 32;
 const float STAT_CTF_STATE = 33;
@@ -209,6 +212,7 @@
 const float RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder
 const float RACE_NET_CHECKPOINT_HIT_RACE = 3; // byte checkpoint, short delta, byte lapsdelta, string opponent
 const float RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT = 4; // byte checkpoint, short delta, byte lapsdelta, string opponent
+const float RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING = 5; // byte nextcheckpoint, float laptime, short recordtime, string recordholder
 
 /**
  * Lower scores are better (e.g. suicides)

Modified: branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -474,6 +474,7 @@
 	MapInfo_Map_author = "<AUTHOR>";
 	MapInfo_Map_supportedGametypes = 0;
 	MapInfo_Map_supportedFeatures = 0;
+	MapInfo_Map_clientstuff = "";
 }
 
 void _MapInfo_Map_ApplyGametype(string s, float pWantedType, float pThisType)
@@ -537,6 +538,23 @@
 	else                  return 0;
 }
 
+float cvar_value_issafe(string s)
+{
+	if(strstrofs(s, "\"", 0) >= 0)
+		return 0;
+	if(strstrofs(s, "\\", 0) >= 0)
+		return 0;
+	if(strstrofs(s, ";", 0) >= 0)
+		return 0;
+	if(strstrofs(s, "$", 0) >= 0)
+		return 0;
+	if(strstrofs(s, "\r", 0) >= 0)
+		return 0;
+	if(strstrofs(s, "\n", 0) >= 0)
+		return 0;
+	return 1;
+}
+
 // load info about a map by name into the MapInfo_Map_* globals
 float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametypeToSet)
 {
@@ -568,6 +586,7 @@
 		fputs(fh, strcat("title ", MapInfo_Map_title, "\n"));
 		fputs(fh, strcat("description ", MapInfo_Map_description, "\n"));
 		fputs(fh, strcat("author ", MapInfo_Map_author, "\n"));
+		fputs(fh, strcat("cdtrack ", ftos(ceil(random() * 9 + 1)), "\n")); // track from 2 to 10
 		if(MapInfo_Map_supportedFeatures & MAPINFO_FEATURE_WEAPONS)       fputs(fh, "has weapons\n");
 		if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_DEATHMATCH)      fputs(fh, "type dm 30 20\n");
 		if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_TEAM_DEATHMATCH) fputs(fh, "type tdm 50 20 2\n");
@@ -643,18 +662,10 @@
 				if(f & pGametypeToSet)
 				{
 					t = car(s); s = cdr(s);
-					if(strstrofs(t, "\"", 0) >= 0)
+					if not(cvar_value_issafe(t))
 						print("Map ", pFilename, " contains a potentially harmful setting, ignored\n");
-					else if(strstrofs(t, "\\", 0) >= 0)
+					else if not (cvar_value_issafe(s))
 						print("Map ", pFilename, " contains a potentially harmful setting, ignored\n");
-					else if(strstrofs(t, ";", 0) >= 0)
-						print("Map ", pFilename, " contains a potentially harmful setting, ignored\n");
-					else if(strstrofs(s, "\"", 0) >= 0)
-						print("Map ", pFilename, " contains a potentially harmful setting, ignored\n");
-					else if(strstrofs(s, "\\", 0) >= 0)
-						print("Map ", pFilename, " contains a potentially harmful setting, ignored\n");
-					else if(strstrofs(s, ";", 0) >= 0)
-						print("Map ", pFilename, " contains a potentially harmful setting, ignored\n");
 					else
 					{
 						dprint("Applying temporary setting ", t, " := ", s, "\n");
@@ -667,6 +678,44 @@
 				dprint("Map ", pFilename, " has a setting for unknown game type ", t, ", ignored\n");
 			}
 		}
+		else if(t == "clientsettemp_for_type")
+		{
+			t = car(s); s = cdr(s);
+			if((f = MapInfo_Type_FromString(t)))
+			{
+				if(f & pGametypeToSet)
+				{
+					t = car(s); s = cdr(s);
+					if not(cvar_value_issafe(t))
+						print("Map ", pFilename, " contains a potentially harmful client setting, ignored\n");
+					else if not (cvar_value_issafe(s))
+						print("Map ", pFilename, " contains a potentially harmful client setting, ignored\n");
+					else
+					{
+						dprint("Applying temporary client setting ", t, " := ", s, "\n");
+						MapInfo_Map_clientstuff = strcat(
+							MapInfo_Map_clientstuff, "cl_cmd settemp \"", t, "\" \"", s, "\"\n"
+						);
+					}
+				}
+			}
+			else
+			{
+				dprint("Map ", pFilename, " has a client setting for unknown game type ", t, ", ignored\n");
+			}
+		}
+		else if(t == "cdtrack")
+		{
+			if(pGametypeToSet)
+			{
+				if not(cvar_value_issafe(t))
+					print("Map ", pFilename, " contains a potentially harmful cdtrack, ignored\n");
+				else
+					MapInfo_Map_clientstuff = strcat(
+						MapInfo_Map_clientstuff, "cd loop \"", s, "\"\n"
+					);
+			}
+		}
 		else
 			dprint("Map ", pFilename, " provides unknown info item ", t, ", ignored\n");
 	}
@@ -851,7 +900,6 @@
 	}
 	cvar_settemp_restore();
 	MapInfo_Get_ByName(s, 1, MapInfo_CurrentGametype());
-	MapInfo_ClearTemps();
 }
 
 void MapInfo_ClearTemps()
@@ -860,6 +908,7 @@
 	MapInfo_Map_title = string_null;
 	MapInfo_Map_description = string_null;
 	MapInfo_Map_author = string_null;
+	MapInfo_Map_clientstuff = string_null;
 	MapInfo_Map_supportedGametypes = 0;
 	MapInfo_Map_supportedFeatures = 0;
 }

Modified: branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -20,6 +20,7 @@
 string MapInfo_Map_title;
 string MapInfo_Map_description;
 string MapInfo_Map_author;
+string MapInfo_Map_clientstuff;
 float MapInfo_Map_supportedGametypes;
 float MapInfo_Map_supportedFeatures;
 

Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -436,3 +436,43 @@
 	s = ftos(1000 + tenths);
 	return strcat(ftos(minutes), ":", substring(s, 1, 2), ".", substring(s, 3, 1));
 }
+
+string ScoreString(float vflags, float value)
+{
+	string valstr;
+	float l;
+
+	value = floor(value + 0.5); // round
+
+	if((value == 0) && (vflags & (SFL_HIDE_ZERO | SFL_RANK | SFL_TIME)))
+		valstr = "";
+	else if(vflags & SFL_RANK)
+	{
+		valstr = ftos(value);
+		l = strlen(valstr);
+		if((l >= 2) && (substring(valstr, l - 2, 1) == "1"))
+			valstr = strcat(valstr, "th");
+		else if(substring(valstr, l - 1, 1) == "1")
+			valstr = strcat(valstr, "st");
+		else if(substring(valstr, l - 1, 1) == "2")
+			valstr = strcat(valstr, "nd");
+		else if(substring(valstr, l - 1, 1) == "3")
+			valstr = strcat(valstr, "rd");
+		else
+			valstr = strcat(valstr, "th");
+	}
+	else if(vflags & SFL_TIME)
+		valstr = mmsss(value);
+	else
+		valstr = ftos(value);
+	
+	return valstr;
+}
+
+vector cross(vector a, vector b)
+{
+	return
+		'1 0 0' * (a_y * b_z - a_z * b_y)
+	+	'0 1 0' * (a_z * b_x - a_x * b_z)
+	+	'0 0 1' * (a_x * b_y - a_y * b_x);
+}

Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -58,3 +58,6 @@
 
 string GametypeNameFromType(float g);
 string mmsss(float t);
+string ScoreString(float vflags, float value);
+
+vector cross(vector a, vector b);

Modified: branches/nexuiz-2.0/data/qcsrc/server/arena.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/arena.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/arena.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -34,8 +34,8 @@
 
 	race_ReadyRestart();
 	
-	self = nextent(world);
-	while(self)
+	for(self = world; (self = nextent(self)); )
+	if(clienttype(self) == CLIENTTYPE_NOTACLIENT)
 	{
 		if(self.classname == STR_ITEM_KH_KEY)
 		{
@@ -102,7 +102,6 @@
 		{
 			self.team = self.team_saved;
 		}
-		self = nextent(self);
 	}
 
 	// Moving the player reset code here since the player-reset depends

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1102,10 +1102,8 @@
 
 	self.welcomemessage_time = 0;
 
+	stuffcmd(self, strcat(clientstuff, "\n"));
 	stuffcmd(self, strcat("exec maps/", mapname, ".cfg\n"));
-	// TODO: is this being used for anything else than cd tracks?
-	// Remember: SVC_CDTRACK exists. Maybe it should be used.
-	//
 	stuffcmd(self, "cl_particles_reloadeffects\n");
 
 	FixClientCvars(self);
@@ -1552,6 +1550,7 @@
 	if (g_midair)
 		self.spawnshieldtime = max(self.spawnshieldtime, time + cvar("g_midair_shieldtime"));
 
+	if (time > restart_countdown)
 	if (time < self.spawnshieldtime)
 		self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
 }
@@ -1920,6 +1919,7 @@
 */
 void() ctf_setstatus;
 .float vote_nagtime;
+.float spectatee_status;
 void PlayerPreThink (void)
 {
 	if(blockSpectators)
@@ -2187,6 +2187,24 @@
 	} else if(self.classname == "spectator") {
 		SpectatorThink();
 	}
+
+	float oldspectatee_status;
+	oldspectatee_status = self.spectatee_status;
+	if(self.classname == "spectator")
+		self.spectatee_status = num_for_edict(self.enemy);
+	else if(self.classname == "observer")
+		self.spectatee_status = num_for_edict(self);
+	else
+		self.spectatee_status = 0;
+	if(self.spectatee_status != oldspectatee_status)
+	{
+		msg_entity = self;
+		WriteByte(MSG_ONE, SVC_TEMPENTITY);
+		WriteByte(MSG_ONE, TE_CSQC_SPECTATING);
+		WriteByte(MSG_ONE, self.spectatee_status);
+		if(g_race)
+			race_InitSpectator();
+	}
 }
 
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_physics.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_physics.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_physics.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -14,6 +14,7 @@
 .float lastflags;
 .float lastground;
 .float wasFlying;
+.float spectatorspeed;
 
 #define SHTEST_DELTA 15
 .float shtest_next;
@@ -206,7 +207,28 @@
 	}
 
 	if(self.flags & FL_NOTARGET)
+	{
 		maxspd_mod = cvar("sv_spectator_speed_multiplier");
+		if(!self.spectatorspeed)
+			self.spectatorspeed = maxspd_mod;
+		if(self.impulse && self.impulse <= 12)
+		{
+			if(self.lastflags & FL_NOTARGET)
+			{
+				if(self.impulse == 10)
+					self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
+				else if(self.impulse == 11)
+					self.spectatorspeed = maxspd_mod;
+				else if(self.impulse == 12)
+					self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
+				else if(self.impulse >= 1 && self.impulse <= 9)
+					self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
+			} // otherwise just clear
+			self.impulse = 0;
+			print("impulse\n");
+		}
+		maxspd_mod = self.spectatorspeed;
+	}
 
 	spd = sv_maxspeed * maxspd_mod * swampspd_mod;
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -355,6 +355,11 @@
 {
 	local float take, save, waves, sdelay;
 
+	if(self.hook)
+		if(self.hook.aiment)
+			if(self.hook.aiment == attacker)
+				RemoveGrapplingHook(self); // STOP THAT, you parasite!
+
 	damage = damage * bound(1.0, self.cvar_cl_handicap, 100.0);
 	if(sv_gentle > 0) {
 		pointparticles(particleeffectnum("damage_hit"), hitloc, force, bound(0, damage, 200));

Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -347,6 +347,8 @@
 		if(cvar("sv_timeout")) {
 			evaluateResumeGame();
 		}
+	} else if(argv(0) == "teamstatus") {
+		Score_NicePrint(self);
 	} else {
 		//if(ctf_clientcommand())
 		//	return;
@@ -384,6 +386,8 @@
 
 	bprint("^1Server is restarting...\n");
 
+	VoteReset();
+
 	// no arena, assault support yet...
 	if(g_arena | g_assault | gameover | intermission_running | race_completing)
 		localcmd("restart\n");

Modified: branches/nexuiz-2.0/data/qcsrc/server/defs.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -446,7 +446,8 @@
 float next_pingtime;
 
 .float Version;
-.float(entity to) SendEntity;
+.float SendFlags;
+.float(entity to, float sendflags) SendEntity;
 
 // player sounds, voice messages
 .string playersound_attack;
@@ -486,3 +487,5 @@
 float independent_players;
 #define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER)
 #define MAKE_INDEPENDENT_PLAYER(e) ((e).solid = SOLID_TRIGGER)
+
+string clientstuff;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -47,6 +47,31 @@
 
 ============================================*/
 
+.string aiment_classname;
+.float aiment_deadflag;
+void SetMovetypeFollow(entity ent, entity e)
+{
+	ent.movetype = MOVETYPE_FOLLOW; // make the hole follow
+	ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid
+	ent.aiment = e; // make the hole follow bmodel
+	ent.punchangle = e.angles; // the original angles of bmodel
+	ent.view_ofs = ent.origin - e.origin; // relative origin
+	ent.v_angle = ent.angles - e.angles; // relative angles
+	ent.aiment_classname = strzone(e.classname);
+	ent.aiment_deadflag = e.deadflag;
+}
+float LostMovetypeFollow(entity ent)
+{
+	if(ent.aiment)
+	{
+		if(ent.aiment.classname != ent.aiment_classname)
+			return 1;
+		if(ent.aiment.deadflag != ent.aiment_deadflag)
+			return 1;
+	}
+	return 0;
+}
+
 .float rope_length;
 .float button6_pressed_before;
 
@@ -67,12 +92,17 @@
 void GrapplingHookThink()
 {
 	float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
-	vector dir, org, end;
+	vector dir, org, end, v0, dv;
 	if(self.owner.health <= 0 || self.owner.hook != self)	// how did that happen?
 	{														// well, better fix it anyway
 		remove(self);
 		return;
 	}
+	if(LostMovetypeFollow(self))
+	{
+		RemoveGrapplingHook(self.owner);
+		return;
+	}
 
 	self.nextthink = time;
 
@@ -112,6 +142,7 @@
 		if(cvar("g_grappling_hook_tarzan"))
 		{
 			newlength = self.rope_length;
+			v0 = self.owner.velocity;
 
 			// first pull the rope...
 			newlength = max(newlength - pullspeed * frametime, minlength);
@@ -130,6 +161,19 @@
 			spd = bound(0, (dist - self.rope_length) / ropestretch, 1);
 			self.owner.velocity = self.owner.velocity * (1 - frametime * ropeairfriction);
 			self.owner.velocity = self.owner.velocity + frametime * dir * spd * rubberforce;
+
+			dv = ((self.owner.velocity - v0) * dir) * dir;
+			if(cvar("g_grappling_hook_tarzan") >= 2)
+			{
+				if(self.aiment.movetype == MOVETYPE_WALK || self.aiment.movetype == MOVETYPE_TOSS)
+				{
+					self.owner.velocity = self.owner.velocity - dv * 0.5;
+					self.aiment.velocity = self.aiment.velocity - dv * 0.5;
+					self.aiment.flags = self.aiment.flags - (self.aiment.flags & FL_ONGROUND);
+					self.aiment.pusher = self.owner;
+					self.aiment.pushltime = time + cvar("g_maxpushtime");
+				}
+			}
 		}
 		else
 		{
@@ -151,7 +195,7 @@
 	}
 
 	makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
-	te_beam(self, self.origin + v_forward * (-9), org);
+	te_beam(self.owner, self.origin + v_forward * (-9), org);
 }
 
 void GrapplingHookTouch (void)
@@ -195,6 +239,10 @@
 	self.movetype = MOVETYPE_NONE;
 	self.rope_length = -1;
 
+	if(other)
+		if(other.movetype != MOVETYPE_NONE)
+			SetMovetypeFollow(self, other);
+
 	//self.owner.disableclientprediction = TRUE;
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_subs.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -344,6 +344,16 @@
 	return a;
 }
 
+void SetBrushEntityModel()
+{
+	if(self.model != "")
+	{
+		precache_model(self.model);
+		setmodel(self, self.model); // no precision needed
+	}
+	setorigin(self, self.origin);
+	setsize(self, self.mins, self.maxs);
+}
 
 /*
 ================
@@ -379,14 +389,7 @@
 	if (self.angles != '0 0 0')
 		SetMovedir ();
 	self.solid = SOLID_TRIGGER;
-	if(self.model != "")
-		setmodel (self, self.model);	// set size and link into world, no precision needed
-	else
-	{
-		// force relinking
-		setorigin(self, self.origin);
-		setsize (self, self.mins, self.maxs);
-	}
+	SetBrushEntityModel();
 	self.movetype = MOVETYPE_NONE;
 	self.modelindex = 0;
 	self.model = "";
@@ -400,15 +403,17 @@
 	if (self.angles != '0 0 0')
 		SetMovedir ();
 	self.solid = SOLID_BSP;
-	if(self.model != "")
-		setmodel (self, self.model);	// set size and link into world, no precision needed
-	else
-	{
-		// force relinking
-		setorigin(self, self.origin);
-		setsize (self, self.mins, self.maxs);
-	}
+	SetBrushEntityModel();
 	self.movetype = MOVETYPE_PUSH;
 //	self.modelindex = 0;
 	self.model = "";
 };
+
+void InitMovingBrushTrigger()
+{
+// trigger angles are used for one-way touches.  An angle of 0 is assumed
+// to mean no restrictions, so use a yaw of 360 instead.
+	self.solid = SOLID_BSP;
+	SetBrushEntityModel();
+	self.movetype = MOVETYPE_PUSH;
+};

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -187,6 +187,8 @@
 			return;		// not facing the right way
 	}
 
+	EXACTTRIGGER_TOUCH;
+
 	self.enemy = other;
 	multi_trigger ();
 };
@@ -238,7 +240,7 @@
 		self.wait = 0.2;
 	self.use = multi_use;
 
-	InitTrigger ();
+	EXACTTRIGGER_INIT;
 
 	if (self.health)
 	{
@@ -355,17 +357,25 @@
 .float triggerhurttime;
 void trigger_hurt_touch()
 {
+	// only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
 	if (!other.owner)
 	{
 		if (other.items & IT_KEY1 || other.items & IT_KEY2)	// reset flag
+		{
+			EXACTTRIGGER_TOUCH;
 			other.pain_finished = min(other.pain_finished, time + 2);
+		}
 		else if (other.classname == "rune")			// reset runes
+		{
+			EXACTTRIGGER_TOUCH;
 			other.nextthink = min(other.nextthink, time + 1);
+		}
 	}
 
 	if (other.takedamage)
 	if (other.triggerhurttime < time)
 	{
+		EXACTTRIGGER_TOUCH;
 		other.triggerhurttime = time + 1;
 		Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
 	}
@@ -383,7 +393,7 @@
 entity trigger_hurt_first;
 void spawnfunc_trigger_hurt()
 {
-	InitTrigger ();
+	EXACTTRIGGER_INIT;
 	self.touch = trigger_hurt_touch;
 	if (!self.dmg)
 		self.dmg = 1000;
@@ -544,10 +554,7 @@
 	self.angles = '0 0 0';
 	self.movetype = MOVETYPE_NONE;
 	self.solid = SOLID_NOT;
-	if(self.model != "")
-		setmodel(self, self.model); // no precision needed
-	setorigin(self, self.origin);
-	setsize(self, self.mins, self.maxs);
+	SetBrushEntityModel();
 	self.model = "";
 	if (!self.cnt)
 		self.cnt = 12;
@@ -599,10 +606,7 @@
 	self.angles = '0 0 0';
 	self.movetype = MOVETYPE_NONE;
 	self.solid = SOLID_NOT;
-	if(self.model != "")
-		setmodel(self, self.model); // no precision needed
-	setorigin(self, self.origin);
-	setsize(self, self.mins, self.maxs);
+	SetBrushEntityModel();
 	self.model = "";
 	if (!self.cnt)
 		self.cnt = 12;
@@ -719,6 +723,8 @@
 	if (other.deadflag && other.classname == "player")
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
     targ = find(world, targetname, self.target);
     if(!targ)
     {
@@ -764,6 +770,8 @@
 	if (other.deadflag && other.classname == "player")
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
     pushdeltatime = time - other.lastpushtime;
     if (pushdeltatime > 0.15) pushdeltatime = 0;
     other.lastpushtime = time;
@@ -798,6 +806,8 @@
 	if (other.deadflag && other.classname == "player")
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
     pushdeltatime = time - other.lastpushtime;
     if (pushdeltatime > 0.15) pushdeltatime = 0;
     other.lastpushtime = time;
@@ -837,7 +847,7 @@
 
 void spawnfunc_trigger_impulse()
 {
-    InitTrigger ();
+	EXACTTRIGGER_INIT;
     if(self.radius)
     {
         if(!self.strength) self.strength = 2000;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -189,6 +189,8 @@
 
 #ifdef MAPINFO
 	MapInfo_LoadMapSettings(mapname);
+	clientstuff = strzone(MapInfo_Map_clientstuff);
+	MapInfo_ClearTemps();
 #endif
 
 	if(sv_cheats)
@@ -334,27 +336,39 @@
 		cvar_set("timelimit", "0");
 	}
 
-	fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ);
-	if(fd != -1)
+	if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
 	{
-		while((s = fgets(fd)))
+		fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ);
+		if(fd != -1)
 		{
-			l = tokenize(s);
-			if(l < 2)
-				continue;
-			if(argv(0) != "fog")
-				continue;
-			s = "";
-			while(l >= 2)
+			while((s = fgets(fd)))
 			{
-				--l;
-				s = strcat(argv(l), " ", s);
+				l = tokenize(s);
+				if(l < 2)
+					continue;
+				if(argv(0) == "cd")
+				{
+					print("Found ^1DEPRECATED^7 cd loop command in .cfg file; put this line in mapinfo instead:\n");
+					print("  cdtrack ", argv(2), "\n");
+				}
+				else if(argv(0) == "fog")
+				{
+					print("Found ^1DEPRECATED^7 fog command in .cfg file; put this line in worldspawn in the .map/.bsp/.ent file instead:\n");
+					print("  \"fog\" \"", s, "\"\n");
+				}
+				else if(argv(0) == "set")
+				{
+					print("Found ^1DEPRECATED^7 set command in .cfg file; put this line in mapinfo instead:\n");
+					print("  clientsettemp_for_type all ", argv(1), " ", argv(2), "\n");
+				}
+				else if(argv(0) != "//")
+				{
+					print("Found ^1DEPRECATED^7 set command in .cfg file; put this line in mapinfo instead:\n");
+					print("  clientsettemp_for_type all ", argv(0), " ", argv(1), "\n");
+				}
 			}
-			s = substring(s, 0, strlen(s) - 1);
-			print("Found ^1DEPRECATED^7 fog command in .cfg file: ", s, "\n");
-			world.fog = strzone(s);
+			fclose(fd);
 		}
-		fclose(fd);
 	}
 
 	next_pingtime = time + 5;
@@ -1477,6 +1491,14 @@
 	// TODO make everything use THIS winning condition (except LMS)
 	WinningConditionHelper();
 	
+	if(teams_matter)
+	{
+		team1_score = TeamScore_GetCompareValue(COLOR_TEAM1);
+		team2_score = TeamScore_GetCompareValue(COLOR_TEAM2);
+		team3_score = TeamScore_GetCompareValue(COLOR_TEAM3);
+		team4_score = TeamScore_GetCompareValue(COLOR_TEAM4);
+	}
+	
 	ClearWinners();
 	if(WinningConditionHelper_winner)
 		WinningConditionHelper_winner.winning = 1;
@@ -1491,7 +1513,7 @@
 		WinningConditionHelper_topscore = -WinningConditionHelper_topscore;
 		limit = -limit;
 	}
-	
+
 	return GetWinningCode(limit && WinningConditionHelper_topscore && (WinningConditionHelper_topscore >= limit), WinningConditionHelper_equality);
 }
 
@@ -1882,12 +1904,7 @@
 	mapvote_screenshot_dir = strzone(mapvote_screenshot_dir);
 
 	if(!cvar("g_maplist_textonly"))
-	{
-		// FIXME reenable this when it works in the engine
-		// MapVote_SendData(MSG_ALL);
-		FOR_EACH_REALCLIENT(msg_entity)
-			MapVote_SendData(MSG_ONE);
-	}
+		MapVote_SendData(MSG_ALL);
 }
 
 void MapVote_SendPicture(float id)
@@ -2178,10 +2195,7 @@
 	if(!cvar("g_maplist_textonly"))
 	if(mapvote_dirty) // 1 if "keeptwo" or "impulse" happened before
 	{
-		// FIXME reenable this when it works in the engine
-		// MapVote_UpdateData(MSG_BROADCAST);
-		FOR_EACH_REALCLIENT(msg_entity)
-			MapVote_UpdateData(MSG_ONE);
+		MapVote_UpdateData(MSG_BROADCAST);
 		mapvote_dirty = FALSE;
 	}
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -202,13 +202,15 @@
 			print("Client not found\n");
 		return;
 	}
-	if (argv(0) == "sdp")
+	if (argv(0) == "teamstatus")
 	{
-		Score_DebugPrint();
+		Score_NicePrint(world);
+		return;
 	}
 	if (argv(0) == "allready")
 	{
 		ReadyRestart();
+		return;
 	}
 
 	print("Invalid command. For a list of supported commands, try sv_cmd help.\n");

Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -110,6 +110,8 @@
 }
 
 string STR_PLAYER = "player";
+string STR_SPECTATOR = "spectator";
+string STR_OBSERVER = "observer";
 
 #if 0
 #define FOR_EACH_CLIENT(v) for(v = world; (v = findflags(v, flags, FL_CLIENT)) != world; )
@@ -1137,3 +1139,52 @@
 		ambientsound ('0 0 0', self.noise, VOL_BASE, ATTN_NONE);
 	}
 }
+
+// sorry, but using \ in macros breaks line numbers
+#define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
+#define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
+#define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
+
+vector ExactTriggerHit_mins;
+vector ExactTriggerHit_maxs;
+float ExactTriggerHit_Recurse()
+{
+	float s;
+	entity se;
+	float f;
+
+	tracebox('0 0 0', ExactTriggerHit_mins, ExactTriggerHit_maxs, '0 0 0', MOVE_NORMAL, other);
+	if not(trace_ent)
+		return 0;
+	if(trace_ent == self)
+		return 1;
+
+	se = trace_ent;
+	s = se.solid;
+	se.solid = SOLID_NOT;
+	f = ExactTriggerHit_Recurse();
+	se.solid = s;
+
+	return f;
+}
+
+float ExactTriggerHit()
+{
+	float f, s;
+
+	if not(self.modelindex)
+		return 1;
+
+	s = self.solid;
+	self.solid = SOLID_BSP;
+	ExactTriggerHit_mins = other.absmin + '1 1 1';
+	ExactTriggerHit_maxs = other.absmax - '1 1 1';
+	f = ExactTriggerHit_Recurse();
+	self.solid = s;
+
+	return f;
+}
+
+// WARNING: this kills the trace globals
+#define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return
+#define EXACTTRIGGER_INIT  InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER

Modified: branches/nexuiz-2.0/data/qcsrc/server/race.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/race.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/race.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -32,15 +32,12 @@
 		return f - 1;
 }
 
-void race_SendNextCheckpoint(entity e)
+void race_SendNextCheckpoint(entity e, float spec)
 {
 	float recordtime;
 	string recordholder;
 	float cp;
 
-	if(clienttype(e) != CLIENTTYPE_REAL)
-		return;
-
 	if(!e.race_laptime)
 		return;
 
@@ -54,15 +51,31 @@
 	if(recordholder == e.netname)
 		recordholder = "";
 
-	msg_entity = e;
-	WriteByte(MSG_ONE, SVC_TEMPENTITY);
-	WriteByte(MSG_ONE, TE_CSQC_RACE);
-	WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT_QUALIFYING);
-	WriteByte(MSG_ONE, cp); // checkpoint the player will be at next
-	WriteShort(MSG_ONE, recordtime);
-	WriteString(MSG_ONE, recordholder);
+	if(!spec)
+		msg_entity = e;
+	WRITESPECTATABLE_MSG_ONE({
+		WriteByte(MSG_ONE, SVC_TEMPENTITY);
+		WriteByte(MSG_ONE, TE_CSQC_RACE);
+		if(spec)
+		{
+			WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING);
+			WriteCoord(MSG_ONE, e.race_laptime);
+		}
+		else
+			WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_NEXT_QUALIFYING);
+		WriteByte(MSG_ONE, cp); // checkpoint the player will be at next
+		WriteShort(MSG_ONE, recordtime);
+		WriteString(MSG_ONE, recordholder);
+	});
 }
 
+void race_InitSpectator()
+{
+	if(g_race_qualifying)
+		if(msg_entity.enemy.race_laptime)
+			race_SendNextCheckpoint(msg_entity.enemy, 1);
+}
+
 void race_SendTime(entity e, float cp, float t, float tvalid)
 {
 	float snew, l;
@@ -95,11 +108,13 @@
 				e.race_completed = 1;
 				MAKE_INDEPENDENT_PLAYER(e);
 				bprint(e.netname, "^7 has finished the race.\n");
+				// TODO support spectators with this (e.g. set a flag for forced sbar)
 				if(clienttype(e) == CLIENTTYPE_REAL)
 				{
 					msg_entity = e;
 					WriteByte(MSG_ONE, SVC_TEMPENTITY);
 					WriteByte(MSG_ONE, TE_CSQC_FORCESCOREBOARD);
+					WriteByte(MSG_ONE, 1);
 					// he can still move, but will see the scoreboard now
 				}
 			}
@@ -161,7 +176,7 @@
 					entity p;
 					FOR_EACH_REALPLAYER(p)
 						if(p.race_checkpoint == cp)
-							race_SendNextCheckpoint(p);
+							race_SendNextCheckpoint(p, 0);
 				}
 			}
 		}
@@ -173,11 +188,10 @@
 			recordholder = "";
 		}
 
-		if(clienttype(e) == CLIENTTYPE_REAL)
+		msg_entity = e;
+		if(g_race_qualifying)
 		{
-			msg_entity = e;
-			if(g_race_qualifying)
-			{
+			WRITESPECTATABLE_MSG_ONE({
 				WriteByte(MSG_ONE, SVC_TEMPENTITY);
 				WriteByte(MSG_ONE, TE_CSQC_RACE);
 				WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_QUALIFYING);
@@ -185,7 +199,7 @@
 				WriteShort(MSG_ONE, t); // time to that intermediate
 				WriteShort(MSG_ONE, recordtime); // previously best time
 				WriteString(MSG_ONE, recordholder); // record holder
-			}
+			});
 		}
 	}
 	else // RACE! Not Qualifying
@@ -202,9 +216,8 @@
 		else
 			lself = lother = othtime = 0;
 
-		if(clienttype(e) == CLIENTTYPE_REAL)
-		{
-			msg_entity = e;
+		msg_entity = e;
+		WRITESPECTATABLE_MSG_ONE({
 			WriteByte(MSG_ONE, SVC_TEMPENTITY);
 			WriteByte(MSG_ONE, TE_CSQC_RACE);
 			WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_RACE);
@@ -221,16 +234,14 @@
 				WriteByte(MSG_ONE, lself - lother);
 				WriteString(MSG_ONE, oth.netname); // record holder
 			}
-		}
+		});
 
 		race_checkpoint_lastplayers[cp] = e;
 		race_checkpoint_lasttimes[cp] = time;
 		race_checkpoint_lastlaps[cp] = lself;
 
-		if(clienttype(oth) == CLIENTTYPE_REAL)
-		if(oth.flags & FL_CLIENT)
-		{
-			msg_entity = oth;
+		msg_entity = oth;
+		WRITESPECTATABLE_MSG_ONE({
 			WriteByte(MSG_ONE, SVC_TEMPENTITY);
 			WriteByte(MSG_ONE, TE_CSQC_RACE);
 			WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT);
@@ -247,7 +258,7 @@
 				WriteByte(MSG_ONE, lother - lself);
 				WriteString(MSG_ONE, e.netname); // record holder
 			}
-		}
+		});
 	}
 }
 
@@ -256,20 +267,45 @@
 	e.race_checkpoint = -1;
 	e.race_laptime = 0;
 
-	if(clienttype(e) != CLIENTTYPE_REAL)
-		return;
-
 	msg_entity = e;
-	WriteByte(MSG_ONE, SVC_TEMPENTITY);
-	WriteByte(MSG_ONE, TE_CSQC_RACE);
-	WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_CLEAR); // next
+	WRITESPECTATABLE_MSG_ONE({
+		WriteByte(MSG_ONE, SVC_TEMPENTITY);
+		WriteByte(MSG_ONE, TE_CSQC_RACE);
+		WriteByte(MSG_ONE, RACE_NET_CHECKPOINT_CLEAR); // next
+	});
 }
 
+void dumpsurface(entity e)
+{
+	float n, si, ni;
+	vector norm, vec;
+	print("Surfaces of ", etos(e), ":\n");
+
+	print("TEST = ", ftos(getsurfacenearpoint(e, '0 0 0')), "\n");
+
+	for(si = 0; ; ++si)
+	{
+		n = getsurfacenumpoints(e, si);
+		if(n <= 0)
+			break;
+		print("  Surface ", ftos(si), ":\n");
+		norm = getsurfacenormal(e, si);
+		print("    Normal = ", vtos(norm), "\n");
+		for(ni = 0; ni < n; ++ni)
+		{
+			vec = getsurfacepoint(e, si, ni);
+			print("    Point ", ftos(ni), " = ", vtos(vec), " (", ftos(norm * vec), ")\n");
+		}
+	}
+}
+
 void checkpoint_touch()
 {
 	if(other.classname != "player")
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
 	if(other.race_checkpoint == -1 || other.race_checkpoint == self.race_checkpoint)
 	{
 		other.race_checkpoint = race_NextCheckpoint(self.race_checkpoint);
@@ -280,7 +316,7 @@
 			other.race_laptime = time;
 
 		if(g_race_qualifying)
-			race_SendNextCheckpoint(other);
+			race_SendNextCheckpoint(other, 0);
 	}
 	else if(other.race_checkpoint == race_NextCheckpoint(self.race_checkpoint))
 	{
@@ -317,7 +353,9 @@
 		remove(self);
 		return;
 	}
-	InitTrigger();
+
+	EXACTTRIGGER_INIT;
+
 	self.use = checkpoint_use;
 	if not(self.spawnflags & 1)
 		self.touch = checkpoint_touch;
@@ -378,11 +416,13 @@
 		self.race_completed = 1;
 		MAKE_INDEPENDENT_PLAYER(self);
 		bprint(self.netname, "^7 has abandoned the race.\n");
+		// TODO support spectators with this (e.g. set a flag for forced sbar)
 		if(clienttype(self) == CLIENTTYPE_REAL)
 		{
 			msg_entity = self;
 			WriteByte(MSG_ONE, SVC_TEMPENTITY);
 			WriteByte(MSG_ONE, TE_CSQC_FORCESCOREBOARD);
+			WriteByte(MSG_ONE, 1);
 			// he can still move, but will see the scoreboard now
 		}
 	}

Modified: branches/nexuiz-2.0/data/qcsrc/server/race.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/race.qh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/race.qh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,3 +1,4 @@
+void race_InitSpectator();
 void race_PreSpawnObserver();
 void race_PreSpawn();
 void race_PostSpawn(entity spot);

Modified: branches/nexuiz-2.0/data/qcsrc/server/scores.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -57,14 +57,26 @@
  * teamscore entities
  */
 
-float TeamScore_SendEntity(entity to)
+float TeamScore_SendEntity(entity to, float sendflags)
 {
 	float i;
 
 	WriteByte(MSG_ENTITY, ENT_CLIENT_TEAMSCORES);
 	WriteByte(MSG_ENTITY, self.team - 1);
+#if MAX_TEAMSCORE <= 3
 	for(i = 0; i < MAX_TEAMSCORE; ++i)
 		WriteShort(MSG_ENTITY, self.teamscores[i]);
+#else
+#if MAX_TEAMSCORE <= 8
+	WriteByte(MSG_ENTITY, sendflags);
+#else
+	WriteShort(MSG_ENTITY, sendflags);
+#endif
+	float p;
+	for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
+		if(sendflags & p)
+			WriteShort(MSG_ENTITY, self.teamscores[i]);
+#endif
 
 	return TRUE;
 }
@@ -76,7 +88,7 @@
 	ts.classname = "csqc_score_team";
 	ts.SendEntity = TeamScore_SendEntity;
 	ts.netname = name; // not used yet, FIXME
-	ts.Version = 1; // immediately send, so csqc knows about the team
+	//ts.SendFlags = SENDFLAGS_CREATE; // immediately send, so csqc knows about the team
 	ts.team = t;
 	Net_LinkEntity(ts);
 	teamscorekeepers[t - 1] = ts;
@@ -93,7 +105,8 @@
 	if(!s)
 		error("Adding score to unknown team!");
 	if(score)
-		s.Version += 1;
+		if(teamscores_label[scorefield] != "")
+			s.SendFlags |= pow(2, scorefield);
 	return (s.(teamscores[scorefield]) += score);
 }
 
@@ -174,22 +187,33 @@
 		TeamScore_Spawn(COLOR_TEAM3, "Yellow");
 	if(teams >= 4)
 		TeamScore_Spawn(COLOR_TEAM4, "Pink");
-	FOR_EACH_REALCLIENT(msg_entity) // cannot use MSG_ALL here, as that may come too early on level changes (that SUCKS)
-		ScoreInfo_Write(MSG_ONE);
+	ScoreInfo_Write(MSG_ALL);
 }
 
 /*
  * per-player score entities
  */
 
-float PlayerScore_SendEntity()
+float PlayerScore_SendEntity(entity to, float sendflags)
 {
 	float i;
 
 	WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES);
 	WriteByte(MSG_ENTITY, num_for_edict(self.owner));
+#if MAX_SCORE <= 3
 	for(i = 0; i < MAX_SCORE; ++i)
 		WriteShort(MSG_ENTITY, self.scores[i]);
+#else
+#if MAX_SCORE <= 8
+	WriteByte(MSG_ENTITY, sendflags);
+#else
+	WriteShort(MSG_ENTITY, sendflags);
+#endif
+	float p;
+	for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
+		if(sendflags & p)
+			WriteShort(MSG_ENTITY, self.scores[i]);
+#endif
 
 	return TRUE;
 }
@@ -203,36 +227,47 @@
 		return;
 	if(g_lms) return;
 	if(g_arena) return;
-	if(g_race) return;
-	//print("clear clear clear... HAHA\n");
+	if(g_race && !g_race_qualifying) return;
 
 	sk = player.scorekeeper;
 	for(i = 0; i < MAX_SCORE; ++i)
+	{
+		if(sk.(scores[i]) != 0)
+			if(scores_label[i] != "")
+				sk.SendFlags |= pow(2, i);
 		sk.(scores[i]) = 0;
-	sk.Version += 1;
+	}
 }
 
 void Score_ClearAll()
 {
 	entity p, sk;
-	float i;
+	float i, t;
 	FOR_EACH_CLIENTSLOT(p)
 	{
 		sk = p.scorekeeper;
 		if(!sk)
 			continue;
 		for(i = 0; i < MAX_SCORE; ++i)
+		{
+			if(sk.(scores[i]) != 0)
+				if(scores_label[i] != "")
+					sk.SendFlags |= pow(2, i);
 			sk.(scores[i]) = 0;
-		sk.Version += 1;
+		}
 	}
-	for(i = 0; i < 16; ++i)
+	for(t = 0; t < 16; ++t)
 	{
-		sk = teamscorekeepers[i];
+		sk = teamscorekeepers[t];
 		if(!sk)
 			continue;
 		for(i = 0; i < MAX_SCORE; ++i)
+		{
+			if(sk.(teamscores[i]) != 0)
+				if(teamscores_label[i] != "")
+					sk.SendFlags |= pow(2, i);
 			sk.(teamscores[i]) = 0;
-		sk.Version += 1;
+		}
 	}
 }
 
@@ -243,7 +278,6 @@
 		error("player already has a scorekeeper");
 	sk = spawn();
 	sk.owner = player;
-	sk.Version = 1;
 	sk.SendEntity = PlayerScore_SendEntity;
 	Net_LinkEntity(sk);
 	player.scorekeeper = sk;
@@ -265,7 +299,8 @@
 	if(!s)
 		error("Adding score to unknown player!");
 	if(score)
-		s.Version += 1;
+		if(scores_label[scorefield] != "")
+			s.SendFlags |= pow(2, scorefield);
 	return (s.(scores[scorefield]) += score);
 }
 
@@ -401,41 +436,6 @@
 	}
 }
 
-void Score_DebugPrint()
-{
-	entity p, sk;
-	float i, t;
-
-	print("netname");
-	for(i = 0; i < MAX_SCORE; ++i)
-		print(":", scores_label[i]);
-	print("\n");
-	FOR_EACH_PLAYER(p)
-	{
-		sk = p.scorekeeper;
-		print(p.netname);
-		for(i = 0; i < MAX_SCORE; ++i)
-			print(":", ftos(sk.(scores[i])));
-		print("\n");
-	}
-
-	print("teamname");
-	for(i = 0; i < MAX_TEAMSCORE; ++i)
-		print(":", teamscores_label[i]);
-	print("\n");
-	for(t = 0; t < 16; ++t)
-	{
-		sk = teamscorekeepers[t];
-		if(sk)
-		{
-			print(ftos(t));
-			for(i = 0; i < MAX_TEAMSCORE; ++i)
-				print(":", ftos(sk.(teamscores[i])));
-			print("\n");
-		}
-	}
-}
-
 string GetScoreLogLabel(string label, float fl)
 {
 	if(fl & SFL_LOWER_IS_BETTER)
@@ -565,17 +565,21 @@
 		if(p1.team != p2.team)
 		{
 			entity t1, t2;
-			t1 = teamscorekeepers[p1.team];
-			t2 = teamscorekeepers[p2.team];
-			return TeamScore_Compare(t1, t2);
+			float r;
+			t1 = teamscorekeepers[p1.team - 1];
+			t2 = teamscorekeepers[p2.team - 1];
+			r = TeamScore_Compare(t1, t2);
+			if(r == 0) // ensure a deterministic order
+				r = p1.team - p2.team;
+			return r;
 		}
 	
 	return PlayerScore_Compare(p1.scorekeeper, p2.scorekeeper);
 }
 
-float PlayerScore_Sort(.float field)
+entity PlayerScore_Sort(.float field)
 {
-	entity p, plist, pprev, pbest, pbestprev;
+	entity p, plist, pprev, pbest, pbestprev, pfirst, plast;
 	float i;
 	plist = world;
 
@@ -588,6 +592,8 @@
 		plist = p;
 	}
 	// Now plist points to the whole list.
+	
+	pfirst = plast = world;
 
 	i = 0;
 	while(plist)
@@ -611,7 +617,165 @@
 		pbest.chain = world;
 
 		pbest.field = ++i;
+		if not(pfirst)
+			pfirst = pbest;
+		if(plast)
+			plast.chain = pbest;
+		plast = pbest;
 	}
 
-	return i;
+	return pfirst;
 }
+
+float TeamScore_GetCompareValue(float t)
+{
+	float s;
+	entity sk;
+
+	if(t <= 0 || t >= 16)
+		error("Reading score of invalid team!");
+
+	sk = teamscorekeepers[t - 1];
+	if not(sk)
+		return -999999999;
+	s = sk.teamscores_primary;
+	if(teamscores_flags_primary & SFL_ZERO_IS_WORST)
+		if(!s)
+			return -999999999;
+	if(teamscores_flags_primary & SFL_LOWER_IS_BETTER)
+		s = -s;
+	return s;
+}
+
+#define NAMEWIDTH 22
+#define SCORESWIDTH 58
+// TODO put this somewhere in common?
+string Score_NicePrint_ItemColor(float vflags)
+{
+	if(vflags & SFL_SORT_PRIO_PRIMARY)
+		return "^3";
+	else if(vflags & SFL_SORT_PRIO_SECONDARY)
+		return "^5";
+	else
+		return "^7";
+}
+
+void Score_NicePrint_Team(entity to, float t, float w)
+{
+	string s, s2;
+	float i;
+	entity sk;
+	float fl, sc;
+	s = "";
+
+	sk = teamscorekeepers[t - 1];
+	if(sk)
+	{
+		s = strcat(s, ColoredTeamName(t));
+		for(i = 0; i < MAX_TEAMSCORE; ++i)
+			if(teamscores_label[i] != "")
+			{
+				fl = teamscores_flags[i];
+				sc = sk.(teamscores[i]);
+				s = strcat(s, " ", Score_NicePrint_ItemColor(fl), ScoreString(fl, sc));
+			}
+	}
+	else
+		s = "Scores:";
+
+	s = strcat(s, strpad(max(0, NAMEWIDTH - strlennocol(s)), ""));
+	
+	for(i = 0; i < MAX_SCORE; ++i)
+		if(scores_label[i] != "")
+		{
+			fl = scores_flags[i];
+			s2 = scores_label[i];
+			s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, substring(s2, 0, w)));
+		}
+
+	print_to(to, s);
+}
+
+void Score_NicePrint_Player(entity to, entity p, float w)
+{
+	string s;
+	float i;
+	entity sk;
+	float fl, sc;
+	s = "  ";
+
+	sk = p.scorekeeper;
+
+	s = strcat(s, p.netname);
+	for(;;)
+	{
+		i = strlennocol(s) - NAMEWIDTH;
+		if(i > 0)
+			s = substring(s, 0, strlen(s) - i);
+		else
+		{
+			s = strcat(s, strpad(i, ""));
+			break;
+		}
+	}
+	
+	for(i = 0; i < MAX_SCORE; ++i)
+		if(scores_label[i] != "")
+		{
+			fl = scores_flags[i];
+			sc = sk.(scores[i]);
+			s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, ScoreString(fl, sc)));
+		}
+
+	print_to(to, s);
+}
+
+void Score_NicePrint_Spectators(entity to)
+{
+	print_to(to, "Spectators:");
+}
+
+void Score_NicePrint_Spectator(entity to, entity p)
+{
+	print_to(to, strcat("  ", p.netname));
+}
+
+.float score_dummyfield;
+void Score_NicePrint(entity to)
+{
+	entity p;
+	float t, i;
+	float w;
+
+	t = 0;
+	for(i = 0; i < MAX_SCORE; ++i)
+		if(scores_label[i] != "")
+			++t;
+	w = bound(6, floor(SCORESWIDTH / t - 1), 9);
+
+	p = PlayerScore_Sort(score_dummyfield);
+	t = -1;
+
+	if(!teamscores_entities_count)
+		Score_NicePrint_Team(to, t, w);
+	while(p)
+	{
+		if(teamscores_entities_count)
+			if(t != p.team)
+				Score_NicePrint_Team(to, p.team, w);
+		Score_NicePrint_Player(to, p, w);
+		t = p.team;
+		p = p.chain;
+	}
+	
+	t = 0;
+	FOR_EACH_CLIENT(p)
+	if(p.classname != "player")
+	{
+		if not(t)
+			Score_NicePrint_Spectators(to);
+		Score_NicePrint_Spectator(to, p);
+		t = 1;
+	}
+}
+

Modified: branches/nexuiz-2.0/data/qcsrc/server/scores.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores.qh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores.qh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -41,6 +41,11 @@
 float TeamScore_AddToTeam(float t, float scorefield, float score);
 
 /**
+ * Returns a value indicating the team score (and higher is better).
+ */
+float TeamScore_GetCompareValue(float t);
+
+/**
  * Adds a score to both the player and the team. Returns the team score if
  * possible, otherwise the player score.
  */
@@ -79,9 +84,9 @@
 void Score_ClearAll();
 
 /**
- * Prints the scores (ugly!) to the console.
+ * Prints the scores to the console of a player.
  */
-void Score_DebugPrint();
+void Score_NicePrint(entity to);
 
 /**
  * Sets the following results for the current scores entities.
@@ -112,5 +117,6 @@
 /**
  * Sorts the players and stores their place in the given field, starting with
  * 1. Non-players get 0 written into that field.
+ * Returns the beginning of a sorted chain of the non-spectators.
  */
-float PlayerScore_Sort(.float field);
+entity PlayerScore_Sort(.float field);

Modified: branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -6,12 +6,25 @@
 float ScoreRules_teams;
 void ScoreRules_basics(float teams, float sprio)
 {
+	float i;
+	for(i = 0; i < MAX_SCORE; ++i)
+		ScoreInfo_SetLabel_PlayerScore(i, "", 0);
+	for(i = 0; i < MAX_TEAMSCORE; ++i)
+		ScoreInfo_SetLabel_TeamScore(i, "", 0);
+
 	ScoreRules_teams = teams;
+
 	if(sprio)
 		ScoreInfo_SetLabel_TeamScore  (ST_SCORE,        "score",     sprio);
-	ScoreInfo_SetLabel_PlayerScore(SP_KILLS,        "kills",     0);
+
+	if not(independent_players)
+		ScoreInfo_SetLabel_PlayerScore(SP_KILLS,        "kills",     0);
+
 	ScoreInfo_SetLabel_PlayerScore(SP_DEATHS,       "deaths",    SFL_LOWER_IS_BETTER);
-	ScoreInfo_SetLabel_PlayerScore(SP_SUICIDES,     "suicides",  SFL_LOWER_IS_BETTER);
+
+	if not(independent_players)
+		ScoreInfo_SetLabel_PlayerScore(SP_SUICIDES,     "suicides",  SFL_LOWER_IS_BETTER);
+
 	if(sprio)
 		ScoreInfo_SetLabel_PlayerScore(SP_SCORE,        "score",     sprio);
 }
@@ -136,8 +149,6 @@
 	}
 	else if(g_race_qualifying)
 	{
-		ScoreInfo_SetLabel_TeamScore(  ST_RACE_LAPS,    "laps",      0);
-		ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS,    "laps",      0);
 		ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest",   SFL_SORT_PRIO_PRIMARY | SFL_LOWER_IS_BETTER | SFL_TIME);
 	}
 	else

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_halflife.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_halflife.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_halflife.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -39,20 +39,22 @@
 {
 	if (other.classname != "player")
 		return;
+
+	EXACTTRIGGER_TOUCH;
+
 	other.ladder_time = time + 0.1;
 	other.ladder_entity = self;
 };
 
 void spawnfunc_func_ladder()
 {
-	InitTrigger ();
+	EXACTTRIGGER_INIT;
 	self.touch = func_ladder_touch;
 };
 
 void spawnfunc_func_water()
 {
-	self.solid = SOLID_TRIGGER;
-	setmodel (self, self.model);	// set size and link into world, precision set by mapper
+	EXACTTRIGGER_INIT;
 	self.touch = func_ladder_touch;
 };
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_items.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_items.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -792,9 +792,7 @@
 
 void spawnfunc_misc_models (void)
 {
-	precache_model (self.model);
-	setmodel (self, self.model); // precision set by mapper
-	setsize (self, self.mins, self.maxs);
+	SetBrushEntityModel();
 }
 
 void func_wall_use (void)
@@ -813,9 +811,7 @@
 
 void spawnfunc_func_wall (void)
 {
-	precache_model (self.model);
-	setmodel (self, self.model); // precision set by mapper
-	setsize (self, self.mins, self.maxs);
+	SetBrushEntityModel();
 	self.solid = SOLID_BSP;
 	self.use = func_wall_use;
 }

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_jumppads.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_jumppads.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_jumppads.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -120,6 +120,8 @@
 	if (other.deadflag && other.classname == "player")
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
 	if(self.target)
 		self.movedir = trigger_push_calculatevelocity(other.origin, self.enemy, self.height);
 
@@ -239,11 +241,7 @@
 	if (self.angles != '0 0 0')
 		SetMovedir ();
 
-	self.solid = SOLID_TRIGGER;
-	setmodel (self, self.model); // no precision needed
-	self.movetype = MOVETYPE_NONE;
-	self.modelindex = 0;
-	self.model = "";
+	EXACTTRIGGER_INIT;
 
 	self.touch = trigger_push_touch;
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -191,10 +191,7 @@
 	self.angles = '0 0 0';
 
 	self.classname = "plat";
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
-	setorigin (self, self.origin);
-	setmodel (self, self.model); // precision set below
+	InitMovingBrushTrigger();
 	self.effects |= EF_LOWPRECISION;
 	setsize (self, self.mins , self.maxs);
 
@@ -308,16 +305,12 @@
 		precache_sound ("plats/train1.wav");
 	}
 
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
 	self.blocked = train_blocked;
 	self.use = train_use;
 	self.classname = "train";
 
-	setmodel (self, self.model); // precision set below
+	InitMovingBrushTrigger();
 	self.effects |= EF_LOWPRECISION;
-	setsize (self, self.mins , self.maxs);
-	setorigin (self, self.origin);
 	self.nextthink = self.ltime + 0.1;
 	self.think = func_train_find;
 };
@@ -368,13 +361,8 @@
 	if (!self.speed)
 		self.speed = 100;
 
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
-
-	setmodel(self, self.model); // precision set below
+	InitMovingBrushTrigger();
 	self.effects |= EF_LOWPRECISION;
-	setsize(self, self.mins, self.maxs);
-	setorigin(self, self.origin);
 
 	// wait for targets to spawn
 	self.nextthink = self.ltime + 0.1;
@@ -436,14 +424,9 @@
 
     self.dmgtime2 = time;
 
+	InitMovingBrushTrigger();
+	// no EF_LOWPRECISION here, as rounding angles is bad
 
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
-
-	setmodel(self, self.model); // no lowprecision here! evil!
-	setsize(self, self.mins, self.maxs);
-	setorigin(self, self.origin);
-
     self.blocked = rotating_blocked;
 
 	// wait for targets to spawn
@@ -512,13 +495,8 @@
 	else // Z
 		self.movedir = '0 0 1' * self.height;
 
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
+	InitMovingBrushTrigger();
 
-	setmodel(self, self.model); // precision set below
-	setsize(self, self.mins, self.maxs);
-	setorigin(self, self.origin);
-
 	// wait for targets to spawn
 	controller = spawn();
 	controller.classname = "func_bobbing_controller";
@@ -647,9 +625,7 @@
 {
 	SetMovedir ();
 
-	self.movetype = MOVETYPE_PUSH;
-	self.solid = SOLID_BSP;
-	setmodel (self, self.model); // precision set below
+	InitMovingBrushTrigger();
 	self.effects |= EF_LOWPRECISION;
 
 	self.blocked = button_blocked;
@@ -1087,10 +1063,7 @@
 	SetMovedir ();
 
 	self.max_health = self.health;
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
-	setorigin (self, self.origin);
-	setmodel (self, self.model); // precision set below
+	InitMovingBrushTrigger();
 	self.effects |= EF_LOWPRECISION;
 	self.classname = "door";
 
@@ -1355,12 +1328,9 @@
 	// Magic formula...
 	self.mangle = self.angles;
 	self.angles = '0 0 0';
-	self.solid = SOLID_BSP;
-	self.movetype = MOVETYPE_PUSH;
 	self.classname = "door";
-	setmodel (self, self.model); // precision set below
+	InitMovingBrushTrigger();
 	self.effects |= EF_LOWPRECISION;
-	setorigin (self, self.origin);
 
 	self.touch = secret_touch;
 	self.blocked = secret_blocked;

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_swamp.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_swamp.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_swamp.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -57,6 +57,8 @@
 	if((other.classname != "player")||(other.deadflag != DEAD_NO))
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
 	// Chech if player alredy got a swampslug.
 	if(other.in_swamp != 1) {
 		// If not attach one.
@@ -86,7 +88,7 @@
 void spawnfunc_trigger_swamp(void)
 {
 	// Init stuff
-	InitTrigger ();
+	EXACTTRIGGER_INIT;
 	self.touch = swamp_touch;	
 
 	// Setup default keys, if missing

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -8,6 +8,8 @@
 	if (!other.flags & FL_CLIENT)	// FIXME: Make missiles firable through the teleport too
 		return;
 
+	EXACTTRIGGER_TOUCH;
+
 	sound (other, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
 	pointparticles(particleeffectnum("teleport"), other.origin, '0 0 0', 1);
 
@@ -125,21 +127,8 @@
 {
 	self.angles = '0 0 0';
 
-	self.solid = SOLID_TRIGGER;
-	self.movetype = MOVETYPE_NONE;
+	EXACTTRIGGER_INIT;
 
-	if(self.model != "")
-		setmodel (self, self.model); // no precision needed
-	else
-	{
-		// force relinking
-		setorigin(self, self.origin);
-		setsize (self, self.mins, self.maxs);
-	}
-
-	self.model = "";
-	self.modelindex = 0;
-
 	self.think = teleport_findtarget;
 	self.nextthink = time + 0.2;
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-08-24 17:48:37 UTC (rev 4176)
@@ -274,6 +274,7 @@
 
 		if(cvar("g_race_teams"))
 		{
+			g_race_qualifying = 0; // not supported!
 			ActivateTeamplay();
 			teams_matter = 1;
 			race_teams = bound(2, cvar("g_race_teams"), 4);
@@ -344,7 +345,7 @@
 			cvar_set("timelimit", ftos(timelimit_override));
 	}
 
-	if(g_race_qualifying)
+	if(g_race && g_race_qualifying)
 	{
 		race_fraglimit = cvar("fraglimit");
 		cvar_set("fraglimit", "0");
@@ -407,37 +408,16 @@
 
 	if(!self.BUTTON_INFO)
 	{
-		if(self.classname == "observer")
-		{
-			if(g_lms)
-			{
-				p = PlayerScore_Add(self, SP_LMS_RANK, 0);
-				if(p >= 666)
-					return centerprint_atprio(self, CENTERPRIO_SPAM, strcat(NEWLINES, "^1Match has already begun\nwait for next round\n\n\n^7press attack to spectate other players"));
-				else if(p > 0)
-					return centerprint_atprio(self, CENTERPRIO_SPAM, strcat(NEWLINES, "^1You have no more lives left\nwait for next round\n\n\n^7press attack to spectate other players"));
-			}
-		}
-		else if(self.classname == "spectator")
-		{
-			if(g_lms)
-			{
-				p = PlayerScore_Add(self, SP_LMS_RANK, 0);
-				if(p)
-					return centerprint_atprio(self, CENTERPRIO_SPAM, strcat(NEWLINES, "spectating ", self.enemy.netname, "\n\n\n^7press attack for next player\npress attack2 for free fly mode"));
-			}
-			if (g_arena)
-				return centerprint_atprio(self, CENTERPRIO_SPAM, strcat(NEWLINES, "spectating ", self.enemy.netname, "\n\n\n^7press attack for next player\npress attack2 for free fly mode"));
-
-			local string specString;
-			specString = strcat(NEWLINES, "spectating ", self.enemy.netname, "\n\n\n^7press jump to play\n^7press attack for next player\npress attack2 for free fly mode");
-			
-			if(time < restart_countdown) //also show the countdown when being a spectator
-				specString = strcat(specString, "\n\n^1Game starts in ", ftos(restartAnnouncer.cnt + 1), " seconds^7");
-			else if (timeoutStatus != 0)
-				specString = strcat(specString, "\n\n", getTimeoutText(1));
-			return centerprint_atprio(self, CENTERPRIO_SPAM, specString);
-		}
+		// TODO get rid of this too
+		local string specString;
+		specString = NEWLINES;
+		if(time < restart_countdown) //also show the countdown when being a spectator
+			specString = strcat(specString, "\n\n^1Game starts in ", ftos(restartAnnouncer.cnt + 1), " seconds^7");
+		else if (timeoutStatus != 0)
+			specString = strcat(specString, "\n\n", getTimeoutText(1));
+		else
+			return;
+		return centerprint_atprio(self, CENTERPRIO_SPAM, specString);
 	}
 
 	if(g_minstagib)

Modified: branches/nexuiz-2.0/data/sound/player/default.sounds
===================================================================
--- branches/nexuiz-2.0/data/sound/player/default.sounds	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/data/sound/player/default.sounds	2008-08-24 17:48:37 UTC (rev 4176)
@@ -1,22 +1,21 @@
-//attack sound/player/voice/attack 1
-//attackinfive sound/player/voice/attackinfive 1
-//coverme sound/player/voice/coverme 1
+attack sound/player/torus/attack 0
+attackinfive sound/player/torus/letsgo 0
+coverme sound/player/torus/coverme 0
 //defend sound/player/voice/defend 1
 //freelance sound/player/voice/freelance 1
-//incoming sound/player/voice/incoming 1
-//meet sound/player/voice/meet 1
-//needhelp sound/player/voice/needhelp 1
-//seenflag sound/player/voice/seenflag 2
-//taunt sound/player/voice/taunt 9
-//teamshoot sound/player/voice/teamshoot 5
-death sound/debug/v_death 0
-drown sound/debug/v_drown 0
-falling sound/debug/v_falling 0
-gasp sound/debug/v_gasp 0
-jump sound/debug/v_jump 0
-pain25 sound/debug/v_pain25 0
-pain50 sound/debug/v_pain50 0
-pain75 sound/debug/v_pain75 0
-pain100 sound/debug/v_pain100 0
-
+incoming sound/player/torus/incoming 0
+meet sound/player/torus/waypoint 0
+needhelp sound/player/torus/needhelp 0
+seenflag sound/player/torus/flagseen 0
+taunt sound/player/torus/taunt 0
+teamshoot sound/player/torus/teamshoot 0
+death sound/player/torus/death 0
+drown sound/player/torus/drown 0
+//falling sound/debug/v_falling 0
+gasp sound/player/torus/gasp 0
+jump sound/player/torus/jump 0
+pain25 sound/player/torus/pain25 0
+pain50 sound/player/torus/pain50 0
+pain75 sound/player/torus/pain75 0
+pain100 sound/player/torus/pain100 0
 // TODO take out ALL the debug sounds, before I will remove them again! Deadline is Oct 1 2008.

Copied: branches/nexuiz-2.0/data/sound/player/torus (from rev 4174, trunk/data/sound/player/torus)

Modified: branches/nexuiz-2.0/misc/autoshader.sh
===================================================================
--- branches/nexuiz-2.0/misc/autoshader.sh	2008-08-24 17:44:48 UTC (rev 4175)
+++ branches/nexuiz-2.0/misc/autoshader.sh	2008-08-24 17:48:37 UTC (rev 4176)
@@ -37,7 +37,7 @@
 		// or: alphafunc GE128
 	}
 	{
-		map $lightmap
+		map \$lightmap
 		blendfunc filter
 		rgbGen identity
 	}




More information about the nexuiz-commits mailing list