r4977 - in branches/nexuiz-2.0: . Docs/server/rcon2irc data data/maps data/models/turrets data/models/turrets/radiant data/qcsrc/common data/qcsrc/menu data/qcsrc/menu/item data/qcsrc/menu/nexuiz data/qcsrc/server data/qcsrc/server/tturrets/include data/qcsrc/server/tturrets/system data/qcsrc/server/tturrets/units data/scripts data/textures misc

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Tue Nov 4 06:54:27 EST 2008


Author: div0
Date: 2008-11-04 06:54:16 -0500 (Tue, 04 Nov 2008)
New Revision: 4977

Added:
   branches/nexuiz-2.0/data/models/turrets/ewheel-base.md3
   branches/nexuiz-2.0/data/models/turrets/ewheel-base.tga
   branches/nexuiz-2.0/data/models/turrets/ewheel-gun1.md3
   branches/nexuiz-2.0/data/models/turrets/ewheel-gun1.tga
   branches/nexuiz-2.0/data/models/turrets/radiant/ewheel.md3
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/demolist.c
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_demo.c
   branches/nexuiz-2.0/data/qcsrc/server/movelib.qc
   branches/nexuiz-2.0/data/qcsrc/server/steerlib.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_ewheel.qc
   branches/nexuiz-2.0/data/textures/seeker_gloss.tga
   branches/nexuiz-2.0/data/textures/seeker_glow.tga
   branches/nexuiz-2.0/data/textures/seeker_norm.tga
   branches/nexuiz-2.0/data/textures/seeker_pants.tga
   branches/nexuiz-2.0/data/unit_ewheel.cfg
Removed:
   branches/nexuiz-2.0/data/maps/campaignmappack.txt
Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   branches/nexuiz-2.0/data/effectinfo.txt
   branches/nexuiz-2.0/data/maps/ons-reborn.map
   branches/nexuiz-2.0/data/mutator_reset.cfg
   branches/nexuiz-2.0/data/qcsrc/common/campaign_common.qh
   branches/nexuiz-2.0/data/qcsrc/common/campaign_file.qc
   branches/nexuiz-2.0/data/qcsrc/menu/classes.c
   branches/nexuiz-2.0/data/qcsrc/menu/item/modalcontroller.c
   branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh
   branches/nexuiz-2.0/data/qcsrc/menu/menu.qc
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/campaign.c
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings.c
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_misc.c
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_singleplayer.c
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/mainwindow.c
   branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/tab.c
   branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc
   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_player.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc
   branches/nexuiz-2.0/data/qcsrc/server/defs.qh
   branches/nexuiz-2.0/data/qcsrc/server/g_casings.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
   branches/nexuiz-2.0/data/qcsrc/server/g_violence.qc
   branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/server/pathlib.qc
   branches/nexuiz-2.0/data/qcsrc/server/portals.qc
   branches/nexuiz-2.0/data/qcsrc/server/progs.src
   branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
   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/tturrets/include/turrets.qh
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets_early.qh
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_damage.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_main.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_checkpoint.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hellion.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hk.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_mlrs.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_plasma.qc
   branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_walker.qc
   branches/nexuiz-2.0/data/qcsrc/server/vote.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_hlac.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_seeker.qc
   branches/nexuiz-2.0/data/scripts/entities.def
   branches/nexuiz-2.0/data/scripts/turrets.def
   branches/nexuiz-2.0/data/textures/seeker.tga
   branches/nexuiz-2.0/data/turrets.cfg
   branches/nexuiz-2.0/data/unit_flac.cfg
   branches/nexuiz-2.0/data/unit_machinegun.cfg
   branches/nexuiz-2.0/data/unit_walker.cfg
   branches/nexuiz-2.0/data/weapons.cfg
   branches/nexuiz-2.0/misc/makebuild.sh
Log:
r4931 | tzork | 2008-10-29 07:21:55 +0100 (Wed, 29 Oct 2008) | 7 lines
Updated pathlib.qc
Turrets updates:
Fixed recursive radiusdamage hell. 
Cleaned up system_damage.qc more. added RFL_DMG_DEATH_NOGIBS for damage_flags to avoid std gibs.
Added unit_ewheel.
Temporarily disabled walker pathing until i have time to fix it.r4934 | div0 | 2008-10-29 10:39:19 +0100 (Wed, 29 Oct 2008) | 2 lines
enable OS X for testing again
r4935 | div0 | 2008-10-29 10:56:39 +0100 (Wed, 29 Oct 2008) | 2 lines
make 10.4 compat binaries
r4936 | div0 | 2008-10-29 10:57:34 +0100 (Wed, 29 Oct 2008) | 2 lines
typo
r4937 | tzork | 2008-10-29 14:41:12 +0100 (Wed, 29 Oct 2008) | 1 line
Oops forgot unit_ewheel.qc
r4938 | tzork | 2008-10-29 20:19:14 +0100 (Wed, 29 Oct 2008) | 1 line
turret_stdproc_use team changes the turret to its .target by default now.
r4939 | tzork | 2008-10-29 20:48:32 +0100 (Wed, 29 Oct 2008) | 2 lines
turret_stdproc_use team changes the turret to its *activator* now.
no need for the special turrets case in assault anymore.
r4940 | div0 | 2008-10-30 11:28:10 +0100 (Thu, 30 Oct 2008) | 2 lines
move airshot and electrobitch to a place where they should actually work
r4941 | div0 | 2008-10-30 12:19:42 +0100 (Thu, 30 Oct 2008) | 2 lines
fix throw logic
r4942 | m0rfar | 2008-10-30 12:45:35 +0100 (Thu, 30 Oct 2008) | 1 line
Change menu text "Demo recording" to "Automatic demo recording"
r4943 | div0 | 2008-10-30 13:07:34 +0100 (Thu, 30 Oct 2008) | 2 lines
allow team mates to cut off the hook too
r4944 | div0 | 2008-10-30 15:44:54 +0100 (Thu, 30 Oct 2008) | 2 lines
separate out seeker's effects from electro trail, and porto's from grenade trail
r4945 | div0 | 2008-10-30 16:33:42 +0100 (Thu, 30 Oct 2008) | 2 lines
add HLAC and Seeker
r4946 | div0 | 2008-10-31 09:31:43 +0100 (Fri, 31 Oct 2008) | 2 lines
multi campaign is back
r4947 | div0 | 2008-10-31 10:01:34 +0100 (Fri, 31 Oct 2008) | 2 lines
campaign fixes. Now campaign + race works.
r4948 | div0 | 2008-10-31 10:09:05 +0100 (Fri, 31 Oct 2008) | 2 lines
trigger_relay_if was useless. Make it useful, by letting it check cvars.
r4949 | div0 | 2008-10-31 12:32:56 +0100 (Fri, 31 Oct 2008) | 2 lines
add missing destructor
r4950 | esteel | 2008-10-31 13:36:48 +0100 (Fri, 31 Oct 2008) | 2 lines
added missing precache for hagarmissile (funny typo btw)
r4951 | div0 | 2008-10-31 14:42:54 +0100 (Fri, 31 Oct 2008) | 2 lines
demo browser
r4952 | div0 | 2008-10-31 15:28:27 +0100 (Fri, 31 Oct 2008) | 2 lines
I have no idea why this happens, but get rid of the damn crash
r4953 | div0 | 2008-10-31 16:38:08 +0100 (Fri, 31 Oct 2008) | 2 lines
avoid portalling flags
r4954 | div0 | 2008-10-31 21:28:27 +0100 (Fri, 31 Oct 2008) | 2 lines
less teleport effect for now
r4955 | div0 | 2008-10-31 23:13:09 +0100 (Fri, 31 Oct 2008) | 2 lines
fix bug :P
r4956 | tzork | 2008-11-01 08:59:52 +0100 (Sat, 01 Nov 2008) | 1 line
Functions for easy access to steering, pathing and moving.
r4957 | tzork | 2008-11-01 09:00:21 +0100 (Sat, 01 Nov 2008) | 1 line
r4958 | div0 | 2008-11-01 12:46:33 +0100 (Sat, 01 Nov 2008) | 2 lines
add missing noimpact checks
r4959 | div0 | 2008-11-01 13:07:50 +0100 (Sat, 01 Nov 2008) | 2 lines
factor out noimpact checks, make ALL projectiles use the anti-skygrapple workaround; make trigger_hurt no longer hurt projectiles (as that sucks)
r4960 | div0 | 2008-11-01 13:11:26 +0100 (Sat, 01 Nov 2008) | 2 lines
fix independent players check when damaged
r4961 | div0 | 2008-11-01 13:12:32 +0100 (Sat, 01 Nov 2008) | 2 lines
add independent check to one missing gibtosser
r4962 | div0 | 2008-11-01 13:17:42 +0100 (Sat, 01 Nov 2008) | 2 lines
nullify gravity bomb on team mates
r4963 | div0 | 2008-11-01 13:37:32 +0100 (Sat, 01 Nov 2008) | 2 lines
fix logic of gravity bomb
r4964 | div0 | 2008-11-01 14:24:25 +0100 (Sat, 01 Nov 2008) | 2 lines
hack to fix broken modelindex
r4965 | div0 | 2008-11-01 14:28:10 +0100 (Sat, 01 Nov 2008) | 2 lines
make it noticable
r4966 | div0 | 2008-11-01 14:32:53 +0100 (Sat, 01 Nov 2008) | 2 lines
remove stupid spam :P
r4967 | div0 | 2008-11-01 15:34:00 +0100 (Sat, 01 Nov 2008) | 2 lines
improve kick vote display
r4968 | div0 | 2008-11-02 20:12:53 +0100 (Sun, 02 Nov 2008) | 5 lines
new seeker texture
misc_gamemodel: support modelscale
-func_static
+func_illusionary
r4969 | div0 | 2008-11-02 20:14:18 +0100 (Sun, 02 Nov 2008) | 2 lines
hopefully fix weaplast
r4970 | div0 | 2008-11-02 20:52:39 +0100 (Sun, 02 Nov 2008) | 3 lines
seeker: add back the fixed 4 weapon shot origins (was a stupid idea to use random vectors instead)
but keep support for >4 missiles
r4971 | div0 | 2008-11-02 21:06:39 +0100 (Sun, 02 Nov 2008) | 2 lines
demo browser: make it regenerate its list when opened
r4972 | div0 | 2008-11-02 21:13:58 +0100 (Sun, 02 Nov 2008) | 2 lines
fix bug breaking showNotify
r4973 | div0 | 2008-11-03 15:22:31 +0100 (Mon, 03 Nov 2008) | 2 lines
hopefully switch weapon switching reallyt
r4974 | esteel | 2008-11-03 15:24:09 +0100 (Mon, 03 Nov 2008) | 1 line
revert change 4969 for now as it breaks lastweap and laser secondary completly
r4975 | esteel | 2008-11-03 15:27:38 +0100 (Mon, 03 Nov 2008) | 1 line
small misunderstanding, re-revert :P
r4976 | div0 | 2008-11-03 15:33:35 +0100 (Mon, 03 Nov 2008) | 2 lines
use misc_gamemodel, not misc_models (deprecated). Not recompiling, as misc_models still works as an alias in the QC code.

Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/.patchsets	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-4929,4932-4932
+revisions_applied = 1-4976

Modified: branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl
===================================================================
--- branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/Docs/server/rcon2irc/rcon2irc.pl	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1040,6 +1040,7 @@
 	# chat: Nexuiz server -> IRC channel, master do
 	[ dp => q{:vote:vdo:(\d+):(.*)} => sub {
 		my ($id, $command) = @_;
+		$command = color_dp2irc $command;
 		my $oldnick = $id ? $store{"playernick_$id"} : "(console)";
 		out irc => 0, "PRIVMSG $config{irc_channel} :* $oldnick\017 used his master status to do \"$command\017\"";
 		return 0;

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -498,7 +498,7 @@
 
 // race
 set g_race 0
-set g_race_qualifying 1
+set g_race_qualifying 2
 // Qualifying uses timelimit, and the one with the best time wins. Fraglimit is nonfunctional then.
 // Normal race uses fraglimit as a limit for the laps.
 // Special mode: g_race_qualifying 2. First runs a qualifying, after

Modified: branches/nexuiz-2.0/data/effectinfo.txt
===================================================================
--- branches/nexuiz-2.0/data/effectinfo.txt	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/effectinfo.txt	2008-11-04 11:54:16 UTC (rev 4977)
@@ -778,7 +778,7 @@
 //gravity 1
 bounce 1.5
 originjitter 1 1 1
-velocityjitter 2000 2000 3000
+velocityjitter 1000 1000 1500
 velocitymultiplier 0.5
 airfriction 2
 
@@ -2968,3 +2968,63 @@
 velocitymultiplier 20
 velocityoffset 0 0 10
 airfriction 1
+
+// port-o-launch trail
+// glowing vapor trail
+effect TR_WIZSPIKE
+trailspacing 2
+type static
+color 0x404040 0x404040
+size 3 3
+tex 62 62
+alpha 256 256 968
+//velocityjitter 16 16 16
+lightradius 90
+lighttime 0
+lightcolor 1.5 3 6
+velocitymultiplier -0.1
+// bright sparks
+effect TR_WIZSPIKE
+trailspacing 6
+count 3
+type snow
+tex 42 42
+color 0x404040 0x404040
+size 2 4
+sizeincrease -20
+alpha 444 512 1866
+bounce 1
+velocityoffset 0 0 15
+airfriction 12
+originjitter 1 1 1
+velocityjitter 50 50 50
+
+// TAG trail
+// glowing vapor trail
+effect TR_VORESPIKE
+trailspacing 2
+type static
+color 0x804000 0x804000
+size 3 3
+tex 62 62
+alpha 256 256 968
+//velocityjitter 16 16 16
+lightradius 90
+lighttime 0
+lightcolor 1.5 3 6
+velocitymultiplier -0.1
+// bright sparks
+effect TR_VORESPIKE
+trailspacing 6
+count 3
+type snow
+tex 42 42
+color 0xff8000 0xff8000
+size 2 4
+sizeincrease -20
+alpha 444 512 1866
+bounce 1
+velocityoffset 0 0 15
+airfriction 12
+originjitter 1 1 1
+velocityjitter 50 50 50

Deleted: branches/nexuiz-2.0/data/maps/campaignmappack.txt
===================================================================
--- branches/nexuiz-2.0/data/maps/campaignmappack.txt	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/maps/campaignmappack.txt	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,38 +0,0 @@
-"//campaign:Map pack Campaign"
-"//game","mapname","bots","skill","frag","mutator-sets","description","long description"
-"dm","q3skoredm1","3","6","15",,"q3skoredm1","By -=skOre=-."
-"dm","qbeast","3","6","20",,"qbeast","By Quint (Marco Quintavalle)."
-"dm","qdolphin","4","6","15",,"qdolphin","By Quint (Marco Quintavalle)."
-"dm","quimera","3","6","10",,"quimera","By Jose "JAJ" Arcediano."
-"dm","zpdm01","3","6","20",,"zpdm01","By ZEphYR."
-"dm","dubneoc","4","6","15",,"dubneoc","By Lasse "Dubbilan" Kolding."
-"dm","jaxtourney2","3","7","15",,"jaxtourney2","By David "Jax_Gator" Cherry."
-"dm","79drdm5_beta2","4","7","20",,"79DrDm5","By Kevin "79DieselRabbit" Worrel."
-"dm","79drgc2","4","7","15",,"79drgc2","By Kevin "79DieselRabbit" Worrel."
-"dm","quintdm3","3","7","10",,"quintdm3","By Quint (Marco Quintavalle)."
-"dm","acid3dm5","3","7","20",,"acid3dm5","By [acid]."
-"dm","ikzdm1","4","7","15",,"ikzdm1","By Iikka "Fingers" Keranen."
-"dm","geo-core","4","7","15",,"geo-core","By Q ."
-"dm","bal3dm3","3","8","20",,"bal3dm3","By Benoit "Bal" Stordeur."
-"dm","ame7q3tny1","3","8","10",,"ame7q3tny1","By Chris "amethyst7" Matz."
-"dm","hal_palindrome","3","8","15",,"hal_palindrome","By John "Hal9000" Schuch."
-"dm","redm04","3","8","15",,"redm04","By ReFlex (redm04)."
-"dm","storm3dm3","3","8","10",,"storm3dm3","By Justin Ingels."
-"dm","batcula","3","8","15",,"batcula","By nunuk."
-"dm","chronic","3","8","10",,"chronic","By MasterPlan."
-"dm","bal3dm5","3","8","10",,"bal3dm5","By Benoit "Bal" Stordeur."
-"dm","cttourney1","3","8","15",,"cttourney1","By Geit."
-"dm","distonic","3","8","20",,"distonic","By nunuk (nicolas bouvier)."
-"dm","pukka3dm2","3","8","10",,"pukka3dm2","By thefury aka sumatra."
-"dm","puma3tourney4","3","8","15",,"puma3tourney4","By =puppetmaster=."
-"dm","straledm5","3","8","15",,"straledm5","By Paul "Strahlemann" Evers."
-"dm","apocalyptica","3","8","20",,"apocalyptica","By =puppetmaster=."
-"dm","HandsOfGod","3","9","15",,"HandsOfGod","By Alex Moore."
-"dm","af3hex","3","9","15",,"af3hex","By haste (Neil Toronto)."
-"dm","ame7q3dm3","3","9","15",,"ame7q3dm3","By Chris "amethyst7" Matz."
-"dm","CMP1-dm6","3","9","15",,"CMP1-dm6","By  Yves "evil lair" Allaire."
-"dm","klzegypt","3","9","15",,"klzegypt","By Killazontherun."
-"dm","ktsdm4","3","9","15",,"ktsdm4","By Ben "Krash" Ackland."
-"dm","map-gleeb_geocomp3","3","9","20",,"map-gleeb_geocomp3","By Gleeb."
-"dm","mIKEctf2","3","9","20",,"mIKEctf2","By mIKE."
-"dm","monolith","3","9","20",,"monolith","By Sock."
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/maps/ons-reborn.map
===================================================================
--- branches/nexuiz-2.0/data/maps/ons-reborn.map	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/maps/ons-reborn.map	2008-11-04 11:54:16 UTC (rev 4977)
@@ -155589,7 +155589,7 @@
 }
 // entity 368
 {
-"classname" "misc_models"
+"classname" "misc_gamemodel"
 "origin" "6208 584 3728"
 "model" "models/train.zym"
 }
@@ -155784,7 +155784,7 @@
 }
 // entity 395
 {
-"classname" "misc_models"
+"classname" "misc_gamemodel"
 "origin" "-6776 -11896 4848"
 "model" "models/aircraft/aircraft.zym"
 }

Copied: branches/nexuiz-2.0/data/models/turrets/ewheel-base.md3 (from rev 4931, trunk/data/models/turrets/ewheel-base.md3)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/turrets/ewheel-base.tga (from rev 4931, trunk/data/models/turrets/ewheel-base.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/turrets/ewheel-gun1.md3 (from rev 4931, trunk/data/models/turrets/ewheel-gun1.md3)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/turrets/ewheel-gun1.tga (from rev 4931, trunk/data/models/turrets/ewheel-gun1.tga)
===================================================================
(Binary files differ)

Copied: branches/nexuiz-2.0/data/models/turrets/radiant/ewheel.md3 (from rev 4931, trunk/data/models/turrets/radiant/ewheel.md3)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/mutator_reset.cfg
===================================================================
--- branches/nexuiz-2.0/data/mutator_reset.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/mutator_reset.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -9,6 +9,7 @@
 set g_norecoil 0
 set g_weaponarena 0
 set g_vampire 0
+set g_race_qualifying 2
 set slowmo 1.0
 set sv_gravity 800
 

Modified: branches/nexuiz-2.0/data/qcsrc/common/campaign_common.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/campaign_common.qh	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/common/campaign_common.qh	2008-11-04 11:54:16 UTC (rev 4977)
@@ -13,6 +13,7 @@
 string campaign_mutators[CAMPAIGN_MAX_ENTRIES];
 string campaign_shortdesc[CAMPAIGN_MAX_ENTRIES];
 string campaign_longdesc[CAMPAIGN_MAX_ENTRIES];
+string campaign_title; // filled upon loading
 
 // load the campaign file, but use the given offset and limit the number of
 // entries being read. Returns the number of entries successfully read (this

Modified: branches/nexuiz-2.0/data/qcsrc/common/campaign_file.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/campaign_file.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/common/campaign_file.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -16,6 +16,7 @@
 
 	campaign_offset = offset;
 	campaign_entries = 0;
+	campaign_title = string_null;
 
 	fn = strcat("maps/campaign", campaign_name, ".txt");
 	fh = fopen(fn, FILE_READ);
@@ -25,8 +26,12 @@
 		{
 			if(strlen(l) == 0)
 				continue; // empty line
+			if(substring(l, 0, 11) == "//campaign:")
+				campaign_title = substring(l, 11, strlen(l) - 11);
 			if(substring(l, 0, 2) == "//")
 				continue; // comment
+			if(substring(l, 0, 12) == "\"//campaign:")
+				campaign_title = substring(l, 12, strlen(l) - 13);
 			if(substring(l, 0, 3) == "\"//")
 				continue; // comment
 			if(lineno >= offset)
@@ -62,19 +67,26 @@
 		fclose(fh);
 	}
 
+	campaign_title = strzone(campaign_title);
+
 	return campaign_entries;
 }
 
 void CampaignFile_Unload()
 {
 	float i;
-	for(i = 0; i < campaign_entries; ++i)
+	if(campaign_title)
 	{
-		strunzone(campaign_gametype[i]);
-		strunzone(campaign_mapname[i]);
-		strunzone(campaign_mutators[i]);
-		strunzone(campaign_shortdesc[i]);
-		strunzone(campaign_longdesc[i]);
+		strunzone(campaign_title);
+		for(i = 0; i < campaign_entries; ++i)
+		{
+			strunzone(campaign_gametype[i]);
+			strunzone(campaign_mapname[i]);
+			strunzone(campaign_mutators[i]);
+			strunzone(campaign_shortdesc[i]);
+			strunzone(campaign_longdesc[i]);
+		}
+		campaign_entries = 0;
+		campaign_title = string_null;
 	}
-	campaign_entries = 0;
 }

Modified: branches/nexuiz-2.0/data/qcsrc/menu/classes.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/classes.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/classes.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -70,3 +70,5 @@
 #include "nexuiz/dialog_multiplayer_playersetup_weapons.c"
 #include "nexuiz/weaponslist.c"
 #include "nexuiz/dialog_multiplayer_playersetup_radar.c"
+#include "nexuiz/dialog_settings_demo.c"
+#include "nexuiz/demolist.c"

Modified: branches/nexuiz-2.0/data/qcsrc/menu/item/modalcontroller.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/item/modalcontroller.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/item/modalcontroller.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -18,6 +18,7 @@
 	ATTRIB(ModalController, fadedAlpha, float, 0.3)
 ENDCLASS(ModalController)
 
+.entity tabSelectingButton;
 .vector origin;
 .vector size;
 void TabButton_Click(entity button, entity tab); // assumes a button has set the above fields to its own absolute origin, its size, and the tab to activate
@@ -229,6 +230,7 @@
 	me.addItem(me, other, '0 0 0', '1 1 1', 1);
 	tabButton.onClick = TabButton_Click;
 	tabButton.onClickEntity = other;
+	other.tabSelectingButton = tabButton;
 	if(other == me.firstChild)
 	{
 		tabButton.forcePressed = 1;

Modified: branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/mbuiltin.qh	2008-11-04 11:54:16 UTC (rev 4977)
@@ -299,6 +299,7 @@
 string(string in) uri_unescape = #511;
 
 string(string, float) netaddress_resolve = #625;
+string(string search, string replace, string subject) strreplace = #484;
 
 #ifdef FIXEDFOPEN
 float 	fopen( string filename, float mode ) =

Modified: branches/nexuiz-2.0/data/qcsrc/menu/menu.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/menu.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/menu.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -422,8 +422,12 @@
 
 	if(par.instanceOfModalController)
 	{
-		// tabs
-		par.initializeDialog(par, wnd);
+		if(wnd.tabSelectingButton)
+			// tabs
+			TabButton_Click(wnd.tabSelectingButton, wnd);
+		else
+			// root
+			par.initializeDialog(par, wnd);
 	}
 	else if(par.instanceOfNexposee)
 	{

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/campaign.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/campaign.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/campaign.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -8,7 +8,10 @@
 	METHOD(NexuizCampaignList, resizeNotify, void(entity, vector, vector, vector, vector))
 	METHOD(NexuizCampaignList, setSelected, void(entity, float))
 	METHOD(NexuizCampaignList, keyDown, float(entity, float, float, float))
+	METHOD(NexuizCampaignList, campaignGo, void(entity, float))
+	METHOD(NexuizCampaignList, destroy, void(entity))
 
+	ATTRIB(NexuizCampaignList, campaignGlob, float, 0)
 	ATTRIB(NexuizCampaignList, realFontSize, vector, '0 0 0')
 	ATTRIB(NexuizCampaignList, columnPreviewOrigin, float, 0)
 	ATTRIB(NexuizCampaignList, columnPreviewSize, float, 0)
@@ -32,9 +35,15 @@
 	ATTRIB(NexuizCampaignList, cvarName, string, string_null)
 	METHOD(NexuizCampaignList, loadCvars, void(entity))
 	METHOD(NexuizCampaignList, saveCvars, void(entity))
+
+	ATTRIB(NexuizCampaignList, buttonNext, entity, NULL)
+	ATTRIB(NexuizCampaignList, buttonPrev, entity, NULL)
+	ATTRIB(NexuizCampaignList, labelTitle, entity, NULL)
 ENDCLASS(NexuizCampaignList)
 entity makeNexuizCampaignList();
 void CampaignList_LoadMap(entity btn, entity me);
+void MultiCampaign_Next(entity btn, entity me);
+void MultiCampaign_Prev(entity btn, entity me);
 #endif
 
 #ifdef IMPLEMENTATION
@@ -110,9 +119,17 @@
 void configureNexuizCampaignListNexuizCampaignList(entity me)
 {
 	me.configureNexuizListBox(me);
+	me.campaignGlob = search_begin("maps/campaign*.txt", TRUE, TRUE);
 	me.loadCvars(me);
+	me.campaignGo(me, 0); // takes care of enabling/disabling buttons too
 }
 
+void destroyNexuizCampaignList(entity me)
+{
+	if(me.campaignGlob >= 0)
+		search_end(me.campaignGlob);
+}
+
 void loadCvarsNexuizCampaignList(entity me)
 {
 	// read campaign cvars
@@ -122,6 +139,8 @@
 		strunzone(me.cvarName);
 	campaign_name = strzone(cvar_string("g_campaign_name"));
 	me.cvarName = strzone(strcat("g_campaign", campaign_name, "_index"));
+	registercvar(me.cvarName, "", 0); // saved by server QC anyway
+	CampaignFile_Unload();
 	CampaignFile_Load(0, CAMPAIGN_MAX_ENTRIES);
 	me.campaignIndex = bound(0, cvar(me.cvarName), campaign_entries);
 	cvar_set(me.cvarName, ftos(me.campaignIndex));
@@ -130,15 +149,72 @@
 	me.nItems = min(me.campaignIndex + 2, campaign_entries);
 	me.selectedItem = min(me.campaignIndex, me.nItems - 1);
 	me.scrollPos = me.nItems * me.itemHeight - 1;
+	if(me.labelTitle)
+		me.labelTitle.setText(me.labelTitle, campaign_title);
 }
 
 void saveCvarsNexuizCampaignList(entity me)
 {
 	// write campaign cvars
-	cvar_set("g_campaign_name", campaign_name);
+	// no reason to do this!
+	// cvar_set("g_campaign_name", campaign_name);
 	// cvar_set(me.cvarName, ftos(me.campaignIndex)); // NOTE: only server QC does that!
 }
 
+void campaignGoNexuizCampaignList(entity me, float step)
+{
+	float canNext, canPrev;
+	string s;
+	float i, j, n;
+
+	canNext = canPrev = 0;
+
+	if(me.campaignGlob >= 0)
+	{
+		n = search_getsize(me.campaignGlob);
+		if(n > 0)
+		{
+			j = -1;
+			s = strcat("maps/campaign", campaign_name, ".txt");
+			for(i = 0; i < n; ++i)
+			{
+				if(search_getfilename(me.campaignGlob, i) == s)
+					j = i;
+			}
+			if(j < 0)
+			{
+				if(step >= 0)
+					j = 0;
+				else
+					j = n - 1;
+			}
+			else
+				j = mod(j + step, n);
+			s = search_getfilename(me.campaignGlob, j);
+			print(s, "\n");
+			s = substring(s, 13, strlen(s) - 17);
+			cvar_set("g_campaign_name", s);
+			me.loadCvars(me);
+			canNext = (j != n - 1);
+			canPrev = (j != 0);
+		}
+	}
+
+	if(me.buttonNext)
+		me.buttonNext.disabled = !canNext;
+	if(me.buttonPrev)
+		me.buttonPrev.disabled = !canPrev;
+}
+
+void MultiCampaign_Next(entity btn, entity me)
+{
+	me.campaignGo(me, +1);
+}
+void MultiCampaign_Prev(entity btn, entity me)
+{
+	me.campaignGo(me, -1);
+}
+
 void drawNexuizCampaignList(entity me)
 {
 	if(cvar(me.cvarName) != me.campaignIndex || cvar_string("g_campaign_name") != campaign_name)

Copied: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/demolist.c (from rev 4976, trunk/data/qcsrc/menu/nexuiz/demolist.c)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/demolist.c	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/demolist.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -0,0 +1,157 @@
+#ifdef INTERFACE
+CLASS(NexuizDemoList) EXTENDS(NexuizListBox)
+    METHOD(NexuizDemoList, configureNexuizDemoList, void(entity))
+    ATTRIB(NexuizDemoList, rowsPerItem, float, 1)
+    METHOD(NexuizDemoList, resizeNotify, void(entity, vector, vector, vector, vector))
+    METHOD(NexuizDemoList, drawListBoxItem, void(entity, float, vector, float))
+    METHOD(NexuizDemoList, getDemos, void(entity))
+    METHOD(NexuizDemoList, startDemo, void(entity))    
+    METHOD(NexuizDemoList, demoName, string(entity, float))
+    METHOD(NexuizDemoList, clickListBoxItem, void(entity, float, vector))
+    METHOD(NexuizDemoList, keyDown, float(entity, float, float, float))
+    METHOD(NexuizDemoList, destroy, void(entity))
+    METHOD(NexuizDemoList, showNotify, void(entity))
+    ATTRIB(NexuizDemoList, listDemo, float, -1)
+    ATTRIB(NexuizDemoList, realFontSize, vector, '0 0 0')
+    ATTRIB(NexuizDemoList, columnNameOrigin, float, 0)
+    ATTRIB(NexuizDemoList, columnNameSize, float, 0)
+    ATTRIB(NexuizDemoList, realUpperMargin, float, 0)
+    ATTRIB(NexuizDemoList, origin, vector, '0 0 0')
+    ATTRIB(NexuizDemoList, itemAbsSize, vector, '0 0 0')
+    ATTRIB(NexuizDemoList, lastClickedDemo, float, -1)
+    ATTRIB(NexuizDemoList, lastClickedTime, float, 0)
+    ATTRIB(NexuizDemoList, filterString, string, string_null)    
+ENDCLASS(NexuizDemoList)
+
+entity makeNexuizDemoList();
+void StartDemo_Click(entity btn, entity me);
+void DemoList_Filter_Change(entity box, entity me);
+#endif
+
+#ifdef IMPLEMENTATION
+
+entity makeNexuizDemoList()
+{
+    entity me;
+    me = spawnNexuizDemoList();
+    me.configureNexuizDemoList(me);
+    return me;
+}
+
+void configureNexuizDemoListNexuizDemoList(entity me)
+{
+    me.configureNexuizListBox(me);
+    me.getDemos(me);    
+}
+
+string demoNameNexuizDemoList(entity me, float i )
+{
+    string s;
+    s = search_getfilename(me.listDemo, i);
+    s = substring(s, 6, strlen(s) - 6 - 4);  // demos/, .dem
+    return s;
+}
+
+
+void getDemosNexuizDemoList(entity me)
+{
+    string s;
+    
+    if(me.filterString)
+    	//subdirectory in filterString allowed    
+    	s=strcat("demos/*", me.filterString, "*.dem");    	
+    else
+    	s="demos/*.dem";
+	
+    //dprint("Search demos with the pattern ", s, "\n");    
+    me.listDemo = search_begin(s, FALSE, TRUE);
+    if(me.listDemo < 0)
+    	me.nItems=0;
+    else
+    	me.nItems=search_getsize(me.listDemo);				
+}
+
+void destroyNexuizDemoList(entity me)
+{
+    search_end(me.listDemo);
+}
+
+void resizeNotifyNexuizDemoList(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+    me.origin = absOrigin;
+    me.itemAbsSize = '0 0 0';
+    resizeNotifyNexuizListBox(me, relOrigin, relSize, absOrigin, absSize);
+
+    me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize_y * me.itemHeight));
+    me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize_x * (1 - me.controlWidth)));
+    me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
+
+    me.columnNameOrigin = me.realFontSize_x;
+    me.columnNameSize = 1 - 2 * me.realFontSize_x;
+}
+
+void drawListBoxItemNexuizDemoList(entity me, float i, vector absSize, float isSelected)
+{
+    string s;
+    if(isSelected)
+    	draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
+		
+    s = me.demoName(me,i);
+    s = draw_TextShortenToWidth(s, me.columnNameSize / me.realFontSize_x, 0);
+    draw_Text(me.realUpperMargin * eY + (me.columnNameOrigin + 0.00 * (me.columnNameSize - draw_TextWidth(s, 0) * me.realFontSize_x)) * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);		
+}
+
+void showNotifyNexuizDemoList(entity me)
+{
+    me.getDemos(me);
+}
+
+void DemoList_Filter_Change(entity box, entity me)
+{	
+    if(me.filterString)
+    	strunzone(me.filterString);
+    
+    if(box.text != "")
+    	me.filterString = strzone(box.text);
+    else
+    	me.filterString = string_null;
+		
+    me.getDemos(me);
+}
+
+void startDemoNexuizDemoList(entity me)
+{
+    string s;
+    s = me.demoName(me,me.selectedItem);
+    localcmd("playdemo demos/", s, ".dem\nwait\ntogglemenu\n");	
+}
+
+void StartDemo_Click(entity btn, entity me)
+{
+    me.startDemo(me);
+}
+
+void clickListBoxItemNexuizDemoList(entity me, float i, vector where)
+{
+    if(i == me.lastClickedDemo)
+        if(time < me.lastClickedTime + 0.3)
+        {
+            // DOUBLE CLICK!
+            me.setSelected(me, i);
+            me.startDemo(me);
+        }
+    me.lastClickedDemo = i;
+    me.lastClickedTime = time;
+}
+
+float keyDownNexuizDemoList(entity me, float scan, float ascii, float shift)
+{
+    if(scan == K_ENTER) {
+        me.startDemo(me);
+        return 1;
+    }
+    else
+        return keyDownListBox(me, scan, ascii, shift);
+}
+#endif
+

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -19,6 +19,7 @@
 		me.TD(me, 1, 1, mc.makeTabButton(mc, "Video",   makeNexuizVideoSettingsTab()));
 		me.TD(me, 1, 1, mc.makeTabButton(mc, "Effects", makeNexuizEffectsSettingsTab()));
 		me.TD(me, 1, 1, mc.makeTabButton(mc, "Audio",   makeNexuizAudioSettingsTab()));
+		me.TD(me, 1, 1, mc.makeTabButton(mc, "Demos",   makeNexuizDemoSettingsTab()));
 		me.TD(me, 1, 1, mc.makeTabButton(mc, "Misc",    makeNexuizMiscSettingsTab()));
 	me.TR(me);
 	me.TR(me);

Copied: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_demo.c (from rev 4976, trunk/data/qcsrc/menu/nexuiz/dialog_settings_demo.c)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_demo.c	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_demo.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -0,0 +1,47 @@
+#ifdef INTERFACE
+CLASS(NexuizDemoSettingsTab) EXTENDS(NexuizTab)
+	METHOD(NexuizDemoSettingsTab, fill, void(entity))
+	ATTRIB(NexuizDemoSettingsTab, title, string, "Demo")
+	ATTRIB(NexuizDemoSettingsTab, intendedWidth, float, 0.9)
+	ATTRIB(NexuizDemoSettingsTab, rows, float, 15)
+	ATTRIB(NexuizDemoSettingsTab, columns, float, 6.5)
+	ATTRIB(NexuizDemoSettingsTab, name, string, "DemoBroswer")	
+ENDCLASS(NexuizDemoSettingsTab)
+entity makeNexuizDemoSettingsTab();
+#endif
+
+#ifdef IMPLEMENTATION
+entity makeNexuizDemoSettingsTab()
+{
+	entity me;
+	me = spawnNexuizDemoSettingsTab();
+	me.configureDialog(me);
+	return me;
+}
+void fillNexuizDemoSettingsTab(entity me)
+{
+	entity e;
+	entity btn;
+	entity dlist;
+
+	me.TR(me);
+		me.TD(me, 1, me.columns, e = makeNexuizCheckBox(0, "cl_autodemo", "Record demos while playing"));
+	me.TR(me);
+	dlist = makeNexuizDemoList();
+	me.TR(me);
+		me.TD(me, 1, 0.5, e = makeNexuizTextLabel(0, "Filter:"));
+		me.TD(me, 1, 0.5, btn = makeNexuizButton("Clear", '0 0 0'));
+			btn.onClick = InputBox_Clear_Click;
+		me.TD(me, 1, me.columns - 1, e = makeNexuizInputBox(0, string_null));
+			e.onChange = DemoList_Filter_Change;
+			e.onChangeEntity = dlist;
+			btn.onClickEntity = e;
+			dlist.controlledTextbox = e;
+	me.TR(me);
+		me.TD(me, me.rows - 4, me.columns, dlist);
+	me.gotoRC(me, me.rows - 1, 0);
+		me.TD(me, 1, me.columns, e = makeNexuizButton("Play", '0 0 0'));
+			e.onClick = StartDemo_Click;
+			e.onClickEntity = dlist;
+}
+#endif

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_misc.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_misc.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_settings_misc.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -32,9 +32,6 @@
 			e.onClickEntity = sk;
 		
 	me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn);
-		me.TD(me, 1, 3, e = makeNexuizCheckBox(0, "cl_autodemo", "Demo recording"));
-	me.TR(me);
-	me.TR(me);
 		me.TD(me, 1, 3, e = makeNexuizCheckBox(0, "showtime", "Show current time"));
 	me.TR(me);
 		me.TD(me, 1, 3, e = makeNexuizCheckBox(0, "showdate", "Show current date"));

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_singleplayer.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_singleplayer.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_singleplayer.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -51,7 +51,7 @@
 
 void fillNexuizSingleplayerDialog(entity me)
 {
-	entity e;
+	entity e, btnPrev, btnNext, lblTitle;
 
 	me.TR(me);
 		me.TDempty(me, (me.columns - 2) / 2);
@@ -61,7 +61,19 @@
 	me.TR(me);
 	me.TR(me);
 	me.TR(me);
-		me.TD(me, me.rows - 5, me.columns, me.campaignBox = makeNexuizCampaignList());
+		me.TD(me, 1, 1, btnPrev = makeNexuizButton("<<", '0 0 0'));
+		me.TD(me, 1, me.columns - 2, lblTitle = makeNexuizTextLabel(0.5, "???"));
+		me.TD(me, 1, 1, btnNext = makeNexuizButton(">>", '0 0 0'));
+	me.TR(me);
+		me.TD(me, me.rows - 6, me.columns, me.campaignBox = makeNexuizCampaignList());
+			btnPrev.onClick = MultiCampaign_Prev;
+			btnPrev.onClickEntity = me.campaignBox;
+			btnNext.onClick = MultiCampaign_Next;
+			btnNext.onClickEntity = me.campaignBox;
+			me.campaignBox.buttonNext = btnNext;
+			me.campaignBox.buttonPrev = btnPrev;
+			me.campaignBox.labelTitle = lblTitle;
+			me.campaignBox.campaignGo(me.campaignBox, 0);
 
 	me.gotoRC(me, me.rows - 1, 0);
 		me.TD(me, 1, me.columns, e = makeNexuizButton("Start!", '0 0 0'));

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/mainwindow.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/mainwindow.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/mainwindow.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -53,7 +53,7 @@
 	me.radarDialog = i = spawnNexuizRadarDialog();
 	i.configureDialog(i);
 	me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-
+	
 	me.mainNexposee = n = spawnNexuizNexposee();
 	/*
 		if(checkextension("DP_GECKO_SUPPORT"))

Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/tab.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/tab.c	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/tab.c	2008-11-04 11:54:16 UTC (rev 4977)
@@ -25,5 +25,6 @@
 void showNotifyNexuizTab(entity me)
 {
 	loadAllCvars(me);
+	showNotifyContainer(me);
 }
 #endif

Modified: branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/menu/skin-customizables.inc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -52,6 +52,7 @@
 	SKINVECTOR(COLOR_DIALOG_CREDITS, '0.7 0.7 1');
 	SKINVECTOR(COLOR_DIALOG_WEAPONS, '1 0.7 0.7');
 	SKINVECTOR(COLOR_DIALOG_RADAR, '0.7 0.7 1');
+	SKINVECTOR(COLOR_DIALOG_DEMOBROSWER, '0.7 0.7 1');
 
 	// nexposee positions of windows (they are the scale transformation
 	// centers, NOT the actual positions of the windows!)

Modified: branches/nexuiz-2.0/data/qcsrc/server/assault.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/assault.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/assault.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -259,6 +259,7 @@
 	activator = self;
 	SUB_UseTargets();
 
+/*
 #ifdef TTURRETS_ENABLED
     entity ent,oldself;
 
@@ -282,6 +283,7 @@
 	}
 	self = oldself;
 #endif
+*/
 
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -549,6 +549,13 @@
 		}
 	}
 
+	if(self.modelindex == 0)
+	{
+		if(self.model != "")
+			bprint("\{1}^1Player ", self.netname, "^1 has a zero modelindex, trying to fix...\n");
+		self.model = ""; // force the != checks to return true
+	}
+
 	if(defaultmodel != "")
 	{
 		if (defaultmodel != self.model)
@@ -1345,7 +1352,8 @@
 	self.nextthink = time;
 	if (!self.owner.modelindex || self.owner.chatbubbleentity != self)
 	{
-		self.owner.chatbubbleentity = world;
+		if(self.owner) // but why can that ever be world?
+			self.owner.chatbubbleentity = world;
 		remove(self);
 		return;
 	}
@@ -1382,7 +1390,8 @@
 	self.nextthink = time;
 	if (!self.owner.modelindex || self.owner.teambubbleentity != self)
 	{
-		self.owner.teambubbleentity = world;
+		if(self.owner) // but why can that ever be world?
+			self.owner.teambubbleentity = world;
 		remove(self);
 		return;
 	}

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -273,7 +273,7 @@
 	else if (take > 10)
 		sound (self, CHAN_PROJECTILE, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM);
 
-	if not(IS_INDEPENDENT_PLAYER(self))
+	if(independent_players)
 	if(sv_gentle < 1) {	
 		if (take > 50)
 			TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);
@@ -308,16 +308,16 @@
 
 
 		// make a meaty mess
-		if(IS_INDEPENDENT_PLAYER(self))
+		if(independent_players)
 		{
 			TossGib (self, "models/gibs/eye.md3", self.origin + self.view_ofs, self.velocity + randomvec() * 150,0);
-			MAKE_INDEPENDENT_PLAYER(self); // undo SOLID_CORPSE
+			self.solid = SOLID_TRIGGER; // undo SOLID_CORPSE
 			self.takedamage = DAMAGE_NO; // can't damage this gib, to prevent better jumps from it
 		}
 		else
 			TossGib (self, "models/gibs/eye.md3", self.origin + self.view_ofs, self.velocity + randomvec() * 150,0);
 		
-		if not(IS_INDEPENDENT_PLAYER(self))
+		if not(independent_players)
 		if(sv_gentle < 1) {
 			te_bloodshower (self.origin + self.mins, self.origin + self.maxs, 1200 * multiplier, 1000);
 			TossGib (world, "models/gibs/bloodyskull.md3", self.origin + self.view_ofs, self.velocity,0);
@@ -364,11 +364,6 @@
 {
 	local float take, save, waves, sdelay;
 
-	if(self.hook)
-		if(self.hook.aiment)
-			if(self.hook.aiment == attacker)
-				RemoveGrapplingHook(self); // STOP THAT, you parasite!
-
 	damage = damage * bound(1.0, self.cvar_cl_handicap, 100.0);
 	if(sv_gentle > 0) {
 		pointparticles(particleeffectnum("damage_hit"), hitloc, force, bound(0, damage, 200));
@@ -398,10 +393,14 @@
 	else if (take > 10)
 		sound (self, CHAN_PROJECTILE, "misc/bodyimpact1.wav", VOL_BASE, ATTN_NORM); // FIXME possibly remove them?
 
-	if (take > 50)
-		TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);
-	if (take > 100)
-		TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.2,1);
+	if(sv_gentle < 1)
+	if not(independent_players)
+	{
+		if (take > 50)
+			TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.1,1);
+		if (take > 100)
+			TossGib (world, "models/gibs/chunk.mdl", hitloc, force * -0.2,1);
+	}
 
 	if (time > self.spawnshieldtime)
 	{

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,7 +1,7 @@
 // switch between weapons
 void W_SwitchWeapon(float imp)
 {
-	if (self.weapon != imp)
+	if (self.switchweapon != imp)
 	if (client_hasweapon(self, imp, TRUE, TRUE))
 		W_SwitchWeapon_Force(self, imp);
 };
@@ -207,7 +207,7 @@
 // toss current weapon
 void W_ThrowWeapon(vector velo, vector delta, float doreduce)
 {
-	local float w, a, wb;
+	local float w, a, wb, wa;
 
 	w = self.weapon;
 	if (w == 0)
@@ -224,8 +224,20 @@
 		return;
 
 	wb = W_WeaponBit(w);
+	wa = W_AmmoItemCode(w);
+	if(!wb)
+		return;
 	if(self.weapons & wb != wb)
 		return;
+	if(start_weapons & wb)
+	{
+		if(wa == IT_SUPERWEAPON && start_items & IT_UNLIMITED_SUPERWEAPONS)
+			return;
+		if(wa != IT_SUPERWEAPON && start_items & IT_UNLIMITED_WEAPON_AMMO)
+			return;
+		if(wa == 0)
+			return;
+	}
 
 	self.weapons = self.weapons - wb;
 	W_SwitchWeapon_Force(self, w_getbestweapon(self));
@@ -452,8 +464,8 @@
 	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_weapon(WEP_SEEKER,           w_seeker,    IT_ROCKETS,     8, 0,     0, "seeker",    "seeker",          "T.A.G. Seeker");
-	register_weapon(WEP_HLAC,             w_hlac,      IT_CELLS,       6, 0,     0, "hlac",      "hlac",            "Heavy Laser Assault Cannon");
+	register_weapon(WEP_SEEKER,           w_seeker,    IT_ROCKETS,     8, 1,     0, "seeker",    "seeker",          "T.A.G. Seeker");
+	register_weapon(WEP_HLAC,             w_hlac,      IT_CELLS,       6, 1,     0, "hlac",      "hlac",            "Heavy Laser Assault Cannon");
 
 	register_weapons_done();
 }

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -9,7 +9,7 @@
 
 void W_SwitchWeapon_Force(entity e, float w)
 {
-	e.cnt = e.weapon ? e.weapon : e.switchweapon;
+	e.cnt = e.switchweapon;
 	e.switchweapon = w;
 }
 
@@ -453,6 +453,7 @@
 	// the two weapon entities will notice this has changed and update their models
 	self.weapon = windex;
 	self.weaponname = e.mdl;
+	self.bulletcounter = 0;
 };
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
@@ -494,6 +495,7 @@
 		//dprint("resetting attack finished to ", ftos(time), "\n");
 	}
 	ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime;
+	self.bulletcounter += 1;
 	//dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
 	return TRUE;
 };

Modified: branches/nexuiz-2.0/data/qcsrc/server/defs.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2008-11-04 11:54:16 UTC (rev 4977)
@@ -495,3 +495,7 @@
 .string message2;
 
 vector railgun_start, railgun_end; // filled by FireRailgunBullet, used by damage code for head shot
+
+// reset to 0 on weapon switch
+// may be useful to all weapons
+.float bulletcounter;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_casings.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_casings.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_casings.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,10 +1,7 @@
 void casingtouch()
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
+
 	if (other.solid == SOLID_BSP)
 	if (vlen(self.velocity) >= 50)
 	if (time >= self.attack_finished_single)

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -508,7 +508,24 @@
         damage_inflictor = inflictor;
         damage_attacker = attacker;
 		attacker_save = attacker;
+	
+	if(targ.classname == "player")
+		if(targ.hook)
+			if(targ.hook.aiment)
+				if(targ.hook.aiment == attacker)
+					RemoveGrapplingHook(targ); // STOP THAT, you parasite!
 
+	// special rule: gravity bomb does not hit team mates (other than for disconnecting the hook)
+	if(DEATH_WEAPONOF(deathtype) == WEP_HOOK)
+	{
+		if(targ.classname == "player")
+			if not(IsDifferentTeam(targ, attacker))
+			{
+				self = oldself;
+				return;
+			}
+	}
+
 	if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
 	{
 		// These are ALWAYS lethal

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -258,11 +258,9 @@
 
 void GrapplingHookTouch (void)
 {
-	if (other == self.owner)
+	if(SUB_OwnerCheck())
 		return;
-	// altered for Nexuiz
-	//else if (pointcontents (self.origin) == CONTENT_SKY)
-	else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+	if(SUB_NoImpactCheck())
 	{
 		RemoveGrapplingHook(self.owner);
 		return;

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -365,28 +365,33 @@
 void trigger_hurt_touch()
 {
 	// only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
-	if (!other.owner)
+	if (other.iscreature)
 	{
-		if (other.items & IT_KEY1 || other.items & IT_KEY2)	// reset flag
+		if (other.takedamage)
+		if (other.triggerhurttime < time)
 		{
 			EXACTTRIGGER_TOUCH;
-			other.pain_finished = min(other.pain_finished, time + 2);
+			other.triggerhurttime = time + 1;
+			Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
 		}
-		else if (other.classname == "rune")			// reset runes
+	}
+	else
+	{
+		if (!other.owner)
 		{
-			EXACTTRIGGER_TOUCH;
-			other.nextthink = min(other.nextthink, time + 1);
+			if (other.items & IT_KEY1 || other.items & IT_KEY2)	// reset flag
+			{
+				EXACTTRIGGER_TOUCH;
+				other.pain_finished = min(other.pain_finished, time + 2);
+			}
+			else if (other.classname == "rune")			// reset runes
+			{
+				EXACTTRIGGER_TOUCH;
+				other.nextthink = min(other.nextthink, time + 1);
+			}
 		}
 	}
 
-	if (other.takedamage)
-	if (other.triggerhurttime < time)
-	{
-		EXACTTRIGGER_TOUCH;
-		other.triggerhurttime = time + 1;
-		Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
-	}
-
 	return;
 };
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_violence.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_violence.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_violence.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -24,7 +24,7 @@
 
 void GibTouch ()
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+	if(SUB_NoImpactCheck())
 	{
 		SUB_VanishOrRemove(self);
 		return;

Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1595,3 +1595,33 @@
 {
 	return trace_hits_box(start, end, thmi - ma, thma - mi);
 }
+
+float SUB_NoImpactCheck()
+{
+	if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+		return 1;
+	if(other == world && self.size != '0 0 0')
+	{
+		vector tic;
+		tic = self.velocity * sys_ticrate;
+		tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
+		traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
+		if(trace_fraction >= 1)
+		{
+			dprint("Odd... did not hit...?\n");
+		}
+		else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+		{
+			dprint("Detected and prevented the sky-grapple bug.\n");
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+#define SUB_OwnerCheck() (other == self.owner)
+
+#define PROJECTILE_TOUCH do { if(SUB_OwnerCheck()) return; if(SUB_NoImpactCheck()) { remove(self); return; } } while(0)
+const string STR_MISC_NULL_WAV = "misc/null.wav";
+#define PROJECTILE_TOUCH_NOSOUND do { if(SUB_OwnerCheck()) return; if(SUB_NoImpactCheck()) { sound (self, CHAN_PROJECTILE, STR_MISC_NULL_WAV, VOL_BASE, ATTN_NORM); remove(self); return; } } while(0)

Copied: branches/nexuiz-2.0/data/qcsrc/server/movelib.qc (from rev 4976, trunk/data/qcsrc/server/movelib.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/movelib.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/movelib.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -0,0 +1,71 @@
+.float mass;
+
+/**
+    Simulate drag
+    self.velocity = movelib_vdrag(self.velocity,0.02,0.5);
+**/
+vector movelib_drag(float drag, float exp)
+{
+    float lspeed,ldrag;
+
+    lspeed = vlen(self.velocity);
+    ldrag = lspeed * drag;
+    ldrag = ldrag * drag * exp;
+    ldrag = 1 - (ldrag / lspeed);
+
+    return self.velocity * ldrag;
+}
+
+/**
+    Simulate drag
+    self.velocity = movelib_vdrag(somespeed,0.01,0.7);
+**/
+float movelib_dragflt(float fspeed,float drag,float exp)
+{
+    float ldrag;
+
+    ldrag = fspeed * drag;
+    ldrag = ldrag * ldrag * exp;
+    ldrag = 1 - (ldrag / fspeed);
+
+    return ldrag;
+}
+
+/**
+    Do a inertia simulation based on velocity.
+    Basicaly, this allows you to simulate objects loss steering with speed.
+    self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
+**/
+vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
+{
+    float influense;
+
+    influense = vlen(self.velocity) * (1 / vel_max);
+
+    influense = bound(newmin,influense,oldmax);
+
+    return (vel_new * (1 - influense)) + (self.velocity * influense);
+}
+
+vector movelib_inertmove(vector new_vel,float new_bias)
+{
+    return new_vel * new_bias + self.velocity * (1-new_bias);
+}
+
+
+/**
+    Applies absolute force to a velocity
+**/
+vector movelib_accelerate(vector vel,float force)
+{
+    return normalize(vel) * (vlen(vel) + force);
+}
+vector movelib_decelerate(vector vel,float force)
+{
+    return normalize(vel) * (vlen(vel) - force);
+}
+
+vector movelib_velocity_transfer(entity source,entity destination)
+{
+    return '0 0 0';
+}

Modified: branches/nexuiz-2.0/data/qcsrc/server/pathlib.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/pathlib.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/pathlib.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,14 +1,33 @@
-.float pathgroup;
+#define PLF_GROUNDSNAP 1
+#define PLF_NOOPTIMIZE 2
+#define PLF_SUBPATH3D  4
 
-.entity path_next;
-.entity path_prev;
-// .entity path_start;
+//#define PATHLIB_RDFIELDS
+#ifdef PATHLIB_RDFIELDS
+    #define path_flags lip
 
+    #define path_subpathing_size autoswitch
+    #define path_subpathing_bboxexpand welcomemessage_time
+
+    #define path_next swampslug
+    #define path_prev lasertarget
+#else
+    .entity path_next;
+    .entity path_prev;
+
+    .float path_subpathing_size;
+    .float path_subpathing_bboxexpand;
+    .float path_flags;
+#endif
+
+#define pathlib_garbagetime 120
+#define pathib_maxdivide 256
+
 .float(vector start,vector end) path_validate;
 
 float pathlib_stdproc_path_validate(vector start,vector end)
 {
-    tracebox(start, self.mins, self.maxs, end, MOVE_NOMONSTERS, self);
+    tracebox(start, self.mins, self.maxs, end, MOVE_NORMAL, self);
 
     if(vlen(trace_endpos - end) < 32)
         return 1;
@@ -16,26 +35,27 @@
     return 0;
 }
 
-void pathlib_point_use()
+vector pathlib_groundsnap(vector where,entity path)
 {
-    remove(self);
+    float lsize;
+
+    lsize = vlen(self.mins - self.maxs) * 0.25;
+
+    traceline(where + ('0 0 1' * lsize) ,where - '0 0 10000',MOVE_NORMAL,self);
+
+    return trace_endpos + ('0 0 1' * lsize);
+
 }
 
 entity pathlib_createpoint(entity parent,entity next,entity first,vector where)
 {
     entity point;
+
     point = spawn();
     point.classname = "path_node";
 
-    //bprint("Create point\n");
-
-    traceline(where + '0 0 32' ,where - '0 0 10000',MOVE_NOMONSTERS,self);
-    where = trace_endpos + '0 0 32';
-
-    setorigin(point,where);
-
     if(first)
-        point.owner = parent;
+        point.owner = first;
     else
     {
         point.classname = "path_master";
@@ -46,58 +66,68 @@
         point.path_prev = parent;
 
     if(next)
+    {
         point.path_next = next;
+        //point.path_nodelength = vlen(point.origin - next.origin)
+    }
     else
         point.classname = "path_end";
 
+    if(point.owner.path_flags & PLF_GROUNDSNAP)
+        where = pathlib_groundsnap(where,parent);
+
+
+    setorigin(point,where);
+
+
     return point;
 }
 
-#define pathib_maxdivide 128
-
-vector pathlib_findsubpath(vector start,vector vcrash,vector end,float maxsize)
+vector pathlib_findsubpath(entity start,vector vcrash,entity end,float maxsize)
 {
-    float x,y;//,z;
+    float x,y,z;
     float step;
-    float clear;
     float dist;
     float pathlength;
     float pathlength_best;
     vector bestpoint;
     vector point;
-    //string s;
+    float zmin,zmax;
 
     pathlength_best = 1000000;
 
-    step = vlen(self.maxs - self.mins) * 1.5;
-    //s = ftos(step);
+    step = vlen(self.maxs - self.mins) * start.owner.path_subpathing_bboxexpand;
 
-    //bprint("pathlib_findsubpath: step=",s);
-    //s = ftos(maxsize);
-    //bprint(" size=",s,"\n");
+    if(start.owner.path_flags & PLF_SUBPATH3D)
+    {
+        zmin = maxsize * -1;
+        zmax = maxsize;
+    }
+    else
+    {
+        zmin = 0;
+        zmax = 1;
+    }
 
-    //for(z = -maxsize; z < maxsize; z += step)
+    for(z = zmin; z < zmax; z += step)
     for(y = -maxsize; y < maxsize; y += step)
     for(x = -maxsize; x < maxsize; x += step)
     {
 
-        point = vcrash;
-        point_x = point_x + x;
-        point_y = point_y + y;
+        point_z = vcrash_z + z;
+        point_x = vcrash_x + x;
+        point_y = vcrash_y + y;
 
-        traceline(point + '0 0 32' ,point - '0 0 10000',MOVE_NOMONSTERS,self);
-        point = trace_endpos + '0 0 32';
 
-        clear = self.path_validate(start,point);
+        if(start.owner.path_flags & PLF_GROUNDSNAP)
+            point = pathlib_groundsnap(point,start);
 
-        if(clear)
+        if(self.path_validate(start.origin,point))
         {
-            //bprint("Good point\n");
-
-            dist = vlen(start - point);
+            dist = vlen(start.origin - point);
             if(dist > step)
             {
-                pathlength = dist + vlen(point - end);
+                pathlength = dist + vlen(point - end.origin);
                 if(pathlength < pathlength_best)
                 {
                     bestpoint = point;
@@ -119,7 +149,6 @@
     vector vcrash;
     vector subpath_point;
     entity subpoint;
-    //bprint("pathlib_path...\n");
 
     // Fail.
     if(start.cnt > pathib_maxdivide)
@@ -130,66 +159,39 @@
 
     vcrash = trace_endpos;
 
-    subpath_point = pathlib_findsubpath(start.origin,vcrash,end.origin,500);
+    subpath_point = pathlib_findsubpath(start,vcrash,end,start.owner.path_subpathing_size);
 
     if(subpath_point == vcrash)
         return 0; // Fail.
 
     subpoint = pathlib_createpoint(start,end,start.owner,subpath_point);
+
     subpoint.cnt = start.cnt +1;
     start.path_next = subpoint;
     end.path_prev = subpoint;
+
     if(self.path_validate(start.origin,end.origin))
         return 1;
 
     return pathlib_path(subpoint,end);
-
-    /*
-    while(!clear)
-    {
-        ++c;
-
-        if(c > pathib_maxdivide)
-            return 0;
-
-        subpath_point = pathlib_findsubpath(subpoint2.origin,vcrash,end.origin,2000);
-        if(subpath_point == vcrash)
-            return 0; // Fail.
-
-        subpoint = pathlib_createpoint(subpoint2,end,start.owner,subpath_point);
-        subpoint.cnt = subpoint2.cnt +1;
-        subpoint2.path_next = subpoint;
-
-        clear = self.path_validate(subpoint2.origin,end.origin);
-        vcrash = trace_endpos;
-        if(clear)
-            return 1;
-        subpoint2 = subpoint;
-
-        // Fail.
-
-    }*
-
-    */
-
-
-    return 1;
 }
 
 void pathlib_path_optimize(entity start,entity end)
 {
     entity point,point_tmp;
-    point = start.path_next;
     float c;
 
+    point = start.path_next;
+
     while(point != end)
     {
         c++;
-        if(c > 200)
+        if(c > 5000)
         {
-            //bprint("pathlib_path_optimize runaway!\n");
+            dprint("pathlib_path_optimize runaway!\n");
             return;
         }
+
         point_tmp = point;
         point = point.path_next;
         if(self.path_validate(point_tmp.path_prev.origin,point_tmp.path_next.origin))
@@ -225,25 +227,37 @@
     }
 }
 
-entity dynpath_make(vector from, vector to)
+/**
+    Run a A*-like pathing from 'from' to 'to'
+**/
+entity pathlib_makepath(vector from, vector to,float pathflags,float subpathing_size, float subpathing_bboxexpand)
 {
     entity e_start,e_end;
 
-    //float t;
-    //t = time;
-
     if(!self.path_validate)
         self.path_validate = pathlib_stdproc_path_validate;
 
+
+    if(subpathing_size < 10)
+        subpathing_size = 500;
+
+    if(subpathing_bboxexpand < 1)
+        subpathing_bboxexpand = 1;
+
     e_start = pathlib_createpoint(world,world,world,from);
+    e_start.path_flags = pathflags;
+
+    e_start.path_subpathing_size = subpathing_size;
+    e_start.path_subpathing_bboxexpand = subpathing_bboxexpand;
+
     e_start.owner = e_start;
+
     e_end = pathlib_createpoint(e_start,world,e_start,to);
     e_start.path_next = e_end;
     e_start.cnt = 0;
 
     if(!pathlib_path(e_start,e_end))
     {
-        //bprint("Crap.\n");
         pathlib_deletepath(e_start);
         remove(e_start);
         return world;
@@ -251,26 +265,22 @@
 
     pathlib_path_optimize(e_start,e_end);
 
-    //string s;
-    //t = time - t;
-    //s = ftos(t);
-    //bprint("^2Path created in ", s, " seconds\n");
-
     return e_start;
 
 }
 
+
+/* TESTING */
 void pathlib_test_think()
 {
-    //bprint("pathlib_test tink...\n");
     pathlib_showpath(self.enemy);
+
     self.nextthink = time + 0.5;
 }
 void pathlib_test_dinit()
 {
     entity path;
     entity end;
-    // bprint("pathlib_test spawning...\n");
 
     if(self.target == "")
     {
@@ -287,8 +297,9 @@
         return;
     }
 
-    setsize(self,'-70 -70 0','70 70 70');
-    path = dynpath_make(self.origin,end.origin);
+    setsize(self,'-50 -50 0','50 50 50');
+    path = pathlib_makepath(self.origin,end.origin, PLF_GROUNDSNAP,500,1.25);
+
     if(!path)
     {
         bprint("^1 ==== ERROR: pathlib_test pathing fail ====\n");

Modified: branches/nexuiz-2.0/data/qcsrc/server/portals.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/portals.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/portals.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -256,6 +256,9 @@
 
 	if(other.classname == "player")
 		return; // handled by think
+
+	if(other.classname == "item_flag_team")
+		return; // never portal these
 	
 	if(other.classname == "grapplinghook")
 		return; // handled by think

Modified: branches/nexuiz-2.0/data/qcsrc/server/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/progs.src	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/progs.src	2008-11-04 11:54:16 UTC (rev 4977)
@@ -47,10 +47,14 @@
 havocbot_roles.qc
 havocbot.qc
 
-// tZorks pathlib
+g_subs.qc
+
+
+// tZork's libs
+movelib.qc
+steerlib.qc
 pathlib.qc
 
-g_subs.qc
 
 runematch.qc
 arena.qc

Copied: branches/nexuiz-2.0/data/qcsrc/server/steerlib.qc (from rev 4976, trunk/data/qcsrc/server/steerlib.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/steerlib.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/steerlib.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -0,0 +1,397 @@
+/**
+    Pull toward a point, The further away, the stronger the pull.
+**/
+vector steerlib_arrive(vector point,float maximal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+    direction = normalize(point - self.origin);
+    return  direction * (distance / maximal_distance);
+}
+
+/**
+    Pull toward a point increasing the pull the closer we get
+**/
+vector steerlib_attract(vector point, float maximal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+    direction = normalize(point - self.origin);
+
+    return  direction * (1-(distance / maximal_distance));
+}
+
+/**
+    Move away from a point.
+**/
+vector steerlib_repell(vector point,float maximal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = bound(0.001,vlen(self.origin - point),maximal_distance);
+    direction = normalize(self.origin - point);
+
+    return  direction * (1-(distance / maximal_distance));
+}
+
+/**
+    Keep at ideal_distance away from point
+**/
+vector steerlib_standoff(vector point,float ideal_distance)
+{
+    float distance;
+    vector direction;
+
+    distance = vlen(self.origin - point);
+
+
+    if(distance < ideal_distance)
+    {
+        direction = normalize(self.origin - point);
+        return direction * (distance / ideal_distance);
+    }
+
+    direction = normalize(point - self.origin);
+    return direction * (ideal_distance / distance);
+
+}
+
+/**
+    A random heading in a forward halfcicrle
+**/
+vector steerlib_waner(float range,float tresh,vector oldpoint)
+{
+    vector wander_point;
+    wander_point = v_forward - oldpoint;
+
+    if (vlen(wander_point) > tresh)
+        return oldpoint;
+
+    range = bound(0,range,1);
+
+    wander_point = self.origin + v_forward * 128;
+    wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
+
+    return normalize(wander_point - self.origin);
+}
+
+/**
+    Dodge a point-
+**/
+vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
+{
+    float distance;
+
+    distance = max(vlen(self.origin - point),min_distance);
+
+    return dodge_dir * (min_distance/distance);
+}
+
+/**
+    flocking by .flock_id
+    Group will move towards the unified direction while keeping close to eachother.
+**/
+.float flock_id;
+vector steerlib_flock(float radius, float standoff,float separation_force,float flock_force)
+{
+    entity flock_member;
+    vector push,pull;
+    float ccount;
+
+    flock_member = findradius(self.origin,radius);
+    while(flock_member)
+    {
+        if(flock_member != self)
+        if(flock_member.flock_id == self.flock_id)
+        {
+            ++ccount;
+            push = push + (steerlib_repell(flock_member.origin,standoff) * separation_force);
+            pull = pull + (steerlib_arrive(flock_member.origin + flock_member.velocity,radius) * flock_force);
+        }
+        flock_member = flock_member.chain;
+    }
+    return push + (pull* (1 / ccount));
+}
+
+/**
+    All members want to be in the center, and keep away from eachother.
+    The furtehr form the center the more they want to be there.
+**/
+vector steerlib_swarm(float radius, float standoff,float separation_force,float swarm_force)
+{
+    entity swarm_member;
+    vector force,center;
+    float ccount;
+
+    swarm_member = findradius(self.origin,radius);
+
+    while(swarm_member)
+    {
+        if(swarm_member.flock_id == self.flock_id)
+        {
+            ++ccount;
+            center = center + swarm_member.origin;
+            force = force + (steerlib_repell(swarm_member.origin,standoff) * separation_force);
+        }
+        swarm_member = swarm_member.chain;
+    }
+
+    center = center * (1 / ccount);
+    force = force + (steerlib_arrive(center,radius) * swarm_force);
+
+    return force;
+}
+
+/**
+    Steer towards the direction least obstructed.
+    Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
+**/
+vector steerlib_traceavoid(float pitch,float length)
+{
+    vector vup_left,vup_right,vdown_left,vdown_right;
+    float fup_left,fup_right,fdown_left,fdown_right;
+    vector v_left,v_down;
+    //vector point;
+
+    /*
+    traceline(self.origin,self.origin + v_forward * length,MOVE_NOMONSTERS,self);
+    if(trace_fraction == 1)
+        return '0 0 0';
+    */
+
+    v_left = v_right * -1;
+    v_down = v_up * -1;
+
+    vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
+    traceline(self.origin, self.origin +  vup_left,MOVE_NOMONSTERS,self);
+    //vup_left = trace_endpos;
+    fup_left = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
+    traceline(self.origin,self.origin + vup_right ,MOVE_NOMONSTERS,self);
+    //vup_right = trace_endpos;
+    fup_right = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
+    traceline(self.origin,self.origin + vdown_left,MOVE_NOMONSTERS,self);
+    //vdown_left = trace_endpos;
+    fdown_left = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
+    traceline(self.origin,self.origin + vdown_right,MOVE_NOMONSTERS,self);
+    //vdown_right = trace_endpos;
+    fdown_right = trace_fraction;
+
+    //te_lightning1(world,self.origin, trace_endpos);
+
+    //(v_for * f_for) +
+
+    //point = self.origin + (vup_left * fup_left) + (vup_right * fup_right) +
+    //        (vdown_left * fdown_left) + (vdown_right * fdown_right);
+
+    vector upwish,downwish,leftwish,rightwish;
+    upwish    = v_up    * (fup_left   + fup_right);
+    downwish  = v_down  * (fdown_left + fdown_right);
+    leftwish  = v_left  * (fup_left   + fdown_left);
+    rightwish = v_right * (fup_right  + fdown_right);
+
+    return (upwish+leftwish+downwish+rightwish) * 0.25;
+
+    //point = point * 0.2; // /5
+
+   // return normalize(point - self.origin) * (1- (fup_left+fup_right+fdown_left+fdown_right) * 0.25);
+}
+
+
+
+//////////////////////////////////////////////
+//     Testting                             //
+// Everything below this point is a mess :D //
+//////////////////////////////////////////////
+#define TLIBS_TETSLIBS
+#ifdef TLIBS_TETSLIBS
+void flocker_die()
+{
+	sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+
+	pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+    self.owner.cnt += 1;
+    self.owner = world;
+
+    self.nextthink = time;
+    self.think = SUB_Remove;
+}
+
+
+void flocker_think()
+{
+    vector dodgemove,swarmmove;
+    vector reprellmove,wandermove,newmove;
+
+    self.angles_x = self.angles_x * -1;
+    makevectors(self.angles);
+    self.angles_x = self.angles_x * -1;
+
+    dodgemove   = steerlib_traceavoid(0.35,1000);
+    swarmmove   = steerlib_swarm(1000,100,150,400);
+    reprellmove = steerlib_repell(self.owner.enemy.origin+self.enemy.velocity,1000) * 700;
+
+    if(vlen(dodgemove) == 0)
+    {
+        self.pos1 = steerlib_waner(0.5,0.1,self.pos1);
+        wandermove  = self.pos1 * 50;
+    }
+    else
+        self.pos1 = normalize(self.velocity);
+
+    dodgemove = dodgemove * 700;
+
+    newmove = swarmmove + reprellmove + wandermove + dodgemove;
+    self.velocity = movelib_inertmove_byspeed(newmove,900,0.4,0.8);
+    //self.velocity  = movelib_inertmove(dodgemove,0.65);
+
+    self.velocity = movelib_drag(0.02,0.6);
+
+    self.angles = vectoangles(self.velocity);
+
+    if(self.health <= 0)
+        flocker_die();
+    else
+        self.nextthink = time + 0.1;
+}
+
+
+void spawn_flocker()
+{
+    entity flocker;
+
+    flocker = spawn ();
+
+    setorigin(flocker, self.origin + '0 0 32');
+    setmodel (flocker, "models/turrets/rocket.md3");
+    setsize (flocker, '-3 -3 -3', '3 3 3');
+
+    flocker.flock_id   = self.flock_id;
+    flocker.classname  = "flocker";
+    flocker.owner      = self;
+    flocker.think      = flocker_think;
+    flocker.nextthink  = time + random() * 5;
+    flocker.solid      = SOLID_BBOX;
+    flocker.movetype   = MOVETYPE_BOUNCEMISSILE;
+    flocker.effects    = EF_LOWPRECISION;
+    flocker.velocity   = randomvec() * 300;
+    flocker.angles     = vectoangles(flocker.velocity);
+    flocker.health     = 10;
+    flocker.pos1      = normalize(flocker.velocity + randomvec() * 0.1);
+
+    self.cnt = self.cnt -1;
+
+}
+
+void flockerspawn_think()
+{
+
+
+    if(self.cnt > 0)
+        spawn_flocker();
+
+    self.nextthink = time + self.delay;
+
+}
+
+void flocker_hunter_think()
+{
+    vector dodgemove,attractmove,newmove;
+    entity e,ee;
+    float d,bd;
+
+    self.angles_x = self.angles_x * -1;
+    makevectors(self.angles);
+    self.angles_x = self.angles_x * -1;
+
+    if(self.enemy)
+    if(vlen(self.enemy.origin - self.origin) < 64)
+    {
+        ee = self.enemy;
+        ee.health = -1;
+        self.enemy = world;
+
+    }
+
+    if(!self.enemy)
+    {
+        e = findchainfloat(flock_id,self.flock_id);
+        while(e)
+        {
+            d = vlen(self.origin - e.origin);
+
+            if(e != self.owner)
+            if(e != ee)
+            if(d > bd)
+            {
+                self.enemy = e;
+                bd = d;
+            }
+            e = e.chain;
+        }
+    }
+
+    if(self.enemy)
+        attractmove = steerlib_attract(self.enemy.origin,5000) * 1100;
+    else
+        attractmove = normalize(self.velocity) * 200;
+
+    dodgemove = steerlib_traceavoid(0.35,1500) * 1700;
+
+    newmove = dodgemove + attractmove;
+    self.velocity = movelib_inertmove_byspeed(newmove,850,0.5,0.9);
+    self.velocity = movelib_drag(0.01,0.5);
+
+
+    self.angles = vectoangles(self.velocity);
+    self.nextthink = time + 0.1;
+}
+
+
+float globflockcnt;
+void spawnfunc_flockerspawn()
+{
+    precache_model ( "models/turrets/rocket.md3");
+    precache_model("models/turrets/c512.md3");
+    ++globflockcnt;
+
+    if(!self.cnt)      self.cnt = 20;
+    if(!self.delay)    self.delay = 0.25;
+    if(!self.flock_id) self.flock_id = globflockcnt;
+
+    self.think     = flockerspawn_think;
+    self.nextthink = time + 0.25;
+
+    self.enemy = spawn();
+
+    setmodel(self.enemy, "models/turrets/rocket.md3");
+    setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
+
+    self.enemy.classname = "FLock Hunter";
+    self.enemy.scale     = 3;
+    self.enemy.effects   = EF_LOWPRECISION;
+    self.enemy.movetype  = MOVETYPE_BOUNCEMISSILE;
+    self.enemy.solid     = SOLID_BBOX;
+    self.enemy.think     = flocker_hunter_think;
+    self.enemy.nextthink = time + 10;
+    self.enemy.flock_id  = self.flock_id;
+    self.enemy.owner     = self;
+}
+#endif

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_items.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_items.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -908,11 +908,6 @@
 // compatibility:
 void spawnfunc_item_quad (void) {self.classname = "item_strength";spawnfunc_item_strength();}
 
-void spawnfunc_misc_gamemodel (void)
-{
-	SetBrushEntityModel();
-}
-
 void spawnfunc_misc_models (void)
 {
 	// exists as alias name for 2.4.2 compat
@@ -942,10 +937,26 @@
 void spawnfunc_func_wall (void)
 {
 	SetBrushEntityModel();
-	self.solid = SOLID_BSP;
+	if(!self.solid)
+		self.solid = SOLID_BSP;
 	self.use = func_wall_use;
 }
 
+void spawnfunc_func_illusionary (void)
+{
+	SetBrushEntityModel();
+	self.use = func_wall_use;
+}
+
+.float modelscale;
+void spawnfunc_misc_gamemodel (void)
+{
+	if(!self.scale)
+		self.scale = self.modelscale;
+	SetBrushEntityModel();
+	self.use = func_wall_use;
+}
+
 float target_item_func_set(float a, float b)
 {
 	if(b == 0)

Modified: branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/target_spawn.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -299,33 +299,12 @@
 	n = self.count;
 
 	// TODO make this generic AND faster than nextent()ing through all, if somehow possible
-	if(self.netname == "targetname")
-		fld = targetname;
-	else if(self.netname == "netname")
-		fld = netname;
-	else if(self.netname == "target")
-		fld = target;
-	else if(self.netname == "classname")
-		fld = classname;
-	else
-	{
-		objerror("invalid field specified for trigger_relay_if");
-		return;
-	}
+	n = (cvar_string(self.netname) == cvar_string(self.message));
+	if(self.spawnflags & 1)
+		n = !n;
 
-	for(e = world; (e = find(e, fld, self.message)) && (n > 0); --n)
-		;
-
-	if(self.spawnflags & 1) // MORE THAN count valid targets
-	{
-		if(n)
-			SUB_UseTargets();
-	}
-	else // AT MOST count valid targets
-	{
-		if(!n)
-			SUB_UseTargets();
-	}
+	if(n)
+		SUB_UseTargets();
 }
 
 void spawnfunc_trigger_relay_if()

Modified: branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -298,10 +298,6 @@
 		gamemode_name = "Race";
 		g_race_qualifying = cvar("g_race_qualifying");
 
-		// In campaign, only this mode makes sense...
-		if(cvar("g_campaign"))
-			g_race_qualifying = 1;
-
 		if(cvar("g_race_teams"))
 		{
 			g_race_qualifying = 0; // not supported!

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets.qh	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets.qh	2008-11-04 11:54:16 UTC (rev 4977)
@@ -12,6 +12,7 @@
 // Non combat units
 #include "../units/unit_fusionreactor.qc"  /// Supply unites that need it with power
 #include "../units/unit_targettrigger.qc"  /// Hit me!
+#include "../units/unit_checkpoint.qc"     /// Halfsmart pathing.
 
 // Combat units
 #include "../units/unit_plasma.qc"  /// Basic energy cannon
@@ -23,6 +24,6 @@
 #include "../units/unit_machinegun.qc" /// whacka
 #include "../units/unit_tessla.qc"  /// Chain lightning capabale turret
 #include "../units/unit_walker.qc"
+#include "../units/unit_ewheel.qc"
 
-
 #endif // TTURRETS_ENABLED

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets_early.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets_early.qh	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/include/turrets_early.qh	2008-11-04 11:54:16 UTC (rev 4977)
@@ -197,15 +197,16 @@
 #define  TFL_DMG_HEADSHAKE       128
 /// Die and stay dead.
 #define  TFL_DMG_DEATH_NORESPAWN 256
+/// Supress std turret gibs on death
+#define  RFL_DMG_DEATH_NOGIBS    512
 
 // Spawnflags
 /// Spawn in teambased modes
 #define TFL_SPAWN_TEAM      2
 /// Spawn in FFA modes
 #define TFL_SPAWN_FFA       4
-/// Respawn after death
-#define TFL_SPAWN_RESPAWN   8
 
+
 /*
 * Fields commnly used by turrets
 */

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_damage.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_damage.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_damage.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -154,30 +154,31 @@
     self.tur_head.effects   = self.effects;
     self.health             = 0;
 
-
 // Trow fake parts arround
     // base
-    makevectors(self.angles);
-    if (random() > 0.5)
+    if not(self.damage_flags & RFL_DMG_DEATH_NOGIBS)
     {
-        turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib2.md3",min(self.respawntime,20),1,1);
-        t_dir = (v_up * 700) + (randomvec() * 300);
-        turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib3.md3",min(self.respawntime,10),1,1);
-        t_dir = (v_up * 700) + (randomvec() * 300);
-        turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib4.md3",min(self.respawntime,10),1,1);
+        makevectors(self.angles);
+        if (random() > 0.5)
+        {
+            turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib2.md3",min(self.respawntime,20),1,1);
+            t_dir = (v_up * 700) + (randomvec() * 300);
+            turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib3.md3",min(self.respawntime,10),1,1);
+            t_dir = (v_up * 700) + (randomvec() * 300);
+            turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib4.md3",min(self.respawntime,10),1,1);
+        }
+        else
+        {
+            turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib1.md3",min(self.respawntime,20),1,1);
+        }
+
+        // Blow the top part up into the air
+        turret_trowgib2( self.origin + (v_up * 50),
+                         v_up * 150 + randomvec() * 50,
+                         '0.2 0.2 0.2',
+                         self.tur_head,time + 0.5 + (random() * 0.5));
     }
-    else
-    {
-        turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib1.md3",min(self.respawntime,20),1,1);
-    }
 
-    // Blow the top part up into the air
-    turret_trowgib2( self.origin + (v_up * 50),
-                     v_up * 150 + randomvec() * 50,
-                     '0.2 0.2 0.2',
-                     self.tur_head,time + 0.5 + (random() * 0.5));
-
-
 // Go boom
     RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,0,world);
 
@@ -207,13 +208,35 @@
     // this function doubles as "teamchange" function.
 
     self.tur_head.team = self.team;
-	if (self.team == COLOR_TEAM1)
-		self.colormod = '1.4 0.8 0.8';
-	else if (self.team == COLOR_TEAM2)
-		self.colormod = '0.8 0.8 1.4';
-	else
-		self.colormod = '0 0 0'; // reset
 
+    /*
+    COLOR_TEAM1       = 4;  // red
+    COLOR_TEAM2       = 13; // blue
+    COLOR_TEAM3       = 12; // yellow
+    COLOR_TEAM4       = 9; // pink
+    */
+
+	self.colormod = '0 0 0';
+
+	switch(self.team)
+	{
+        case COLOR_TEAM1: // Red
+            self.colormod = '1.4 0.8 0.8';
+            break;
+
+        case COLOR_TEAM2: // Blue
+            self.colormod = '0.8 0.8 1.4';
+            break;
+
+        case COLOR_TEAM3: // Yellow
+            self.colormod = '1.4 1.4 0.6';
+            break;
+
+        case COLOR_TEAM4: // Pink
+            self.colormod = '1.4 0.6 1.4';
+            break;
+	}
+
     self.deadflag           = DEAD_NO;
     self.tur_head.deadflag  = self.deadflag;
     self.effects            = 0;
@@ -253,17 +276,18 @@
 void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
 {
     entity baseent,oldself;
-    // entity player;
 
     if (self.health <= 0) return;
 
     // Damage func is shared on all parts as standard, we need to know what the master entity of this turret is.
-    // if ((self.classname == "turret_head")||(self.classname == "turret_gun")||(self.classname == "turret_badge"))
     if (self.owner)
         baseent = self.owner;
     else
         baseent = self;
 
+    oldself = self;
+    self = baseent;
+
     if (teamplay != 0)
     {
         if (self.team == attacker.team)
@@ -278,41 +302,38 @@
             FOR_EACH_PLAYER(player)
             	if(player.team == self.team)
             		sprint(player, "The enemy is attacking your base!");
-
             */
         }
-
     }
 
     baseent.health = baseent.health - damage;
 
     // thorw head slightly off aim when hit?
-    if ((self.classname == "turret_head") || (self.classname == "turret_gun"))
+    if (oldself.classname == "turret_head")
         if (self.damage_flags & TFL_DMG_HEADSHAKE)
-        {
-            // makevectors(baseent.tur_head.v_angle);
-            baseent.tur_head.angles = baseent.tur_head.angles + randomvec() * damage;
-        }
+            self.tur_head.angles = self.tur_head.angles + randomvec() * damage;
 
     if (self.turrcaps_flags & TFL_TURRCAPS_MOVE)
-    {
         self.velocity = self.velocity + vforce;
-    }
 
-
     // Start burning when we have 10% or less health left
     if (self.health < (self.tur_health * 0.1))
-        self.effects = EF_FLAME;
+        self.tur_head.effects = EF_FLAME;
 
-    if (self.health <= 0)
+    self = oldself;
+
+    if (baseent.health <= 0)
     {
-        oldself = self;
-        self = baseent;
-        turret_stdproc_die();
-        self = oldself;
+        baseent.event_damage           = SUB_Null;
+        baseent.tur_head.event_damage  = SUB_Null;
+        baseent.takedamage             = DAMAGE_NO;
+        baseent.tur_head.takedamage    = baseent.takedamage;
+        baseent.nextthink = time;
+        baseent.think = turret_stdproc_die;
+    }
 
-        //baseent.turret_diefunc();
-    }
+
+
 }
 
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_main.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/system/system_main.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -735,8 +735,17 @@
 {
     // bprint("Used:",self.netname, " By ",other.netname,"\n");
 
+    self.team = activator.team;
+
+    if(self.team == 0)
+        self.tur_active = 0;
+    else
+        self.tur_active = 1;
+
     // ONS Uses _use to communicate.
-    if (g_onslaught)
+    //if (g_onslaught)
+    /*
+    if (1) // if anyone ever figures out why i needed a active toggle here, fix this
     {
         entity e;
 
@@ -763,6 +772,7 @@
         else
             self.tur_active = 1;
     }
+    */
 
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_checkpoint.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_checkpoint.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_checkpoint.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,41 +1,62 @@
-void checkpoint_think()
+/**
+    turret_checkpoint
+    Semi smart pathing system for move capable turrets.
+**/
+
+#define checkpoint_path swampslug
+#define checkpoint_target enemy
+
+#define checkpoint_cache_who flagcarried
+#define checkpoint_cache_from lastrocket
+#define checkpoint_cache_to selected_player
+
+entity path_makeorcache(entity forwho,entity start, entity end)
 {
-    if(self.goalcurrent != world)
-        te_lightning1(self,self.origin,self.goalcurrent.origin);
+    entity oldself;
+    entity pth;
+    oldself = self;
+    self = forwho;
 
-
-    self.nextthink = time + 0.5;
+    pth = pathlib_makepath(start.origin,end.origin,PLF_GROUNDSNAP,500,1.5);
+    self = oldself;
+    return pth;
 }
 
-void turret_checkpoint_dinit()
+void turret_checkpoint_use()
 {
-    entity e;
+    if(other.checkpoint_path)
+        pathlib_deletepath(other.checkpoint_path);
 
+    other.checkpoint_path = world;
 
+    if(self.checkpoint_target)
+        other.checkpoint_path = path_makeorcache(other,self,self.checkpoint_target);
+
+}
+
+/*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
+-----------KEYS------------
+target: .targetname of next waypoint in chain.
+wait:   Pause at this point # seconds.
+-----------SPAWNFLAGS-----------
+---------NOTES----------
+If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
+If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
+*/
+void spawnfunc_turret_checkpoint()
+{
     if(self.target != "")
     {
-        e = find(world,targetname,self.target);
-        if(!e)
-        {
-            bprint("turret_checkpoint without valid target! (",vtos(self.origin),")\n");
-            remove(self);
-            return;
-        }
-
-        // TODO:: ADD WORLD-INTERACTIVE PATH SUBDEVISION IF PATH NOT CLEAR
-        self.goalcurrent = e;
+        self.checkpoint_target = find(world,targetname,self.target);
+        if(!self.checkpoint_target)
+            dprint("A turret_checkpoint faild to find its target!\n");
     }
 
 }
 
-/**
-.wait
-**/
-void spawnfunc_turret_checkpoint()
+// Compat.
+void spawnfunc_walker_checkpoint()
 {
-    if(!self.wait)
-        self.wait = 5;
-
-    self.think = turret_checkpoint_dinit;
-    self.nextthink = time + 0.25;
+    self.classname = "turret_checkpoint";
+    spawnfunc_turret_checkpoint();
 }

Copied: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_ewheel.qc (from rev 4976, trunk/data/qcsrc/server/tturrets/units/unit_ewheel.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_ewheel.qc	                        (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_ewheel.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -0,0 +1,210 @@
+void turret_ewheel_projectile_explode()
+{
+    vector org2;
+
+    org2 = findbetterlocation (self.origin, 8);
+    pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1);
+
+#ifdef TURRET_DEBUG
+    float d;
+
+    d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+    self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
+    self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+    RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+#endif
+    sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", 1, ATTN_NORM);
+
+    remove (self);
+}
+
+
+void ewheel_attack()
+{
+    entity proj;
+    vector v;
+    float f,i;
+
+    for(i=0;i<2;i++)
+    {
+        f = gettagindex(self.tur_head,"tag_fire");
+        v = gettaginfo(self.tur_head,f);
+        v_y = v_y * -1;
+        self.tur_shotorg = v;
+        turret_do_updates(self);
+
+        sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", 1, ATTN_NORM);
+        pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg_updated, self.tur_shotdir_updated * 1000, 1);
+
+        proj                    = spawn ();
+        setorigin(proj, self.tur_shotorg_updated);
+        setsize(proj, '-0.5 -0.5 -0.5', '0.5 0.5 0.5');
+        setmodel(proj, "models/laser.mdl"); // precision set above
+        proj.classname       = "ewheel bolt";
+        proj.owner           = self;
+        proj.bot_dodge       = FALSE;
+        proj.bot_dodgerating = self.shot_dmg;
+        proj.think           = turret_ewheel_projectile_explode;
+        proj.nextthink       = time + 9;
+        proj.solid           = SOLID_BBOX;
+        proj.movetype        = MOVETYPE_FLYMISSILE;
+        proj.velocity        = (self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+        proj.angles          = vectoangles(proj.velocity);
+        proj.touch           = turret_ewheel_projectile_explode;
+        proj.effects         = EF_LOWPRECISION |  EF_BRIGHTFIELD;
+        proj.enemy           = self.enemy;
+        proj.flags           = FL_PROJECTILE | FL_NOTARGET;
+
+        self.tur_head.frame += 1;
+
+        if (self.tur_head.frame > 3)
+        self.tur_head.frame = 0;
+        }
+
+}
+
+void ewheel_postthink()
+{
+    vector wish_angle,real_angle;
+    float turn_limit;
+
+    if (!self.enemy)
+    {
+        self.velocity = '0 0 0';
+        return;
+    }
+
+    wish_angle = normalize(self.enemy.origin - self.origin);
+    wish_angle = vectoangles(wish_angle);
+    real_angle = wish_angle - self.angles;
+
+    if (real_angle_y < 0) real_angle_y += 360;
+    if (real_angle_y > 180) real_angle_y -= 360;
+
+    turn_limit = cvar("g_turrets_unit_ewheel_turnrate");
+    // Convert from dgr/sec to dgr/tic
+    turn_limit  = turn_limit / (1 / self.ticrate);
+    real_angle_y = bound(turn_limit * -1,real_angle_y,turn_limit);
+    self.angles_y = self.angles_y + real_angle_y;
+    self.angles_z = bound(-10,real_angle_y * -1,10);
+
+    if(self.frame > 40)
+        self.frame = 1;
+
+    self.angles_z = 0;
+    if(self.tur_dist_enemy > self.target_range_optimal)
+    {
+        self.angles_z = bound(-15,real_angle_y * -1,15);
+        makevectors(self.angles);
+        self.velocity = v_forward * 250;
+        self.frame += 2;
+        return;
+    }
+
+    self.velocity = '0 0 0';
+
+
+}
+
+void ewheel_respawnhook()
+{
+
+
+    setorigin(self,self.pos1);
+
+    //self.angles = self.wkr_spawn.angles;
+
+}
+
+void ewheel_diehook()
+{
+}
+
+void turret_ewheel_dinit()
+{
+    entity e;
+
+    if (self.netname == "")      self.netname     = "Ewheel Turret";
+
+    // self.ticrate = 0.05;
+
+    if (self.target != "")
+    {
+        e = find(world,targetname,self.target);
+        if (!e)
+        {
+            bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");
+            self.target = "";
+        }
+
+        if (e.classname != "turret_checkpoint")
+            dprint("Warning: not a turrret path\n");
+        else
+            self.goalcurrent = e;
+    }
+
+    self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+    self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_LINKED;
+    self.aim_flags = TFL_AIM_SIMPLE;// TFL_AIM_LEAD | TFL_AIM_ZEASE;
+
+    self.turret_respawnhook = ewheel_respawnhook;
+    self.turret_diehook = ewheel_diehook;
+
+    self.ticrate = 0.05;
+    if (turret_stdproc_init("ewheel_std") == 0)
+    {
+        remove(self);
+        return;
+    }
+
+    self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+    self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+    self.damage_flags |= RFL_DMG_DEATH_NOGIBS;
+
+    //self.flags      = FL_CLIENT;
+    self.iscreature = TRUE;
+    self.movetype   = MOVETYPE_WALK;
+    self.solid      = SOLID_SLIDEBOX;
+    self.takedamage = DAMAGE_AIM;
+
+    setmodel(self,"models/turrets/ewheel-base.md3");
+    setmodel(self.tur_head,"models/turrets/ewheel-gun1.md3");
+
+    setattachment(self.tur_head,self,"tag_head");
+
+    self.pos1 = self.origin;
+
+    vector v;
+    float f;
+    f = gettagindex(self.tur_head,"tag_fire");
+    v = gettaginfo(self.tur_head,f);
+    v_y = v_y * -1;
+
+    //setsize(self,WALKER_MIN,WALKER_MAX);
+    //setsize(self,'-70 -70 0','70 70 55');
+
+    self.tur_shotorg = v;
+    self.tur_aimorg  = v;
+
+    self.tur_aimorg_x = 0;
+    self.tur_aimorg_y = 0;
+    self.tur_aimorg_z = 25;
+
+    self.idle_aim = '0 0 0';
+
+    // Our fire routine
+    self.turret_firefunc  = ewheel_attack;
+    self.turret_postthink = ewheel_postthink;
+    self.tur_head.frame = 1;
+}
+
+
+void spawnfunc_turret_ewheel()
+{
+    precache_model ("models/turrets/ewheel-base.md3");
+    precache_model ("models/turrets/ewheel-gun1.md3");
+
+    self.think = turret_ewheel_dinit;
+    self.nextthink = time + 0.5;
+}

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hellion.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hellion.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hellion.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -149,6 +149,14 @@
     vector org2;
     float d;
 
+    if(self.event_damage != SUB_Null)
+    {
+        self.event_damage = SUB_Null;
+        self.think = turret_hellion_missile_explode;
+        self.nextthink = time;
+        return;
+    }
+
     sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", 1, ATTN_NORM);
     org2 = findbetterlocation (self.origin, 16);
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hk.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hk.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_hk.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -351,6 +351,14 @@
     vector org2;
     float d;
 
+    if(self.event_damage != SUB_Null)
+    {
+        self.event_damage = SUB_Null;
+        self.think = turret_hk_missile_explode;
+        self.nextthink = time;
+        return;
+    }
+
     if ((other == self.owner)||(other == self.owner.tur_head))
         return;
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_mlrs.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_mlrs.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_mlrs.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,7 +1,7 @@
 void spawnfunc_turret_mlrs();
 void turret_mlrs_dinit();
 void turret_mlrs_attack();
-void turret_mlrs_projectile_explode();
+void turret_mlrs_rocket_explode();
 
 void turret_mlrs_postthink()
 {
@@ -34,14 +34,14 @@
     missile.takedamage         = DAMAGE_YES;
     missile.damageforcescale   = 4;
     missile.health             = 30;
-    missile.think              = turret_mlrs_projectile_explode;
+    missile.think              = turret_mlrs_rocket_explode;
     missile.nextthink          = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
     missile.solid              = SOLID_BBOX;
     missile.movetype           = MOVETYPE_FLYMISSILE;
     missile.effects            = EF_LOWPRECISION;
     missile.velocity           = (self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
     missile.angles             = vectoangles(missile.velocity);
-    missile.touch              = turret_mlrs_projectile_explode;
+    missile.touch              = turret_mlrs_rocket_explode;
     missile.flags              = FL_PROJECTILE;
     missile.solid              = SOLID_BBOX;
     missile.enemy              = self.enemy;
@@ -51,17 +51,23 @@
     //self.tur_head.frame = 7 - self.volly_counter;
 }
 
-void turret_mlrs_projectile_explode()
+void turret_mlrs_rocket_explode()
 {
     vector org2;
 
-    //vector	org2;
+    if(self.event_damage != SUB_Null)
+    {
+        self.event_damage = SUB_Null;
+        self.think = turret_mlrs_rocket_explode;
+        self.nextthink = time;
+        return;
+    }
+
+
     sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", 1, ATTN_NORM);
     org2 = findbetterlocation (self.origin, 16);
     pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
 
-    self.event_damage = SUB_Null;
-
 #ifdef TURRET_DEBUG
     float d;
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_plasma.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_plasma.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_plasma.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -33,6 +33,8 @@
     turret_tag_fire_update();
 
     sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", 1, ATTN_NORM);
+    pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg_updated, self.tur_shotdir_updated * 1000, 1);
+
     proj                    = spawn ();
     setorigin(proj, self.tur_shotorg_updated);
     setsize(proj, '-0.5 -0.5 -0.5', '0.5 0.5 0.5');
@@ -53,12 +55,9 @@
     proj.enemy           = self.enemy;
     proj.flags           = FL_PROJECTILE | FL_NOTARGET;
 
-    if (self.tur_head.frame == 0)
-        self.tur_head.frame = 1;
+    if(self.tur_head.frame )
+        self.tur_head.frame = 0;
 
-    // Snapback the head
-    // self.tur_head.angles_x = self.tur_head.angles_x + min((self.shot_dmg * 0.05),self.aim_maxpitch);
-
 }
 
 void turret_plasma_dual_attack()

Modified: branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_walker.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_walker.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/tturrets/units/unit_walker.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -48,10 +48,10 @@
     where = self.origin + v_forward * 128;
 
     e = findradius(where,80);
-    while(e)
+    while (e)
     {
-        if(turret_validate_target(self,e,self.target_validate_flags))
-            if(e != self)
+        if (turret_validate_target(self,e,self.target_validate_flags))
+            if (e != self)
                 Damage(e,self,self,cvar("g_turrets_unit_walker_std_meele_dmg "),DEATH_TURRET,'0 0 0', v_forward * cvar("g_turrets_unit_walker_std_meele_force") );
 
         e = e.chain;
@@ -61,86 +61,90 @@
 void walker_animate()
 {
 
-    if(self.tur_head.frame != 0)
+    if (self.tur_head.frame != 0)
         self.tur_head.frame = self.tur_head.frame +1;
 
-    if(self.tur_head.frame > 12)
+    if (self.tur_head.frame > 12)
         self.tur_head.frame = 0;
 
 
-    switch(self.animflag)
+    switch (self.animflag)
     {
-        case ANIM_NO:
-            //if(self.frame != 0)
-            //    self.frame = 0;
+    case ANIM_NO:
+        //if(self.frame != 0)
+        //    self.frame = 0;
         break;
 
-        case ANIM_WALK:
-            self.frame = self.frame + 1;
-            if(self.frame > 25)
-                self.frame = 5;
+    case ANIM_WALK:
+        self.frame = self.frame + 1;
+        if (self.frame > 25)
+            self.frame = 5;
         break;
 
-        case ANIM_RUN:
-            self.frame = self.frame + 2;
-            if(self.frame > 25)
-                self.frame = 5;
+    case ANIM_RUN:
+        self.frame = self.frame + 2;
+        if (self.frame > 25)
+            self.frame = 5;
         break;
 
-        case ANIM_STRAFE_L:
-            if(self.frame < 35) self.frame = 35;
-            self.frame = self.frame + 1;
-            if(self.frame > 55) self.frame = 35;
+    case ANIM_STRAFE_L:
+        if (self.frame < 35) self.frame = 35;
+        self.frame = self.frame + 1;
+        if (self.frame > 55) self.frame = 35;
         break;
 
-        case ANIM_STRAFE_R:
-            if(self.frame < 65) self.frame = 65;
-            self.frame = self.frame + 1;
-            if(self.frame > 85) self.frame = 65;
+    case ANIM_STRAFE_R:
+        if (self.frame < 65) self.frame = 65;
+        self.frame = self.frame + 1;
+        if (self.frame > 85) self.frame = 65;
         break;
 
-        case ANIM_JUMP:
-            if(self.frame < 95) self.frame = 95;
-            if(self.frame > 100)
+    case ANIM_JUMP:
+        if (self.frame < 95) self.frame = 95;
+        if (self.frame > 100)
             self.frame = self.frame + 1;
 
         break;
 
-        case ANIM_LAND:
-            if(self.frame < 100) self.frame = 100;
-            self.frame = self.frame + 1;
-            if(self.frame > 107)
-                self.animflag = ANIM_NO;
+    case ANIM_LAND:
+        if (self.frame < 100) self.frame = 100;
+        self.frame = self.frame + 1;
+        if (self.frame > 107)
+            self.animflag = ANIM_NO;
         break;
 
-        case ANIM_PAIN:
-            if(self.frame < 90) self.frame = 90;
-            self.frame = self.frame + 1;
-            if(self.frame > 95)
-                self.animflag = ANIM_NO;
+    case ANIM_PAIN:
+        if (self.frame < 90) self.frame = 90;
+        self.frame = self.frame + 1;
+        if (self.frame > 95)
+            self.animflag = ANIM_NO;
         break;
 
-        case ANIM_MEELE:
-            if(self.frame < 123) self.frame = 123;
-            self.frame = self.frame + 1;
+    case ANIM_MEELE:
+        if (self.frame < 123) self.frame = 123;
+        self.frame = self.frame + 1;
 
-            if(self.frame == 133)
-                walker_meele_dmg();
+        if (self.frame == 133)
+            walker_meele_dmg();
 
-            if(self.frame > 140)
-                self.animflag = ANIM_NO;
+        if (self.frame > 140)
+            self.animflag = ANIM_NO;
 
     }
 }
 
-
-
-
-
 void walker_rocket_explode()
 {
     vector org2;
 
+    if(self.event_damage != SUB_Null)
+    {
+        self.event_damage = SUB_Null;
+        self.think = walker_rocket_explode;
+        self.nextthink = time;
+        return;
+    }
+
     sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", 1, ATTN_NORM);
     org2 = findbetterlocation (self.origin, 16);
 
@@ -150,8 +154,6 @@
     WriteCoord (MSG_BROADCAST, org2_y);
     WriteCoord (MSG_BROADCAST, org2_z);
 
-    self.event_damage = SUB_Null;
-
     RadiusDamage (self, self.owner, cvar("g_turrets_unit_walker_std_rocket_dmg"), 0, cvar("g_turrets_unit_walker_std_rocket_radius"), world, cvar("g_turrets_unit_walker_std_rocket_force"), DEATH_TURRET, world);
 
     remove (self);
@@ -188,16 +190,16 @@
     olddir = normalize(self.velocity);
     edist = vlen(self.enemy.origin - self.origin);
 
-    // Simulate crudely guidance
-    if(self.cnt < time)
+    // Simulate crude guidance
+    if (self.cnt < time)
     {
-        if(edist < 1000)
+        if (edist < 1000)
             self.tur_shotorg = randomvec() * min(edist,64);
         else
             self.tur_shotorg = randomvec() * min(edist,256);
         self.cnt = time + 0.5;
     }
-    if(edist < 256)
+    if (edist < 256)
         self.tur_shotorg = '0 0 0';
 
 
@@ -208,7 +210,7 @@
         return;
     }
 
-    if((random() < 0.01) && (self.shot_dmg != 1337))
+    if ((random() < 0.01) && (self.shot_dmg != 1337))
     {
         walker_rocket_loop();
         return;
@@ -260,7 +262,8 @@
 void walker_rocket_loop3()
 {
     self.nextthink = time + 0.1;
-    if(vlen(self.origin - self.tur_shotorg) < 128 )
+
+    if (vlen(self.origin - self.tur_shotorg) < 128 )
     {
         self.think = walker_rocket_think;
         return;
@@ -271,15 +274,10 @@
     float m_speed;
 
     m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
-
     olddir = normalize(self.velocity);
-
-
     newdir = normalize(self.tur_shotorg  - self.origin);
-
     newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
 
-
     self.velocity = newdir * m_speed;
     self.angles = vectoangles(self.velocity);
 }
@@ -288,7 +286,7 @@
 {
     self.nextthink = time + 0;
 
-    if(vlen(self.origin - self.tur_shotorg) < 128 )
+    if (vlen(self.origin - self.tur_shotorg) < 128 )
     {
         self.tur_shotorg = self.origin - '0 0 200';
         self.think = walker_rocket_loop3;
@@ -300,15 +298,10 @@
     float m_speed;
 
     m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
-
     olddir = normalize(self.velocity);
-
     newdir = normalize(self.tur_shotorg  - self.origin);
-
     newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
-
     self.velocity = newdir * m_speed;
-
     self.angles = vectoangles(self.velocity);
 
 }
@@ -317,16 +310,11 @@
 {
 
     self.nextthink= time + 0;
-
     self.tur_shotorg = self.origin + '0 0 400';
-
     self.think = walker_rocket_loop2;
-
     self.shot_dmg = 1337;
 }
 
-
-
 void walker_fire_rocket(vector org)
 {
 
@@ -357,16 +345,18 @@
     rocket.cnt                = time + 1;
     rocket.enemy              = self.enemy;
 
-    if(random() < 0.01)
+    if (random() < 0.01)
         rocket.think          = walker_rocket_loop;
     else
         rocket.think          = walker_rocket_think;
 
+    rocket.event_damage       = walker_rocket_damage;
+
     rocket.nextthink          = time + 0.2;
     rocket.solid              = SOLID_BBOX;
     rocket.movetype           = MOVETYPE_FLYMISSILE;
     rocket.effects            = EF_LOWPRECISION;
-    rocket.velocity           = ((v_forward + v_up * 0.5) +(randomvec() * 0.15))* cvar("g_turrets_unit_walker_std_rocket_speed");
+    rocket.velocity           = ((v_forward + v_up * 0.35) +(randomvec() * 0.15))* cvar("g_turrets_unit_walker_std_rocket_speed");
     rocket.angles             = vectoangles(rocket.velocity);
     rocket.touch              = walker_rocket_explode;
     rocket.flags              = FL_PROJECTILE;
@@ -390,13 +380,14 @@
     vector org;
 
     self.cnt = self.cnt -1;
-    if(self.cnt < 0)
+
+    if (self.cnt < 0)
     {
         remove(self);
         return;
     }
 
-    if(self.cnt> 1)
+    if (self.cnt > 1)
         f = gettagindex(self.owner,"tag_rocket01");
     else
         f = gettagindex(self.owner,"tag_rocket02");
@@ -405,7 +396,6 @@
 
 
     self.nextthink = time + 0.2;
-
     self = self.owner;
     walker_fire_rocket(org);
 }
@@ -416,16 +406,11 @@
     vector real_angle;
     float turn_limit;
 
-
-
-    if(self.flags & FL_ONGROUND)
-    {
+    if ((self.flags & FL_ONGROUND)&&(self.animflag != ANIM_MEELE))
         self.animflag = ANIM_NO;
-    }
 
-    if(self.enemy)
-    {
-        if(self.tur_head.attack_finished_single < time)
+    if (self.enemy)
+        if (self.tur_head.attack_finished_single < time)
         {
             entity rv;
             rv = spawn();
@@ -437,43 +422,38 @@
             self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
         }
 
-    }
 
-    if(self.goalcurrent)
+    if (self.checkpoint_path)
     {
-        //if(self.enemy && (self.tur_dist_enemy < self.target_range_fire))
-        //   self.animflag = ANIM_TURN;
-        //else
-        //{
-            if(vlen(self.origin  - self.goalcurrent.origin) < 64)
-                if(self.goalcurrent.goalcurrent == world)
-                    self.goalcurrent = world; // Path endpoint reached, go roaming.
-                else
-                    self.goalcurrent = self.goalcurrent.goalcurrent;
+        if (vlen(self.origin  - self.goalcurrent.origin) < 64)
+            if (self.goalcurrent.path_next == world)
+            {
 
-            self.animflag = ANIM_WALK;
-        //}
+                self.checkpoint_path = world; // Path endpoint reached, go roaming.
+            }
+            else
+                self.goalcurrent = self.goalcurrent.path_next;
 
-
+        self.animflag = ANIM_WALK;
     }
     else // Roaming mode
     {
 
-        if(self.enemy)
+        if (self.enemy)
         {
             wish_angle = angleofs(self,self.enemy); //normalize(self.origin-self.enemy.origin);
 
-            if(self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
+            if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
             {
 
-                if(fabs(wish_angle_y) < 15)
+                if (fabs(wish_angle_y) < 15)
                     self.animflag = ANIM_MEELE;
             }
             else
             {
-                if(fabs(wish_angle_y) < 15)
+                if (fabs(wish_angle_y) < 15)
                     self.animflag = ANIM_RUN;
-                else if(fabs(wish_angle_y) < 30)
+                else if (fabs(wish_angle_y) < 30)
                     self.animflag = ANIM_WALK;
                 else
                     self.animflag = ANIM_TURN;
@@ -481,7 +461,8 @@
 
         }
         else
-            self.animflag = ANIM_NO;
+            if(self.animflag != ANIM_MEELE)
+                self.animflag = ANIM_NO;
     }
 
 
@@ -490,12 +471,15 @@
     s_speed = vlen(self.velocity);
 
     // Turn on the spot
-    if (self.animflag == ANIM_TURN) {
-        if(self.enemy)
+    if (self.animflag == ANIM_TURN)
+    {
+        if (self.enemy)
             wish_angle = normalize(self.enemy.origin - self.origin);
         else
-            wish_angle = normalize(self.goalcurrent.origin - self.origin);        wish_angle = vectoangles(wish_angle);                  // And make a angle
+            wish_angle = normalize(self.goalcurrent.origin - self.origin);
 
+        wish_angle = vectoangles(wish_angle);
+
         real_angle = wish_angle - self.angles;
 
         if (real_angle_x < 0) real_angle_x += 360;
@@ -513,24 +497,24 @@
 
         self.angles_y = self.angles_y + real_angle_y;
 
-        if(self.enemy)
+        if (self.enemy)
             v_forward = normalize(self.enemy.origin - self.origin);
         else
             v_forward = normalize(self.goalcurrent.origin - self.origin);
 
         makevectors(self.angles);
 
-        if(s_speed > s_turn)
+        if (s_speed > s_turn)
             self.velocity = (v_forward * max((s_speed - s_decel),s_turn));
-        if(s_speed < s_turn)
+        if (s_speed < s_turn)
             self.velocity = (v_forward * min((s_speed + s_accel1),s_turn));
     }
     else if (self.animflag == ANIM_WALK) // Gg walking
     {
-        if(self.goalcurrent)
+        if (self.goalcurrent)
             wish_angle = normalize(self.goalcurrent.origin - self.origin);
         else
-            if(self.enemy)
+            if (self.enemy)
                 wish_angle = normalize(self.enemy.origin - self.origin);
             else
                 wish_angle = self.angles;
@@ -554,31 +538,36 @@
 
         self.angles_y = self.angles_y + real_angle_y;
 
-        if(self.goalcurrent)
+        if (self.goalcurrent)
             v_forward = normalize(self.goalcurrent.origin - self.origin);
         else
-            if(self.enemy)
+            if (self.enemy)
                 v_forward = normalize(self.enemy.origin - self.origin);
 
         makevectors(self.angles);
-        //self.velocity = v_forward * s_walk;
+        self.velocity = v_forward * s_walk;
 
         //if(self.flags & FL_ONGROUND)
+        /*
         {
+            float s_z;
+            s_z = self.velocity_z;
             if(s_speed > s_walk)
                 self.velocity = (v_forward * max((s_speed - s_decel),s_walk));
             if(s_speed <= s_walk)
                 self.velocity = (v_forward * min((s_speed + s_accel1),s_walk));
+            self.velocity_z = s_z;//s_walk;
         }
+        */
 
 
     }
     else if (self.animflag == ANIM_RUN) // Move fast, turn slow
     {
-        if(self.goalcurrent)
+        if (self.goalcurrent)
             wish_angle = normalize(self.goalcurrent.origin - self.origin);
         else
-            if(self.enemy)
+            if (self.enemy)
                 wish_angle = normalize(self.enemy.origin - self.origin);
             else
                 wish_angle = self.angles;
@@ -602,26 +591,28 @@
         self.angles_y = self.angles_y + real_angle_y;
 
 
-        if(self.enemy)
+        if (self.enemy)
             v_forward = normalize(self.enemy.origin - self.origin);
         else
             v_forward = normalize(self.goalcurrent.origin - self.origin);
 
         makevectors(self.angles);
 
-        if(self.flags & FL_ONGROUND)
+        if (self.flags & FL_ONGROUND)
         {
-            if(s_speed > s_run)
+            if (s_speed > s_run)
                 self.velocity = (v_forward * max((s_speed - s_decel),s_run));
-            if(s_speed <= s_run)
+            if (s_speed <= s_run)
                 self.velocity = (v_forward * min((s_speed + s_accel2),s_run));
         }
-    } else {
+    }
+    else
+    {
 
-        if(self.flags & FL_ONGROUND)
+        if (self.flags & FL_ONGROUND)
         {
             makevectors(self.angles);
-            if(s_speed > 0)
+            if (s_speed > 0)
                 self.velocity = min(s_speed - s_decel,0) * v_forward;
         }
     }
@@ -648,7 +639,7 @@
 
     te_smallflash(self.tur_shotorg_updated);
 
-    if(!(self.uzi_bulletcounter & 3))
+    if (!(self.uzi_bulletcounter & 3))
     {
 
         trailparticles(self,particleeffectnum("EF_MGTURRETTRAIL"),self.tur_shotorg_updated,trace_endpos);
@@ -671,6 +662,8 @@
 void walker_respawnhook()
 {
     vector vtmp;
+    entity e;
+
     self.origin = self.wkr_spawn.origin;
     self.wkr_props.solid = SOLID_BBOX;
     self.wkr_props.alpha = 1;
@@ -680,9 +673,27 @@
     vtmp_z +=self.wkr_spawn.origin_z + self.wkr_spawn.maxs_z;
     setorigin(self,vtmp);
 
+    if (self.target != "")
+    {
+        e = find(world,targetname,self.target);
+        if (!e)
+        {
+            bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
+            self.target = "";
+
+            //remove(self);
+            //return;
+        }
+
+        if (e.classname != "turret_checkpoint")
+            dprint("Warning: not a turrret path\n");
+        else
+            self.goalcurrent = e;
+    }
 }
 void walker_diehook()
 {
+
     self.wkr_props.solid = SOLID_NOT;
     self.wkr_props.alpha = -1;
 }
@@ -694,27 +705,23 @@
 
     if (self.netname == "")      self.netname     = "Walker Turret";
 
-    if(self.target != "")
+    /*
+    if (self.target != "")
     {
         e = find(world,targetname,self.target);
-        if(!e)
+        if (!e)
         {
             bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
             self.target = "";
-
-            //remove(self);
-            //return;
         }
 
-        if(e.classname != "walker_checkpoint")
-            dprint("Warning: not a walker path\n");
+        if (e.classname != "turret_checkpoint")
+            dprint("Warning: not a turrret path\n");
         else
             self.goalcurrent = e;
     }
+    */
 
-
-
-
     self.wkr_props = spawn();
     self.wkr_spawn = spawn();
 
@@ -731,16 +738,15 @@
         remove(self);
         return;
     }
-    // self.scale = 1.5;
-    //setsize(self,'38 38 55','-38 -38 1');
+    self.damage_flags |= RFL_DMG_DEATH_NOGIBS;
 
     self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-    self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+    self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
 
     //self.flags      = FL_CLIENT;
     self.iscreature = TRUE;
     self.movetype   = MOVETYPE_WALK;
-    self.solid      = SOLID_BBOX;// SOLID_SLIDEBOX;
+    self.solid      = SOLID_SLIDEBOX;
     self.takedamage = DAMAGE_AIM;
 
     setmodel(self.wkr_props,"models/turrets/walker_props.md3");

Modified: branches/nexuiz-2.0/data/qcsrc/server/vote.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/vote.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/vote.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -97,7 +97,7 @@
 		if(!(victim = GetKickVoteVictim(vote, cmd, e)))
 			return FALSE;
 		RemapVote_vote = GetKickVoteVictim_newcommand;
-		RemapVote_display = strcat("^1", vote, " (^7", victim.netname, "^1): ", GetKickVoteVictim_reason);
+		RemapVote_display = strcat("^1", RemapVote_vote, " (^7", victim.netname, "^1): ", GetKickVoteVictim_reason);
 	}
 	else
 	{

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -7,11 +7,7 @@
 {
 	float finalhit;
 	float f;
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 	pointparticles(particleeffectnum("crylink_impactbig"), self.origin, '0 0 0', 1);
 	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
 	if(finalhit)
@@ -37,11 +33,7 @@
 {
 	float finalhit;
 	float f;
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 	pointparticles(particleeffectnum("crylink_impact"), self.origin, '0 0 0', 1);
 	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
 	if(finalhit)

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -4,6 +4,12 @@
 	vector org2;
 	org2 = findbetterlocation (self.origin, 8);
 
+	if(other.takedamage == DAMAGE_AIM)
+		if(other.classname == "player")
+			if(IsDifferentTeam(self.owner, other))
+				if(IsFlying(other))
+					announce(self.owner, "announcer/male/electrobitch.ogg");
+
 	self.event_damage = SUB_Null;
 	if (self.movetype == MOVETYPE_BOUNCE)
 	{
@@ -16,12 +22,6 @@
 		RadiusDamage (self, self.owner, cvar("g_balance_electro_primary_damage"), cvar("g_balance_electro_primary_edgedamage"), cvar("g_balance_electro_primary_radius"), world, cvar("g_balance_electro_primary_force"), self.projectiledeathtype, other);
 	}
 
-	if(other.takedamage == DAMAGE_AIM)
-		if(other.classname == "player")
-			if(IsDifferentTeam(self.owner, other))
-				if(IsFlying(other))
-					announce(self.owner, "announcer/male/electrobitch.ogg");
-
 	sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
 
 	remove (self);
@@ -42,12 +42,7 @@
 
 void W_Plasma_Touch (void)
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM);
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH_NOSOUND;
 	if (other.takedamage == DAMAGE_AIM) {
 		W_Plasma_Explode ();
 	} else {
@@ -58,14 +53,7 @@
 
 void W_Plasma_TouchExplode (void)
 {
-	entity o;
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM);
-		remove(self);
-		return;
-	}
-	o = self.owner;
+	PROJECTILE_TOUCH_NOSOUND;
 	W_Plasma_Explode ();
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -5,15 +5,15 @@
 	pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
 	sound (self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
 
-	self.event_damage = SUB_Null;
-	RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_primary_damage"), cvar("g_balance_grenadelauncher_primary_edgedamage"), cvar("g_balance_grenadelauncher_primary_radius"), world, cvar("g_balance_grenadelauncher_primary_force"), self.projectiledeathtype, other);
-
 	if(other.takedamage == DAMAGE_AIM)
 		if(other.classname == "player")
 			if(IsDifferentTeam(self.owner, other))
 				if(IsFlying(other))
 					announce(self.owner, "announcer/male/airshot.ogg");
 
+	self.event_damage = SUB_Null;
+	RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_primary_damage"), cvar("g_balance_grenadelauncher_primary_edgedamage"), cvar("g_balance_grenadelauncher_primary_radius"), world, cvar("g_balance_grenadelauncher_primary_force"), self.projectiledeathtype, other);
+
 	remove (self);
 }
 
@@ -38,21 +38,13 @@
 
 void W_Grenade_Touch1 (void)
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 	W_Grenade_Explode ();
 }
 
 void W_Grenade_Touch2 (void)
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 	if (other.takedamage == DAMAGE_AIM)
 	{
 		self.use ();

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -40,24 +40,13 @@
 
 void W_Hagar_Touch (void)
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
-	if (other == self.owner)
-		return;
-
+	PROJECTILE_TOUCH;
 	self.use ();
 }
 
 void W_Hagar_Touch2 (void)
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 
 	if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) {
 		self.use();

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_hlac.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_hlac.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_hlac.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -5,15 +5,8 @@
 	vector org2;
 	vector normal;
 
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 
-	if (other == self.owner)
-		return;
-
 	normal = trace_plane_normal;
 	dir = normalize (self.owner.origin - self.origin);
 	org2 = findbetterlocation (self.origin, 8);
@@ -34,15 +27,8 @@
 	vector org2;
 	vector normal;
 
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 
-	if (other == self.owner)
-		return;
-
 	normal = trace_plane_normal;
 	dir = normalize (self.owner.origin - self.origin);
 	org2 = findbetterlocation (self.origin, 8);

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_hook.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -14,11 +14,7 @@
 
 void W_Hook_Touch2 (void)
 {
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 	self.use();
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -6,15 +6,8 @@
 	vector org2;
 	vector normal;
 
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 
-	if (other == self.owner)
-		return;
-
 	normal = trace_plane_normal;
 	dir = normalize (self.owner.origin - self.origin);
 	org2 = findbetterlocation (self.origin, 8);
@@ -116,8 +109,7 @@
 			}
 			else
 			{
-				if (self.BUTTON_ATCK2)
-				if (client_hasweapon(self, self.cnt, TRUE, FALSE))
+				if(self.switchweapon == WEP_LASER) // don't do this if already switching
 					W_SwitchWeapon (self.cnt);
 			}
 		}

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -72,6 +72,8 @@
 {
 	vector norm;
 
+	// do not use PROJECTILE_TOUCH here
+
 	if(other.classname == "portal")
 		return; // handled by the portal
 
@@ -168,7 +170,7 @@
 	gren.solid = SOLID_BBOX;
 	gren.effects = EF_LOWPRECISION | EF_RED | EF_ADDITIVE;
 	gren.scale = 4;
-	gren.modelflags = MF_GRENADE;
+	gren.modelflags = MF_TRACER;
 	setmodel(gren, "models/grenademodel.md3"); // precision set above
 	setsize(gren, '0 0 0', '0 0 0');
 	setorigin(gren, w_shotorg);

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -182,12 +182,7 @@
 {
 	if(self.owner && self.owner.lastrocket == self)
 		self.owner.lastrocket = world;
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM);
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH_NOSOUND;
 	W_Rocket_Explode ();
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_seeker.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_seeker.qc	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_seeker.qc	2008-11-04 11:54:16 UTC (rev 4977)
@@ -4,124 +4,123 @@
 
 void Seeker_Missile_Explode ()
 {
-    vector	org2;
-    float b;
-    org2 = findbetterlocation (self.origin, 12);
-    te_explosion (org2);
+	vector	org2;
+	float b;
+	org2 = findbetterlocation (self.origin, 12);
+	te_explosion (org2);
 
-    b = crandom();
-    if (b<-0.7)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", 1, ATTN_NORM);
-    else if (b<0.4)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", 1, ATTN_NORM);
-    else if (b<1)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", 1, ATTN_NORM);
+	b = crandom();
+	if (b<-0.7)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", 1, ATTN_NORM);
+	else if (b<0.4)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", 1, ATTN_NORM);
+	else if (b<1)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", 1, ATTN_NORM);
 
-    self.event_damage = SUB_Null;
-    RadiusDamage (self, self.owner, cvar("g_balance_seeker_missile_damage"), cvar("g_balance_seeker_missile_edgedamage"), cvar("g_balance_seeker_missile_radius"), world, cvar("g_balance_seeker_missile_force"), self.projectiledeathtype, other);
+	self.event_damage = SUB_Null;
+	RadiusDamage (self, self.owner, cvar("g_balance_seeker_missile_damage"), cvar("g_balance_seeker_missile_edgedamage"), cvar("g_balance_seeker_missile_radius"), world, cvar("g_balance_seeker_missile_force"), self.projectiledeathtype, other);
 
-    remove (self);
+	remove (self);
 }
 
 void Seeker_Missile_Touch()
 {
-    if (other == self.owner)
-        return;
+	PROJECTILE_TOUCH;
 
-    Seeker_Missile_Explode();
+	Seeker_Missile_Explode();
 }
 
 void Seeker_Missile_Think()
 {
-    entity e;
-    vector desireddir, olddir, newdir;
-    float turnrate;
-    float dist;
+	entity e;
+	vector desireddir, olddir, newdir;
+	float turnrate;
+	float dist;
 
-    if (time > self.cnt)
-        Seeker_Missile_Explode();
+	if (time > self.cnt)
+		Seeker_Missile_Explode();
 
-    if (!self.switchweapon)
-        self.switchweapon = cvar("g_balance_seeker_missile_speed");
+	if (!self.switchweapon)
+		self.switchweapon = cvar("g_balance_seeker_missile_speed");
 
-    if ((self.switchweapon < cvar("g_balance_seeker_missile_speed_max")) && cvar("g_balance_seeker_missile_speed_accel"))
-        self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_accel");
+	if ((self.switchweapon < cvar("g_balance_seeker_missile_speed_max")) && cvar("g_balance_seeker_missile_speed_accel"))
+		self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_accel");
 
-    if (self.switchweapon > cvar("g_balance_seeker_missile_speed_max"))
-        self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_decel");
+	if (self.switchweapon > cvar("g_balance_seeker_missile_speed_max"))
+		self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_decel");
 
-    if (self.enemy != world)
+	if (self.enemy != world)
 		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
 			self.enemy = world;
 
-    if (self.enemy != world)
-    {
-        e               = self.enemy;
-        turnrate        = cvar("g_balance_seeker_missile_turnrate");		    // how fast to turn
-        desireddir      = normalize(e.origin - self.origin);
-        olddir          = normalize(self.velocity);				            // get my current direction
-        dist            = vlen(e.origin - self.origin);
+	if (self.enemy != world)
+	{
+		e               = self.enemy;
+		turnrate        = cvar("g_balance_seeker_missile_turnrate");		    // how fast to turn
+		desireddir      = normalize(e.origin - self.origin);
+		olddir          = normalize(self.velocity);				            // get my current direction
+		dist            = vlen(e.origin - self.origin);
 
-        // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
-        if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist")))
-        {
-            // Is it a better idea (shorter distance) to trace to the target itself?
-            if ( vlen(self.origin + olddir * self.wait) < dist)
-                traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
-            else
-                traceline(self.origin, self.enemy.origin, FALSE, self);
+		// Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
+		if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist")))
+		{
+			// Is it a better idea (shorter distance) to trace to the target itself?
+			if ( vlen(self.origin + olddir * self.wait) < dist)
+				traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
+			else
+				traceline(self.origin, self.enemy.origin, FALSE, self);
 
-            // Setup adaptive tracelength
-            self.wait = vlen(self.origin - trace_endpos);
-            if (self.wait < cvar("g_balance_seeker_missile_smart_trace_min")) self.wait = cvar("g_balance_seeker_missile_smart_trace_min");
-            if (self.wait > cvar("g_balance_seeker_missile_smart_trace_max")) self.wait = cvar("g_balance_seeker_missile_smart_trace_max");
+			// Setup adaptive tracelength
+			self.wait = vlen(self.origin - trace_endpos);
+			if (self.wait < cvar("g_balance_seeker_missile_smart_trace_min")) self.wait = cvar("g_balance_seeker_missile_smart_trace_min");
+			if (self.wait > cvar("g_balance_seeker_missile_smart_trace_max")) self.wait = cvar("g_balance_seeker_missile_smart_trace_max");
 
-            // Calc how important it is that we turn and add this to the desierd (enemy) dir.
-            desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
-        }
+			// Calc how important it is that we turn and add this to the desierd (enemy) dir.
+			desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
+		}
 
-        //newdir = normalize((olddir + desireddir * turnrate) * 0.5);// take the average of the 2 directions; not the best method but simple & easy
-        newdir = normalize(olddir + desireddir * turnrate);// take the average of the 2 directions; not the best method but simple & easy
+		//newdir = normalize((olddir + desireddir * turnrate) * 0.5);// take the average of the 2 directions; not the best method but simple & easy
+		newdir = normalize(olddir + desireddir * turnrate);// take the average of the 2 directions; not the best method but simple & easy
 
-        self.velocity = newdir * self.switchweapon;			                    // make me fly in the new direction at my flight speed
-    }
+		self.velocity = newdir * self.switchweapon;			                    // make me fly in the new direction at my flight speed
+	}
 
-    // Proxy
-    if (cvar("g_balance_seeker_missile_proxy"))
-    {
-        if ( dist <= cvar("g_balance_seeker_missile_proxy_maxrange"))
-        {
-            if (self.autoswitch == 0)
-            {
-                self.autoswitch = time + cvar("g_balance_seeker_missile_proxy_delay");
-            }
-            else
-            {
-                if (self.autoswitch <= time)
-                {
-                    Seeker_Missile_Explode();
-                    self.autoswitch = 0;
-                }
-            }
-        }
-        else
-        {
-            if (self.autoswitch != 0)
-                self.autoswitch = 0;
-        }
-    }
-    ///////////////
+	// Proxy
+	if (cvar("g_balance_seeker_missile_proxy"))
+	{
+		if ( dist <= cvar("g_balance_seeker_missile_proxy_maxrange"))
+		{
+			if (self.autoswitch == 0)
+			{
+				self.autoswitch = time + cvar("g_balance_seeker_missile_proxy_delay");
+			}
+			else
+			{
+				if (self.autoswitch <= time)
+				{
+					Seeker_Missile_Explode();
+					self.autoswitch = 0;
+				}
+			}
+		}
+		else
+		{
+			if (self.autoswitch != 0)
+				self.autoswitch = 0;
+		}
+	}
+	///////////////
 
-    if (self.enemy.deadflag != DEAD_NO)
-    {
-        self.enemy = world;
-        self.cnt = time + 1 + (random() * 4);
-        self.nextthink = self.cnt;
-        return;
-    }
+	if (self.enemy.deadflag != DEAD_NO)
+	{
+		self.enemy = world;
+		self.cnt = time + 1 + (random() * 4);
+		self.nextthink = self.cnt;
+		return;
+	}
 
-    self.angles = vectoangles(self.velocity);			// turn model in the new flight direction
-    self.nextthink = time + 0.05;
+	self.angles = vectoangles(self.velocity);			// turn model in the new flight direction
+	self.nextthink = time + 0.05;
 
 }
 
@@ -129,279 +128,307 @@
 
 void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
-    float d;
-    d = damage;
+	float d;
+	d = damage;
 
-    if (self.owner == attacker)
-        d = d * 0.25;
+	if (self.owner == attacker)
+		d = d * 0.25;
 
-    self.health = self.health - d;
+	self.health = self.health - d;
 
-    if (self.health <= 0)
+	if (self.health <= 0)
 		W_PrepareExplosionByDamage(attacker, Seeker_Missile_Explode);
 }
 
 #define EF_ROCKET				16777216
 void Seeker_Missile_Animate()
 {
-    self.frame = self.frame +1;
-    self.nextthink = time + 0.05;
+	self.frame = self.frame +1;
+	self.nextthink = time + 0.05;
 
-    if (self.enemy != world)
+	if (self.enemy != world)
 		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
 			self.enemy = world;
 
-    if(self.frame == 5)
-    {
+	if(self.frame == 5)
+	{
 		self.think           = Seeker_Missile_Think;
-        self.nextthink       = time + cvar("g_balance_seeker_missile_activate_delay");
-        self.effects         = EF_LOWPRECISION | EF_NOSHADOW | EF_ROCKET;
+		self.nextthink       = time + cvar("g_balance_seeker_missile_activate_delay");
+		self.effects         = EF_LOWPRECISION | EF_NOSHADOW | EF_ROCKET;
 
-        if (cvar("g_balance_seeker_guided_proxy"))
-            self.movetype    = MOVETYPE_BOUNCEMISSILE;
-        else
-            self.movetype    = MOVETYPE_FLYMISSILE;
-    }
+		if (cvar("g_balance_seeker_guided_proxy"))
+			self.movetype    = MOVETYPE_BOUNCEMISSILE;
+		else
+			self.movetype    = MOVETYPE_FLYMISSILE;
+	}
 }
 
 void Seeker_Fire_Missile(vector f_org)
 {
-    local entity missile;
+	local entity missile;
 
-    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-        self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_missile_ammo");
+	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_missile_ammo");
 
-    makevectors(self.v_angle);
-    W_SetupShot (self, f_org, FALSE, 2, "weapons/hagar_fire.wav");
-    pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+	makevectors(self.v_angle);
+	W_SetupShot (self, f_org, FALSE, 2, "weapons/hagar_fire.wav");
+	pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 
-    //self.detornator         = FALSE;
+	//self.detornator         = FALSE;
 
-    missile                 = spawn();
-    missile.owner           = self;
-    missile.classname       = "seeker_missile";
-    missile.bot_dodge       = TRUE;
-    missile.bot_dodgerating = cvar("g_balance_seeker_missile_damage");
+	missile                 = spawn();
+	missile.owner           = self;
+	missile.classname       = "seeker_missile";
+	missile.bot_dodge       = TRUE;
+	missile.bot_dodgerating = cvar("g_balance_seeker_missile_damage");
 
-    missile.think           = Seeker_Missile_Animate;
+	missile.think           = Seeker_Missile_Animate;
 
-    //if (!cvar("g_balance_seeker_missile_proxy"))
-    missile.touch           = Seeker_Missile_Touch;
+	//if (!cvar("g_balance_seeker_missile_proxy"))
+	missile.touch           = Seeker_Missile_Touch;
 
-    missile.event_damage    = Seeker_Missile_Damage;
-    missile.nextthink       = time + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
-    missile.cnt             = time + cvar("g_balance_seeker_missile_lifetime");
-    missile.enemy           = self.enemy;
-    missile.switchweapon           = cvar("g_balance_seeker_missile_speed");
-    missile.effects         = EF_LOWPRECISION | EF_NOSHADOW;// | EF_ROCKET;
-    missile.solid           = SOLID_BBOX;
-    missile.scale           = 2;
-    missile.takedamage          = DAMAGE_YES;
-    missile.damageforcescale    = 4;
-    missile.health              = 5;
+	missile.event_damage    = Seeker_Missile_Damage;
+	missile.nextthink       = time + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
+	missile.cnt             = time + cvar("g_balance_seeker_missile_lifetime");
+	missile.enemy           = self.enemy;
+	missile.switchweapon           = cvar("g_balance_seeker_missile_speed");
+	missile.effects         = EF_LOWPRECISION | EF_NOSHADOW;// | EF_ROCKET;
+	missile.solid           = SOLID_BBOX;
+	missile.scale           = 2;
+	missile.takedamage          = DAMAGE_YES;
+	missile.damageforcescale    = 4;
+	missile.health              = 5;
 	missile.projectiledeathtype = WEP_SEEKER;
 
-    setorigin (missile, w_shotorg);
-    setmodel  (missile, "models/tagrocket.md3");
-    setsize (missile, '-2 -2 -2', '2 2 2');
+	setorigin (missile, w_shotorg);
+	setmodel  (missile, "models/tagrocket.md3");
+	setsize (missile, '-2 -2 -2', '2 2 2');
 
 
-    missile.movetype    = MOVETYPE_FLYMISSILE;// MOVETYPE_TOSS;
+	missile.movetype    = MOVETYPE_FLYMISSILE;// MOVETYPE_TOSS;
 
-    missile.flags       = FL_PROJECTILE;
+	missile.flags       = FL_PROJECTILE;
 
-    missile.velocity    = (w_shotdir + '0 0 0.45') * missile.switchweapon;
-    W_SetupProjectileVelocity(missile);
+	missile.velocity    = (w_shotdir + '0 0 0.45') * missile.switchweapon;
+	W_SetupProjectileVelocity(missile);
 
-    missile.switchweapon = vlen(missile.velocity);
-    missile.angles = vectoangles (missile.velocity);
+	missile.switchweapon = vlen(missile.velocity);
+	missile.angles = vectoangles (missile.velocity);
 
 }
 
 void Seeker_Vollycontroler_Think()
 {
-    entity oldself,oldenemy;
-    self.cnt = self.cnt - 1;
+	float c;
+	entity oldself,oldenemy;
+	self.cnt = self.cnt - 1;
 
-    if ((self.owner.ammo_rockets < cvar("g_balance_seeker_missile_ammo")) || (self.cnt <= -1) || (self.owner.deadflag != DEAD_NO))
-    {
-        remove(self);
-        return;
-    }
+	if ((self.owner.ammo_rockets < cvar("g_balance_seeker_missile_ammo")) || (self.cnt <= -1) || (self.owner.deadflag != DEAD_NO))
+	{
+		remove(self);
+		return;
+	}
 
-    self.nextthink = time + cvar("g_balance_seeker_missile_delay");
+	self.nextthink = time + cvar("g_balance_seeker_missile_delay");
 
-    oldself = self;
-    self = self.owner;
+	oldself = self;
+	self = self.owner;
 
-    oldenemy = self.enemy;
-    self.enemy = oldself.enemy;
+	oldenemy = self.enemy;
+	self.enemy = oldself.enemy;
 
-	Seeker_Fire_Missile('56 13 -15' + 7 * randomvec());
+	c = mod(oldself.cnt, 4);
+	switch(c)
+	{
+		case 0:
+			Seeker_Fire_Missile('37.5 17 -22');
+			break;
+		case 1:
+			Seeker_Fire_Missile('37.5 9.5 -22');
+			break;
+		case 2:
+			Seeker_Fire_Missile('40 17 -29');
+			break;
+		case 3:
+		default:
+			Seeker_Fire_Missile('40 9.5 -29');
+			break;
+	}
 
-
-
-    self.enemy = oldenemy;
-    self = oldself;
+	self.enemy = oldenemy;
+	self = oldself;
 }
 
 void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
-    self.health = self.health - damage;
-    if (self.health <= 0)
-        self.think ();
+	self.health = self.health - damage;
+	if (self.health <= 0)
+		self.think ();
 }
 
 void Seeker_Tag_Explode ()
 {
-    vector	org2;
-    float b;
+	vector	org2;
+	float b;
 
-    //if(other==self.owner)
-    //    return;
+	//if(other==self.owner)
+	//    return;
 
-    org2 = findbetterlocation (self.origin, 12);
-    te_explosion (org2);
+	org2 = findbetterlocation (self.origin, 12);
+	te_explosion (org2);
 
-    b = crandom();
-    if (b<-0.7)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", 1, ATTN_NORM);
-    else if (b<0.4)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", 1, ATTN_NORM);
-    else if (b<1)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", 1, ATTN_NORM);
+	b = crandom();
+	if (b<-0.7)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", 1, ATTN_NORM);
+	else if (b<0.4)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", 1, ATTN_NORM);
+	else if (b<1)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", 1, ATTN_NORM);
 
-    remove (self);
+	remove (self);
 }
 
 void Seeker_Tag_Think()
 {
-    remove(self);
-    return;
+	remove(self);
+	return;
 }
 
 void Seeker_Tag_Touch()
 {
-    vector dir;
-    vector org2;
+	vector dir;
+	vector org2;
 
-	if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		remove(self);
-		return;
-	}
+	PROJECTILE_TOUCH;
 
-    if (other == self.owner)
-        return;
+	dir     = normalize (self.owner.origin - self.origin);
+	org2    = findbetterlocation (self.origin, 8);
 
-    dir     = normalize (self.owner.origin - self.origin);
-    org2    = findbetterlocation (self.origin, 8);
+	te_knightspike(org2);
 
-    te_knightspike(org2);
+	self.event_damage = SUB_Null;
+	sound (self, CHAN_PROJECTILE, "weapons/laserimpact.wav", 1, ATTN_NORM);
 
-    self.event_damage = SUB_Null;
-    sound (self, CHAN_PROJECTILE, "weapons/laserimpact.wav", 1, ATTN_NORM);
+	if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
+	{
+		entity e;
+		e           = spawn();
+		e.cnt       = cvar("g_balance_seeker_missile_count");
+		e.owner     = self.owner;
+		e.enemy     = other;
+		e.think     = Seeker_Vollycontroler_Think;
+		e.nextthink = time;
 
-    if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
-    {
-        entity e;
-        e           = spawn();
-        e.cnt       = cvar("g_balance_seeker_missile_count");
-        e.owner     = self.owner;
-        e.enemy     = other;
-        e.think     = Seeker_Vollycontroler_Think;
-        e.nextthink = time;
+		//sprint(self.owner, "^1Target lock ^3[^7 ",other.netname, " ^3]^1 acquired - autofire activated.\n");
+		//sprint(other,"^1You are targeted!\n");
 
-        //sprint(self.owner, "^1Target lock ^3[^7 ",other.netname, " ^3]^1 acquired - autofire activated.\n");
-        //sprint(other,"^1You are targeted!\n");
+		// stuffcmd(other,"play2 weapons/zany-alarm4.ogg\n");
+		// stuffcmd(self.owner, "play2 weapons/zany-lock4.ogg\n");
+	}
 
-        // stuffcmd(other,"play2 weapons/zany-alarm4.ogg\n");
-        // stuffcmd(self.owner, "play2 weapons/zany-lock4.ogg\n");
-    }
-
-    remove(self);
-    return;
+	remove(self);
+	return;
 }
 
 
 
 void Seeker_Fire_Tag()
 {
-    local entity missile;
-    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-        self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_tag_ammo");
+	local entity missile;
+	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_tag_ammo");
 
-    W_SetupShot (self, '56 13 -15', FALSE, 2, "weapons/hagar_fire.wav");
+	W_SetupShot (self, '56 13 -15', FALSE, 2, "weapons/hagar_fire.wav");
 
-    missile                 = spawn();
-    missile.owner           = self;
-    missile.classname       = "seeker_tag";
-    missile.bot_dodge       = TRUE;
-    missile.bot_dodgerating = 50;
-    missile.touch           = Seeker_Tag_Touch;
-    missile.think           = Seeker_Tag_Think;
-    missile.nextthink       = time + 15;
-    missile.movetype        = MOVETYPE_FLY;
-    missile.solid           = SOLID_BBOX;
-    missile.owner           = self;
+	missile                 = spawn();
+	missile.owner           = self;
+	missile.classname       = "seeker_tag";
+	missile.bot_dodge       = TRUE;
+	missile.bot_dodgerating = 50;
+	missile.touch           = Seeker_Tag_Touch;
+	missile.think           = Seeker_Tag_Think;
+	missile.nextthink       = time + 15;
+	missile.movetype        = MOVETYPE_FLY;
+	missile.solid           = SOLID_BBOX;
+	missile.owner           = self;
 
-    missile.takedamage       = DAMAGE_YES;
-    missile.event_damage    = Seeker_Tag_Explode;
-    missile.health          = 5;
+	missile.takedamage       = DAMAGE_YES;
+	missile.event_damage    = Seeker_Tag_Explode;
+	missile.health          = 5;
 
-    setmodel (missile, "models/laser.mdl");
-    setorigin (missile, w_shotorg);
+	setmodel (missile, "models/laser.mdl"); // TODO make this seeker specific
+	setorigin (missile, w_shotorg);
+	setsize (missile, '0 0 0', '0 0 0');
 
-    missile.effects     = EF_BRIGHTFIELD | EF_FULLBRIGHT | EF_NOSHADOW | EF_LOWPRECISION;
-    missile.flags       = FL_PROJECTILE;
+	missile.effects     = EF_FULLBRIGHT | EF_NOSHADOW | EF_LOWPRECISION;
+	missile.modelflags  = MF_TRACER3;
+	missile.flags       = FL_PROJECTILE;
 
-    missile.velocity    = w_shotdir  * cvar("g_balance_seeker_tag_speed");
-    missile.movetype    = MOVETYPE_BOUNCEMISSILE;
-    W_SetupProjectileVelocity(missile);
-    missile.angles = vectoangles (missile.velocity);
+	missile.velocity    = w_shotdir  * cvar("g_balance_seeker_tag_speed");
+	missile.movetype    = MOVETYPE_BOUNCEMISSILE;
+	W_SetupProjectileVelocity(missile);
+	missile.angles = vectoangles (missile.velocity);
 }
 
 
 void Seeker_Flac_Explode ()
 {
-    vector	org2;
-    float b;
-    org2 = findbetterlocation (self.origin, 12);
-    te_explosion (org2);
+	vector	org2;
+	float b;
+	org2 = findbetterlocation (self.origin, 12);
+	te_explosion (org2);
 
-    b = crandom();
-    if (b<-0.7)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", 1, ATTN_NORM);
-    else if (b<0.4)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", 1, ATTN_NORM);
-    else if (b<1)
-        sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", 1, ATTN_NORM);
+	b = crandom();
+	if (b<-0.7)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", 1, ATTN_NORM);
+	else if (b<0.4)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", 1, ATTN_NORM);
+	else if (b<1)
+		sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", 1, ATTN_NORM);
 
-    self.event_damage = SUB_Null;
+	self.event_damage = SUB_Null;
 
-    RadiusDamage (self, self.owner, cvar("g_balance_seeker_flac_damage"), cvar("g_balance_seeker_flac_edgedamage"), cvar("g_balance_seeker_flac_radius"), world, cvar("g_balance_seeker_flac_force"), self.projectiledeathtype, other);
+	RadiusDamage (self, self.owner, cvar("g_balance_seeker_flac_damage"), cvar("g_balance_seeker_flac_edgedamage"), cvar("g_balance_seeker_flac_radius"), world, cvar("g_balance_seeker_flac_force"), self.projectiledeathtype, other);
 
-    remove (self);
+	remove (self);
 }
 
 void Seeker_Flac_Touch()
 {
-    if (other == self.owner)
-        return;
+	PROJECTILE_TOUCH;
 
-    Seeker_Flac_Explode();
+	Seeker_Flac_Explode();
 }
 
 void Seeker_Fire_Flac()
 {
 	local entity missile;
+	vector f_org;
+	float c;
 
 	if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
 		self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_flac_ammo");
 
-    W_SetupShot (self, '56 13 -15', FALSE, 2, "weapons/hagar_fire.wav");
+	c = mod(self.bulletcounter, 4);
+	switch(c)
+	{
+		case 1:
+			f_org = '37.5 17 -22';
+			break;
+		case 2:
+			f_org = '37.5 9.5 -22';
+			break;
+		case 3:
+			f_org = '40 17 -29';
+			break;
+		case 0:
+		default:
+			f_org = '40 9.5 -29';
+			break;
+	}
+	W_SetupShot (self, f_org, FALSE, 2, "weapons/hagar_fire.wav");
 
-	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+		pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 
 	missile = spawn ();
 	missile.owner = missile.realowner = self;
@@ -421,7 +448,7 @@
 	missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
 
 	missile.effects = EF_LOWPRECISION;
-	missile.modelflags = MF_GRENADE;
+	missile.modelflags = MF_TRACER3;
 
 	missile.movetype = MOVETYPE_FLY;
 	w_shotdir = w_shotdir + '0 0 0.3';
@@ -440,53 +467,54 @@
 
 float w_seeker(float req)
 {
-    if (req == WR_AIM)
-        self.BUTTON_ATCK = bot_aim(cvar("g_balance_seeker_tag_speed"), 0, 20, FALSE);
+	if (req == WR_AIM)
+		self.BUTTON_ATCK = bot_aim(cvar("g_balance_seeker_tag_speed"), 0, 20, FALSE);
 
-    else if (req == WR_THINK)
-    {
-        if (self.BUTTON_ATCK)
-            if (weapon_prepareattack(0, cvar("g_balance_seeker_tag_refire")))
-            {
-                Seeker_Fire_Tag();
-                weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_tag_animtime"), w_ready);
-            }
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK)
+			if (weapon_prepareattack(0, cvar("g_balance_seeker_tag_refire")))
+			{
+				Seeker_Fire_Tag();
+				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_tag_animtime"), w_ready);
+			}
 
-        if (self.BUTTON_ATCK2)
-            if (weapon_prepareattack(1, cvar("g_balance_seeker_flac_refire")))
-            {
-                Seeker_Fire_Flac();
-                weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_flac_animtime"), w_ready);
-            }
+		if (self.BUTTON_ATCK2)
+			if (weapon_prepareattack(1, cvar("g_balance_seeker_flac_refire")))
+			{
+				Seeker_Fire_Flac();
+				weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_flac_animtime"), w_ready);
+			}
 
-    }
-    else if (req == WR_PRECACHE)
-    {
-        precache_model ("models/tagrocket.md3");
-        precache_model ("models/weapons/g_seeker.md3");
-        precache_model ("models/weapons/v_seeker.md3");
-        precache_model ("models/weapons/w_seeker.zym");
-        precache_sound ("weapons/hagar_fire.wav");
-        precache_sound ("weapons/hagexp1.wav");
-        precache_sound ("weapons/hagexp2.wav");
-        precache_sound ("weapons/hagexp3.wav");
-        precache_sound ("weapons/laserimpact.wav");
-    }
-    else if (req == WR_SETUP)
-        weapon_setup(WEP_SEEKER);
-    else if (req == WR_CHECKAMMO1)
-        return self.ammo_rockets >= cvar("g_balance_seeker_tag_ammo") + cvar("g_balance_seeker_missile_ammo");
-    else if (req == WR_CHECKAMMO2)
-        return self.ammo_rockets >= cvar("g_balance_seeker_flac_ammo");
-    else if (req == WR_SUICIDEMESSAGE)
-        w_deathtypestring = "played with tiny rockets";
-    else if (req == WR_KILLMESSAGE)
+	}
+	else if (req == WR_PRECACHE)
 	{
+		precache_model ("models/hagarmissile.mdl");
+		precache_model ("models/tagrocket.md3");
+		precache_model ("models/weapons/g_seeker.md3");
+		precache_model ("models/weapons/v_seeker.md3");
+		precache_model ("models/weapons/w_seeker.zym");
+		precache_sound ("weapons/hagar_fire.wav");
+		precache_sound ("weapons/hagexp1.wav");
+		precache_sound ("weapons/hagexp2.wav");
+		precache_sound ("weapons/hagexp3.wav");
+		precache_sound ("weapons/laserimpact.wav");
+	}
+	else if (req == WR_SETUP)
+		weapon_setup(WEP_SEEKER);
+	else if (req == WR_CHECKAMMO1)
+		return self.ammo_rockets >= cvar("g_balance_seeker_tag_ammo") + cvar("g_balance_seeker_missile_ammo");
+	else if (req == WR_CHECKAMMO2)
+		return self.ammo_rockets >= cvar("g_balance_seeker_flac_ammo");
+	else if (req == WR_SUICIDEMESSAGE)
+		w_deathtypestring = "played with tiny rockets";
+	else if (req == WR_KILLMESSAGE)
+	{
 		if(w_deathtype & HITTYPE_SECONDARY)
 			w_deathtypestring = "ran into #'s flac";
 		else
 			w_deathtypestring = "was tagged by";
 	}
-    return TRUE;
+	return TRUE;
 };
 

Modified: branches/nexuiz-2.0/data/scripts/entities.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/entities.def	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/scripts/entities.def	2008-11-04 11:54:16 UTC (rev 4977)
@@ -198,13 +198,6 @@
 target: targetname of first path_corner to move to at the default speed; ideally, this path_corner shall be exactly where the train starts
 */
 
-/*QUAKED func_wall (0 .5 .8) ? 
-A solid brush entity.
-Behaves just like solid brushes, except that it is a separate entity (a submodel) and can be targeted.
--------- KEYS --------
-targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature.
-*/
-
 /*QUAKED info_location (1 1 0) (-8 -8 -8) (8 8 8) 
 Location for use by the %l escape in "say" messages.
 The closest "visible" info_location entity is chosen to find the right location name for a point.
@@ -567,15 +560,39 @@
 colormap: 1024 + 16 * pantscolor + shirtcolor
 velocity: when movetype isn't 0, initial velocity vector
 angles: initial looking direction
+modelscale: scaling factor
 effects: sum of 1 = BRIGHTFIELD, 4 = BRIGHTLIGHT, 8 = DIMLIGHT, 32 = ADDITIVE, 64 = BLUE, 128 = RED, 512 = FULLBRIGHT, 1024 = FLAME, 2048 = STARDUST, 4096 = NOSHADOW, 8192 = NODEPTHTEST, 32768 = DOUBLESIDED, 8388608 = NOMODELFLAGS (ignores the following coming from a model file), 16777216 = ROCKET, 33554432 = GRENADE, 67108864 = GIB, 134217728 = ROTATE, 268435456 = TRACER, 536870912 = ZOMGIB, 1073741824 = TRACER2, -2147483648 = TRACER3
 loddistance1: distance after which to show the first LOD model replacement (default: 1000)
 loddistance2: distance after which to show the second LOD model replacement (default: 2000)
 lodmodel1: file name of the first LOD model replacement
 lodmodel2: file name of the second LOD model replacement
+targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature.
 -------- Q3MAP2 KEYS --------
 _frame: frame of model to include (set equal to frame if _castshadows is set)
-modelscale: scaling factor (set equal to scale if _castshadows is set)
 _castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
+targetname: if targeted by a misc_model, its brushes get inserted into this
+_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
+*/
+
+/*QUAKED func_illusionary (0 .5 .8) ? 
+A non-solid brush entity. Use func_wall if you want it solid.
+The keys below actually apply to most brush entities as they are engine features; however, they are described here as they aren't overridden by game code in misc_models. Its q3map2 keys below will work on any brush entity!
+-------- KEYS --------
+movetype: way in which it moves: one of 0 = NONE, 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
+avelocity: vector giving its angular velocity (useful for spinning models)
+scale: scale factor of the model (range: 0.0625 to 15.9375)
+colormap: 1024 + 16 * pantscolor + shirtcolor
+velocity: when movetype isn't 0, initial velocity vector
+angles: initial looking direction
+effects: sum of 1 = BRIGHTFIELD, 4 = BRIGHTLIGHT, 8 = DIMLIGHT, 32 = ADDITIVE, 64 = BLUE, 128 = RED, 512 = FULLBRIGHT, 1024 = FLAME, 2048 = STARDUST, 4096 = NOSHADOW, 8192 = NODEPTHTEST, 32768 = DOUBLESIDED, 8388608 = NOMODELFLAGS (ignores the following coming from a model file), 16777216 = ROCKET, 33554432 = GRENADE, 67108864 = GIB, 134217728 = ROTATE, 268435456 = TRACER, 536870912 = ZOMGIB, 1073741824 = TRACER2, -2147483648 = TRACER3
+loddistance1: distance after which to show the first LOD model replacement (default: 1000)
+loddistance2: distance after which to show the second LOD model replacement (default: 2000)
+lodtarget1: targetname of the first LOD model entity (can be used instead of lodmodel1 to use a brush model instead)
+lodtarget2: targetname of the second LOD model entity (can be used instead of lodmodel2 to use a brush model instead)
+targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
+-------- Q3MAP2 KEYS --------
+_castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
+_receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
 _clone: copies brushes from entity with identical _clonename. Still needs a single brush that will get replaced.
 _clonename: template name so one can clone from it
 min: override automatically found minimum coordinate bounds
@@ -584,12 +601,12 @@
 _celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
 */
 
-/*QUAKED func_static (0 .5 .8) ? 
-A non-solid brush entity. Use func_wall if you want it solid.
+/*QUAKED func_wall (0 .5 .8) ? 
+A solid brush entity. Use func_illusionary if you want it solid.
 The keys below actually apply to most brush entities as they are engine features; however, they are described here as they aren't overridden by game code in misc_models. Its q3map2 keys below will work on any brush entity!
 -------- KEYS --------
 movetype: way in which it moves: one of 0 = NONE, 1 = ANGLENOCLIP, 2 = ANGLECLIP, 3 = WALK, 4 = STEP, 5 = FLY, 6 = TOSS, 7 = PUSH, 8 = NOCLIP, 9 = FLYMISSILE, 10 = BOUNCE, 11 = BOUNCEMISSILE
-solid: solidity: one of 0 = NOT, 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE
+solid: solidity: one of 1 = TRIGGER, 2 = BBOX, 3 = SLIDEBOX, 4 = BSP, 5 = CORPSE
 avelocity: vector giving its angular velocity (useful for spinning models)
 scale: scale factor of the model (range: 0.0625 to 15.9375)
 colormap: 1024 + 16 * pantscolor + shirtcolor
@@ -600,9 +617,8 @@
 loddistance2: distance after which to show the second LOD model replacement (default: 2000)
 lodtarget1: targetname of the first LOD model entity (can be used instead of lodmodel1 to use a brush model instead)
 lodtarget2: targetname of the second LOD model entity (can be used instead of lodmodel2 to use a brush model instead)
+targetname: when invoking it by a button etc., it changes the color to the initiator of the action (e.g. the one pressing a button). In Onslaught, this can be used to color control points for team who owns them. In other game types, this can be used as a fun feature. Works only with _shirt and _pants textures.
 -------- Q3MAP2 KEYS --------
-_frame: frame of model to include (set equal to frame if _castshadows is set)
-modelscale: scaling factor (set equal to scale if _castshadows is set)
 _castshadows: Allows per-entity control over shadow casting. Defaults to 0 on entities, 1 on world. 0 = no shadow casting. 1 = cast shadows on world. > 1 = cast shadows on entities with _rs (or _receiveshadows) with the corresponding value, AND world. Negative values imply same, but DO NOT cast shadows on world.
 _receiveshadows: Allows per-entity control over shadow reception. Defaults to 1 on everything (world shadows). 0 = receives NO shadows. > 1 = receive shadows only from corresponding keyed entities (see above) and world. < 1 = receive shadows ONLY from corresponding keyed entities.
 _clone: copies brushes from entity with identical _clonename. Still needs a single brush that will get replaced.
@@ -1135,14 +1151,36 @@
 INDICATE: indicate amount of damage already taken by coloring
 */
 
-/*QUAKED trigger_relay_if (0 1 0) (-8 -8 -8) (8 8 8) MORETHAN
-Relays the trigger event if there are at most count entities of the given type.
+/*QUAKED trigger_relay_if (0 1 0) (-8 -8 -8) (8 8 8) NEGATE
+Relays the trigger event if a cvar is set to a specified value.
 -------- KEYS --------
 target: The entity/entities to relay the trigger events to
 targetname: The name other entities can use to target this entity
-netname: The name of the field to check (can currently only be targetname, netname, target or classname)
-message: The value of the field to check
+netname: The name of the cvar to check
+message: The value of the cvar to check
 count: The count of entities that must be found
 -------- SPAWNFLAGS --------
-MORETHAN: trigger if there are more than the given count, not at least
+NEGATE: trigger if the cvar does NOT match the value.
 */
+
+/*QUAKED weapon_hlac (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
+the Heavy Laser Assault Cannon.
+-------- KEYS --------
+respawntime: time till it respawns (default: 30)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/weapons/g_hlac.md3"
+*/
+
+/*QUAKED weapon_seeker (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
+the T.A.G. Seeker.
+-------- KEYS --------
+respawntime: time till it respawns (default: 30)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/weapons/g_seeker.md3"
+*/

Modified: branches/nexuiz-2.0/data/scripts/turrets.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/turrets.def	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/scripts/turrets.def	2008-11-04 11:54:16 UTC (rev 4977)
@@ -194,18 +194,27 @@
 */
 
 
-/*QUAKED walker_checkpoint (1 0 1) (-16 -16 -16) (16 16 16)
+/*QUAKED turret_walker (1 0 0) (-32 -32 0) (32 32 50)
 -----------KEYS------------
-target: .targetname of next wapoint in chain. 
+turret_scale_damage: 2 = double damage, 0.5 = half
+turret_scale_range:  2 = double range, 0.5 = half
+turret_scale_refire: 2 = doubble refire (SLOWER!), 0.5 = half (FASTER!)
+turret_scale_ammo:   2 = doubble ammo carry & regen, 0.5 = half ammo carry & regen
+turret_scale_aim:    2 = aim twice as fast, 0,5 = aim at half speed
+turret_scale_health: 2 = double health, 0.5 = half
 
+team : 5=red, 14=blue
 -----------SPAWNFLAGS-----------
+---------NOTES----------
 
----------NOTES----------
-If a loop is of targets are formed, any walker entering this loop will patrol it indefinitly.
-If the checkpoint chain in not looped, teh walker will go "Roaming" when teh last point is reached. 
+A nasty mechanical ceature that will engage longrange target with missiles, midrange with its miniguna and meele things up close and personal.
+
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/turrets/radiant/walker.md3"
 */
 
-/*QUAKED turret_walker (1 0 0) (-32 -32 0) (32 32 50)
+
+/*QUAKED turret_ewheel (1 0 0) (-32 -32 0) (32 32 50)
 -----------KEYS------------
 turret_scale_damage: 2 = double damage, 0.5 = half
 turret_scale_range:  2 = double range, 0.5 = half
@@ -214,14 +223,24 @@
 turret_scale_aim:    2 = aim twice as fast, 0,5 = aim at half speed
 turret_scale_health: 2 = double health, 0.5 = half
 
-target : Enter this walker_checkpoint chain
-
 team : 5=red, 14=blue
 -----------SPAWNFLAGS-----------
 ---------NOTES----------
 
-A nasty mechanical ceature that will engage longrange target with missiles, midrange with its miniguna and meele things up close and personal.
+Small, agile and move capable turret.
 
 -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
-model="models/turrets/radiant/walker.md3"
+model="models/turrets/radiant/ewheel.md3"
 */
+
+
+/*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
+-----------KEYS------------
+target: .targetname of next wapoint in chain.
+wait:   Pause at this point # seconds.
+-----------SPAWNFLAGS-----------
+
+---------NOTES----------
+If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
+If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
+*/
\ No newline at end of file

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

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

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

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

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

Modified: branches/nexuiz-2.0/data/turrets.cfg
===================================================================
--- branches/nexuiz-2.0/data/turrets.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/turrets.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -4,7 +4,7 @@
 
 // Target scanning and validation can be resource intensive
 // Dont let turrets look for new targets more frequently then this
-set g_turrets_targetscan_mindelay 0.5
+set g_turrets_targetscan_mindelay 0.1
 
 // Turrets with no target returns to their idle aim after this much time.
 set g_turrets_aimidle_delay 5
@@ -45,6 +45,8 @@
 // A walking minigun with longrage missiles and closerange meele attack.
 exec unit_walker.cfg
 
+// OMG! Its the Evil Wheel! :O
+exec unit_ewheel.cfg
 // not exec'd: gauss
 
 

Copied: branches/nexuiz-2.0/data/unit_ewheel.cfg (from rev 4931, trunk/data/unit_ewheel.cfg)
===================================================================
--- branches/nexuiz-2.0/data/unit_ewheel.cfg	                        (rev 0)
+++ branches/nexuiz-2.0/data/unit_ewheel.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -0,0 +1,39 @@
+set g_turrets_unit_ewheel_std_health 200	
+set g_turrets_unit_ewheel_std_respawntime 30
+
+// dgr / sec
+set g_turrets_unit_ewheel_turnrate 180
+
+set g_turrets_unit_ewheel_std_shot_dmg 10
+set g_turrets_unit_ewheel_std_shot_refire 0.15
+set g_turrets_unit_ewheel_std_shot_spread 0.025
+set g_turrets_unit_ewheel_std_shot_force 	20
+set g_turrets_unit_ewheel_std_shot_radius 50
+set g_turrets_unit_ewheel_std_shot_speed 7000
+
+set g_turrets_unit_ewheel_std_shot_volly 2
+set g_turrets_unit_ewheel_std_shot_volly_refire 0.5
+
+// Note this is the effective range for rocket engagement
+set g_turrets_unit_ewheel_std_target_range 6000
+set g_turrets_unit_ewheel_std_target_range_fire 4000
+set g_turrets_unit_ewheel_std_target_range_optimal 1000
+set g_turrets_unit_ewheel_std_target_range_min 50
+
+set g_turrets_unit_ewheel_std_target_select_rangebias 0.25
+set g_turrets_unit_ewheel_std_target_select_samebias 0.25
+set g_turrets_unit_ewheel_std_target_select_anglebias 0.5
+set g_turrets_unit_ewheel_std_target_select_playerbias 1
+set g_turrets_unit_ewheel_std_target_select_missilebias 0
+
+set g_turrets_unit_ewheel_std_ammo_max 4000
+set g_turrets_unit_ewheel_std_ammo 500
+set g_turrets_unit_ewheel_std_ammo_recharge 100
+
+set g_turrets_unit_ewheel_std_aim_firetolerance_dist 200
+set g_turrets_unit_ewheel_std_aim_firetolerance_angle 16
+set g_turrets_unit_ewheel_std_aim_speed 90
+set g_turrets_unit_ewheel_std_aim_maxrot 20
+set g_turrets_unit_ewheel_std_aim_maxpitch 45
+
+set g_turrets_unit_ewheel_std_track_type 1
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/unit_flac.cfg
===================================================================
--- branches/nexuiz-2.0/data/unit_flac.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/unit_flac.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -1,19 +1,19 @@
 set g_turrets_unit_flac_std_health 700	
 set g_turrets_unit_flac_std_respawntime 90
 
-set g_turrets_unit_flac_std_shot_dmg 75
-set g_turrets_unit_flac_std_shot_refire 0.19
+set g_turrets_unit_flac_std_shot_dmg 35
+set g_turrets_unit_flac_std_shot_refire 0.1
 set g_turrets_unit_flac_std_shot_radius 250
-set g_turrets_unit_flac_std_shot_speed 4000
+set g_turrets_unit_flac_std_shot_speed 6000
 set g_turrets_unit_flac_std_shot_spread 0.07
 set g_turrets_unit_flac_std_shot_force 50
-set g_turrets_unit_flac_std_shot_volly 0
-set g_turrets_unit_flac_std_shot_volly_refire 0.5
+set g_turrets_unit_flac_std_shot_volly 4
+set g_turrets_unit_flac_std_shot_volly_refire 1.5
 
-set g_turrets_unit_flac_std_target_range 5000
+set g_turrets_unit_flac_std_target_range 4000
 set g_turrets_unit_flac_std_target_range_min 500
-set g_turrets_unit_flac_std_target_range_fire 5000
-set g_turrets_unit_flac_std_target_range_optimal 2500
+set g_turrets_unit_flac_std_target_range_fire 3500
+set g_turrets_unit_flac_std_target_range_optimal 1000
 
 set g_turrets_unit_flac_std_target_select_rangebias 0.25
 set g_turrets_unit_flac_std_target_select_samebias 0.25
@@ -27,7 +27,7 @@
 
 set g_turrets_unit_flac_std_aim_firetolerance_dist 200
 set g_turrets_unit_flac_std_aim_firetolerance_angle 5
-set g_turrets_unit_flac_std_aim_speed 200
+set g_turrets_unit_flac_std_aim_speed 100
 set g_turrets_unit_flac_std_aim_maxrot 360
 set g_turrets_unit_flac_std_aim_maxpitch 35
 

Modified: branches/nexuiz-2.0/data/unit_machinegun.cfg
===================================================================
--- branches/nexuiz-2.0/data/unit_machinegun.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/unit_machinegun.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -33,7 +33,7 @@
 
 set g_turrets_unit_machinegun_std_track_type 3
 set g_turrets_unit_machinegun_std_track_accel_pitch 0.25
-set g_turrets_unit_machinegun_std_track_accel_rot 0.75
+set g_turrets_unit_machinegun_std_track_accel_rot 0.5
 set g_turrets_unit_machinegun_std_track_blendrate 0.2
 
 

Modified: branches/nexuiz-2.0/data/unit_walker.cfg
===================================================================
--- branches/nexuiz-2.0/data/unit_walker.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/unit_walker.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -53,5 +53,5 @@
 
 // Meele attack. Only happens when theres a target directly in front 
 set g_turrets_unit_walker_std_meele_range 160
-set g_turrets_unit_walker_std_meele_dmg 200
-set g_turrets_unit_walker_std_meele_force 1000
\ No newline at end of file
+set g_turrets_unit_walker_std_meele_dmg 500
+set g_turrets_unit_walker_std_meele_force 600
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/weapons.cfg
===================================================================
--- branches/nexuiz-2.0/data/weapons.cfg	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/data/weapons.cfg	2008-11-04 11:54:16 UTC (rev 4977)
@@ -319,7 +319,7 @@
 set g_balance_seeker_flac_lifetime      0.1
 set g_balance_seeker_flac_lifetime_rand 0.05
 set g_balance_seeker_flac_speed         3000
-set g_balance_seeker_flac_spread	    0.5
+set g_balance_seeker_flac_spread	    0.4
 
 set g_balance_seeker_flac_damage       15
 set g_balance_seeker_flac_edgedamage   10

Modified: branches/nexuiz-2.0/misc/makebuild.sh
===================================================================
--- branches/nexuiz-2.0/misc/makebuild.sh	2008-11-03 14:33:35 UTC (rev 4976)
+++ branches/nexuiz-2.0/misc/makebuild.sh	2008-11-04 11:54:16 UTC (rev 4977)
@@ -108,12 +108,12 @@
 
 build()
 {
-	buildon eos.thruhere.net                        nexuiz-linux-686    fteqcc-linux-686    /tmp/Darkplaces.build 'CC="gcc -g" DP_MODPLUG_STATIC_LIBDIR=/home/divverent/modplug-i386/lib' strip
+	buildon nexmacbuild                           nexuiz-osx          fteqcc-osx          /tmp/Darkplaces.build 'CC="gcc -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4"' strip
+	buildon eos.thruhere.net                      nexuiz-linux-686    fteqcc-linux-686    /tmp/Darkplaces.build 'CC="gcc -g" DP_MODPLUG_STATIC_LIBDIR=/home/divverent/modplug-i386/lib' strip
 	buildon alientrap.org                         nexuiz-linux-x86_64 fteqcc-linux-x86_64 /tmp/Darkplaces.build 'CC="gcc -g -Wl,--hash-style=sysv" DP_MODPLUG_STATIC_LIBDIR=/home/divverent/modplug-x86_64/lib' strip
 	buildon alientrap.org                         nexuiz              fteqcc.exe          /tmp/Darkplaces.build 'DP_MAKE_TARGET=mingw CC="/chroot/debian-etch/usr/bin/i586-mingw32msvc-gcc -g -DSUPPORTDIRECTX -I/home/divverent/dxheaders" WINDRES=/chroot/debian-etch/usr/bin/i586-mingw32msvc-windres SDL_CONFIG=/home/divverent/sdl-win32/SDL-1.2.13/bin/sdl-config' /chroot/debian-etch/usr/bin/i586-mingw32msvc-strip
-# OS X SUPPORT DISCONTINUED	buildon mac.alientrap.org                     nexuiz-osx          fteqcc-osx          /tmp/Darkplaces.build 'CC="gcc -g -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk"' strip
-# OS X SUPPORT DISCONTINUED		mv "$tmpdir/nexuiz-osx-agl"     "$tmpdir/Nexuiz.app/Contents/MacOS/nexuiz-osx-agl-bin"
-# OS X SUPPORT DISCONTINUED		mv "$tmpdir/nexuiz-osx-sdl"     "$tmpdir/Nexuiz-SDL.app/Contents/MacOS/nexuiz-osx-sdl-bin"
+		mv "$tmpdir/nexuiz-osx-agl"     "$tmpdir/Nexuiz.app/Contents/MacOS/nexuiz-osx-agl-bin"
+		mv "$tmpdir/nexuiz-osx-sdl"     "$tmpdir/Nexuiz-SDL.app/Contents/MacOS/nexuiz-osx-sdl-bin"
 }
 
 # avoid dupes
@@ -155,7 +155,7 @@
 fi
 
 # prepare directory structure
-# OS X SUPPORT DISCONTINUED cp -r "$osxapps"/*.app "$tmpdir"
+cp -r "$osxapps"/*.app "$tmpdir"
 mkdir "$tmpdir/debuginfo"
 mkdir "$tmpdir/fteqcc"
 




More information about the nexuiz-commits mailing list