r4817 - in branches/nexuiz-2.0: . data data/gfx data/gfx/menu data/gfx/menu/default data/models/sprites data/models/weapons data/qcsrc/client data/qcsrc/common data/qcsrc/server data/scripts data/textures modelsource

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Wed Oct 22 10:23:00 EDT 2008


Author: div0
Date: 2008-10-22 10:22:57 -0400 (Wed, 22 Oct 2008)
New Revision: 4817

Added:
   branches/nexuiz-2.0/data/effectinfo-addcomments.pl
   branches/nexuiz-2.0/data/gfx/inv_weapon11.tga
   branches/nexuiz-2.0/data/gfx/menu/wickedz/
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-blue_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-blue_frame1.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-neut_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-neut_frame1.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-red_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-red_frame1.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-blue_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-blue_frame1.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-red_frame0.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-red_frame1.tga
   branches/nexuiz-2.0/data/models/weapons/g_hookgun.md3
   branches/nexuiz-2.0/data/models/weapons/v_hookgun.md3
   branches/nexuiz-2.0/data/models/weapons/w_hookgun.zym
   branches/nexuiz-2.0/data/qcsrc/server/func_breakable.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc
   branches/nexuiz-2.0/data/textures/hookgun.tga
   branches/nexuiz-2.0/data/textures/hookgun_gloss.tga
   branches/nexuiz-2.0/data/textures/hookgun_norm.tga
   branches/nexuiz-2.0/data/textures/hookgun_pants.tga
   branches/nexuiz-2.0/modelsource/hookgun.zip
Removed:
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-blue.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-neut.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-red.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-blue.tga
   branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-red.tga
   branches/nexuiz-2.0/data/qcsrc/client/ons.qc
Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/data/build-compat-pack.sh
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   branches/nexuiz-2.0/data/effectinfo.txt
   branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt
   branches/nexuiz-2.0/data/keybinds.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/hook.qc
   branches/nexuiz-2.0/data/qcsrc/client/progs.src
   branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc
   branches/nexuiz-2.0/data/qcsrc/client/waypointsprites.qc
   branches/nexuiz-2.0/data/qcsrc/common/constants.qh
   branches/nexuiz-2.0/data/qcsrc/common/util.qc
   branches/nexuiz-2.0/data/qcsrc/server/arena.qc
   branches/nexuiz-2.0/data/qcsrc/server/assault.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
   branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_hook.qh
   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/keyhunt.qc
   branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/server/mode_onslaught.qc
   branches/nexuiz-2.0/data/qcsrc/server/progs.src
   branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc
   branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
   branches/nexuiz-2.0/data/qcsrc/server/waypointsprites.qc
   branches/nexuiz-2.0/data/scripts/entities.def
   branches/nexuiz-2.0/data/turrets.cfg
   branches/nexuiz-2.0/data/weapons.cfg
   branches/nexuiz-2.0/data/weaponsPro.cfg
Log:
r4790 | div0 | 2008-10-21 08:20:01 +0200 (Tue, 21 Oct 2008) | 2 lines
add on-hand hook weapon placable by mapper (weapon_hook)
r4791 | div0 | 2008-10-21 08:34:20 +0200 (Tue, 21 Oct 2008) | 2 lines
slight retune of the gravity bomb
r4792 | div0 | 2008-10-21 10:08:24 +0200 (Tue, 21 Oct 2008) | 2 lines
improved settings, fixed pro
r4793 | div0 | 2008-10-21 12:07:35 +0200 (Tue, 21 Oct 2008) | 2 lines
slightly more visible race penalty nagging
r4794 | div0 | 2008-10-21 15:48:58 +0200 (Tue, 21 Oct 2008) | 2 lines
allow $target in target_spawn too, to do counters or similar stuff
r4795 | div0 | 2008-10-21 16:32:57 +0200 (Tue, 21 Oct 2008) | 2 lines
clean up the func_breakable mess a bit; TODO merge it with assault's
r4796 | div0 | 2008-10-21 19:21:36 +0200 (Tue, 21 Oct 2008) | 3 lines
func_breakable: more cleanups, assault merge, entities.def docs
hook: onhand hook now is turned off by offhand hook
r4797 | div0 | 2008-10-21 19:45:12 +0200 (Tue, 21 Oct 2008) | 2 lines
experimental g_start_delay cvar to wait for other players to join
r4798 | div0 | 2008-10-22 08:02:33 +0200 (Wed, 22 Oct 2008) | 3 lines
effectinfo.txt: improve self-documentation (hope I broke nothing) by referencing the code that uses the effects
clientcommands: add cheat commands "cmd pointparticles" and "cmd trailparticles" to try out effects
r4799 | div0 | 2008-10-22 08:07:59 +0200 (Wed, 22 Oct 2008) | 2 lines
add the perl script that annotates effectinfo.txt; fix effectindexdump command
r4800 | div0 | 2008-10-22 08:16:35 +0200 (Wed, 22 Oct 2008) | 2 lines
add wickedz skin and set it as default. FINALLY...
r4801 | div0 | 2008-10-22 09:34:05 +0200 (Wed, 22 Oct 2008) | 2 lines
onslaught sprite code is back, now using csqc. no radar support yet, but that will be easy.
r4802 | div0 | 2008-10-22 10:14:49 +0200 (Wed, 22 Oct 2008) | 2 lines
add simple radar icons for ons
r4803 | div0 | 2008-10-22 10:59:18 +0200 (Wed, 22 Oct 2008) | 2 lines
more stuff in the team radar
r4804 | div0 | 2008-10-22 11:02:18 +0200 (Wed, 22 Oct 2008) | 2 lines
remove debug print
r4805 | div0 | 2008-10-22 13:24:34 +0200 (Wed, 22 Oct 2008) | 3 lines
- experimental CSQC change: get rid of old ONS team radar code, support ons_showmap using the new radar by changing its parameters when M key is used
- send preferred hook shot origin over the net to csqc to support both onhand and offhand hook
r4806 | div0 | 2008-10-22 13:29:07 +0200 (Wed, 22 Oct 2008) | 2 lines
hook gun model by morphed
r4807 | div0 | 2008-10-22 14:07:24 +0200 (Wed, 22 Oct 2008) | 2 lines
turn off crosshair in ons_showmap mode too
r4808 | div0 | 2008-10-22 14:10:50 +0200 (Wed, 22 Oct 2008) | 2 lines
as ons_map no longer is ons specific, rename it to "radar" and keep "ons_map" as an alias.
r4809 | div0 | 2008-10-22 15:01:38 +0200 (Wed, 22 Oct 2008) | 2 lines
always exec turrets.cfg on startup, so turret maps workr4810 | esteel | 2008-10-22 15:04:50 +0200 (Wed, 22 Oct 2008) | 2 lines
added new files since revision 4768 to build-compat-pack.sh
r4811 | div0 | 2008-10-22 15:06:05 +0200 (Wed, 22 Oct 2008) | 2 lines
add the "radar" command
r4812 | div0 | 2008-10-22 15:09:20 +0200 (Wed, 22 Oct 2008) | 2 lines
add m as default bind for enlarged radar
r4813 | esteel | 2008-10-22 15:11:31 +0200 (Wed, 22 Oct 2008) | 2 lines
also delete files from build-compat-pack.sh
r4814 | div0 | 2008-10-22 15:13:51 +0200 (Wed, 22 Oct 2008) | 2 lines
sort it :)
r4815 | div0 | 2008-10-22 16:21:21 +0200 (Wed, 22 Oct 2008) | 2 lines
fix hook shot origin

Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/.patchsets	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-4788
+revisions_applied = 1-4815

Modified: branches/nexuiz-2.0/data/build-compat-pack.sh
===================================================================
--- branches/nexuiz-2.0/data/build-compat-pack.sh	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/build-compat-pack.sh	2008-10-22 14:22:57 UTC (rev 4817)
@@ -15,6 +15,7 @@
 	gfx/dismal_mini.tga
 	gfx/final_rage_mini.tga
 	gfx/inv_weapon10.tga
+	gfx/inv_weapon11.tga
 	gfx/inv_weapon9.tga
 	gfx/reslimed_mini.tga
 	gfx/runningman_1on1remix_mini.tga
@@ -23,8 +24,8 @@
 	gfx/sb_kh_full.tga
 	gfx/sb_kh_outline.tga
 	gfx/sb_playercolor_base.tga
+	gfx/sb_playercolor_pants.tga
 	gfx/sb_playercolor_shirt.tga
-	gfx/sb_playercolor_pants.tga
 	gfx/silvercity_mini.tga
 	gfx/stormkeep_mini.tga
 	gfx/strength_mini.tga
@@ -48,12 +49,17 @@
 	models/sprites/keycarrier-red.tga
 	models/sprites/keycarrier-yellow.tga
 	models/sprites/key-dropped.tga
-	models/sprites/ons-cp-atck-blue.tga
-	models/sprites/ons-cp-atck-neut.tga
-	models/sprites/ons-cp-atck-red.tga
+	models/sprites/ons-cp-atck-blue_frame0.tga
+	models/sprites/ons-cp-atck-blue_frame1.tga
+	models/sprites/ons-cp-atck-neut_frame0.tga
+	models/sprites/ons-cp-atck-neut_frame1.tga
+	models/sprites/ons-cp-atck-red_frame0.tga
+	models/sprites/ons-cp-atck-red_frame1.tga
 	models/sprites/ons-cp-blue.tga
-	models/sprites/ons-cp-dfnd-blue.tga
-	models/sprites/ons-cp-dfnd-red.tga
+	models/sprites/ons-cp-dfnd-blue_frame0.tga
+	models/sprites/ons-cp-dfnd-blue_frame1.tga
+	models/sprites/ons-cp-dfnd-red_frame0.tga
+	models/sprites/ons-cp-dfnd-red_frame1.tga
 	models/sprites/ons-cp-neut.tga
 	models/sprites/ons-cp-red.tga
 	models/sprites/ons-gen-blue.tga
@@ -66,16 +72,19 @@
 	models/sprites/race-finish.tga
 	models/sprites/redbase.tga
 	models/sprites/waypoint.tga
+	models/weapons/g_hookgun.md3
 	models/weapons/g_minstanex.md3
 	models/weapons/g_porto.md3
+	models/weapons/v_hookgun.md3
 	models/weapons/v_minstanex.md3
 	models/weapons/v_porto.md3
+	models/weapons/w_hookgun.zym
 	models/weapons/w_minstanex.zym
 	models/weapons/w_porto.zym
 	particles/particlefont.tga
-	sound/announcer/male/impressive.ogg
 	sound/announcer/male/airshot.ogg
 	sound/announcer/male/headshot.ogg
+	sound/announcer/male/impressive.ogg
 	sound/misc/typehit.wav
 	sound/player/default.sounds
 	sound/player/torus/attack.ogg
@@ -103,6 +112,10 @@
 	sound/porto/explode.ogg
 	sound/porto/fire.ogg
 	sound/porto/unsupported.ogg
+	textures/hookgun_gloss.tga
+	textures/hookgun_norm.tga
+	textures/hookgun_pants.tga
+	textures/hookgun.tga
 	textures/nex_bump.tga
 	textures/nex_gloss.tga
 	textures/nex_glow.tga

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-10-22 14:22:57 UTC (rev 4817)
@@ -668,6 +668,7 @@
 bind F11 disconnect
 bind F12 screenshot
 bind F4 ready
+bind m radar
 
 // Gamepad defaults. Tested with Logitech Rumblepad 2, I hope similar ones works as well.
 bind JOY1 "+crouch"
@@ -985,7 +986,7 @@
 alias +userbind "_userbind_call userbind${1}_press"
 alias -userbind "_userbind_call userbind${1}_release"
 
-seta menu_skin "wickedblack"
+seta menu_skin "wickedz"
 set menu_slowmo 1
 
 // loadfont console     gfx/vera-mono
@@ -1111,7 +1112,7 @@
 
 alias allready "sv_cmd allready"
 
-seta cl_weaponpriority "10 9 8 11 7 6 5 4 3 2 1"
+seta cl_weaponpriority "9 8 11 7 6 5 4 3 2 1 10 12" // default porto and hook as LOW priority, use the weapon key numbers otherwise
 seta cl_weaponpriority_useforcycling 0
 // impulse 200, 210, 220:
 seta cl_weaponpriority0 "9 8 4"      // explosives    (RL Hagar Mortar)
@@ -1120,7 +1121,7 @@
 seta cl_weaponpriority2 "7 3"        // hitscan exact (Nex MG)
 seta cl_weaponpriority3 "7 3 2"      // hitscan all   (Nex MG Shotgun)
 seta cl_weaponpriority4 "8 6 5 2"    // spam          (Hagar Crylink Electro Shotgun)
-seta cl_weaponpriority5 ""
+seta cl_weaponpriority5 "1 12 10"    // for moving    (Laser Hook Port-O-Launch)
 seta cl_weaponpriority6 ""
 seta cl_weaponpriority7 ""
 seta cl_weaponpriority8 ""
@@ -1142,6 +1143,7 @@
 set g_weaponreplace_9 ""
 set g_weaponreplace_10 ""
 set g_weaponreplace_11 ""
+set g_weaponreplace_12 ""
 
 seta sv_status_privacy 1 // hide IP addresses from "status" replies shown to clients
 
@@ -1162,3 +1164,12 @@
 alias cl_teamradar_rotate "toggle cl_teamradar_rotation 0 1 2 3 4"
 
 set g_maplist_allow_hidden 1 // allow hidden maps to be, e.g., voted for and in the maplist
+
+set g_start_delay 0 // delay before the game starts, so everyone can join; recommended to set this to like 15 on a public server
+
+alias ons_map           "cl_cmd radar" // legacy alias
+alias radar             "cl_cmd radar"
+alias sbar_columns_set  "cl_cmd sbar_columns_set $*"
+alias sbar_columns_help "cl_cmd sbar_columns_help $*"
+
+exec turrets.cfg

Copied: branches/nexuiz-2.0/data/effectinfo-addcomments.pl (from rev 4809, trunk/data/effectinfo-addcomments.pl)
===================================================================
--- branches/nexuiz-2.0/data/effectinfo-addcomments.pl	                        (rev 0)
+++ branches/nexuiz-2.0/data/effectinfo-addcomments.pl	2008-10-22 14:22:57 UTC (rev 4817)
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $out = "";
+my %found;
+
+open my $fh, '<', 'effectinfo.txt';
+while(<$fh>)
+{
+	chomp;
+
+	next if /^\/\/ used in /;
+	next if /^\/\/ used nowhere in code$/;
+
+	if(/^effect\s+([^\s\/]+)\s*(?:\/\/.*)?$/i)
+	{
+		if(!$found{$1})
+		{
+			print STDERR "Handling $1...\n";
+			$found{$1} = 1;
+			my $search =
+				$1 eq 'TR_BLOOD' ? 'MF_GIB' :
+				$1 eq 'TR_SLIGHTBLOOD' ? 'MF_ZOMGIB' :
+				$1 eq 'TR_WIZSPIKE' ? 'MF_TRACER' :
+				$1 eq 'TR_KNIGHTSPIKE' ? 'MF_TRACER2' :
+				$1 eq 'TR_ROCKET' ? 'MF_ROCKET' :
+				$1 eq 'TR_GRENADE' ? 'MF_GRENADE' :
+				$1 eq 'TR_VORESPIKE' ? 'MF_TRACER3' :
+				$1;
+			local $ENV{effectre} =
+				$search eq lc $search
+					? "\"$search\""
+					: "\"$search\"|\\<" . lc($search) . "\\>|\\<" . $search . "\\>";
+			print "$ENV{effectre}\n";
+			my $occurrences = `grep -E "\$effectre" qcsrc/server/*.qc qcsrc/client/*.qc`;
+			$occurrences =~ s/\r/\n/g;
+			$occurrences =~ s/;//g;
+			my $found = 0;
+			for(split /\n/, $occurrences)
+			{
+				next if $_ eq '';
+				next if /^qcsrc\/server\/gamecommand\.qc:/; # list of quake effects is there
+				next if /^qcsrc\/client\/csqc_builtins\.qc:/; # list of quake effects is there
+				next if /^qcsrc\/client\/csqc_constants\.qc:/; # list of quake effects is there
+				$out .= "// used in $_\n";
+				$found = 1;
+			}
+			if(!$found)
+			{
+				$out .= "// used nowhere in code\n";
+			}
+		}
+	}
+
+	$out .= "$_\n";
+}
+close $fh;
+
+open $fh, '>', 'effectinfo.txt';
+print $fh $out;
+close $fh;

Modified: branches/nexuiz-2.0/data/effectinfo.txt
===================================================================
--- branches/nexuiz-2.0/data/effectinfo.txt	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/effectinfo.txt	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1,16 +1,9 @@
-/*
-// quake wizard spike impact
-effect TE_WIZSPIKE
-count 30
-type alphastatic
-color 0x372b17 0x73571f
-alpha 51 256 512
-originjitter 4 4 4
-velocityjitter 16 16 16
-*/
-
 // item respawn effect
 // flare particle and light
+// used in qcsrc/server/bots.qc:		//te_wizspike(start)
+// used in qcsrc/server/bots.qc:				te_wizspike(org)
+// used in qcsrc/server/bots.qc:	//te_wizspike(e.origin)
+// used in qcsrc/server/bots.qc:		//te_wizspike(e.nearestwaypoint.wpnearestpoint)
 effect TE_WIZSPIKE
 countabsolute 1
 type static
@@ -32,19 +25,12 @@
 originjitter 16 16 16
 velocityjitter 32 32 32
 
-/*
-// quake hell knight fireball impact
-effect TE_KNIGHTSPIKE
-count 20
-type alphastatic
-color 0x5f0700 0xcf632b
-alpha 51 256 512
-originjitter 4 4 4
-velocityjitter 16 16 16
-*/
-
 // laser impact
 // decal
+// used in qcsrc/server/bots.qc:		//te_knightspike(end)
+// used in qcsrc/server/bots.qc:			te_knightspike(start)
+// used in qcsrc/server/bots.qc:						te_knightspike(org)
+// used in qcsrc/server/bots.qc:		te_knightspike(org)
 effect TE_KNIGHTSPIKE
 countabsolute 1
 type decal
@@ -78,6 +64,7 @@
 
 // machinegun bullet impact
 // bullet impact decal
+// used nowhere in code
 effect TE_SPIKE
 countabsolute 1
 type decal
@@ -121,6 +108,7 @@
 
 // electro combo explosion
 // decal
+// used nowhere in code
 effect TE_SPIKEQUAD
 countabsolute 1
 type decal
@@ -152,21 +140,10 @@
 liquidfriction 16
 //velocityoffset 0 0 120
 velocityjitter 512 512 512
-/*
-// inner cloud of smoke
-effect TE_SPIKEQUAD
-count 0.25
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 24 24
-alpha 256 256 256
-originjitter 20 20 20
-velocityjitter 32 32 32
-*/
 
 // quake effect
 // decal
+// used nowhere in code
 effect TE_SUPERSPIKE
 countabsolute 1
 type decal
@@ -210,6 +187,7 @@
 
 // quake effect
 // decal
+// used nowhere in code
 effect TE_SUPERSPIKEQUAD
 countabsolute 1
 type decal
@@ -256,6 +234,11 @@
 
 // shotgun pellet impact
 // decal
+// used in qcsrc/server/bots.qc:			//te_gunshot(org)
+// used in qcsrc/server/bots.qc:					te_gunshot(org)
+// used in qcsrc/server/bots.qc:					te_gunshot(org)
+// used in qcsrc/server/bots.qc:						te_gunshot(org)
+// used in qcsrc/server/bots.qc:		//te_gunshot(end)
 effect TE_GUNSHOT
 countabsolute 1
 type decal
@@ -297,56 +280,9 @@
 velocityoffset 0 0 80
 velocityjitter 64 64 64
 
-/*
-// quake effect
-// decal
-effect TE_GUNSHOTQUAD
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-lightradius 100
-lightradiusfade 500
-lightcolor 0.15 0.15 1.5
-// dust/smoke drifting away from the impact
-effect TE_GUNSHOTQUAD
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
-effect TE_GUNSHOTQUAD
-count 1
-type smoke
-tex 0 8
-color 0x202020 0x202020
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// sparks that disappear on impact
-effect TE_GUNSHOTQUAD
-count 15
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-*/
-
 // crylink impact effect
 // decal
+// used nowhere in code
 effect TE_GUNSHOTQUAD
 countabsolute 1
 type decal
@@ -379,6 +315,7 @@
 
 // mortar/hagar explosion (smaller than rocket)
 // decal
+// used nowhere in code
 effect TE_EXPLOSION
 countabsolute 1
 type decal
@@ -439,54 +376,10 @@
 liquidfriction 0.8
 velocityoffset 0 0 80
 velocityjitter 256 256 256
-/*
-// experimental black smoke
-effect TE_EXPLOSION
-count 32
-type alphastatic
-tex 0 8
-color 0x000000 0x000000
-size 32 32
-alpha 128 256 512
-bounce 1.5
-airfriction 5
-liquidfriction 5
-originjitter 10 10 10
-velocityjitter 256 256 256
-*/
-/*
-// experimental debris
-effect TE_EXPLOSION
-count 32
-type alphastatic
-tex 0 8
-color 0x202020 0x404040
-size 2 4
-alpha 128 256 128
-gravity 1
-airfriction 0.4
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-*/
-/*
-// experimental dark smoke
-effect TE_EXPLOSION
-count 16
-type alphastatic
-tex 0 8
-color 0x101010 0x202020
-size 32 32
-alpha 128 256 256
-airfriction 2
-liquidfriction 2
-originjitter 24 24 24
-velocityjitter 64 64 64
-*/
 
 // quake effect
 // decal
+// used nowhere in code
 effect TE_EXPLOSIONQUAD
 countabsolute 1
 type decal
@@ -537,6 +430,7 @@
 
 // quake effect
 // decal
+// used in qcsrc/server/keyhunt.qc:	te_tarexplosion(lostkey.origin)
 effect TE_TAREXPLOSION
 countabsolute 1
 type decal
@@ -586,6 +480,7 @@
 velocityjitter 256 256 256
 
 // bloody impact effect indicating damage
+// used nowhere in code
 effect TE_BLOOD
 count 0.333
 type blood
@@ -599,6 +494,8 @@
 velocitymultiplier 1
 
 // sparks (quake effect)
+// used in qcsrc/server/antilag.qc:		te_spark(antilag_takebackorigin(e, time - e.antilag_debug), '0 0 0', 32)
+// used in qcsrc/server/g_triggers.qc:	self.mdl = "TE_SPARK"
 effect TE_SPARK
 count 1
 type spark
@@ -614,6 +511,7 @@
 
 // nex impact
 // decal
+// used in qcsrc/server/bots.qc:		te_plasmaburn(org)
 effect TE_PLASMABURN
 countabsolute 1
 type decal
@@ -632,19 +530,6 @@
 color 0x80C0FF 0x80C0FF
 size 8 8
 alpha 256 256 512
-/*
-// experimental
-effect TE_PLASMABURN
-count 64
-type static
-color 0x2030FF 0x80C0FF
-size 2 4
-alpha 256 256 512
-bounce 1.5
-airfriction 8
-liquidfriction 8
-velocityjitter 512 512 512
-*/
 // small sparks which form a sphere as they slow down
 effect TE_PLASMABURN
 count 256
@@ -658,12 +543,15 @@
 velocityjitter 128 128 128
 
 // quake effect
+// used in qcsrc/server/bots.qc:	//te_smallflash((e.absmin + e.absmax) * 0.5)
+// used in qcsrc/server/bots.qc:		//te_smallflash((e.absmin + e.absmax) * 0.5)
 effect TE_SMALLFLASH
 lightradius 200
 lightradiusfade 1000
 lightcolor 2 2 2
 
 // quake effect
+// used nowhere in code
 effect TE_FLAMEJET
 count 1
 type smoke
@@ -678,6 +566,7 @@
 velocitymultiplier 1
 
 // quake effect
+// used nowhere in code
 effect TE_LAVASPLASH
 count 64
 type alphastatic
@@ -691,6 +580,7 @@
 velocityjitter 128 128 0
 
 // player teleport effect
+// used nowhere in code
 effect TE_TELEPORT
 count 112
 type static
@@ -704,6 +594,7 @@
 velocityjitter 0 0 256
 
 // nex beam
+// used in qcsrc/server/w_minstanex.qc:	trailparticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, trace_endpos)
 effect TE_TEI_G3
 countabsolute 1
 type beam
@@ -722,25 +613,9 @@
 //liquidfriction -4
 velocityjitter 8 8 8
 type smoke
-/*
-// experimental
-effect TE_TEI_G3
-trailspacing 1
-type static
-tex 0 8
-color 0x202020 0x404040
-size 1 1
-sizeincrease 1
-alpha 256 256 128
-gravity -0.01
-//bounce 1.5
-//airfriction 4
-//liquidfriction 4
-//velocityoffset 0 0 80
-//velocityjitter 4 4 4
-*/
 
 // smoke effect
+// used nowhere in code
 effect TE_TEI_SMOKE
 count 0.333
 type smoke
@@ -754,6 +629,7 @@
 
 // rocket explosion (bigger than mortar and hagar)
 // decal
+// used nowhere in code
 effect TE_TEI_BIGEXPLOSION
 countabsolute 1
 type decal
@@ -817,6 +693,7 @@
 
 // electro explosion
 // decal
+// used nowhere in code
 effect TE_TEI_PLASMAHIT
 countabsolute 1
 type decal
@@ -846,18 +723,6 @@
 bounce 1.5
 //velocityoffset 0 0 120
 velocityjitter 512 512 512
-/*
-// inner cloud of smoke
-effect TE_TEI_PLASMAHIT
-count 0.25
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 24 24
-alpha 256 256 512
-originjitter 20 20 20
-velocityjitter 32 32 32
-*/
 
 
 
@@ -874,6 +739,9 @@
 
 
 // bloody impact effect indicating damage
+// used in qcsrc/server/cl_player.qc:		pointparticles(particleeffectnum("blood"), hitloc, force, bound(0, damage, 200))
+// used in qcsrc/server/cl_player.qc:		pointparticles(particleeffectnum("blood"), hitloc, force, bound(0, damage, 200))
+// used in qcsrc/server/g_violence.qc:		pointparticles(particleeffectnum("blood"), self.origin + '0 0 1', '0 0 30', 10)
 effect blood
 count 0.333
 type blood
@@ -889,6 +757,8 @@
 
 
 // player teleport effect
+// used in qcsrc/server/t_teleporters.qc:	pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1)
+// used in qcsrc/server/t_teleporters.qc:	pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1)
 effect teleport
 count 112
 type static
@@ -904,6 +774,7 @@
 
 
 // normal super gory blood trail (used by gibs)
+// used nowhere in code
 effect TR_BLOOD
 trailspacing 16
 type blood
@@ -920,6 +791,7 @@
 
 
 // thinner blood trail (used by quake zombies)
+// used nowhere in code
 effect TR_SLIGHTBLOOD
 trailspacing 32
 type blood
@@ -936,6 +808,9 @@
 
 
 // func_stardust effect, used in some maps to indicate teleporters
+// used in qcsrc/server/assault.qc:		//self.effects = EF_STARDUST
+// used in qcsrc/server/g_triggers.qc:	self.effects = EF_STARDUST
+// used in qcsrc/server/portals.qc:	portal.effects = EF_STARDUST | EF_BLUE
 effect EF_STARDUST
 count 75
 type static
@@ -953,6 +828,8 @@
 
 
 // flare particle and light
+// used in qcsrc/server/t_items.qc:	//pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1)
+// used in qcsrc/server/t_items.qc:	pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1)
 effect item_respawn
 countabsolute 1
 type static
@@ -972,6 +849,7 @@
 
 
 
+// used in qcsrc/server/t_jumppads.qc:			pointparticles(particleeffectnum("jumppad_activate"), other.origin, other.velocity, 1)
 effect jumppad_activate
 lightradius 200
 lightradiusfade 2000
@@ -979,6 +857,7 @@
 
 
 
+// used in qcsrc/server/w_laser.qc:	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect laser_muzzleflash
 count 1
 type smoke
@@ -997,6 +876,7 @@
 
 
 // decal
+// used in qcsrc/server/w_laser.qc:	pointparticles(particleeffectnum("laser_impact"), org2, normal * 1000, 1)
 effect laser_impact
 countabsolute 1
 type decal
@@ -1041,6 +921,8 @@
 
 
 
+// used in qcsrc/server/w_shotgun.qc:	pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_primary_ammo"))
+// used in qcsrc/server/w_shotgun.qc:	pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_secondary_ammo"))
 effect shotgun_muzzleflash
 count 3
 type smoke
@@ -1073,6 +955,7 @@
 
 // shotgun pellet impact
 // decal
+// used in qcsrc/server/w_common.qc:				pointparticles(particleeffectnum("shotgun_impact"), trace_endpos, trace_plane_normal * 1000, 1)
 effect shotgun_impact
 countabsolute 1
 type decal
@@ -1124,6 +1007,7 @@
 
 
 
+// used in qcsrc/server/w_uzi.qc:	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect uzi_muzzleflash
 count 2
 type static
@@ -1149,19 +1033,11 @@
 velocityjitter 300 300 300
 velocitymultiplier 0.5
 airfriction 12
-/*
-// explosion
-effect uzi_muzzleflash
-count 3
-type smoke
-tex 48 55
-size 20 5
-alpha 255 255 2024
-color 0xFF9600 0x0090ff
-*/
 
 
 // decal
+// used in qcsrc/server/cl_client.qc:	//pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1)
+// used in qcsrc/server/w_common.qc:				pointparticles(particleeffectnum("machinegun_impact"), trace_endpos, trace_plane_normal * 1000, 1)
 effect machinegun_impact
 countabsolute 1
 type decal
@@ -1213,6 +1089,9 @@
 
 
 
+// used in qcsrc/server/w_grenadelauncher.qc:	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_grenadelauncher.qc:	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_porto.qc:	//pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect grenadelauncher_muzzleflash
 count 3
 type smoke
@@ -1243,6 +1122,9 @@
 
 // hagar trail
 // smoke
+// used in qcsrc/server/w_hagar.qc:	missile.modelflags = MF_GRENADE
+// used in qcsrc/server/w_hagar.qc:	missile.modelflags = MF_GRENADE
+// used in qcsrc/server/w_porto.qc:	gren.modelflags = MF_GRENADE
 effect TR_GRENADE
 trailspacing 6
 type alphastatic
@@ -1287,6 +1169,9 @@
 
 // mortar trail
 // smoke
+// used in qcsrc/server/w_grenadelauncher.qc:	gren.modelflags = MF_TRACER2
+// used in qcsrc/server/w_grenadelauncher.qc:	gren.modelflags = MF_TRACER2
+// used in qcsrc/server/w_hook.qc:	gren.modelflags = MF_TRACER2
 effect TR_KNIGHTSPIKE // used for MF_TRACER2
 notunderwater
 trailspacing 5
@@ -1327,6 +1212,8 @@
 
 
 // decal
+// used in qcsrc/server/w_grenadelauncher.qc:	pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1)
+// used in qcsrc/server/w_grenadelauncher.qc:	pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1)
 effect grenade_explode
 countabsolute 1
 type decal
@@ -1412,6 +1299,8 @@
 
 
 
+// used in qcsrc/server/w_electro.qc:	pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_electro.qc:	pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect electro_muzzleflash
 count 1
 type smoke
@@ -1441,6 +1330,7 @@
 
 // electro trail
 // glowing vapor trail
+// used nowhere in code
 effect TR_NEXUIZPLASMA
 trailspacing 2
 type static
@@ -1472,6 +1362,7 @@
 
 
 // decal
+// used in qcsrc/server/w_electro.qc:		pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1)
 effect electro_impact
 countabsolute 1
 type decal
@@ -1518,6 +1409,7 @@
 velocityjitter 320 320 320
 
 // decal
+// used in qcsrc/server/w_electro.qc:		pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1)
 effect electro_ballexplode
 countabsolute 1
 type decal
@@ -1562,6 +1454,7 @@
 
 
 // decal
+// used in qcsrc/server/w_electro.qc:	pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1)
 effect electro_combo
 countabsolute 1
 type decal
@@ -1616,6 +1509,8 @@
 
 
 
+// used in qcsrc/server/w_crylink.qc:	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
+// used in qcsrc/server/w_crylink.qc:	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
 effect crylink_muzzleflash
 count 1
 type smoke
@@ -1645,6 +1540,7 @@
 
 // crylink impact effect
 // decal
+// used in qcsrc/server/w_crylink.qc:	pointparticles(particleeffectnum("crylink_impact"), self.origin, '0 0 0', 1)
 effect crylink_impact
 countabsolute 1
 type decal
@@ -1692,6 +1588,8 @@
 
 
 
+// used in qcsrc/server/w_minstanex.qc:	pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_nex.qc:	pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect nex_muzzleflash
 count 10
 type smoke
@@ -1728,6 +1626,7 @@
 //size 6 6
 //alpha 128 128 192
 // nex beam: ring smoke
+// used in qcsrc/server/w_nex.qc:	trailparticles(world, particleeffectnum("nex_beam"), w_shotorg, trace_endpos)
 effect nex_beam
 trailspacing 32
 color 0x1680A0 0x1680A0
@@ -1769,6 +1668,8 @@
 
 // nex impact
 // decal
+// used in qcsrc/server/w_minstanex.qc:		pointparticles(particleeffectnum("nex_impact"), trace_endpos - w_shotdir * 6, '0 0 0', 1)
+// used in qcsrc/server/w_nex.qc:		pointparticles(particleeffectnum("nex_impact"), trace_endpos - w_shotdir * 6, '0 0 0', 1)
 effect nex_impact
 countabsolute 1
 type decal
@@ -1823,6 +1724,8 @@
 
 
 
+// used in qcsrc/server/w_hagar.qc:	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_hagar.qc:	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect hagar_muzzleflash
 count 4
 type smoke
@@ -1850,6 +1753,7 @@
 
 
 
+// used in qcsrc/server/w_hagar.qc:		pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1)
 effect hagar_bounce
 count 4
 type smoke
@@ -1880,6 +1784,8 @@
 
 
 // decal
+// used in qcsrc/server/w_hagar.qc:	pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
+// used in qcsrc/server/w_hagar.qc:	pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
 effect hagar_explode
 countabsolute 1
 type decal
@@ -1967,6 +1873,7 @@
 
 
 
+// used in qcsrc/server/w_rocketlauncher.qc:	pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
 effect rocketlauncher_muzzleflash
 count 20
 type smoke
@@ -1998,6 +1905,7 @@
 
 // rocket trail
 // smoke
+// used nowhere in code
 effect TR_ROCKET
 trailspacing 5
 type alphastatic
@@ -2058,6 +1966,9 @@
 
 // rocket explosion (bigger than mortar and hagar)
 // decal
+// used in qcsrc/server/cl_player.qc:				pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1)
+// used in qcsrc/server/portals.qc:		pointparticles(particleeffectnum("rocket_explode"), portal.origin + v_forward * 16, v_forward * 1024, 4)
+// used in qcsrc/server/w_rocketlauncher.qc:	pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1)
 effect rocket_explode
 countabsolute 1
 type decal
@@ -2145,6 +2056,7 @@
 
 
 
+// used in qcsrc/server/g_hook.qc:	pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1)
 effect grapple_muzzleflash
 lightradius 160
 lightradiusfade 800
@@ -2152,6 +2064,7 @@
 
 
 
+// used in qcsrc/server/g_hook.qc:	pointparticles(particleeffectnum("grapple_impact"), self.origin, '0 0 0', 1)
 effect grapple_impact
 lightradius 160
 lightradiusfade 800
@@ -2159,6 +2072,7 @@
 
 
 
+// used nowhere in code
 effect nex242_misc_laser_beam
 countabsolute 1
 type beam
@@ -2168,6 +2082,7 @@
 color 0xff0000 0xff0000
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_beam_end
 count 1
 type spark
@@ -2181,6 +2096,7 @@
 
 
 
+// used nowhere in code
 effect nex242_misc_laser_beam_fast
 countabsolute 1
 type beam
@@ -2190,6 +2106,7 @@
 color 0xff0000 0xff0000
 sizeincrease 0.1
 
+// used nowhere in code
 effect nex242_misc_laser_beam_fast_end
 count 1
 type spark
@@ -2202,6 +2119,7 @@
 velocitymultiplier 100
 
 // additional laser colors (mike)
+// used nowhere in code
 effect nex242_misc_laser_green_beam
 countabsolute 1
 type beam
@@ -2211,6 +2129,7 @@
 color 0x00ff00 0x00ff00
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_green_beam_end
 count 1
 type spark
@@ -2222,6 +2141,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_blue_beam
 countabsolute 1
 type beam
@@ -2231,6 +2151,7 @@
 color 0x0000ff 0x0000ff
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_blue_beam_end
 count 1
 type spark
@@ -2242,6 +2163,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_yellow_beam
 countabsolute 1
 type beam
@@ -2251,6 +2173,7 @@
 color 0xffff00 0xffff00
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_yellow_beam_end
 count 1
 type spark
@@ -2262,6 +2185,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_cyan_beam
 countabsolute 1
 type beam
@@ -2271,6 +2195,7 @@
 color 0x00ffff 0x00ffff
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_cyan_beam_end
 count 1
 type spark
@@ -2282,6 +2207,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_magenta_beam
 countabsolute 1
 type beam
@@ -2291,6 +2217,7 @@
 color 0xff00ff 0xff00ff
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_magenta_beam_end
 count 1
 type spark
@@ -2302,6 +2229,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_white_beam
 countabsolute 1
 type beam
@@ -2311,6 +2239,7 @@
 color 0xffffff 0xffffff
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_white_beam_end
 count 1
 type spark
@@ -2322,6 +2251,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_black_beam
 countabsolute 1
 type beam
@@ -2331,6 +2261,7 @@
 color 0x000000 0x000000
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_black_beam_end
 count 1
 type spark
@@ -2342,6 +2273,7 @@
 velocityjitter 64 64 64
 velocitymultiplier 100
 
+// used nowhere in code
 effect nex242_misc_laser_orange_beam
 countabsolute 1
 type beam
@@ -2351,6 +2283,7 @@
 color 0xff6600 0xff6600
 sizeincrease 1
 
+// used nowhere in code
 effect nex242_misc_laser_orange_beam_end
 count 1
 type spark
@@ -2367,6 +2300,7 @@
 
 // bigger crylink impact effect
 // decal
+// used in qcsrc/server/w_crylink.qc:	pointparticles(particleeffectnum("crylink_impactbig"), self.origin, '0 0 0', 1)
 effect crylink_impactbig
 countabsolute 1
 type decal
@@ -2415,6 +2349,7 @@
 // Zero-violence effects
 
 // impact effect indicating damage
+// used in qcsrc/server/cl_player.qc:		pointparticles(particleeffectnum("damage_hit"), hitloc, force, bound(0, damage, 200))
 effect damage_hit
 count 1
 type static
@@ -2430,6 +2365,7 @@
 
 // effect for removing player model
 // "teleport"
+// used in qcsrc/server/cl_player.qc:			pointparticles(particleeffectnum("damage_dissolve"), self.origin, force, 1)
 effect damage_dissolve
 count 96
 type static
@@ -2464,6 +2400,7 @@
 velocityjitter 512 512 512
 
 // decal
+// used in qcsrc/server/g_triggers.qc:			self.cnt = particleeffectnum("laser_deadly")
 effect laser_deadly
 countabsolute 1
 type decal
@@ -2504,6 +2441,7 @@
 
 //torch
 //fire
+// used nowhere in code
 effect torch_small
 //notunderwater
 count 16
@@ -2532,6 +2470,7 @@
 //bounce 1
 
 //fountain01
+// used nowhere in code
 effect fountain01
 count 32
 tex 0 8
@@ -2546,3 +2485,61 @@
 velocityjitter 81 81 150
 color 0x7cbaff 0xcfd1ff
 velocitymultiplier 2
+
+
+
+// decal
+// used in qcsrc/server/w_hook.qc:	pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1)
+effect hookbomb_explode
+countabsolute 1
+type decal
+tex 8 16
+size 96 96
+alpha 256 256 0
+originjitter 40 40 40
+lightradius 1600
+lightradiusfade 800
+lightcolor 1 4 8
+// fire effect which make brigt dot inside
+effect hookbomb_explode
+notunderwater
+count 100
+type static
+tex 48 55
+color 0x003fe0 0x92dfff
+size 12 32
+sizeincrease 80
+alpha 512 328 756
+bounce 1
+airfriction 8
+liquidfriction 8
+originjitter 8 8 8
+velocityjitter 1024 1024 1024
+// smoke
+effect hookbomb_explode
+type alphastatic
+notunderwater
+tex 0 8
+count 160
+size 80 160
+sizeincrease 300
+alpha 500 600 556
+velocityoffset 0 0 0
+velocityjitter 256 256 256
+airfriction 0
+color 0x000000 0x111111
+bounce 6
+// underwater bubbles
+effect hookbomb_explode
+underwater
+count 60
+type bubble
+tex 62 62
+color 0x404040 0x808080
+size 3 3
+alpha 128 256 64
+gravity -0.125
+bounce 1.5
+liquidfriction 0.0625
+originjitter 16 16 16
+velocityjitter 192 192 192

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

Modified: branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt
===================================================================
--- branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/gfx/menu/default/skinvalues.txt	2008-10-22 14:22:57 UTC (rev 4817)
@@ -16,6 +16,7 @@
 COLOR_DIALOG_SINGLEPLAYER       '1 1 0.7'
 COLOR_DIALOG_CREDITS            '0.7 0.7 1'
 COLOR_DIALOG_WEAPONS            '1 0.7 0.7'
+COLOR_DIALOG_RADAR              '0.7 0.7 1'
 
 // nexposee positions of windows (they are the scale transformation
 // centers, NOT the actual positions of the windows!)
@@ -152,6 +153,8 @@
 COLOR_SERVERLIST_MEDPING        '1 1 0'
 COLOR_SERVERLIST_HIGHPING       '1 0 0'
 ALPHA_SERVERLIST_HIGHPING       0.4
+ALPHA_SERVERLIST_FAVORITE       0.8
+COLOR_SERVERLIST_FAVORITE       '1 1 1'
 
 // item: slider
 //   uses "slider" images

Copied: branches/nexuiz-2.0/data/gfx/menu/wickedz (from rev 4809, trunk/data/gfx/menu/wickedz)

Modified: branches/nexuiz-2.0/data/keybinds.txt
===================================================================
--- branches/nexuiz-2.0/data/keybinds.txt	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/keybinds.txt	2008-10-22 14:22:57 UTC (rev 4817)
@@ -5,7 +5,7 @@
 "+moveright"                            "strafe right"
 "+jump"                                 "jump / swim"
 "+crouch"                               "crouch / sink"
-"+hook"                                 "grappling hook"
+"+hook"                                 "off-hand hook"
 ""                                      ""
 ""                                      "Attacking"
 "+attack"                               "primary fire"
@@ -31,6 +31,7 @@
 "+zoom"                                 "zoom"
 "+showscores"                           "show scores"
 "screenshot"                            "screen shot"
+"radar"                                 "toggle full radar"
 ""                                      ""
 ""                                      "Communicate"
 "messagemode"                           "public chat"

Deleted: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-blue.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-blue_frame0.tga (from rev 4809, trunk/data/models/sprites/ons-cp-atck-blue_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-blue_frame1.tga (from rev 4809, trunk/data/models/sprites/ons-cp-atck-blue_frame1.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-neut.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-neut_frame0.tga (from rev 4809, trunk/data/models/sprites/ons-cp-atck-neut_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-neut_frame1.tga (from rev 4809, trunk/data/models/sprites/ons-cp-atck-neut_frame1.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-red.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-red_frame0.tga (from rev 4809, trunk/data/models/sprites/ons-cp-atck-red_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-atck-red_frame1.tga (from rev 4809, trunk/data/models/sprites/ons-cp-atck-red_frame1.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-blue.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-blue_frame0.tga (from rev 4809, trunk/data/models/sprites/ons-cp-dfnd-blue_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-blue_frame1.tga (from rev 4809, trunk/data/models/sprites/ons-cp-dfnd-blue_frame1.tga)
===================================================================
(Binary files differ)

Deleted: branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-red.tga
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-red_frame0.tga (from rev 4809, trunk/data/models/sprites/ons-cp-dfnd-red_frame0.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/sprites/ons-cp-dfnd-red_frame1.tga (from rev 4809, trunk/data/models/sprites/ons-cp-dfnd-red_frame1.tga)
===================================================================
(Binary files differ)

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

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

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

Modified: branches/nexuiz-2.0/data/qcsrc/client/Defs.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Defs.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/Defs.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -205,3 +205,7 @@
 
 // short mapname
 string shortmapname;
+
+// database for misc stuff
+float tempdb;
+vector hook_shotorigin;

Modified: branches/nexuiz-2.0/data/qcsrc/client/Main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -73,6 +73,7 @@
 
 	configdb = db_create();
 	binddb = db_create();
+	tempdb = db_create();
 	compressShortVector_init();
 
 	drawfont = 0;
@@ -146,6 +147,7 @@
 	remove(players);
 	db_close(configdb);
 	db_close(binddb);
+	db_close(tempdb);
 
 	cvar_clientsettemp_restore();
 }
@@ -284,15 +286,6 @@
 	} else if(strCmd == "-button3") { // secondary
 		button_attack2 = 0;
 		return false;
-	} else if(strCmd == "ons_map") {
-		Cmd_ons_map();
-		return true;
-	} else if(strCmd == "sbar_columns_set") {
-		Cmd_Sbar_SetFields(argc);
-		return true;
-	} else if(strCmd == "sbar_columns_help") {
-		Cmd_Sbar_Help(argc);
-		return true;
 	} else if(strCmd == "+showscores") {
 		sb_showscores = true;
 		return true;
@@ -317,6 +310,15 @@
 	else if(cmd == "settemp") {
 		cvar_clientsettemp(argv(1), argv(2));
 	}
+	else if(cmd == "radar") {
+		ons_showmap = !ons_showmap;
+	}
+	else if(cmd == "sbar_columns_set") {
+		Cmd_Sbar_SetFields(argc);
+	}
+	else if(cmd == "sbar_columns_help") {
+		Cmd_Sbar_Help(argc);
+	}
 	
 	return false;
 }
@@ -464,6 +466,7 @@
 
 // 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_RadarLink();
 void(float bIsNewEntity) CSQC_Ent_Update =
 {
 	float t;
@@ -493,6 +496,8 @@
 		Ent_Nagger();
 	else if(self.enttype == ENT_CLIENT_WAYPOINT)
 		Ent_WaypointSprite();
+	else if(self.enttype == ENT_CLIENT_RADARLINK)
+		Ent_RadarLink();
 	else
 		error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n"));
 	
@@ -635,6 +640,9 @@
 	maxclients = ReadByte();
 	for(i = 0; i < 24; ++i)
 		weaponimpulse[i] = ReadByte() - 1;
+	hook_shotorigin_x = ReadCoord();
+	hook_shotorigin_y = ReadCoord();
+	hook_shotorigin_z = ReadCoord();
 	CSQC_CheckRevision();
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/client/View.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/View.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -281,7 +281,7 @@
 	// Draw the Crosshair
 	float scoreboard_active;
 	scoreboard_active = Sbar_WouldDrawScoreboard();
-	R_SetView(VF_DRAWCROSSHAIR, !scoreboard_active);
+	R_SetView(VF_DRAWCROSSHAIR, !scoreboard_active && !ons_showmap);
 	
 	// Draw the Engine Status Bar (the default Quake HUD)
 	R_SetView(VF_DRAWENGINESBAR, 0);
@@ -339,26 +339,11 @@
 	self = e;
 	
 	// draw radar
-	if(gametype == GAME_ONSLAUGHT)
+	if(teamplay)
 	{
-		if(cvar("cl_teamradar") >= 2)
-		{
-			if(!scoreboard_active)
-				teamradar_view();
-		}
-		else
-			ons_view();
-		//drawstring('0 0', minimapname, '8 8 0', '1 1 1', 1, 0);
-		//drawsetcliparea(0,0,800,600);
-		//drawresetcliparea();
+		if((cvar_string("cl_teamradar") != "0" && !scoreboard_active) || ons_showmap)
+			teamradar_view();
 	}
-	else if(teamplay)
-	{
-		//if(cvar("cl_teamradar") >= 1) // TODO change it back to this
-		if(cvar_string("cl_teamradar") != "0") // (so it is on by default)
-			if(!scoreboard_active)
-				teamradar_view();
-	}
 
 	// draw sbar
 	if(cvar("r_letterbox") == 0)

Modified: branches/nexuiz-2.0/data/qcsrc/client/hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/hook.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/hook.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -38,7 +38,7 @@
 	if(time >= self.HookKillTime)
 		return;
 	if(self.sv_entnum == player_localentnum - 1)
-		a = view_origin + view_forward * 8 - view_right * 8 + view_up * -12;
+		a = view_origin + view_forward * hook_shotorigin_x + view_right * hook_shotorigin_y + view_up * hook_shotorigin_z;
 	else
 		a = self.HookStart;
 	b = self.HookEnd;

Deleted: branches/nexuiz-2.0/data/qcsrc/client/ons.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/ons.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/ons.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1,61 +0,0 @@
-void() Cmd_ons_map =
-{
-	ons_showmap = !ons_showmap;
-};
-
-vector(vector coord) mapcoords =
-{
-	local vector ret;
-	ret = coord; // put that up to ret's definition and it's '0 0 0' ... stupid fteqcc
-	ret -= mi_center;
-	ret_x = ret_x * 256.0 / mi_scale_x;
-	ret_y = -ret_y * 256.0 / mi_scale_y;
-	ret_z = 0;
-	ret = ret + '400 178 0';
-	return ret;
-};
-
-void(vector coord, vector pangles, vector rgb) drawplayer =
-{
-	makevectors(pangles);
-	v_forward_z = 0;
-	v_forward = normalize(v_forward);
-	v_forward_y *= -1.0;
-	v_right_x = -v_forward_y;
-	v_right_y = v_forward_x;
-	// Ryling on !tex[0] => texture_white
-	// beware of the order, it has to be clockwise!
-	R_BeginPolygon("", 0);
-	R_PolygonVertex(coord+v_forward*2, '0 0 0', rgb, 1);
-	R_PolygonVertex(coord+v_right*3-v_forward*2, '0 1 0', rgb, 1);
-	R_PolygonVertex(coord-v_forward, '1 0 0', rgb, 1);
-	R_PolygonVertex(coord-v_right*3-v_forward*2, '1 1 0', rgb, 1);
-	R_EndPolygon();
-};
-
-void() ons_view =
-{
-	if(ons_showmap) {
-		local float color;
-		local vector coord, rgb;
-
-		color = GetPlayerColor(player_localentnum-1);
-		rgb = GetTeamRGB(color);
-
-		coord = mapcoords(pmove_org);
-			
-		drawpic('272 50 0', minimapname, '256 256 0', '1 1 1', 1, 0);
-		drawpic('257 35 0', "gfx/ons-frame.tga", '286 286 0', '1 1 1', 1, 0);
-		drawpic('257 35 0', "gfx/ons-frame-team.tga", '286 286 0', rgb, 1, 0);
-
-		drawplayer(coord, input_angles, '1 1 1');
-
-		local entity tm;
-		for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
-		if(GetPlayerColor(tm.sv_entnum) == color)
-		{
-			//print(strcat("GPS: ", ftos(tm.sv_entnum), " - ", vtos(tm.origin), "\n"));
-			drawplayer(mapcoords(tm.origin), tm.angles, rgb);
-		}
-	}
-};

Modified: branches/nexuiz-2.0/data/qcsrc/client/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/progs.src	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/progs.src	2008-10-22 14:22:57 UTC (rev 4817)
@@ -19,7 +19,6 @@
 miscfunctions.qc
 teamplay.qc
 
-ons.qc
 ctf.qc
 
 sbar.qc

Modified: branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/teamradar.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -119,6 +119,29 @@
 	}
 }
 
+void draw_teamradar_link(vector start, vector end, float colors)
+{
+	vector c0, c1, norm;
+
+	start = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(start));
+	end = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(end));
+	norm = normalize(start - end);
+	norm_z = norm_x;
+	norm_x = -norm_y;
+	norm_y = norm_z;
+	norm_z = 0;
+
+	c0 = colormapPaletteColor(colors & 0x0F, FALSE);
+	c1 = colormapPaletteColor((colors & 0xF0) / 0x10, FALSE);
+
+	R_BeginPolygon("", 0);
+	R_PolygonVertex(start - norm, '0 0 0', c0, 1);
+	R_PolygonVertex(start + norm, '0 1 0', c0, 1);
+	R_PolygonVertex(end + norm, '1 1 0', c1, 1);
+	R_PolygonVertex(end - norm, '1 0 0', c1, 1);
+	R_EndPolygon();
+}
+
 float cl_teamradar_scale;
 float cl_teamradar_background_alpha;
 float cl_teamradar_foreground_alpha;
@@ -129,24 +152,39 @@
 
 void teamradar_loadcvars()
 {
-	cl_teamradar_scale = cvar("cl_teamradar_scale");
-	cl_teamradar_background_alpha = cvar("cl_teamradar_background_alpha");
-	cl_teamradar_foreground_alpha = cvar("cl_teamradar_foreground_alpha");
-	cl_teamradar_rotation = cvar("cl_teamradar_rotation");
-	cl_teamradar_size = stov(cvar_string("cl_teamradar_size"));
-	cl_teamradar_position = stov(cvar_string("cl_teamradar_position"));
-	cl_teamradar_zoommode = cvar("cl_teamradar_zoommode");
+	if(ons_showmap)
+	{
+		cl_teamradar_scale = 42; // dummy, not used (see zoommode)
+		cl_teamradar_background_alpha = 1;
+		cl_teamradar_foreground_alpha = 1;
+		cl_teamradar_rotation = cvar("cl_teamradar_rotation");
+		if(!cl_teamradar_rotation)
+			cl_teamradar_rotation = 4;
+		cl_teamradar_size = '256 256 0'; // TODO make somewhat variable?
+		cl_teamradar_position = '0.5 0.5 0';
+		cl_teamradar_zoommode = 3;
+	}
+	else
+	{
+		cl_teamradar_scale = cvar("cl_teamradar_scale");
+		cl_teamradar_background_alpha = cvar("cl_teamradar_background_alpha");
+		cl_teamradar_foreground_alpha = cvar("cl_teamradar_foreground_alpha");
+		cl_teamradar_rotation = cvar("cl_teamradar_rotation");
+		cl_teamradar_size = stov(cvar_string("cl_teamradar_size"));
+		cl_teamradar_position = stov(cvar_string("cl_teamradar_position"));
+		cl_teamradar_zoommode = cvar("cl_teamradar_zoommode");
 
-	// others default to 0
-	// match this to defaultNexuiz.cfg!
-	if(!cl_teamradar_scale) cl_teamradar_scale = 4096;
-	if(!cl_teamradar_background_alpha) cl_teamradar_background_alpha = 0.4;
-	if(!cl_teamradar_foreground_alpha) cl_teamradar_foreground_alpha = 0.8;
-	if(!cl_teamradar_size_x) cl_teamradar_size_x = 128;
-	if(!cl_teamradar_size_y) cl_teamradar_size_y = cl_teamradar_size_x;
+		// others default to 0
+		// match this to defaultNexuiz.cfg!
+		if(!cl_teamradar_scale) cl_teamradar_scale = 4096;
+		if(!cl_teamradar_background_alpha) cl_teamradar_background_alpha = 0.4;
+		if(!cl_teamradar_foreground_alpha) cl_teamradar_foreground_alpha = 0.8;
+		if(!cl_teamradar_size_x) cl_teamradar_size_x = 128;
+		if(!cl_teamradar_size_y) cl_teamradar_size_y = cl_teamradar_size_x;
 
-	cl_teamradar_size_z = 0;
-	cl_teamradar_position_z = 0;
+		cl_teamradar_size_z = 0;
+		cl_teamradar_position_z = 0;
+	}
 }
 
 void() teamradar_view =
@@ -241,6 +279,31 @@
 	);
 
 	draw_teamradar_background(cl_teamradar_background_alpha, cl_teamradar_foreground_alpha);
+
+	if(ons_showmap)
+	{
+		drawresetcliparea();
+
+		vector frame_origin, frame_size;
+		frame_origin = frame_size = '0 0 0';
+
+		frame_origin_x = teamradar_origin2d_x - teamradar_size2d_x * 0.55859375;
+		frame_origin_y = teamradar_origin2d_y - teamradar_size2d_y * 0.55859375;
+		frame_size_x = teamradar_size2d_x * 1.1171875;
+		frame_size_y = teamradar_size2d_y * 1.1171875;
+		drawpic(frame_origin, "gfx/ons-frame.tga", frame_size, '1 1 1', 1, 0);
+		drawpic(frame_origin, "gfx/ons-frame-team.tga", frame_size, rgb, 1, 0);
+
+		drawsetcliparea(
+			teamradar_origin2d_x - teamradar_size2d_x * 0.5,
+			teamradar_origin2d_y - teamradar_size2d_y * 0.5,
+			teamradar_size2d_x,
+			teamradar_size2d_y
+		);
+	}
+
+	for(tm = world; (tm = find(tm, classname, "radarlink")); )
+		draw_teamradar_link(tm.origin, tm.velocity, tm.team);
 	for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
 		draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm.teamradar_time, tm.teamradar_color, tm.alpha);
 	for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
@@ -253,3 +316,39 @@
 
 	drawresetcliparea();
 };
+
+
+
+// radar links
+
+void Ent_RadarLink()
+{
+	float sendflags;
+	sendflags = ReadByte();
+
+	InterpolateOrigin_Undo();
+
+	self.iflags = IFLAG_VELOCITY;
+	self.classname = "radarlink";
+
+	if(sendflags & 1)
+	{
+		self.origin_x = ReadCoord();
+		self.origin_y = ReadCoord();
+		self.origin_z = ReadCoord();
+	}
+
+	if(sendflags & 2)
+	{
+		self.velocity_x = ReadCoord();
+		self.velocity_y = ReadCoord();
+		self.velocity_z = ReadCoord();
+	}
+
+	if(sendflags & 4)
+	{
+		self.team = ReadByte();
+	}
+
+	InterpolateOrigin_Note();
+}

Modified: branches/nexuiz-2.0/data/qcsrc/client/waypointsprites.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/waypointsprites.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/client/waypointsprites.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -11,6 +11,7 @@
 	return vec;
 }
 
+float waypointsprite_initialized;
 float waypointsprite_fadedistance;
 float waypointsprite_normdistance;
 float waypointsprite_minscale;
@@ -101,7 +102,9 @@
 				spriteimage = self.netname;
 			break;
 		case SPRITERULE_TEAMPLAY:
-			if(self.team == t)
+			if(t == COLOR_SPECTATOR + 1)
+				spriteimage = self.netname3;
+			else if(self.team == t)
 				spriteimage = self.netname2;
 			else
 				spriteimage = self.netname;
@@ -181,7 +184,14 @@
 
 	float vidscale;
 	vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
-	drawrotpic(o, rot * 90 * DEG2RAD, strcat("models/sprites/", spriteimage), SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, 0);
+
+	t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
+	if(t == 0)
+		spriteimage = strcat("models/sprites/", spriteimage);
+	else
+		spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor(time * 2), t)));
+
+	drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP);
 }
 
 void Ent_WaypointSprite()
@@ -268,4 +278,29 @@
 	waypointsprite_scale = cvar("g_waypointsprite_scale");
 	if(!waypointsprite_scale)
 		waypointsprite_scale = 1.0;
+
+	if(!waypointsprite_initialized)
+	{
+		float dh, n, i, o, f;
+		string s, sname, sframes;
+		dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
+		n = search_getsize(dh);
+		for(i = 0; i < n; ++i)
+		{
+			s = search_getfilename(dh, i);
+			if(substring(s, 0, 15) != "models/sprites/")
+				continue;
+			if(substring(s, strlen(s) - 4, 4) != ".tga")
+				continue;
+			s = substring(s, 15, strlen(s) - 19);
+
+			o = strstrofs(s, "_frame", 0);
+			sname = strcat("/spriteframes/", substring(s, 0, o));
+			sframes = substring(s, o + 6, strlen(s) - o - 6);
+			f = stof(sframes) + 1;
+			db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
+		}
+		search_end(dh);
+	}
+	waypointsprite_initialized = 1;
 }

Modified: branches/nexuiz-2.0/data/qcsrc/common/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-10-22 14:22:57 UTC (rev 4817)
@@ -20,7 +20,8 @@
 // Revision 19: fog
 // Revision 20: naggers
 // Revision 21: entcs for players optimized (position data down from 12 to 7 bytes); waypointsprites in csqc for team radar
-#define CSQC_REVISION 21
+// Revision 22: hook shot origin
+#define CSQC_REVISION 22
 
 // probably put these in common/
 // so server/ and client/ can be synced better
@@ -52,16 +53,19 @@
 const float ENT_CLIENT_LASER = 8;
 const float ENT_CLIENT_NAGGER = 9; // flags [votecalledvote]
 const float ENT_CLIENT_WAYPOINT = 10; // flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable]
+const float ENT_CLIENT_RADARLINK = 11; // flags [startorigin] [endorigin] [startcolor+16*endcolor]
 
-	const float SPRITERULE_DEFAULT = 0;
-	const float SPRITERULE_TEAMPLAY = 1;
+const float SPRITERULE_DEFAULT = 0;
+const float SPRITERULE_TEAMPLAY = 1;
 
-	const float RADARICON_FLAG = 1;
-	const float RADARICON_FLAGCARRIER = 1;
-	const float RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them
-	const float RADARICON_DANGER = 1;
-	const float RADARICON_WAYPOINT = 1;
-	const float RADARICON_HELPME = 1;
+const float RADARICON_FLAG = 1;
+const float RADARICON_FLAGCARRIER = 1;
+const float RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them
+const float RADARICON_DANGER = 1;
+const float RADARICON_WAYPOINT = 1;
+const float RADARICON_HELPME = 1;
+const float RADARICON_CONTROLPOINT = 1;
+const float RADARICON_GENERATOR = 1;
 
 ///////////////////////////
 // key constants
@@ -309,8 +313,9 @@
 float WEP_ROCKET_LAUNCHER	=  9; float WEPBIT_ROCKET_LAUNCHER	= 256;
 float WEP_PORTO				= 10; float WEPBIT_PORTO			= 512;
 float WEP_MINSTANEX			= 11; float WEPBIT_MINSTANEX		= 1024;
-float WEP_LAST				= 11; float WEPBIT_ALL              = 2047;
-float WEP_COUNT             = 12;
+float WEP_HOOK     			= 12; float WEPBIT_HOOK     		= 2048;
+float WEP_LAST				= 12; float WEPBIT_ALL              = 4095;
+float WEP_COUNT             = 13;
 
 float	IT_UNLIMITED_AMMO       = 1;
 // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.

Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -951,7 +951,7 @@
 	float data;
 	float end;
 	float i;
-	
+
 	_argc_sane = 0;
 	data = 0;
 	end = strlen(s);

Modified: branches/nexuiz-2.0/data/qcsrc/server/arena.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/arena.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/arena.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -17,6 +17,7 @@
 void dom_controlpoint_setup();
 void onslaught_generator_reset();
 void onslaught_controlpoint_reset();
+void func_breakable_reset();
 
 /**
  * Resets the state of all clients, items, flags, runes, keys, weapons, waypoints, ... of the map.
@@ -107,6 +108,10 @@
 		{
 			self.team = self.team_saved;
 		}
+		else if(self.classname == "func_breakable" || self.classname == "func_assault_destructible")
+		{
+			func_breakable_reset();
+		}
 	}
 
 	// Waypoints come LAST (keyhunt keys reference them)

Modified: branches/nexuiz-2.0/data/qcsrc/server/assault.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/assault.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/assault.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1,3 +1,5 @@
+void spawnfunc_func_breakable();
+
 //=============================================================================
 
 /*QUAKED spawnfunc_info_player_attacker (1 0 0) (-16 -16 -24) (16 16 45) INITIAL
@@ -194,59 +196,10 @@
 	}
 }
 
-void assault_destructible_use() {
-	self.cnt = 1; // mark active
-	self.takedamage = DAMAGE_YES;
-}
-
-void assault_destructible_destroy() {
-	self.model = "";
-	self.takedamage = DAMAGE_NO;
-	self.solid = SOLID_NOT;
-	SUB_UseTargets();
-}
-
-void assault_destructible_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) {
-
-	if(self.cnt > 0 && assault_attacker_team == attacker.team) {
-		self.health = self.health - damage;
-		if(self.health / self.max_health < 0.25)
-			self.colormod = '1 0 0';
-		else if(self.health / self.max_health < 0.375)
-			self.colormod = '1 0.25 0';
-		else if(self.health / self.max_health < 0.50)
-			self.colormod = '1 0.5 0';
-		else if(self.health / self.max_health < 0.625)
-			self.colormod = '1 0.75 0';
-		else if(self.health / self.max_health < 0.75)
-			self.colormod = '1 1 0';
-		else
-			self.colormod = '1 1 1';
-	}
-
-	if(self.health < 0) {
-		activator = attacker;
-		assault_destructible_destroy();
-	}
-}
-
 // destructible walls that can be used to trigger target_objective_decrease
 void spawnfunc_func_assault_destructible() {
-	if(!self.health)
-		self.health = 100;
-
-	self.max_health = self.health;
-
-	self.cnt = 0; // not yet activated
-
-	self.classname = "func_assault_destructible";
-	self.mdl = self.model;
-	setmodel(self, self.mdl);
-
-	self.solid = SOLID_BSP;
-	self.use = assault_destructible_use;
-	self.event_damage = assault_destructible_damage;
-
+	self.spawnflags = 3;
+	spawnfunc_func_breakable();
 }
 
 void assault_wall_think() {

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -807,6 +807,9 @@
 	WriteByte(MSG_ONE, maxclients);
 	for(i = 1; i <= 24; ++i)
 		WriteByte(MSG_ONE, (get_weaponinfo(i)).impulse + 1);
+	WriteCoord(MSG_ONE, hook_shotorigin_x);
+	WriteCoord(MSG_ONE, hook_shotorigin_y);
+	WriteCoord(MSG_ONE, hook_shotorigin_z);
 }
 
 /*
@@ -2266,6 +2269,7 @@
 .float idlekick_lasttimeleft;
 .float race_penalty;
 .float race_penalty_nagged;
+.float race_penalty_nagtime;
 void PlayerPostThink (void)
 {
 	// Savage: Check for nameless players
@@ -2323,16 +2327,28 @@
 							if(!self.race_penalty_nagged)
 							{
 								// TODO better notification for this!
-								centerprint_atprio(self, CENTERPRIO_IDLEKICK, "^1DO NOT MOVE DURING THE COUNTDOWN.");
+								self.race_penalty_nagtime = 0;
 								self.race_penalty_nagged = 1;
 							}
 						}
 						else if(!self.race_penalty)
 						{
-							centerprint_atprio(self, CENTERPRIO_IDLEKICK, "^1FIVE SECONDS PENALTY.");
+							self.race_penalty_nagtime = 0;
 							self.race_penalty = time + 5;
 						}
 					}
+					if(time > self.race_penalty_nagtime)
+					{
+						if(self.race_penalty > time)
+						{
+							centerprint_atprio(self, CENTERPRIO_IDLEKICK, "^1FIVE SECONDS PENALTY.");
+						}
+						else if(self.race_penalty_nagged && time < game_starttime - 2)
+						{
+							centerprint_atprio(self, CENTERPRIO_IDLEKICK, "^1DO NOT MOVE DURING THE COUNTDOWN.");
+						}
+						self.race_penalty_nagtime = time + self.cvar_scr_centertime * 0.6;
+					}
 					self.movetype = MOVETYPE_NONE;		
 					self.velocity = '0 0 0';
 					self.avelocity = '0 0 0';

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -451,5 +451,6 @@
 	register_weapon(WEP_ROCKET_LAUNCHER,  w_rlauncher, IT_ROCKETS,     9, 1, 10000, "rl",        "rocketlauncher",  "Rocket Launcher");
 	register_weapon(WEP_PORTO,            w_porto,     IT_SUPERWEAPON, 0, 0,     0, "porto" ,    "porto",           "Port-O-Launch");
 	register_weapon(WEP_MINSTANEX,        w_minstanex, IT_CELLS,       7, 0, 10000, "minstanex", "minstanex",       "MinstaNex");
+	register_weapon(WEP_HOOK,             w_hook,      IT_CELLS,       0, 0,     0, "hookgun",   "hook",            "Grappling Hook");
 	register_weapons_done();
 }

Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -221,9 +221,11 @@
 }
 
 //float ctf_clientcommand();
+float readyrestart_happened;
 void SV_ParseClientCommand(string s) {
 	local string cmd;
-	local float i, j, tokens;
+	local float i, j, tokens, f, effectnum;
+	local vector start, end;
 
 	tokens = tokenize_sane(s);
 
@@ -330,13 +332,16 @@
 				return sprint(self, "^1You cannot reset the game while a timeout is active!\n");
 			}
 			
-			if(game_starttime == 0 || cvar("sv_ready_restart_repeatable"))
+			//if(!restartAnnouncer)
 			{
-				self.ready = TRUE;
-				bprint(self.netname, "^2 is ready\n");
-				ReadyCount();
-			} else {
-				sprint(self, "^1game has already been restarted\n");
+				if(!readyrestart_happened || cvar("sv_ready_restart_repeatable"))
+				{
+					self.ready = TRUE;
+					bprint(self.netname, "^2 is ready\n");
+					ReadyCount();
+				} else {
+					sprint(self, "^1game has already been restarted\n");
+				}
 			}
 		}
 	} else if(argv(0) == "maplist") {
@@ -414,6 +419,36 @@
 		Score_NicePrint(self);
 	} else if(argv(0) == "cvar_changes") {
 		sprint(self, cvar_changes);
+	} else if(argv(0) == "pointparticles") {
+		if(sv_cheats && tokens == 5)
+		{
+			// arguments:
+			//   effectname
+			//   origin (0..1, on crosshair line)
+			//   velocity
+			//   howmany
+			effectnum = particleeffectnum(argv(1));
+			f = stof(argv(2));
+			start = (1-f) * self.origin + f * self.cursor_trace_endpos;
+			end = stov(argv(3));
+			f = stof(argv(4));
+			pointparticles(effectnum, start, end, f);
+		}
+		else
+			print("Usage: sv_cheats 1; restart; cmd pointparticles effectname position(0..1) velocityvector multiplier\n");
+	} else if(argv(0) == "trailparticles") {
+		if(sv_cheats && tokens == 3)
+		{
+			// arguments:
+			//   effectname
+			//   shot origin vector
+			effectnum = particleeffectnum(argv(1));
+			W_SetupShot(self, stov(argv(2)), FALSE, FALSE, "");
+			traceline(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, MOVE_NORMAL, self);
+			trailparticles(self, effectnum, w_shotorg, trace_endpos);
+		}
+		else
+			print("Usage: sv_cheats 1; restart; cmd trailparticles effectname shotorigin\n");
 	} else {
 		//if(ctf_clientcommand())
 		//	return;
@@ -461,6 +496,7 @@
 	if(checkrules_overtimeend)
 		checkrules_overtimeend = 0;
 
+	readyrestart_happened = 1;
 	game_starttime = time + RESTART_COUNTDOWN;
 	restart_mapalreadyrestarted = 0; //reset this var, needed when cvar sv_ready_restart_repeatable is in use
 
@@ -488,7 +524,7 @@
 	restartAnnouncer = spawn();
 	restartAnnouncer.think = restartAnnouncer_Think;
 	restartAnnouncer.nextthink = time;
-	restartAnnouncer.cnt = RESTART_COUNTDOWN;
+	restartAnnouncer.spawnflags = !!cvar("sv_ready_restart_after_countdown");
 	
 	//after a restart every players number of allowed timeouts gets reset, too
 	if(cvar("sv_timeout"))
@@ -552,8 +588,12 @@
 void restartAnnouncer_Think() {
 	local entity plr;
 	local string s;
-	if(self.cnt <= 0) { //show the "Begin" message and
-		if (cvar("sv_ready_restart_after_countdown")) {
+	float f, c;
+	c = game_starttime - time;
+	f = floor(0.5 + c);
+	if(c <= 0) { //show the "Begin" message and
+		if(self.spawnflags & 1)
+		{
 			restart_mapalreadyrestarted = 1;
 			reset_map();
 		}
@@ -572,16 +612,15 @@
 	else {
 		FOR_EACH_REALCLIENT(plr) {
 			if(plr.classname == "player") {
-				s = strcat(NEWLINES, "^1Game starts in ", ftos(self.cnt), " seconds");
+				s = strcat(NEWLINES, "^1Game starts in ", ftos(f), " seconds");
 				centerprint(plr, s);
 			}
 		}
 
-		if(self.cnt <= 3) {
-			play2all(strcat("announcer/robotic/", ftos(self.cnt), ".ogg"));
+		if(f <= 3) {
+			play2all(strcat("announcer/robotic/", ftos(f), ".ogg"));
 		}
-		self.nextthink = time + 1;
-		self.cnt -= 1;
+		self.nextthink = game_starttime - (f - 1);
 	}
 }
 

Copied: branches/nexuiz-2.0/data/qcsrc/server/func_breakable.qc (from rev 4809, trunk/data/qcsrc/server/func_breakable.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/func_breakable.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/func_breakable.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -0,0 +1,181 @@
+// TODO add assault's colormodding to this, make assault redirect to this one
+// TODO add the fields this uses to the entities.def when done
+
+.string mdl_dead; // or "" to hide when broken
+.string debris; // space separated list of debris models
+// other fields:
+//   mdl = particle effect name
+//   count = particle effect multiplier
+//   targetname = target to trigger to unbreak the model
+//   target = targets to trigger when broken
+//   health = amount of damage it can take
+//   spawnflags:
+//     1 = start disabled (needs to be triggered to activate)
+//     2 = indicate damage
+// notes:
+//   for mdl_dead to work, origin must be set (using a common/origin brush).
+//   Otherwise mdl_dead will be displayed at the map origin, and nobody would
+//   want that!
+
+.vector mins_save, maxs_save;
+
+void func_breakable_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+
+//
+// func_breakable
+// - basically func_assault_destructible for general gameplay use
+//
+void LaunchDebris (string debrisname) =
+{
+	local	entity dbr;
+
+	dbr = spawn();
+	dbr.origin = self.origin + self.absmin
+	           + '1 0 0' * random() * (self.absmax_x - self.absmin_x)
+	           + '0 1 0' * random() * (self.absmax_y - self.absmin_y)
+	           + '0 0 1' * random() * (self.absmax_z - self.absmin_z);
+	setmodel (dbr, debrisname );
+	dbr.movetype = MOVETYPE_BOUNCE;
+	dbr.solid = SOLID_NOT;
+	// TODO parametrize this
+	dbr.velocity_x = 70 * crandom();
+	dbr.velocity_y = 70 * crandom();
+	dbr.velocity_z = 140 + 70 * random();
+	dbr.avelocity_x = random()*600;
+	dbr.avelocity_y = random()*600;
+	dbr.avelocity_z = random()*600;
+	SUB_SetFade(dbr, time + 1 + random() * 5, 1);
+};
+
+void func_breakable_colormod()
+{
+	float h;
+	if not(self.spawnflags & 2)
+		return;
+	h = self.health / self.max_health;
+	if(h < 0.25)
+		self.colormod = '1 0 0';
+	else if(h <= 0.75)
+		self.colormod = '1 0 0' + '0 1 0' * (2 * h - 0.5);
+	else
+		self.colormod = '1 1 1';
+}
+
+void func_breakable_look_destroyed()
+{
+	if(self.mdl_dead == "")
+	{
+		self.model = "";
+		self.solid = SOLID_NOT;
+	}
+	else
+	{
+		setmodel(self, self.mdl_dead);
+		self.solid = SOLID_BSP;
+	}
+}
+
+void func_breakable_look_restore()
+{
+	setmodel(self, self.mdl);
+	self.solid = SOLID_BSP;
+}
+
+void func_breakable_behave_destroyed()
+{
+	self.health = self.max_health;
+	self.takedamage = DAMAGE_NO;
+	self.event_damage = SUB_Null;
+	self.state = 1;
+	setsize(self, '0 0 0', '0 0 0');
+	func_breakable_colormod();
+}
+
+void func_breakable_behave_restore()
+{
+	self.health = self.max_health;
+	self.takedamage = DAMAGE_AIM;
+	self.event_damage = func_breakable_damage;
+	self.state = 0;
+	setsize(self, self.mins_save, self.maxs_save);
+	func_breakable_colormod();
+}
+
+void func_breakable_destroyed()
+{
+	func_breakable_look_destroyed();
+	func_breakable_behave_destroyed();
+}
+
+void func_breakable_restore()
+{
+	func_breakable_look_restore();
+	func_breakable_behave_restore();
+}
+
+void func_breakable_destroy() {
+	float n, i;
+
+	func_breakable_destroyed();
+
+	// now throw around the debris
+	n = tokenize_sane(self.debris);
+	for(i = 0; i < n; ++i)
+		LaunchDebris(argv(i));
+
+	if(self.cnt)
+		pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count);
+
+	SUB_UseTargets();
+}
+
+void func_breakable_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if(self.state == 1)
+		return;
+	self.health = self.health - damage;
+	if(self.health < 0)
+	{
+		activator = attacker;
+		func_breakable_destroy();
+	}
+	func_breakable_colormod();
+}
+
+void func_breakable_reset()
+{
+	func_breakable_look_restore();
+	if(self.spawnflags & 1)
+		func_breakable_behave_destroyed();
+	else
+		func_breakable_behave_restore();
+}
+
+// destructible walls that can be used to trigger target_objective_decrease
+void spawnfunc_func_breakable() {
+	float n, i;
+	if(!self.health)
+		self.health = 100;
+	self.max_health = self.health;
+
+	if(self.mdl != "")
+		self.cnt = particleeffectnum(self.mdl);
+	if(self.count == 0)
+		self.count = 1;
+
+	self.mdl = self.model;
+	SetBrushEntityModel();
+	self.mins_save = self.mins;
+	self.maxs_save = self.mins;
+
+	self.use = func_breakable_restore;
+
+	// precache all the models
+	if (self.mdl_dead)
+		precache_model(self.mdl_dead);
+	n = tokenize_sane(self.debris);
+	for(i = 0; i < n; ++i)
+		precache_model(argv(i));
+
+	func_breakable_reset();
+}

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -130,7 +130,7 @@
 	self.nextthink = time;
 
 	makevectors(self.owner.v_angle);
-	org = self.owner.origin + self.owner.view_ofs + v_forward * 8 - v_right * 8 + v_up * -12;
+	org = self.owner.origin + self.owner.view_ofs + v_forward * hook_shotorigin_x + v_right * hook_shotorigin_y + v_up * hook_shotorigin_z;
 
 #if 0
 	tracebox(org, self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self.owner);
@@ -250,8 +250,6 @@
 
 			self.owner.flags (-) FL_ONGROUND;
 		}
-
-		org = org + dir*50; // get the beam out of the player's eyes
 	}
 
 	makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
@@ -326,7 +324,7 @@
 
 	// UGLY WORKAROUND: play this on CHAN_WEAPON2 so it can't cut off fire sounds
 	sound (self, CHAN_WEAPON2, "weapons/hook_fire.wav", VOL_BASE, ATTN_NORM);
-	org = self.origin + self.view_ofs + v_forward * 8 - v_right * 8 + '0 0 -12';
+	org = self.origin + self.view_ofs + v_forward * hook_shotorigin_x + v_right * hook_shotorigin_y + v_up * hook_shotorigin_z;
 	pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1);
 
 	missile = spawn ();
@@ -387,10 +385,10 @@
 		// offhand hook controls
 		if(self.BUTTON_HOOK)
 		{
-			if not(self.hook || (self.hook_state & HOOK_WAITING_FOR_REFIRE))
+			if not(self.hook || (self.hook_state & HOOK_WAITING_FOR_RELEASE))
 			{
 				self.hook_state |= HOOK_FIRING;
-				self.hook_state |= HOOK_WAITING_FOR_REFIRE;
+				self.hook_state |= HOOK_WAITING_FOR_RELEASE;
 			}
 		}
 		else
@@ -398,7 +396,7 @@
 			if(self.hook)
 			{
 				self.hook_state |= HOOK_REMOVING;
-				self.hook_state (-) HOOK_WAITING_FOR_REFIRE;
+				self.hook_state (-) HOOK_WAITING_FOR_RELEASE;
 			}
 		}
 
@@ -415,6 +413,12 @@
 		}
 	}
 
+	if(!g_grappling_hook && self.weapon != WEP_HOOK)
+	{
+		self.hook_state (-) HOOK_FIRING;
+		self.hook_state |= HOOK_REMOVING;
+	}
+
 	if (self.hook_state & HOOK_FIRING)
 	{
 		if (self.hook)
@@ -458,6 +462,14 @@
 	// note: The hook entity does the actual pulling
 }
 
+void GrappleHookInit()
+{
+	if(g_grappling_hook)
+		hook_shotorigin = '8 -8 -12';
+	else
+		hook_shotorigin = '25 8 -8';
+}
+
 void SetGrappleHookBindings()
 {
 	// this function has been modified for Nexuiz

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qh	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qh	2008-10-22 14:22:57 UTC (rev 4817)
@@ -10,5 +10,8 @@
 float HOOK_REMOVING = 2;
 float HOOK_PULLING = 4;
 float HOOK_RELEASING = 8;
-float HOOK_WAITING_FOR_REFIRE = 16;
+float HOOK_WAITING_FOR_RELEASE = 16;
 .float hook_state;
+
+void GrappleHookInit();
+vector hook_shotorigin;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -289,6 +289,7 @@
 
 	InitGameplayMode();
 	readlevelcvars();
+	GrappleHookInit();
 
 	player_count = 0;
 	bot_waypoints_for_items = cvar("g_waypoints_for_items");

Modified: branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/gamecommand.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -420,7 +420,7 @@
 	fh = fopen("effectinfo.txt", FILE_READ);
 	while((s = fgets(fh)))
 	{
-		tokenize_sane(s);
+		tokenize_insane(s); // tokenize_sane would hit the loop counter :(
 		if(argv(0) == "effect")
 		{
 			if(db_get(d, argv(1)) != "1")

Modified: branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/keyhunt.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -307,13 +307,13 @@
 			player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player;
 			WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY);
 			if(player.team == COLOR_TEAM1)
-				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "");
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red");
 			else if(player.team == COLOR_TEAM2)
-				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "");
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue");
 			else if(player.team == COLOR_TEAM3)
-				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "");
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow");
 			else if(player.team == COLOR_TEAM4)
-				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "");
+				WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink");
 			WaypointSprite_UpdateTeamRadar(player.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0));
 			if(!kh_no_radar_circles)
 				WaypointSprite_Ping(player.waypointsprite_attachedforcarrier);
@@ -339,7 +339,7 @@
 			FOR_EACH_KH_KEY(k)
 			{
 				if(k.owner)
-					WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model, "keycarrier-finish", "");
+					WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model, "keycarrier-finish", k.owner.waypointsprite_attachedforcarrier.model);
 			}
 		}
 		else
@@ -350,7 +350,7 @@
 			FOR_EACH_KH_KEY(k)
 			{
 				if(k.owner)
-					WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model, "keycarrier-friend", "");
+					WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model, "keycarrier-friend", k.owner.waypointsprite_attachedforcarrier.model);
 			}
 		}
 	}

Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -840,6 +840,12 @@
 			}
 		}
 	}
+
+	if(g_grappling_hook) // offhand hook
+	{
+		start_weapons (-) WEP_HOOK;
+		warmup_start_weapons (-) WEP_HOOK;
+	}
 }
 
 void readlevelcvars(void)
@@ -905,6 +911,18 @@
 	g_pickup_healthmega                = cvar("g_pickup_healthmega");
 	g_pickup_healthmega_max            = cvar("g_pickup_healthmega_max");
 
+	if not(inWarmupStage)
+	{
+		game_starttime                 = cvar("g_start_delay");
+		if(game_starttime)
+		{
+			restartAnnouncer = spawn();
+			restartAnnouncer.think = restartAnnouncer_Think;
+			restartAnnouncer.nextthink = time + 0.1;
+			restartAnnouncer.spawnflags = 0;
+		}
+	}
+
 	readplayerstartcvars();
 }
 
@@ -1441,100 +1459,6 @@
 						return 0;
 }
 
-//
-// func_breakable
-// - basically func_assault_destructible for general gameplay use
-//
-float () crandom;
-void () SUB_UseTargets, assault_destructible_use, SUB_Remove, SUB_Null;
-void LaunchDebris (string debrisname) =
-{
-	local	entity dbr;
-
-	if (debrisname == "" || !debrisname)
-		return;
-
-	dbr = spawn();
-	dbr.origin = self.origin;
-	setmodel (dbr, debrisname );
-	setsize (dbr, '0 0 0', '0 0 0');
-	dbr.velocity_x = 70 * crandom();
-	dbr.velocity_y = 70 * crandom();
-	dbr.velocity_z = 140 + 70 * random();
-	dbr.movetype = MOVETYPE_BOUNCE;
-	dbr.solid = SOLID_BBOX;
-	dbr.avelocity_x = random()*600;
-	dbr.avelocity_y = random()*600;
-	dbr.avelocity_z = random()*600;
-	dbr.think = SUB_Remove;
-	dbr.nextthink = time + 13 + random()*10;
-};
-
-.string debris1, debris2, debris3;
-.string mdl_dead;
-void func_breakable_destroy() {
-	if (self.mdl_dead)
-		setmodel(self, self.mdl_dead);
-	else {
-		self.model = "";
-		self.solid = SOLID_NOT;
-	}
-	self.takedamage = DAMAGE_NO;
-
-	// now throw around the debris
-	LaunchDebris(self.debris1);
-	LaunchDebris(self.debris2);
-	LaunchDebris(self.debris3);
-
-	SUB_UseTargets();
-
-	self.event_damage = SUB_Null;
-}
-
-void func_breakable_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) {
-
-	if(self.cnt > 0) {
-		self.health = self.health - damage;
-		// add pain effects?
-	}
-
-	if(self.health < 0) {
-		activator = attacker;
-		func_breakable_destroy();
-	}
-}
-
-// destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_breakable() {
-	if(!self.health)
-		self.health = 100;
-
-	self.max_health = self.health;
-
-	//self.cnt = 0; // not yet activated
-
-
-
-	self.classname = "func_breakable";
-	self.mdl = self.model;
-	setmodel(self, self.mdl);
-
-	self.solid = SOLID_BSP;
-
-	// precache all the models
-	if (self.mdl_dead)
-		precache_model(self.mdl_dead);
-	if (self.debris1)
-		precache_model(self.debris1);
-	if (self.debris2)
-		precache_model(self.debris2);
-	if (self.debris3)
-		precache_model(self.debris3);
-
-	self.use = assault_destructible_use;	// shared use function, b/c they woudl do the same thing anyways
-	self.event_damage = func_breakable_damage;
-}
-
 void Net_LinkEntity(entity e)
 {
 	e.model = "net_entity";

Modified: branches/nexuiz-2.0/data/qcsrc/server/mode_onslaught.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/mode_onslaught.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/mode_onslaught.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1,3 +1,7 @@
+void onslaught_generator_updatesprite(entity e);
+void onslaught_controlpoint_updatesprite(entity e);
+void onslaught_link_checkupdate();
+
 .entity sprite;
 .string target2;
 .float iscaptured;
@@ -8,13 +12,10 @@
 .float iscpneighbor_blue;
 .float isshielded;
 .float lasthealth;
+.float lastteam;
+.float lastshielded;
 
-#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
-float ons_sprite_cp_red, ons_sprite_cp_blue, ons_sprite_cp_neut;
-float ons_sprite_cp_atck_red, ons_sprite_cp_atck_blue, ons_sprite_cp_atck_neut;
-float ons_sprite_cp_dfnd_red, ons_sprite_cp_dfnd_blue;
-float ons_sprite_gen_red, ons_sprite_gen_blue, ons_sprite_gen_shielded;
-#endif
+.string model1, model2, model3;
 
 void onslaught_updatelinks()
 {
@@ -176,6 +177,7 @@
 				l.goalentity.bot_attack = TRUE;
 			}
 		}
+		onslaught_controlpoint_updatesprite(l);
 		l = l.chain;
 	}
 	// count generators owned by each team
@@ -190,6 +192,7 @@
 			if (l.team == COLOR_TEAM3) t3 = 1;
 			if (l.team == COLOR_TEAM4) t4 = 1;
 		}
+		onslaught_generator_updatesprite(l);
 		l = l.chain;
 	}
 	// see if multiple teams remain (if not, it's game over)
@@ -424,71 +427,139 @@
 	self.nextthink = time;
 };
 
-#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
-float onslaught_generator_waypointsprite_for_player(entity e)
+string onslaught_generator_waypointsprite_for_team(entity e, float t)
 {
-	if(e.classname == "player")
-		if(e.team == self.owner.team)
+	if(t == e.team)
+	{
+		if(e.team == COLOR_TEAM1)
+			return "ons-gen-red";
+		else if(e.team == COLOR_TEAM2)
+			return "ons-gen-blue";
+	}
+	if(e.isshielded)
+		return "ons-gen-shielded";
+	if(e.team == COLOR_TEAM1)
+		return "ons-gen-red";
+	else if(e.team == COLOR_TEAM2)
+		return "ons-gen-blue";
+	return "";
+}
+
+void onslaught_generator_updatesprite(entity e)
+{
+	string s1, s2, s3;
+	s1 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM1);
+	s2 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM2);
+	s3 = onslaught_generator_waypointsprite_for_team(e, -1);
+	WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+
+	if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
+	{
+		e.lastteam = e.team + 2;
+		e.lastshielded = e.isshielded;
+		if(e.lastshielded)
 		{
-			if(self.owner.team == COLOR_TEAM1)
-				return ons_sprite_gen_red;
-			else if(self.owner.team == COLOR_TEAM2)
-				return ons_sprite_gen_blue;
+			if(e.team == COLOR_TEAM1)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0 0');
+			else if(e.team == COLOR_TEAM2)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0 0 0.5');
+			else
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
 		}
-	if(self.owner.isshielded)
-		return ons_sprite_gen_shielded;
-	if(self.owner.team == COLOR_TEAM1)
-		return ons_sprite_gen_red;
-	else if(self.owner.team == COLOR_TEAM2)
-		return ons_sprite_gen_blue;
-	return 0;
+		else
+		{
+			if(e.team == COLOR_TEAM1)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '1 0 0');
+			else if(e.team == COLOR_TEAM2)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0 0 1');
+			else
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
+		}
+		WaypointSprite_Ping(e.sprite);
+	}
 }
 
-float onslaught_controlpoint_waypointsprite_for_player(entity e)
+string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
 {
 	float a;
-	if(e.classname == "player")
+	if(t != -1)
 	{
-		a = onslaught_controlpoint_attackable(self.owner, e.team);
+		a = onslaught_controlpoint_attackable(e, t);
 		if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
 		{
-			if(self.owner.team == COLOR_TEAM1)
-				return ons_sprite_cp_atck_red;
-			else if(self.owner.team == COLOR_TEAM2)
-				return ons_sprite_cp_atck_blue;
+			if(e.team == COLOR_TEAM1)
+				return "ons-cp-atck-red";
+			else if(e.team == COLOR_TEAM2)
+				return "ons-cp-atck-blue";
 			else
-				return ons_sprite_cp_atck_neut;
+				return "ons-cp-atck-neut";
 		}
 		else if(a == -2) // DEFEND THIS ONE NOW
 		{
-			if(self.owner.team == COLOR_TEAM1)
-				return ons_sprite_cp_dfnd_red;
-			else if(self.owner.team == COLOR_TEAM2)
-				return ons_sprite_cp_dfnd_blue;
+			if(e.team == COLOR_TEAM1)
+				return "ons-cp-dfnd-red";
+			else if(e.team == COLOR_TEAM2)
+				return "ons-cp-dfnd-blue";
 		}
-		else if(self.owner.team == e.team || a == -1 || a == 1) // own point, or fire at it
+		else if(e.team == t || a == -1 || a == 1) // own point, or fire at it
 		{
-			if(self.owner.team == COLOR_TEAM1)
-				return ons_sprite_cp_red;
-			else if(self.owner.team == COLOR_TEAM2)
-				return ons_sprite_cp_blue;
+			if(e.team == COLOR_TEAM1)
+				return "ons-cp-red";
+			else if(e.team == COLOR_TEAM2)
+				return "ons-cp-blue";
 		}
 		else if(a == 2) // touch it
-			return ons_sprite_cp_neut;
+			return "ons-cp-neut";
 	}
 	else
 	{
-		if(self.owner.team == COLOR_TEAM1)
-			return ons_sprite_cp_red;
-		else if(self.owner.team == COLOR_TEAM2)
-			return ons_sprite_cp_blue;
+		if(e.team == COLOR_TEAM1)
+			return "ons-cp-red";
+		else if(e.team == COLOR_TEAM2)
+			return "ons-cp-blue";
 		else
-			return ons_sprite_cp_neut;
+			return "ons-cp-neut";
 	}
-	return 0;
+	return "";
 }
-#endif
 
+void onslaught_controlpoint_updatesprite(entity e)
+{
+	string s1, s2, s3;
+	s1 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM1);
+	s2 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM2);
+	s3 = onslaught_controlpoint_waypointsprite_for_team(e, -1);
+	WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+
+	float sh;
+	sh = !(onslaught_controlpoint_can_be_linked(e, COLOR_TEAM1) || onslaught_controlpoint_can_be_linked(e, COLOR_TEAM2));
+
+	if(e.lastteam != e.team + 2 || e.lastshielded != sh)
+	{
+		e.lastteam = e.team + 2;
+		e.lastshielded = sh;
+		if(e.lastshielded)
+		{
+			if(e.team == COLOR_TEAM1)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0 0');
+			else if(e.team == COLOR_TEAM2)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0 0 0.5');
+			else
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0.5 0.5');
+		}
+		else
+		{
+			if(e.team == COLOR_TEAM1)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '1 0 0');
+			else if(e.team == COLOR_TEAM2)
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0 0 1');
+			else
+				WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
+		}
+		WaypointSprite_Ping(e.sprite);
+	}
+}
+
 /*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
 Base generator.
 
@@ -506,45 +577,6 @@
 		return;
 	}
 
-#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
-	if(!ons_sprite_cp_blue)
-	{
-		precache_model("models/sprites/ons-cp-blue.sp2");
-		setmodel(self, "models/sprites/ons-cp-blue.sp2");
-		ons_sprite_cp_blue = self.modelindex;
-		precache_model("models/sprites/ons-cp-red.sp2");
-		setmodel(self, "models/sprites/ons-cp-red.sp2");
-		ons_sprite_cp_red = self.modelindex;
-		precache_model("models/sprites/ons-cp-neut.sp2");
-		setmodel(self, "models/sprites/ons-cp-neut.sp2");
-		ons_sprite_cp_neut = self.modelindex;
-		precache_model("models/sprites/ons-cp-dfnd-blue.sp2");
-		setmodel(self, "models/sprites/ons-cp-dfnd-blue.sp2");
-		ons_sprite_cp_dfnd_blue = self.modelindex;
-		precache_model("models/sprites/ons-cp-dfnd-red.sp2");
-		setmodel(self, "models/sprites/ons-cp-dfnd-red.sp2");
-		ons_sprite_cp_dfnd_red = self.modelindex;
-		precache_model("models/sprites/ons-cp-atck-blue.sp2");
-		setmodel(self, "models/sprites/ons-cp-atck-blue.sp2");
-		ons_sprite_cp_atck_blue = self.modelindex;
-		precache_model("models/sprites/ons-cp-atck-red.sp2");
-		setmodel(self, "models/sprites/ons-cp-atck-red.sp2");
-		ons_sprite_cp_atck_red = self.modelindex;
-		precache_model("models/sprites/ons-cp-atck-neut.sp2");
-		setmodel(self, "models/sprites/ons-cp-atck-neut.sp2");
-		ons_sprite_cp_atck_neut = self.modelindex;
-		precache_model("models/sprites/ons-gen-blue.sp2");
-		setmodel(self, "models/sprites/ons-gen-blue.sp2");
-		ons_sprite_gen_blue = self.modelindex;
-		precache_model("models/sprites/ons-gen-red.sp2");
-		setmodel(self, "models/sprites/ons-gen-red.sp2");
-		ons_sprite_gen_red = self.modelindex;
-		precache_model("models/sprites/ons-gen-shielded.sp2");
-		setmodel(self, "models/sprites/ons-gen-shielded.sp2");
-		ons_sprite_gen_shielded = self.modelindex;
-	}
-#endif
-
 	local entity e;
 	precache_model("models/onslaught/generator.md3");
 	precache_model("models/onslaught/generator_shield.md3");
@@ -581,10 +613,10 @@
 	self.think = onslaught_generator_delayed;
 	self.nextthink = time + 0.2;
 
-#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
 	WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite);
-	self.sprite.waypointsprite_for_player = onslaught_generator_waypointsprite_for_player;
-#endif
+	WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
+
+	onslaught_updatelinks();
 };
 
 void onslaught_generator_reset()
@@ -778,14 +810,13 @@
 	//setsize(e, '-32 -32 0', '32 32 128');
 	setorigin(e, self.origin);
 	e.colormap = self.colormap;
-	onslaught_updatelinks();
 
 	waypoint_spawnforitem(self);
 
-#ifdef YOU_HAVE_FIXED_ONSLAUGHT_WAYPOINTS
 	WaypointSprite_SpawnFixed(string_null, e.origin + '0 0 1' * e.maxs_z, self, sprite);
-	self.sprite.waypointsprite_for_player = onslaught_controlpoint_waypointsprite_for_player;
-#endif
+	WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
+
+	onslaught_updatelinks();
 };
 
 void onslaught_controlpoint_reset()
@@ -809,6 +840,71 @@
 	SUB_UseTargets(); // to reset the structures, playerspawns etc.
 }
 
+float onslaught_link_send(entity to, float sendflags)
+{
+	WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
+	WriteByte(MSG_ENTITY, sendflags);
+	if(sendflags & 1)
+	{
+		WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
+		WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
+		WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
+	}
+	if(sendflags & 2)
+	{
+		WriteCoord(MSG_ENTITY, self.enemy.origin_x);
+		WriteCoord(MSG_ENTITY, self.enemy.origin_y);
+		WriteCoord(MSG_ENTITY, self.enemy.origin_z);
+	}
+	if(sendflags & 4)
+	{
+		WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
+	}
+	return TRUE;
+}
+
+void onslaught_link_checkupdate()
+{
+	// TODO check if the two sides have moved (currently they won't move anyway)
+	float redpower, bluepower;
+
+	redpower = bluepower = 0;
+	if(self.goalentity.islinked)
+	{
+		if(self.goalentity.team == COLOR_TEAM1)
+			redpower = 1;
+		else if(self.goalentity.team == COLOR_TEAM2)
+			bluepower = 1;
+	}
+	if(self.enemy.islinked)
+	{
+		if(self.enemy.team == COLOR_TEAM1)
+			redpower = 2;
+		else if(self.enemy.team == COLOR_TEAM2)
+			bluepower = 2;
+	}
+
+	float cc;
+	if(redpower == 1 && bluepower == 2)
+		cc = (COLOR_TEAM1 - 1) * 0x01 + (COLOR_TEAM2 - 1) * 0x10;
+	else if(redpower == 2 && bluepower == 1)
+		cc = (COLOR_TEAM1 - 1) * 0x10 + (COLOR_TEAM2 - 1) * 0x01;
+	else if(redpower)
+		cc = (COLOR_TEAM1 - 1) * 0x11;
+	else if(bluepower)
+		cc = (COLOR_TEAM2 - 1) * 0x11;
+	else
+		cc = 0;
+
+	if(cc != self.clientcolors)
+	{
+		self.clientcolors = cc;
+		self.SendFlags |= 4;
+	}
+
+	self.nextthink = time;
+}
+
 void onslaught_link_delayed()
 {
 	self.goalentity = find(world, targetname, self.target);
@@ -818,6 +914,10 @@
 	if (!self.enemy)
 		objerror("can not find target2\n");
 	dprint(etos(self.goalentity), " linked with ", etos(self.enemy), "\n");
+
+	self.SendFlags |= 3;
+	self.think = onslaught_link_checkupdate;
+	self.nextthink = time;
 }
 
 /*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
@@ -840,4 +940,6 @@
 		objerror("target and target2 must be set\n");
 	self.think = onslaught_link_delayed;
 	self.nextthink = time + 0.1;
+	self.SendEntity = onslaught_link_send;
+	Net_LinkEntity(self);
 };

Modified: branches/nexuiz-2.0/data/qcsrc/server/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/progs.src	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/progs.src	2008-10-22 14:22:57 UTC (rev 4817)
@@ -83,6 +83,7 @@
 w_hagar.qc
 w_rocketlauncher.qc
 w_porto.qc
+w_hook.qc
 
 t_items.qc
 cl_weapons.qc
@@ -140,3 +141,4 @@
 portals.qc
 
 target_spawn.qc
+func_breakable.qc

Modified: branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -93,6 +93,11 @@
 						valueent = world;
 					value = "";
 				}
+				else if(value == "target")
+				{
+					valueent = e;
+					value = "";
+				}
 				else if(value == "time")
 				{
 					valueent = world;

Modified: branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -392,7 +392,7 @@
 		local string specString;
 		specString = NEWLINES;
 		if(time < game_starttime) //also show the countdown when being a spectator
-			specString = strcat(specString, "\n\n^1Game starts in ", ftos(restartAnnouncer.cnt + 1), " seconds^7");
+			specString = strcat(specString, "\n\n^1Game starts in ", ftos(ceil(game_starttime - time)), " seconds^7");
 		else if (timeoutStatus != 0)
 			specString = strcat(specString, "\n\n", getTimeoutText(1));
 		else

Copied: branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc (from rev 4809, trunk/data/qcsrc/server/w_hook.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -0,0 +1,153 @@
+void W_Hook_Explode2 (void)
+{
+	vector org2;
+
+	org2 = findbetterlocation (self.origin, 12);
+	pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1);
+	sound (self, CHAN_PROJECTILE, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM);
+
+	self.event_damage = SUB_Null;
+	RadiusDamage (self, self.owner, cvar("g_balance_hook_secondary_damage"), cvar("g_balance_hook_secondary_edgedamage"), cvar("g_balance_hook_secondary_radius"), self.owner, cvar("g_balance_hook_secondary_force"), self.projectiledeathtype, other);
+
+	remove(self);
+}
+
+void W_Hook_Touch2 (void)
+{
+	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+	{
+		remove(self);
+		return;
+	}
+	self.use();
+}
+
+void W_Hook_Attack2()
+{
+	local entity gren;
+
+	if not(self.items & IT_UNLIMITED_AMMO)
+		self.ammo_cells = self.ammo_cells - cvar("g_balance_hook_secondary_ammo");
+	W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/hookbomb_fire.wav");
+
+	gren = spawn ();
+	gren.owner = self;
+	gren.classname = "hookbomb";
+	gren.bot_dodge = TRUE;
+	gren.bot_dodgerating = cvar("g_balance_hook_secondary_damage");
+	gren.movetype = MOVETYPE_TOSS;
+	gren.solid = SOLID_BBOX;
+	gren.effects = EF_LOWPRECISION;
+	gren.modelflags = MF_TRACER2;
+	gren.projectiledeathtype = WEP_HOOK | HITTYPE_SECONDARY;
+	setmodel(gren, "models/grenademodel.md3"); // precision set above // FIXME replace
+	setsize(gren, '0 0 0', '0 0 0');
+	setorigin(gren, w_shotorg);
+
+	gren.nextthink = time + cvar("g_balance_hook_secondary_lifetime");
+	gren.think = adaptor_think2use;
+	gren.use = W_Hook_Explode2;
+	gren.touch = W_Hook_Touch2;
+	gren.velocity = '0 0 1' * cvar("g_balance_hook_secondary_speed");
+	gren.gravity = cvar("g_balance_hook_secondary_gravity");
+	//W_SetupProjectileVelocity(gren); // just falling down!
+
+	gren.angles = '0 0 0';
+	gren.flags = FL_PROJECTILE;
+}
+
+void spawnfunc_weapon_hook (void)
+{
+	if(g_grappling_hook) // offhand hook
+	{
+		startitem_failed = TRUE;
+		remove(self);
+		return;
+	}
+	weapon_defaultspawnfunc(WEP_HOOK);
+}
+
+float w_hook(float req)
+{
+	if (req == WR_AIM)
+	{
+		// ... sorry ...
+	}
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK || self.BUTTON_HOOK)
+		{
+			if(!self.hook)
+			if not(self.hook_state & HOOK_WAITING_FOR_RELEASE)
+			if (weapon_prepareattack(0, cvar("g_balance_hook_primary_refire")))
+			{
+				if not(self.items & IT_UNLIMITED_AMMO)
+					self.ammo_cells = self.ammo_cells - cvar("g_balance_hook_primary_ammo");
+				self.hook_state |= HOOK_FIRING;
+				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hook_primary_animtime"), w_ready);
+			}
+		}
+
+		if (self.BUTTON_ATCK2)
+		{
+			if (weapon_prepareattack(1, cvar("g_balance_hook_secondary_refire")))
+			{
+				W_Hook_Attack2();
+				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_hook_secondary_animtime"), w_ready);
+			}
+		}
+
+		if (self.BUTTON_CROUCH)
+		{
+			self.hook_state (-) HOOK_PULLING;
+			if (self.BUTTON_ATCK || self.BUTTON_HOOK)
+				self.hook_state (-) HOOK_RELEASING;
+			else
+				self.hook_state |= HOOK_RELEASING;
+		}
+		else
+		{
+			self.hook_state |= HOOK_PULLING;
+			self.hook_state (-) HOOK_RELEASING;
+
+			if (self.BUTTON_ATCK || self.BUTTON_HOOK)
+			{
+				// already fired
+				if(self.hook)
+					self.hook_state |= HOOK_WAITING_FOR_RELEASE;
+			}
+			else
+			{
+				self.hook_state |= HOOK_REMOVING;
+				self.hook_state (-) HOOK_WAITING_FOR_RELEASE;
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_hook.md3");
+		precache_model ("models/weapons/v_hook.md3");
+		precache_model ("models/weapons/w_hook.zym");
+		precache_sound ("weapons/hook_fire.wav");
+		precache_sound ("weapons/hook_impact.wav");
+		precache_sound ("weapons/hookbomb_fire.wav");
+		precache_sound ("weapons/hookbomb_impact.wav");
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_HOOK);
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		return self.ammo_cells >= cvar("g_balance_hook_primary_ammo");
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		return self.ammo_cells >= cvar("g_balance_hook_secondary_ammo");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+		w_deathtypestring = "did the impossible";
+	else if (req == WR_KILLMESSAGE)
+		w_deathtypestring = "has run into #'s gravity bomb";
+	return TRUE;
+};

Modified: branches/nexuiz-2.0/data/qcsrc/server/waypointsprites.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/waypointsprites.qc	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/qcsrc/server/waypointsprites.qc	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1,5 +1,6 @@
 ..entity owned_by_field;
 .float rule;
+.string model1;
 .string model2;
 .string model3;
 
@@ -7,9 +8,9 @@
 
 void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3)
 {
-	if(m1 != e.model)
+	if(m1 != e.model1)
 	{
-		e.model = m1;
+		e.model1 = m1;
 		e.SendFlags |= 2;
 	}
 	if(m2 != e.model2)
@@ -175,7 +176,7 @@
 	}
 
 	if(sendflags & 2)
-		WriteString(MSG_ENTITY, self.model);
+		WriteString(MSG_ENTITY, self.model1);
 
 	if(sendflags & 4)
 		WriteString(MSG_ENTITY, self.model2);
@@ -242,7 +243,8 @@
 	wp.think = WaypointSprite_Think;
 	wp.nextthink = time;
 	wp.effects = EF_NODEPTHTEST | EF_LOWPRECISION;
-	wp.model = spr;
+	wp.model1 = spr;
+	wp.model = "net_entity";
 	wp.modelindex = 1;
 	wp.SendEntity = WaypointSprite_SendEntity;
 	wp.customizeentityforclient = WaypointSprite_Customize;

Modified: branches/nexuiz-2.0/data/scripts/entities.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/entities.def	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/scripts/entities.def	2008-10-22 14:22:57 UTC (rev 4817)
@@ -1059,7 +1059,7 @@
 model="models/weapons/g_porto.md3"
 */
 
-/*QUAKED target_items (0 0 1) ? AND OR ANDNOT
+/*QUAKED target_items (0 0 1) (-8 -8 -8) (8 8 8) AND OR ANDNOT
 Sets the items of any player who triggers this.
 For the number fields, not specifying a value means not changing it. To clear armor, you need to explicitly set "armor" to "-1".
 You may want to target this by a race checkpoint, a teleporter, or a trigger_multiple with ALLENTS set (so it removes weapons thrown through the field to avoid getting a weapon through it).
@@ -1082,7 +1082,7 @@
 */
 
 /*QUAKED target_spawn (1 0 1) (-8 -8 -8) (8 8 8) - ONLOAD
-Spawns an entity when triggered.
+Spawns or modifies an entity when triggered.
 The entity field list is a single string of the form:
 'field' 'value' 'field' 'value' ... 'classname' 'item_bullets' ... 'field' 'value'
 The special "field" name $ calls a void(void) function, for example a spawn function.
@@ -1091,7 +1091,7 @@
 $E.field
 $E.field+offset
 $E.field+offset+randomoffset
-where "E" can be self, activator and pusher.
+where "E" can be self, activator, target (the entity being created/modified) and pusher.
 Example is a Mario-style question mark block which could throw a new weapon_nex when activated like this:
 {
 "classname" "func_button"
@@ -1115,3 +1115,20 @@
 -------- SPAWNFLAGS --------
 ONLOAD: create a first entity on map load
 */
+
+/*QUAKED func_breakable (1 0 0) ? DISABLED INDICATE
+This is a brush model which can be damaged.
+Once all health is consumed it'll disappear and trigger the targeted entity/entities.
+When triggered, it resets to full health, and unbreaks.
+-------- KEYS --------
+health: The damage this trigger can take
+target: The entity/entities to be triggered once this entity gets invisible
+targetname: The name other entities can use to target this entity
+mdl: particle effect name to show when destroyed
+count: particle effect multiplier
+mdl_dead: optional replacement model to show when destroyed
+debris: names of debris models to show when destroyed, separated by spaces
+-------- SPAWNFLAGS --------
+DISABLED: do not allow damaging this until it is first activated
+INDICATE: indicate amount of damage already taken by coloring
+*/

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

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

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

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

Modified: branches/nexuiz-2.0/data/turrets.cfg
===================================================================
--- branches/nexuiz-2.0/data/turrets.cfg	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/turrets.cfg	2008-10-22 14:22:57 UTC (rev 4817)
@@ -8,12 +8,13 @@
 exec unit_fusreac.cfg	
 exec unit_mlrs.cfg
 exec unit_hellion.cfg
-//exec unit_gauss.cfg
 exec unit_flac.cfg
 exec unit_minigun.cfg
 exec unit_tesla.cfg
-exec unit_walker.cfg
 exec unit_machinegun.cfg
 exec unit_phaser.cfg
 
-set g_turrets_reloadcvars 1
+// not exec'd: gauss, walker
+
+set g_turrets_reloadcvars 1 // reload when this cfg has been exec'd
+alias g_turrets_reload "set g_turrets_reloadcvars 1"

Modified: branches/nexuiz-2.0/data/weapons.cfg
===================================================================
--- branches/nexuiz-2.0/data/weapons.cfg	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/weapons.cfg	2008-10-22 14:22:57 UTC (rev 4817)
@@ -9,6 +9,7 @@
 set g_start_weapon_rocketlauncher 0
 set g_start_weapon_minstanex 0
 set g_start_weapon_porto 0
+set g_start_weapon_hook 0
 set g_start_ammo_shells 50
 set g_start_ammo_nails 0
 set g_start_ammo_rockets 0
@@ -225,3 +226,18 @@
 set g_balance_porto_primary_ammo 25
 set g_balance_portal_health 200 // these get recharged whenever the portal is used
 set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+
+// TESTING: on-hand hook with bomb
+set g_balance_hook_primary_ammo 0 // hook monkeys
+set g_balance_hook_primary_refire 0 // hook monkeys
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 800 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 25 // a whole pack
+set g_balance_hook_secondary_lifetime 30 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim

Modified: branches/nexuiz-2.0/data/weaponsPro.cfg
===================================================================
--- branches/nexuiz-2.0/data/weaponsPro.cfg	2008-10-22 14:22:02 UTC (rev 4816)
+++ branches/nexuiz-2.0/data/weaponsPro.cfg	2008-10-22 14:22:57 UTC (rev 4817)
@@ -9,6 +9,7 @@
 set g_start_weapon_rocketlauncher 0
 set g_start_weapon_minstanex 0
 set g_start_weapon_porto 0
+set g_start_weapon_hook 0
 set g_start_ammo_shells 40
 set g_start_ammo_nails 0
 set g_start_ammo_rockets 0
@@ -104,6 +105,7 @@
 set g_balance_grenadelauncher_secondary_refire 0.5
 set g_balance_grenadelauncher_secondary_animtime 0.3
 set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 10
 
 set g_balance_electro_primary_damage 50
 set g_balance_electro_primary_edgedamage 10
@@ -125,6 +127,7 @@
 set g_balance_electro_secondary_refire 0.3
 set g_balance_electro_secondary_animtime 0.3
 set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 5
 set g_balance_electro_combo_damage 70
 set g_balance_electro_combo_edgedamage 0
 set g_balance_electro_combo_force 200
@@ -220,3 +223,20 @@
 set g_balance_porto_primary_speed 2000
 set g_balance_porto_primary_lifetime 30
 set g_balance_porto_primary_ammo 25
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+
+// TESTING: on-hand hook with bomb
+set g_balance_hook_primary_ammo 0 // hook monkeys
+set g_balance_hook_primary_refire 0 // hook monkeys
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 800 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 25 // a whole pack
+set g_balance_hook_secondary_lifetime 30 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim

Copied: branches/nexuiz-2.0/modelsource/hookgun.zip (from rev 4809, trunk/modelsource/hookgun.zip)
===================================================================
(Binary files differ)




More information about the nexuiz-commits mailing list