r5925 - in branches/nexuiz-2.0: . data data/models/items data/qcsrc/client data/qcsrc/common data/qcsrc/server data/scripts data/sound/misc misc/tools

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Feb 23 02:06:58 EST 2009


Author: div0
Date: 2009-02-23 02:06:57 -0500 (Mon, 23 Feb 2009)
New Revision: 5925

Added:
   branches/nexuiz-2.0/data/models/items/g_a50.md3
   branches/nexuiz-2.0/data/sound/misc/armor17_5.wav
Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/data/check-sounds.sh
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   branches/nexuiz-2.0/data/qcsrc/client/Main.qc
   branches/nexuiz-2.0/data/qcsrc/client/particles.qc
   branches/nexuiz-2.0/data/qcsrc/common/constants.qh
   branches/nexuiz-2.0/data/qcsrc/server/bots.qc
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/constants.qh
   branches/nexuiz-2.0/data/qcsrc/server/ctf.qc
   branches/nexuiz-2.0/data/qcsrc/server/defs.qh
   branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
   branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
   branches/nexuiz-2.0/data/qcsrc/server/havocbot_roles.qc
   branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/server/race.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
   branches/nexuiz-2.0/data/qcsrc/server/t_quake3.qc
   branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc
   branches/nexuiz-2.0/data/scripts/entities.def
   branches/nexuiz-2.0/data/weapons.cfg
   branches/nexuiz-2.0/data/weaponsHavoc.cfg
   branches/nexuiz-2.0/misc/tools/demotc-race-record-extractor.sh
Log:
r5914 | div0 | 2009-02-20 19:17:23 +0100 (Fri, 20 Feb 2009) | 2 lines
nex beam stuff by green
r5915 | div0 | 2009-02-20 19:23:53 +0100 (Fri, 20 Feb 2009) | 2 lines
g_ctf_flag_mdl_red
r5916 | div0 | 2009-02-20 19:26:22 +0100 (Fri, 20 Feb 2009) | 2 lines
a 50 armor
r5917 | div0 | 2009-02-20 19:28:59 +0100 (Fri, 20 Feb 2009) | 2 lines
fix cfgs
r5918 | mand1nga | 2009-02-21 23:55:27 +0100 (Sat, 21 Feb 2009) | 6 lines
Bots: Added bunny-hopping support :)
Added function to debug the goal stack visually
Added .aistatus field
Lowered ammo/health eagerness a bit
Lowered enemy rating radius from 20000 to 10000
r5919 | mand1nga | 2009-02-22 00:10:29 +0100 (Sun, 22 Feb 2009) | 2 lines
Replaced magic numbers with BOT_PICKUP_RATING_* "constants" on StartItem() calls. Adjusted some values a bit.
r5920 | div0 | 2009-02-22 13:45:42 +0100 (Sun, 22 Feb 2009) | 2 lines
also write a record marker for CTF (so one can extract record runs from demos)
r5921 | div0 | 2009-02-22 13:46:48 +0100 (Sun, 22 Feb 2009) | 2 lines
new cvar check values
r5922 | div0 | 2009-02-22 13:50:10 +0100 (Sun, 22 Feb 2009) | 2 lines
make it support the latest change
r5923 | div0 | 2009-02-22 14:05:49 +0100 (Sun, 22 Feb 2009) | 2 lines
make also CTF skin cvar'red
r5924 | mand1nga | 2009-02-22 16:57:49 +0100 (Sun, 22 Feb 2009) | 2 lines
Bots: Check for dangers when running

Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/.patchsets	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-5911
+revisions_applied = 1-5924

Modified: branches/nexuiz-2.0/data/check-sounds.sh
===================================================================
--- branches/nexuiz-2.0/data/check-sounds.sh	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/check-sounds.sh	2009-02-23 07:06:57 UTC (rev 5925)
@@ -87,25 +87,32 @@
 						;;
 					//*)
 						identifiers_seen="$identifiers_seen ${TITLE#//}"
-						good=false
-						case "$COUNT" in
-							0)
-								if psoundtry "$SOUND"; then
-									good=false
-								fi
-								;;
-							*)
-								for i in `seq 1 $COUNT`; do
-									if psoundtry "$SOUND$i"; then
-										good=true
+						for X in $allidentifiers; do
+							if [ "$X" = "${TITLE#//}" ]; then
+								good=true
+							fi
+						done
+						if $good; then
+							good=false
+							case "$COUNT" in
+								0)
+									if psoundtry "$SOUND"; then
+										good=false
 									fi
-								done
-								;;
-						esac
-						if $good; then
-							echo "$S references existing sound $SOUND but commented out"
-						else
-							echo "$S does not have a sound for ${TITLE#//} yet"
+									;;
+								*)
+									for i in `seq 1 $COUNT`; do
+										if psoundtry "$SOUND$i"; then
+											good=true
+										fi
+									done
+									;;
+							esac
+							if $good; then
+								echo "$S references existing sound $SOUND but commented out"
+							else
+								echo "$S does not have a sound for ${TITLE#//} yet"
+							fi
 						fi
 						;;
 					*)

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2009-02-23 07:06:57 UTC (rev 5925)
@@ -27,7 +27,7 @@
 seta g_configversion 0
 
 // default.cfg versioning (update using update-cvarcount.sh, run that every time after adding a new cvar)
-set cvar_check_default 1e27a8f2f0ba60542af81e2272d39ad7
+set cvar_check_default b0a00a4f304f7d8fad16a6146442f62d
 
 // Nexuiz version (formatted for machines)
 // used to determine if a client version is compatible
@@ -273,6 +273,9 @@
 set sv_timeout_leadtime 4	"how long the players will be informed that a timeout was calledbefore it starts, in seconds"
 set sv_timeout_resumetime 3	"how long the remaining timeout-time will be after a player called the resumegame command"
 
+set g_allow_oldnexbeam 0 "If enabled, clients are allowed to use old v2.3 Nexgun beam"
+set cl_particles_oldnexbeam 0 "Uses the old v2.3 Nexgun beam instead of the new beam, only works if server allows it (g_allow_oldnexbeam = 1)"
+
 // use default physics
 exec physics25.cfg
 
@@ -337,7 +340,7 @@
 seta skill_auto 0	"when 1, \"skill\" gets adjusted to match the best player on the map"
 // general bot AI cvars
 set bot_ai_thinkinterval 0.05
-set bot_ai_strategyinterval 2
+set bot_ai_strategyinterval 5
 set bot_ai_enemydetectioninterval 0.5
 set bot_ai_dodgeupdateinterval 0.1
 set bot_ai_chooseweaponinterval 0.3
@@ -361,6 +364,10 @@
 set bot_ai_weapon_combo_threshold 0.3	"Try to make a combo N seconds after the last attack"
 set bot_ai_friends_aware_pickup_radius "500"	"Bots will not pickup items if a team mate is this distance near the item"
 set bot_ai_ignoregoal_timeout 3	"Ignore goals making bots to get stuck in front of a wall for N seconds"
+set bot_ai_bunnyhop_skilloffset 7	"Bots with skill equal or greater than this value will perform the  \"bunnyhop\" technique"
+set bot_ai_bunnyhop_startdistance 250 "Run to goals located further than this distance"
+set bot_ai_bunnyhop_stopdistance 220 "Stop jumping after reaching this distance to the goal"
+set bot_ai_bunnyhop_firstjumpdelay 0.5 "Start running to the goal only if it was seen for more than N seconds"
 // Better don't touch these, there are hard to tweak!
 set bot_ai_aimskill_order_mix_1st 0.01
 set bot_ai_aimskill_order_mix_2nd 0.1
@@ -520,6 +527,13 @@
 set g_ctf_shield_min_negscore 20	"shield the player from the flag if he's got -20 points or less"
 set g_ctf_shield_force 100	"push force of the shield"
 
+// fun for server admins
+set g_ctf_flag_red_model "models/ctf/flags.md3"
+set g_ctf_flag_red_skin 0
+set g_ctf_flag_blue_model "models/ctf/flags.md3"
+set g_ctf_flag_blue_skin 1
+set g_ctf_captimerecord_allow_assisted 0 "if enabled, assisted CTF records (with other players on the server) are recorded too"
+
 exec ctfscoring-div0.cfg
 
 // runematch
@@ -1177,6 +1191,7 @@
 set con_completion_ply		*.dem
 set con_completion_tdem		*.dem
 set con_completion_exec		*.cfg
+set con_completion_cat		"*.cfg *.txt *.log"
 set con_completion_chmap	map
 set con_completion_gotomap	map
 set con_completion_vmap		map

Copied: branches/nexuiz-2.0/data/models/items/g_a50.md3 (from rev 5924, trunk/data/models/items/g_a50.md3)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/qcsrc/client/Main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1009,6 +1009,10 @@
 			Net_ReadZCurveParticles();
 			bHandled = true;
 			break;
+		case TE_CSQC_NEXGUNBEAMPARTICLE:
+			Net_ReadNexgunBeamParticle();
+			bHandled = true;
+			break;
 		default:
 			// No special logic for this temporary entity; return 0 so the engine can handle it
 			bHandled = false;

Modified: branches/nexuiz-2.0/data/qcsrc/client/particles.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/particles.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/client/particles.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -243,3 +243,18 @@
 
 	zcurveparticles(effectnum, start, end, end_dz, speed, 5); // at most 32 segments
 }
+
+void Net_ReadNexgunBeamParticle()
+{
+	vector shotorg, endpos;
+	shotorg_x = ReadCoord(); shotorg_y = ReadCoord(); shotorg_z = ReadCoord();
+	endpos_x = ReadCoord(); endpos_y = ReadCoord(); endpos_z = ReadCoord();
+	
+	pointparticles(particleeffectnum("nex_muzzleflash"), shotorg, normalize(endpos - shotorg) * 1000, 1);
+	
+	//draw either the old v2.3 beam or the new beam
+	if (cvar("cl_particles_oldnexbeam") && (getstati(STAT_ALLOW_OLDNEXBEAM) || isdemo()))
+		trailparticles(world, particleeffectnum("TE_TEI_G3"), shotorg, endpos);
+	else
+		trailparticles(world, particleeffectnum("nex_beam"), shotorg, endpos);
+}

Modified: branches/nexuiz-2.0/data/qcsrc/common/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2009-02-23 07:06:57 UTC (rev 5925)
@@ -46,6 +46,7 @@
 const float TE_CSQC_RACE = 101;
 const float TE_CSQC_SPAWN = 102;
 const float TE_CSQC_ZCURVEPARTICLES = 103;
+const float TE_CSQC_NEXGUNBEAMPARTICLE = 104;
 
 const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
 const float RACE_NET_CHECKPOINT_CLEAR = 1;
@@ -242,6 +243,7 @@
 const float STAT_STRENGTH_FINISHED = 38;
 const float STAT_INVINCIBLE_FINISHED = 39;
 const float STAT_PRESSED_KEYS = 42;
+const float STAT_ALLOW_OLDNEXBEAM = 43; // this stat could later contain some other bits of info, like, more server-side particle config
 const float CTF_STATE_ATTACK = 1;
 const float CTF_STATE_DEFEND = 2;
 const float CTF_STATE_COMMANDER = 3;

Modified: branches/nexuiz-2.0/data/qcsrc/server/bots.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/bots.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/bots.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1,8 +1,14 @@
+.float aistatus;
+float AI_STATUS_ROAMING			= 1;	// Bot is just crawling the map. No enemies at sight
+float AI_STATUS_ATTACKING		= 2;	// There are enemies at sight
+float AI_STATUS_RUNNING			= 4;	// Bot is bunny hopping
+float AI_STATUS_DANGER_AHEAD	= 8;	// There is lava/slime/abism ahead
+
+.string netname_freeme;
+
 // rough simulation of walking from one point to another to test if a path
 // can be traveled, used by havocbot
 
-.string netname_freeme;
-
 vector stepheightvec;
 float navigation_testtracewalk;
 float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
@@ -1310,6 +1316,21 @@
 	org = self.origin;// + self.velocity * 0.1;
 	m1 = org + self.mins;
 	m2 = org + self.maxs;
+
+	// Loose goal touching check for running state
+	if(self.aistatus & AI_STATUS_RUNNING)
+	if(self.goalcurrent.classname=="waypoint")
+	{
+		if(vlen(self.origin - self.goalcurrent.origin)<150)
+		{
+				traceline(self.origin + self.view_ofs , self.goalcurrent.origin, TRUE, world);
+				if(trace_fraction==1)
+				{
+					navigation_poproute();
+				}
+		}
+	}
+
 	while (self.goalcurrent && boxesoverlap(m1, m2, self.goalcurrent.absmin, self.goalcurrent.absmax))
 		navigation_poproute();
 }

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -2078,6 +2078,7 @@
 {
 	self.stat_sys_ticrate = cvar("sys_ticrate");
 	self.stat_game_starttime = game_starttime;
+	self.stat_allow_oldnexbeam = cvar("g_allow_oldnexbeam");
 
 	if(blockSpectators && frametime)
 		// WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).

Modified: branches/nexuiz-2.0/data/qcsrc/server/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/constants.qh	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/constants.qh	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1,5 +1,5 @@
-string CVAR_CHECK_DEFAULT = "1e27a8f2f0ba60542af81e2272d39ad7";
-string CVAR_CHECK_WEAPONS = "f156bf358766dfc169eb26dc36a765b9";
+string CVAR_CHECK_DEFAULT = "b0a00a4f304f7d8fad16a6146442f62d";
+string CVAR_CHECK_WEAPONS = "32e7dc7d745187473f0040d14892e2bb";
 
 float	FALSE					= 0;
 float	TRUE					= 1;

Modified: branches/nexuiz-2.0/data/qcsrc/server/ctf.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/ctf.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/ctf.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -427,7 +427,7 @@
 		{
 			return;
 		}
-		if(player_count - currentbots <= 1) // at most one human
+		if(cvar("g_ctf_captimerecord_allow_assisted") || player_count - currentbots <= 1) // at most one human
 		{
 			t = time - other.flagcarried.flagpickuptime;
 			s = ftos_decimals(t, 2);
@@ -444,7 +444,7 @@
 				flagcaptimerecord = t;
 				db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(t));
 				db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), h1);
-				GameLogEcho(strcat(":recordset:", ftos(other.playerid), ":", ftos(t)));
+				write_recordmarker(other, time - t, t);
 			}
 			else if (t < flagcaptimerecord)
 			{
@@ -452,7 +452,7 @@
 				flagcaptimerecord = t;
 				db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(t));
 				db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), h1);
-				GameLogEcho(strcat(":recordset:", ftos(other.playerid), ":", ftos(t)));
+				write_recordmarker(other, time - t, t);
 			}
 			else
 			{
@@ -735,11 +735,11 @@
 	}
 	self.netname = "^1RED^7 flag";
 	self.target = "###item###";
-	self.skin = 0;
+	self.skin = cvar("g_ctf_flag_red_skin");
 	if(self.spawnflags & 1)
 		self.noalign = 1;
 	if (!self.model)
-		self.model = "models/ctf/flags.md3";
+		self.model = cvar_string("g_ctf_flag_red_model");
 	if (!self.noise)
 		self.noise = "ctf/take.wav";
 	if (!self.noise1)
@@ -833,11 +833,11 @@
 	}
 	self.netname = "^4BLUE^7 flag";
 	self.target = "###item###";
-	self.skin = 1;
+	self.skin = cvar("g_ctf_flag_blue_skin");
 	if(self.spawnflags & 1)
 		self.noalign = 1;
 	if (!self.model)
-		self.model = "models/ctf/flags.md3";
+		self.model = cvar_string("g_ctf_flag_blue_model");
 	if (!self.noise)
 		self.noise = "ctf/take.wav";
 	if (!self.noise1)

Modified: branches/nexuiz-2.0/data/qcsrc/server/defs.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/defs.qh	2009-02-23 07:06:57 UTC (rev 5925)
@@ -514,6 +514,7 @@
 .string message2;
 
 vector railgun_start, railgun_end; // filled by FireRailgunBullet, used by damage code for head shot
+.float stat_allow_oldnexbeam;
 
 // reset to 0 on weapon switch
 // may be useful to all weapons

Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -542,6 +542,7 @@
 	addstat(STAT_WEAPONS, AS_INT, weapons);
 	addstat(STAT_SWITCHWEAPON, AS_INT, switchweapon);
 	addstat(STAT_GAMESTARTTIME, AS_FLOAT, stat_game_starttime);
+	addstat(STAT_ALLOW_OLDNEXBEAM, AS_INT, stat_allow_oldnexbeam);
 	Nagger_Init();
 	
 	addstat(STAT_STRENGTH_FINISHED, AS_FLOAT, strength_finished);

Modified: branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1,10 +1,13 @@
-
 .void() havocbot_role;
 void() havocbot_chooserole;
 .float havocbot_keyboardskill;
 .float facingwalltime, ignoregoaltime;
 .entity ignoregoal;
 
+#ifdef DEBUG_BOT_GOALSTACK
+void debuggoalstack();
+#endif
+
 vector havocbot_dodge()
 {
 	// LordHavoc: disabled because this is too expensive
@@ -132,6 +135,126 @@
 	self.movement = self.movement + (keyboard - self.movement) * blend;
 };
 
+.entity bot_lastseengoal;
+.float bot_timelastseengoal;
+.float bot_canruntogoal;
+void havocbot_bunnyhop(vector dir)
+{
+	local float distance;
+	local vector deviation;
+
+	if(self.goalcurrent.classname == "player")
+		return;
+
+	if(self.aistatus & AI_STATUS_DANGER_AHEAD)
+		return;
+
+	if(self.bot_lastseengoal != self.goalcurrent && !(self.aistatus & AI_STATUS_RUNNING))
+	{
+		self.bot_canruntogoal = 0;
+		self.bot_timelastseengoal = 0;
+	}
+
+	distance = vlen(self.origin - self.goalcurrent.origin);
+
+	// Run only to visible goals
+	traceline(self.origin + self.view_ofs , self.goalcurrent.origin, TRUE, world);
+	if(self.flags & FL_ONGROUND)
+	if(trace_fraction == 1)
+	{
+			self.bot_lastseengoal = self.goalcurrent;
+
+			// seen it before
+			if(self.bot_timelastseengoal)
+			{
+				// for a period of time
+				if(time - self.bot_timelastseengoal > cvar("bot_ai_bunnyhop_firstjumpdelay"))
+				{
+					local float checkdistance;
+					checkdistance = TRUE;
+
+					// don't run if it is too close
+					if(self.bot_canruntogoal==0)
+					{
+						if(distance > cvar("bot_ai_bunnyhop_startdistance"))
+							self.bot_canruntogoal = 1;
+						else	
+							self.bot_canruntogoal = -1;
+					}
+
+					if(self.bot_canruntogoal != 1)
+						return;
+
+					if(self.aistatus & AI_STATUS_ROAMING)
+					if(self.goalcurrent.classname=="waypoint")
+					if(fabs(self.goalcurrent.origin_z - self.origin_z) < self.maxs_z - self.mins_z)
+					if(self.goalstack01!=world)
+					{
+						deviation = self.goalstack01.origin - (self.origin + self.view_ofs);
+						deviation = vectoangles(deviation) - self.v_angle;
+						while (deviation_y < -180) deviation_y = deviation_y + 360;
+						while (deviation_y > 180) deviation_y = deviation_y - 360;
+
+						if(deviation_y < 20 && deviation_y > -20)
+						if(distance < vlen(self.origin - self.goalstack01.origin))
+						if(fabs(self.goalstack01.origin_z - self.goalcurrent.origin_z) < self.maxs_z - self.mins_z)
+						{
+							traceline(self.origin + self.view_ofs , self.goalstack01.origin, TRUE, world);
+							if(trace_fraction==1)
+							{
+								checkdistance = FALSE;
+							}
+						}
+					}
+
+					if(checkdistance)
+					{
+						self.aistatus &~= AI_STATUS_RUNNING;
+						if(distance > cvar("bot_ai_bunnyhop_stopdistance"))
+							self.BUTTON_JUMP = TRUE;
+					}
+					else
+					{
+						self.aistatus |= AI_STATUS_RUNNING;
+						self.BUTTON_JUMP = TRUE;
+					}
+				}
+			}
+			else
+			{
+				self.bot_timelastseengoal = time;
+			}
+	}
+	else
+	{
+		self.bot_timelastseengoal = 0;
+	}
+
+	// Release jump button
+	if(self.flags & FL_ONGROUND == 0)
+	{
+		if(self.velocity_z < 0)
+			self.BUTTON_JUMP = FALSE;
+
+		// Strafe 
+		local float maxspeed;
+		maxspeed = cvar("sv_maxspeed");
+
+		if(self.aistatus & AI_STATUS_RUNNING)
+		if(vlen(self.velocity)>maxspeed)
+		{
+			deviation = vectoangles(dir) - self.v_angle;
+			while (deviation_y < -180) deviation_y = deviation_y + 360;
+			while (deviation_y > 180) deviation_y = deviation_y - 360;
+
+			if ( deviation_y > 2 )
+				self.movement_y = maxspeed;
+			if ( deviation_y < -2 )
+				self.movement_y = maxspeed * -1;
+		}
+	}
+};
+
 //.float havocbotignoretime;
 //.vector bot_dodgevector;
 //.float bot_dodgevector_time;
@@ -182,8 +305,9 @@
 		return;
 	}
 
-//	te_wizspike(self.goalcurrent.origin);
-//	te_lightning2(world, self.origin, self.goalcurrent.origin);
+#ifdef DEBUG_BOT_GOALSTACK
+	debuggoalstack();
+#endif
 
 	m1 = self.goalcurrent.origin + self.goalcurrent.mins;
 	m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
@@ -231,63 +355,61 @@
 
 			// avoiding dangers and obstacles
 			// TODO: don't make this check every frame
-			if(self.flags & FL_ONGROUND)
+			local vector dst_ahead, dst_down;
+			dst_ahead = self.origin + self.view_ofs + (self.velocity * 0.32);
+			dst_down = dst_ahead + '0 0 -1500';				
+			
+			traceline(self.origin + self.view_ofs , dst_ahead, TRUE, world);
+
+			// Check head-banging against walls
+			if(vlen(self.origin + self.view_ofs - trace_endpos) < 2)
 			{
-				local vector dst_ahead, dst_down;
-				dst_ahead = self.origin + self.view_ofs + (self.velocity * 0.3);
-				dst_down = dst_ahead + '0 0 -1500';				
-				
-				traceline(self.origin + self.view_ofs , dst_ahead, TRUE, world);
-
-				// Check head-banging against walls
-				if(vlen(self.origin + self.view_ofs - trace_endpos) < 2)
+				if(self.facingwalltime && time > self.facingwalltime)
 				{
-					if(self.facingwalltime && time > self.facingwalltime)
-					{
-						self.ignoregoal = self.goalcurrent;
-						self.ignoregoaltime = time + cvar("bot_ai_ignoregoal_timeout");
-						navigation_poproute();
-					}
-					else
-					{
-						self.facingwalltime = time + 0.05;
-					}
+					self.ignoregoal = self.goalcurrent;
+					self.ignoregoaltime = time + cvar("bot_ai_ignoregoal_timeout");
+					navigation_poproute();
 				}
 				else
 				{
-					self.facingwalltime = 0;
+					self.facingwalltime = time + 0.05;
+				}
+			}
+			else
+			{
+				self.facingwalltime = 0;
 
-					if(self.ignoregoal != world && time > self.ignoregoaltime)
+				if(self.ignoregoal != world && time > self.ignoregoaltime)
+				{
+					self.ignoregoal = world;
+					self.ignoregoaltime = 0;
+				}
+			}
+		
+			// Check for water/slime/lava and edges
+			self.aistatus &~= AI_STATUS_DANGER_AHEAD;
+			if(trace_fraction == 1){
+				traceline(dst_ahead , dst_down, TRUE, world);
+				//	te_lightning2(world, self.origin, dst_ahead);	// Draw "ahead" look 
+				s = pointcontents(trace_endpos + '0 0 1');
+				if (s != CONTENT_SOLID)
+				if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+					evadelava = normalize(self.velocity) * -1;
+				else if (s == CONTENT_SKY)
+					evadeobstacle = normalize(self.velocity) * -1;
+				else if (tracebox_hits_trigger_hurt(dst_ahead, self.mins, self.maxs, trace_endpos))
+				{
+					//	te_lightning2(world, dst_ahead, dst_down);	// Draw "downwards" look
+					// if ain't a safe goal with "holes" (like the soylent jumpad)
+					if(!boxesoverlap(dst_ahead - self.view_ofs + self.mins, dst_ahead - self.view_ofs + self.maxs, 
+							self.goalcurrent.absmin, self.goalcurrent.absmax))
 					{
-						self.ignoregoal = world;
-						self.ignoregoaltime = 0;
-					}
-				}
-			
-				// Check for water/slime/lava and edges
-				if(trace_fraction == 1){
-					traceline(dst_ahead , dst_down, TRUE, world);
-					//	te_lightning2(world, self.origin, dst_ahead);	// Draw "ahead" look 
-					s = pointcontents(trace_endpos + '0 0 1');
-					if (s != CONTENT_SOLID)
-					if (s == CONTENT_LAVA || s == CONTENT_SLIME)
-						evadelava = normalize(self.velocity) * -1;
-					else if (s == CONTENT_SKY)
+						// Remove dangerous dynamic goals from stack
+						if (self.goalcurrent.classname == "player" || self.goalcurrent.classname == "droppedweapon")
+							navigation_poproute();
+						// try to stop
+						flatdir = '0 0 0';
 						evadeobstacle = normalize(self.velocity) * -1;
-					else if (tracebox_hits_trigger_hurt(dst_ahead, self.mins, self.maxs, trace_endpos))
-					{
-						//	te_lightning2(world, dst_ahead, dst_down);	// Draw "downwards" look
-						// if ain't a safe goal with "holes" (like the soylent jumpad)
-						if(!boxesoverlap(dst_ahead - self.view_ofs + self.mins, dst_ahead - self.view_ofs + self.maxs, 
-								self.goalcurrent.absmin, self.goalcurrent.absmax))
-						{
-							// Remove dangerous dynamic goals from stack
-							if (self.goalcurrent.classname == "player" || self.goalcurrent.classname == "droppedweapon")
-								navigation_poproute();
-							// try to stop
-							flatdir = '0 0 0';
-							evadeobstacle = normalize(self.velocity) * -1;
-						}
 					}
 				}
 			}
@@ -296,6 +418,9 @@
 			evadeobstacle_z = 0;
 			evadelava_z = 0;
 			makevectors(self.v_angle_y * '0 1 0');
+
+			if(evadeobstacle!='0 0 0'||evadelava!='0 0 0')
+				self.aistatus |= AI_STATUS_DANGER_AHEAD;
 		}
 
 		dodge = havocbot_dodge();
@@ -313,7 +438,6 @@
 	//dir = self.bot_dodgevector;
 	//if (self.bot_dodgevector_jumpbutton)
 	//	self.BUTTON_JUMP = 1;
-
 	self.movement_x = dir * v_forward * maxspeed;
 	self.movement_y = dir * v_right * maxspeed;
 	self.movement_z = dir * v_up * maxspeed;
@@ -322,6 +446,11 @@
 	if (skill < 10)
 		havocbot_keyboard_movement(destorg);
 
+	// Bunnyhop!
+//	if(self.aistatus & AI_STATUS_ROAMING)
+	if(skill >= cvar("bot_ai_bunnyhop_skilloffset"))
+		havocbot_bunnyhop(dir);
+
 	if ((dir * v_up) >= cvar("sv_jumpvelocity")*0.5 && (self.flags & FL_ONGROUND)) self.BUTTON_JUMP=1;
 	if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill)*0.1,1)) self.BUTTON_JUMP=TRUE;
 	if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill)*0.1,1)) self.havocbot_ducktime=time+0.3/bound(0.1,skill,10);
@@ -650,6 +779,9 @@
 	lag_update();
 	if (self.bot_aimtarg)
 	{
+		self.aistatus |= AI_STATUS_ATTACKING;
+		self.aistatus &~= AI_STATUS_ROAMING;
+
 		weapon_action(self.weapon, WR_AIM);
 		if (cvar("bot_nofire") || IS_INDEPENDENT_PLAYER(self))
 		{
@@ -659,13 +791,16 @@
 	}
 	else if (self.goalcurrent)
 	{
+		self.aistatus |= AI_STATUS_ROAMING;
+		self.aistatus &~= AI_STATUS_ATTACKING;
+
 		local vector now,v,next;//,heading;
 		local float distance,skillblend,distanceblend,blend;
 		next = now = self.goalcurrent.origin - (self.origin + self.view_ofs);
 		distance = vlen(now);
 		//heading = self.velocity;
 		//dprint(self.goalstack01.classname,etos(self.goalstack01),"\n");
-		if(self.goalstack01 != self && self.goalstack01 != world)
+		if(self.goalstack01 != self && self.goalstack01 != world && self.aistatus & AI_STATUS_RUNNING == 0)
 			next = self.goalstack01.origin - (self.origin + self.view_ofs);
 		skillblend=bound(0,(skill-2.5)*0.5,1); //lower skill player can't preturn
 		distanceblend=bound(0,distance/cvar("bot_ai_keyboard_distance"),1);
@@ -694,3 +829,69 @@
 	self.havocbot_keyboardskill=random()-0.5;
 	havocbot_chooserole();
 }
+
+
+#ifdef DEBUG_BOT_GOALSTACK
+
+.float goalcounter;
+.vector lastposition;
+
+// Debug the goal stack visually
+void debuggoalstack()
+{
+	local entity target;
+	local vector org;
+
+	if(self.goalcounter==0)target=self.goalcurrent;
+	else if(self.goalcounter==1)target=self.goalstack01;
+	else if(self.goalcounter==2)target=self.goalstack02;
+	else if(self.goalcounter==3)target=self.goalstack03;
+	else if(self.goalcounter==4)target=self.goalstack04;
+	else if(self.goalcounter==5)target=self.goalstack05;
+	else if(self.goalcounter==6)target=self.goalstack06;
+	else if(self.goalcounter==7)target=self.goalstack07;
+	else if(self.goalcounter==8)target=self.goalstack08;
+	else if(self.goalcounter==9)target=self.goalstack09;
+	else if(self.goalcounter==10)target=self.goalstack10;
+	else if(self.goalcounter==11)target=self.goalstack11;
+	else if(self.goalcounter==12)target=self.goalstack12;
+	else if(self.goalcounter==13)target=self.goalstack13;
+	else if(self.goalcounter==14)target=self.goalstack14;
+	else if(self.goalcounter==15)target=self.goalstack15;
+	else if(self.goalcounter==16)target=self.goalstack16;
+	else if(self.goalcounter==17)target=self.goalstack17;
+	else if(self.goalcounter==18)target=self.goalstack18;
+	else if(self.goalcounter==19)target=self.goalstack19;
+	else if(self.goalcounter==20)target=self.goalstack20;
+	else if(self.goalcounter==21)target=self.goalstack21;
+	else if(self.goalcounter==22)target=self.goalstack22;
+	else if(self.goalcounter==23)target=self.goalstack23;
+	else if(self.goalcounter==24)target=self.goalstack24;
+	else if(self.goalcounter==25)target=self.goalstack25;
+	else if(self.goalcounter==26)target=self.goalstack26;
+	else if(self.goalcounter==27)target=self.goalstack27;
+	else if(self.goalcounter==28)target=self.goalstack28;
+	else if(self.goalcounter==29)target=self.goalstack29;
+	else if(self.goalcounter==30)target=self.goalstack30;
+	else if(self.goalcounter==31)target=self.goalstack31;
+
+	if(target==world)
+	{
+		self.goalcounter = 0;
+		self.lastposition='0 0 0';
+		return;
+	}
+
+	if(self.lastposition=='0 0 0')
+		org = self.origin;
+	else
+		org = self.lastposition;
+
+
+	te_lightning2(world, org, target.origin);
+	self.lastposition = target.origin;
+
+	self.goalcounter++;
+}
+
+#endif
\ No newline at end of file

Modified: branches/nexuiz-2.0/data/qcsrc/server/havocbot_roles.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/havocbot_roles.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/havocbot_roles.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -76,12 +76,14 @@
 		rating = rating + max(0, 1 - self.ammo_cells / g_pickup_cells_max);
 
 	if (item.armorvalue)
-	if (self.armorvalue < item.max_armorvalue)
-		rating = rating + max(0, 1 - self.armorvalue / item.max_armorvalue);
+	if (self.armorvalue < item.max_armorvalue * 0.5)
+		rating = rating + max(0, 1 - self.armorvalue / (item.max_armorvalue * 0.5));
 
 	if (item.health)
-	if (self.health < item.max_health)
-		rating = rating + max(0, 1 - self.health / item.max_health);
+	if (self.health < item.max_health * 0.5)
+	{
+		rating = rating + max(0, 1 - self.health / (item.max_health * 0.5));
+	}
 
 	// TODO: if the item is not recognized then default to item.bot_pickupevalfunc(self, item);
 		
@@ -199,7 +201,7 @@
 
 		if(rating > 0)
 			navigation_routerating(head, rating * ratingscale, 2000);
-			
+
 		head = head.chain;
 	}
 };
@@ -714,7 +716,7 @@
 		self.bot_strategytime = time + cvar("bot_ai_strategyinterval");
 		navigation_goalrating_start();
 		havocbot_goalrating_items(10000, self.origin, 10000);
-		havocbot_goalrating_enemyplayers(5000, self.origin, 20000);
+		havocbot_goalrating_enemyplayers(5000, self.origin, 10000);
 		//havocbot_goalrating_waypoints(1, self.origin, 1000);
 		navigation_goalrating_end();
 	}

Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -705,6 +705,8 @@
 float g_pickup_armorsmall_max;
 float g_pickup_armormedium;
 float g_pickup_armormedium_max;
+float g_pickup_armorbig;
+float g_pickup_armorbig_max;
 float g_pickup_armorlarge;
 float g_pickup_armorlarge_max;
 float g_pickup_healthsmall;
@@ -1058,6 +1060,8 @@
 	g_pickup_armorsmall_max            = cvar("g_pickup_armorsmall_max");
 	g_pickup_armormedium               = cvar("g_pickup_armormedium");
 	g_pickup_armormedium_max           = cvar("g_pickup_armormedium_max");
+	g_pickup_armorbig                  = cvar("g_pickup_armorbig");
+	g_pickup_armorbig_max              = cvar("g_pickup_armorbig_max");
 	g_pickup_armorlarge                = cvar("g_pickup_armorlarge");
 	g_pickup_armorlarge_max            = cvar("g_pickup_armorlarge_max");
 	g_pickup_healthsmall               = cvar("g_pickup_healthsmall");
@@ -2000,3 +2004,15 @@
 	end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
 	zcurveparticles(effectno, start, end, end_dz, vlen(vel));
 }
+
+string GetGametype(); // g_world.qc
+void write_recordmarker(entity pl, float tstart, float dt)
+{
+	GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt / 10)));
+
+	// also write a marker into demo files for demotc-race-record-extractor to find
+	stuffcmd(pl,
+		strcat(
+			strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", mmsss(dt * 10)),
+			" ", ftos(tstart), " ", ftos(dt), "\n"));
+}

Modified: branches/nexuiz-2.0/data/qcsrc/server/race.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/race.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/race.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -152,8 +152,7 @@
 						bprint(e.netname, "^7 set the all-time fastest lap record with ", mmsss(t), "\n");
 						db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t));
 						db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname);
-						GameLogEcho(strcat(":recordset:", ftos(e.playerid), ":", ftos(t / 10)));
-						stuffcmd(e, strcat("//RACE RECORD SET ", mmsss(t), "\n"));
+						write_recordmarker(e, time - t/10, t/10);
 					}
 					else if(t < grecordtime)
 					{
@@ -163,8 +162,7 @@
 							bprint(e.netname, "^7 broke ", grecordholder, "^7's all-time fastest lap record with ", mmsss(t), "\n");
 						db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/time"), ftos(t));
 						db_put(ServerProgsDB, strcat(GetMapname(), "/racerecord/netname"), e.netname);
-						GameLogEcho(strcat(":recordset:", ftos(e.playerid), ":", ftos(t / 10)));
-						stuffcmd(e, strcat("//RACE RECORD SET ", mmsss(t), "\n"));
+						write_recordmarker(e, time - t/10, t/10);
 					}
 					else
 					{

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_items.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_items.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -592,7 +592,7 @@
 		self.strength_finished = 30;
 		StartItem ("models/items/g_strength.md3",
 			"misc/powerup.wav", g_pickup_respawntime_powerup,
-			"Invisibility", IT_STRENGTH, 0, FL_POWERUP, generic_pickupevalfunc, 1000);
+			"Invisibility", IT_STRENGTH, 0, FL_POWERUP, generic_pickupevalfunc, BOT_PICKUP_RATING_MID);
 	}
 	// replace with extra lives
 	if (itemid == IT_NAILS)
@@ -600,7 +600,7 @@
 		self.max_health = 1;
 		StartItem ("models/items/g_h100.md3",
 			"misc/megahealth.wav", g_pickup_respawntime_powerup,
-			"Extralife", IT_NAILS, 0, FL_POWERUP, generic_pickupevalfunc, 1000);
+			"Extralife", IT_NAILS, 0, FL_POWERUP, generic_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
 
 	}
 	// replace with speed
@@ -610,7 +610,7 @@
 		self.invincible_finished = 30;
 		StartItem ("models/items/g_invincible.md3",
 			"misc/powerup_shield.wav", g_pickup_respawntime_powerup,
-			"Speed", IT_INVINCIBLE, 0, FL_POWERUP, generic_pickupevalfunc, 1000);
+			"Speed", IT_INVINCIBLE, 0, FL_POWERUP, generic_pickupevalfunc, BOT_PICKUP_RATING_MID);
 	}
 
 }
@@ -845,7 +845,7 @@
 		self.armorvalue = g_pickup_armorsmall;
 	if(!self.max_armorvalue)
 		self.max_armorvalue = g_pickup_armorsmall_max;
-	StartItem ("models/items/g_a1.md3", "misc/armor1.wav", g_pickup_respawntime_short, "5 Armor", IT_ARMOR_SHARD, 0, 0, commodity_pickupevalfunc, 1000);
+	StartItem ("models/items/g_a1.md3", "misc/armor1.wav", g_pickup_respawntime_short, "5 Armor", IT_ARMOR_SHARD, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
 }
 
 void spawnfunc_item_armor_medium (void) {
@@ -853,15 +853,23 @@
 		self.armorvalue = g_pickup_armormedium;
 	if(!self.max_armorvalue)
 		self.max_armorvalue = g_pickup_armormedium_max;
-	StartItem ("models/items/g_armormedium.md3", "misc/armor10.wav", g_pickup_respawntime_medium, "25 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
+	StartItem ("models/items/g_armormedium.md3", "misc/armor10.wav", g_pickup_respawntime_medium, "25 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
 }
 
+void spawnfunc_item_armor_big (void) {
+	if(!self.armorvalue)
+		self.armorvalue = g_pickup_armorbig;
+	if(!self.max_armorvalue)
+		self.max_armorvalue = g_pickup_armorbig_max;
+	StartItem ("models/items/g_a50.md3", "misc/armor17_5.wav", g_pickup_respawntime_long, "50 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
+}
+
 void spawnfunc_item_armor_large (void) {
 	if(!self.armorvalue)
 		self.armorvalue = g_pickup_armorlarge;
 	if(!self.max_armorvalue)
 		self.max_armorvalue = g_pickup_armorlarge_max;
-	StartItem ("models/items/g_a25.md3", "misc/armor25.wav", g_pickup_respawntime_long, "100 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
+	StartItem ("models/items/g_a25.md3", "misc/armor25.wav", g_pickup_respawntime_long, "100 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
 }
 
 void spawnfunc_item_health_small (void) {
@@ -869,7 +877,7 @@
 		self.max_health = g_pickup_healthsmall_max;
 	if(!self.health)
 		self.health = g_pickup_healthsmall;
-	StartItem ("models/items/g_h1.md3", "misc/minihealth.wav", g_pickup_respawntime_short, "5 Health", IT_5HP, 0, 0, commodity_pickupevalfunc, 20000);
+	StartItem ("models/items/g_h1.md3", "misc/minihealth.wav", g_pickup_respawntime_short, "5 Health", IT_5HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
 }
 
 void spawnfunc_item_health_medium (void) {
@@ -877,7 +885,7 @@
 		self.max_health = g_pickup_healthmedium_max;
 	if(!self.health)
 		self.health = g_pickup_healthmedium;
-	StartItem ("models/items/g_h25.md3", "misc/mediumhealth.wav", g_pickup_respawntime_short, "25 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, 20000);
+	StartItem ("models/items/g_h25.md3", "misc/mediumhealth.wav", g_pickup_respawntime_short, "25 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
 }
 
 void spawnfunc_item_health_large (void) {
@@ -885,7 +893,7 @@
 		self.max_health = g_pickup_healthlarge_max;
 	if(!self.health)
 		self.health = g_pickup_healthlarge;
-	StartItem ("models/items/g_h50.md3", "misc/mediumhealth.wav", g_pickup_respawntime_medium, "50 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, 20000);
+	StartItem ("models/items/g_h50.md3", "misc/mediumhealth.wav", g_pickup_respawntime_medium, "50 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
 }
 
 void spawnfunc_item_health_mega (void) {
@@ -902,7 +910,7 @@
 			self.max_health = g_pickup_healthmega_max;
 		if(!self.health)
 			self.health = g_pickup_healthmega;
-		StartItem ("models/items/g_h100.md3", "misc/megahealth.wav", g_pickup_respawntime_long, "100 Health", IT_HEALTH, 0, 0, commodity_pickupevalfunc, 20000);
+		StartItem ("models/items/g_h100.md3", "misc/megahealth.wav", g_pickup_respawntime_long, "100 Health", IT_HEALTH, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
 	}
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/server/t_quake3.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_quake3.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_quake3.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -35,7 +35,7 @@
                           
 // Armor                  
 void spawnfunc_item_armor_body()     { spawnfunc_item_armor_large();   }
-void spawnfunc_item_armor_combat()   { spawnfunc_item_armor_medium();  }
+void spawnfunc_item_armor_combat()   { spawnfunc_item_armor_big();  }
 void spawnfunc_item_armor_shard()    { spawnfunc_item_armor_small();   }
 void spawnfunc_item_enviro()         { spawnfunc_item_armor_medium();  }
 //void spawnfunc_item_flight()       /* not supported */

Modified: branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1,3 +1,15 @@
+void SendCSQCNexBeamParticle() {
+	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+	WriteByte(MSG_BROADCAST, TE_CSQC_NEXGUNBEAMPARTICLE);
+	
+	WriteCoord(MSG_BROADCAST, w_shotorg_x);
+	WriteCoord(MSG_BROADCAST, w_shotorg_y);
+	WriteCoord(MSG_BROADCAST, w_shotorg_z);
+	WriteCoord(MSG_BROADCAST, trace_endpos_x);
+	WriteCoord(MSG_BROADCAST, trace_endpos_y);
+	WriteCoord(MSG_BROADCAST, trace_endpos_z);
+}
+
 void W_Nex_Attack (void)
 {
 	float flying;
@@ -11,10 +23,9 @@
 	if(yoda && flying)
 		announce(self, "announcer/male/yoda.wav");
 
-	pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	// beam effect
-	trailparticles(world, particleeffectnum("nex_beam"), w_shotorg, trace_endpos);
+	//beam and muzzle flash done on client
+	SendCSQCNexBeamParticle();
+	
 	// flash and burn the wall
 	if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
 		Damage_DamageInfo(trace_endpos, cvar("g_balance_nex_damage"), 0, 0, cvar("g_balance_nex_force") * w_shotdir, WEP_NEX);

Modified: branches/nexuiz-2.0/data/scripts/entities.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/entities.def	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/scripts/entities.def	2009-02-23 07:06:57 UTC (rev 5925)
@@ -321,6 +321,20 @@
 model="models/items/g_a25.md3"
 */
 
+/*QUAKED item_armor_big (.4 .8 .4) (-30 -30 0) (30 30 32) FLOATING
+Big Armor (default 50 armor points)
+-------- KEYS --------
+respawntime: time till it respawns (default: 20)
+armorvalue: amount of armor it gives (default: 50 (g_pickup_armorlarge))
+max_armorvalue: max of armor it increases to (default: 999 (g_pickup_armorlarge_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
+cnt: weight of this item for random selection using "team". Set to a lower value for items you want to see less likely.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/items/g_a50.md3"
+*/
+
 /*QUAKED item_armor_medium (.4 .8 .4) (-30 -30 0) (30 30 32) FLOATING
 Medium Armor (default 25 armor points)
 -------- KEYS --------

Copied: branches/nexuiz-2.0/data/sound/misc/armor17_5.wav (from rev 5924, trunk/data/sound/misc/armor17_5.wav)
===================================================================
(Binary files differ)

Modified: branches/nexuiz-2.0/data/weapons.cfg
===================================================================
--- branches/nexuiz-2.0/data/weapons.cfg	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/weapons.cfg	2009-02-23 07:06:57 UTC (rev 5925)
@@ -3,7 +3,7 @@
 //
 // And... don't forget to edit weaponsPro.cfg too.
 
-set cvar_check_weapons f156bf358766dfc169eb26dc36a765b9
+set cvar_check_weapons 32e7dc7d745187473f0040d14892e2bb
 
 set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
@@ -36,6 +36,8 @@
 set g_pickup_armorsmall_max 999
 set g_pickup_armormedium 25
 set g_pickup_armormedium_max 999
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 999
 set g_pickup_armorlarge 100
 set g_pickup_armorlarge_max 999
 set g_pickup_healthsmall 5

Modified: branches/nexuiz-2.0/data/weaponsHavoc.cfg
===================================================================
--- branches/nexuiz-2.0/data/weaponsHavoc.cfg	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/data/weaponsHavoc.cfg	2009-02-23 07:06:57 UTC (rev 5925)
@@ -1,4 +1,4 @@
-set cvar_check_weapons f156bf358766dfc169eb26dc36a765b9
+set cvar_check_weapons 32e7dc7d745187473f0040d14892e2bb
 
 set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
 set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
@@ -31,6 +31,8 @@
 set g_pickup_armorsmall_max 200
 set g_pickup_armormedium 25
 set g_pickup_armormedium_max 100
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 100
 set g_pickup_armorlarge 100
 set g_pickup_armorlarge_max 200
 set g_pickup_healthsmall 5
@@ -297,7 +299,7 @@
 // TAG Seeker
 set g_balance_seeker_tag_speed   9000
 set g_balance_seeker_tag_ammo    1
-set g_balance_seeker_tag_animtime 0.1
+set g_balance_seeker_tag_animtime 0.3
 set g_balance_seeker_tag_refire  0.7
 
 set g_balance_seeker_missile_delay 0.25
@@ -318,7 +320,7 @@
 set g_balance_seeker_missile_count		    4
 set g_balance_seeker_missile_lifetime 	    15
 set g_balance_seeker_missile_refire           0.5
-set g_balance_seeker_missile_animtime 	    0.25
+set g_balance_seeker_missile_animtime 	    0.3
 set g_balance_seeker_missile_ammo             2
 
 set g_balance_seeker_missile_proxy            0
@@ -348,10 +350,10 @@
 set g_balance_seeker_flac_ammo         0.5
 
 // NOTE: maps should not use this weapon yet
-set g_balance_campingrifle_magazinecapacity 12
-set g_balance_campingrifle_reloadtime 1.4
-set g_balance_campingrifle_primary_damage 90
-set g_balance_campingrifle_primary_headshotaddeddamage 160
+set g_balance_campingrifle_magazinecapacity 8
+set g_balance_campingrifle_reloadtime 1.1 // this + primary animtime = 1.4 = exactly 2 shots
+set g_balance_campingrifle_primary_damage 60
+set g_balance_campingrifle_primary_headshotaddeddamage 100
 set g_balance_campingrifle_primary_spread 0
 set g_balance_campingrifle_primary_force 2
 set g_balance_campingrifle_primary_speed 35000
@@ -360,14 +362,14 @@
 set g_balance_campingrifle_primary_animtime 0.3
 set g_balance_campingrifle_primary_ammo 10
 set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
-set g_balance_campingrifle_secondary_damage 60
-set g_balance_campingrifle_secondary_headshotaddeddamage 0
+set g_balance_campingrifle_secondary_damage 35
+set g_balance_campingrifle_secondary_headshotaddeddamage 15 // 50 damage only on head
 set g_balance_campingrifle_secondary_spread 0.008
 set g_balance_campingrifle_secondary_force 1
 set g_balance_campingrifle_secondary_speed 20000
 set g_balance_campingrifle_secondary_lifetime 5
 set g_balance_campingrifle_secondary_refire 0.12
-set g_balance_campingrifle_secondary_animtime 0.06
+set g_balance_campingrifle_secondary_animtime 0.1
 set g_balance_campingrifle_secondary_ammo 10
 set g_balance_campingrifle_secondary_health 5
 set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu

Modified: branches/nexuiz-2.0/misc/tools/demotc-race-record-extractor.sh
===================================================================
--- branches/nexuiz-2.0/misc/tools/demotc-race-record-extractor.sh	2009-02-22 15:57:49 UTC (rev 5924)
+++ branches/nexuiz-2.0/misc/tools/demotc-race-record-extractor.sh	2009-02-23 07:06:57 UTC (rev 5925)
@@ -15,6 +15,7 @@
 	timecode=${timecode%:}
 	result=${result#\"}
 	result=${result%\"}
+	result=${result%% *}
 
 	echo "Possible record found at $timecode: $result, extracting..."
 




More information about the nexuiz-commits mailing list