r2362 - in branches/nexuiz-2.0/data: . qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Fri Apr 20 07:34:36 EDT 2007
Author: div0
Date: 2007-04-20 07:34:36 -0400 (Fri, 20 Apr 2007)
New Revision: 2362
Modified:
branches/nexuiz-2.0/data/default.cfg
branches/nexuiz-2.0/data/qcsrc/server/bots.qc
branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
Log:
spawnpoints drop on g_spawnpoints_autodrop; merged Qantourisc's bot AI
Modified: branches/nexuiz-2.0/data/default.cfg
===================================================================
--- branches/nexuiz-2.0/data/default.cfg 2007-04-20 11:34:00 UTC (rev 2361)
+++ branches/nexuiz-2.0/data/default.cfg 2007-04-20 11:34:36 UTC (rev 2362)
@@ -149,10 +149,27 @@
set bot_ai_strategyinterval 2
set bot_ai_enemydetectioninterval 0.5
set bot_ai_aimskill_blendrate 2
-set bot_ai_aimskill_fixedrate 30
+set bot_ai_aimskill_fixedrate 15
set bot_ai_aimskill_firetolerance_distdegrees 180
set bot_ai_aimskill_firetolerance_mindegrees 2
-set bot_ai_aimskill_firetolerance_maxdegrees 30
+set bot_ai_aimskill_firetolerance_maxdegrees 45
+set bot_ai_aimskill_mouse 1
+set bot_ai_keyboard_distance 250
+set bot_ai_keyboard_treshold 0.94
+set bot_ai_aimskill_offset 1
+set bot_ai_aimskill_think 1
+// 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
+set bot_ai_aimskill_order_mix_3th 0.01
+set bot_ai_aimskill_order_mix_4th 0.05
+set bot_ai_aimskill_order_mix_5th 0.01
+set bot_ai_aimskill_order_filter_1st 0.2
+set bot_ai_aimskill_order_filter_2nd 0.2
+set bot_ai_aimskill_order_filter_3th 0.05
+set bot_ai_aimskill_order_filter_4th 0.25
+set bot_ai_aimskill_order_filter_5th 0.3
+
// waypoint editor enable
set g_waypointeditor 0
set bot_ignore_bots 0
@@ -184,6 +201,7 @@
set g_midair 0
set g_midair_shieldtime 0.3
set g_spawnshieldtime 0
+set g_spawnpoints_autodrop 1
set g_forced_respawn 0
set g_fullbrightplayers 0
set g_fullbrightitems 0
Modified: branches/nexuiz-2.0/data/qcsrc/server/bots.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/bots.qc 2007-04-20 11:34:00 UTC (rev 2361)
+++ branches/nexuiz-2.0/data/qcsrc/server/bots.qc 2007-04-20 11:34:36 UTC (rev 2362)
@@ -326,7 +326,13 @@
};
+// Random skill system
+.float bot_thinkskill;
+.float bot_mouseskill;
+.float bot_predictionskill;
+.float bot_offsetskill;
+
// waypoint navigation system
// itemscore = (howmuchmoreIwant / howmuchIcanwant) / itemdistance
@@ -1496,7 +1502,15 @@
};
.float bot_badaimtime;
+.float bot_aimthinktime;
+.vector bot_mouseaim;
.vector bot_badaimoffset;
+.vector bot_1st_order_aimfilter;
+.vector bot_2nd_order_aimfilter;
+.vector bot_3th_order_aimfilter;
+.vector bot_4th_order_aimfilter;
+.vector bot_5th_order_aimfilter;
+.vector bot_olddesiredang;
float(vector v, float maxfiredeviation) bot_aimdir =
{
/*
@@ -1551,9 +1565,9 @@
if (time >= self.bot_badaimtime)
{
self.bot_badaimtime = max(self.bot_badaimtime + 0.3, time);
- self.bot_badaimoffset = randomvec() * bound(0, 5 - 0.5 * skill, 5);
+ self.bot_badaimoffset = randomvec() * bound(0, 5 - 0.5 * (skill+self.bot_offsetskill), 5);
}
- desiredang = vectoangles(v) + self.bot_badaimoffset;
+ desiredang = vectoangles(v) + self.bot_badaimoffset*cvar("bot_ai_aimskill_offset");
//dprint(" desired:", vtos(desiredang));
if (desiredang_x >= 180)
desiredang_x = desiredang_x - 360;
@@ -1570,6 +1584,64 @@
//}
// calculate turn angles
+ diffang = (desiredang - self.bot_olddesiredang)*(1/frametime);
+ self.bot_olddesiredang = desiredang;
+ //dprint(" diff:", vtos(diffang));
+
+ // wrap yaw turn
+ while (diffang_y < -180)
+ diffang_y = diffang_y + 360;
+ while (diffang_y > 180)
+ diffang_y = diffang_y - 360;
+
+ // Here we will try to anticipate the comming aiming direction
+ self.bot_1st_order_aimfilter= self.bot_1st_order_aimfilter
+ + (diffang - self.bot_1st_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_1st"),1);
+ self.bot_2nd_order_aimfilter= self.bot_2nd_order_aimfilter
+ + (self.bot_1st_order_aimfilter - self.bot_2nd_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_2nd"),1);
+ self.bot_3th_order_aimfilter= self.bot_3th_order_aimfilter
+ + (self.bot_2nd_order_aimfilter - self.bot_3th_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_3th"),1);
+ self.bot_4th_order_aimfilter= self.bot_4th_order_aimfilter
+ + (self.bot_3th_order_aimfilter - self.bot_4th_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_4th"),1);
+ self.bot_5th_order_aimfilter= self.bot_5th_order_aimfilter
+ + (self.bot_4th_order_aimfilter - self.bot_5th_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_5th"),1);
+
+ local float blend;
+ //blend = (bound(0,skill,10)*0.1)*pow(1-bound(0,skill,10)*0.05,2.5)*5.656854249; //Plot formule before changing !
+ blend = bound(0,skill,10)*0.1;
+ desiredang = desiredang + blend *
+ (
+ self.bot_1st_order_aimfilter * cvar("bot_ai_aimskill_order_mix_1st")
+ + self.bot_2nd_order_aimfilter * cvar("bot_ai_aimskill_order_mix_2nd")
+ + self.bot_3th_order_aimfilter * cvar("bot_ai_aimskill_order_mix_3th")
+ + self.bot_4th_order_aimfilter * cvar("bot_ai_aimskill_order_mix_4th")
+ + self.bot_5th_order_aimfilter * cvar("bot_ai_aimskill_order_mix_5th")
+ );
+ while (desiredang_z < -180)
+ desiredang_z = desiredang_z + 360;
+ while (desiredang_z > 180)
+ desiredang_z = desiredang_z - 360;
+ // calculate turn angles
+ diffang = desiredang - self.bot_mouseaim;
+ //dprint(" diff:", vtos(diffang));
+
+ // wrap yaw turn
+ while (diffang_y < -180)
+ diffang_y = diffang_y + 360;
+ while (diffang_y > 180)
+ diffang_y = diffang_y - 360;
+
+ if (time >= self.bot_aimthinktime)
+ {
+ self.bot_aimthinktime = max(self.bot_aimthinktime + 0.5 - 0.05*(skill+self.bot_thinkskill), time);
+ self.bot_mouseaim = self.bot_mouseaim + diffang * (1-random()*0.1*bound(1,10-skill,10));
+ }
+
+ //self.v_angle = self.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
+
+ desiredang = self.bot_mouseaim*bound(0,cvar("bot_ai_aimskill_think"),1) + desiredang * bound(0,(1-cvar("bot_ai_aimskill_think")),1);
+
+ // calculate turn angles
diffang = desiredang - self.v_angle;
//dprint(" diff:", vtos(diffang));
@@ -1578,17 +1650,30 @@
diffang_y = diffang_y + 360;
while (diffang_y > 180)
diffang_y = diffang_y - 360;
+ // calculate turn angles
+ diffang = desiredang - self.v_angle;
+ //dprint(" diff:", vtos(diffang));
+ // wrap yaw turn
+ while (diffang_y < -180)
+ diffang_y = diffang_y + 360;
+ while (diffang_y > 180)
+ diffang_y = diffang_y - 360;
+
// jitter tracking
dist = vlen(diffang);
//diffang = diffang + randomvec() * (dist * 0.05 * (3.5 - bound(0, skill, 3)));
// turn
local float r, fixedrate, blendrate;
- fixedrate = cvar("bot_ai_aimskill_fixedrate") / max(1, dist);
+ fixedrate = cvar("bot_ai_aimskill_fixedrate") / bound(1,dist,1000);
blendrate = cvar("bot_ai_aimskill_blendrate");
r = max(fixedrate, blendrate);
- self.v_angle = self.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
+ //self.v_angle = self.v_angle + diffang * bound(frametime, r * frametime * (2+skill*skill*0.05-random()*0.05*(10-skill)), 1);
+ self.v_angle = self.v_angle + diffang * bound(frametime, r * frametime * (2+pow(skill+self.bot_mouseskill,3)*0.005-random()), 1);
+ self.v_angle = self.v_angle * bound(0,cvar("bot_ai_aimskill_mouse"),1) + desiredang * bound(0,(1-cvar("bot_ai_aimskill_mouse")),1);
+ //self.v_angle = self.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
+ //self.v_angle = self.v_angle + diffang * (1/ blendrate);
self.v_angle_z = 0;
while (self.v_angle_y < -180)
self.v_angle_y = self.v_angle_y + 360;
@@ -1599,6 +1684,7 @@
makevectors(self.v_angle);
shotorg = self.origin + self.view_ofs;
shotdir = v_forward;
+
//dprint(" dir:", vtos(v_forward));
//te_lightning2(world, shotorg, shotorg + shotdir * 100);
@@ -1612,8 +1698,14 @@
//bprint("e ");bprintvector(diffang);bprint(" < ");bprintfloat(maxfiredeviation);bprint("\n");
// decide whether to fire this time
- if ((normalize(v) * shotdir) >= cos(maxfiredeviation))
- self.bot_firetimer = time + 0.3;
+ // note the maxfiredeviation is in degrees so this has to convert to radians first
+ //if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
+ if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
+ self.bot_firetimer = time + 0.3/bound(1,skill*0.3,3);
+ traceline(shotorg,shotorg+shotdir*1000,FALSE,world);
+ if ( vlen(trace_endpos-shotorg)>bound(0,skill*20,20) && random()<bound(0,skill*0.5,10)*frametime*2 )
+ self.bot_canfire = 0;
+ //dprint(ftos(maxfiredeviation),"\n");
//dprint(" diff:", vtos(diffang), "\n");
return self.bot_canfire && (time < self.bot_firetimer);
@@ -1621,6 +1713,7 @@
vector(vector targorigin, vector targvelocity, float shotspeed, float shotdelay) bot_shotlead =
{
+ // Try to add code here that predicts gravity effect here, no clue HOW to though ... well not yet atleast...
return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed);
};
@@ -1650,7 +1743,11 @@
shotorg = self.origin + self.view_ofs;
shotdir = v_forward;
v = bot_shotlead(self.bot_aimtargorigin, self.bot_aimtargvelocity, shotspeed, self.bot_aimlatency);
- r = bound(cvar("bot_ai_aimskill_firetolerance_mindegrees"), cvar("bot_ai_aimskill_firetolerance_distdegrees") / ((vlen(v - shotorg) + 100) * (skill + 2)), cvar("bot_ai_aimskill_firetolerance_maxdegrees"));
+ local float distanceratio;
+ distanceratio =sqrt(bound(0,skill,10000))*0.3*(vlen(v-shotorg)-100)/cvar("bot_ai_aimskill_firetolerance_distdegrees");
+ distanceratio = bound(0,distanceratio,1);
+ r = (cvar("bot_ai_aimskill_firetolerance_maxdegrees")-cvar("bot_ai_aimskill_firetolerance_mindegrees"))
+ * (1-distanceratio) + cvar("bot_ai_aimskill_firetolerance_mindegrees");
if (applygravity && self.bot_aimtarg)
{
if (!findtrajectorywithleading(shotorg, '0 0 0', '0 0 0', self.bot_aimtarg, shotspeed, shotspeedupward, maxshottime, 0, self))
@@ -1705,7 +1802,9 @@
// calculate an aiming latency based on the skill setting
// (simulated network latency + naturally delayed reflexes)
- self.ping = 0.7 - bound(0, 0.05 * skill, 0.6);
+ //self.ping = 0.7 - bound(0, 0.05 * skill, 0.5); // moved the reflexes to bot_aimdir (under the name 'think')
+ // minimum ping 20+10 random
+ self.ping = bound(0,0.07 - bound(0, skill * 0.005,0.05)+random()*0.01,0.65); // Now holds real lag to server, and higer skill players take a less laggy server
// skill 10 = ping 0.2 (adrenaline)
// skill 0 = ping 0.7 (slightly drunk)
@@ -1767,6 +1866,7 @@
void() havocbot_setupbot;
float JoinBestTeam(entity pl, float only_return_best);
+
void() bot_clientconnect =
{
if (clienttype(self) != CLIENTTYPE_BOT)
@@ -1776,6 +1876,10 @@
self.createdtime = self.nextthink;
JoinBestTeam(self, FALSE);
havocbot_setupbot();
+ self.bot_mouseskill=random()-0.5;
+ self.bot_thinkskill=random()-0.5;
+ self.bot_predictionskill=random()-0.5;
+ self.bot_offsetskill=random()-0.5;
};
entity() bot_spawn =
Modified: branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc 2007-04-20 11:34:00 UTC (rev 2361)
+++ branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc 2007-04-20 11:34:36 UTC (rev 2362)
@@ -1,6 +1,7 @@
.void() havocbot_role;
void() havocbot_chooserole;
+.float havocbot_keyboardskill;
vector() havocbot_dodge =
{
@@ -51,6 +52,9 @@
};
//.float havocbotignoretime;
+.float havocbot_keyboardtime;
+.float havocbot_ducktime;
+.vector havocbot_keyboard;
void() havocbot_movetogoal =
{
local vector destorg;
@@ -67,6 +71,15 @@
//if (self.goalentity)
// te_lightning2(self, self.origin, (self.goalentity.absmin + self.goalentity.absmax) * 0.5);
self.movement = '0 0 0';
+
+ if(self.jumppadcount)
+ {
+ if(self.flags & FL_ONGROUND)
+ self.jumppadcount = FALSE;
+ else
+ return;
+ }
+
if (self.goalcurrent == world)
return;
navigation_poptouchedgoals();
@@ -91,13 +104,14 @@
flatdir = normalize(flatdir);
if (!self.waterlevel)
{
- if (!(self.flags & FL_ONGROUND))
- {
- // prevent goal checks when we can't walk
- if (self.bot_strategytime < time + 0.1)
- self.bot_strategytime = time + 0.1;
- return;
- }
+ // Since new update in air contol, we can move in air
+ //if (!(self.flags & FL_ONGROUND))
+ //{
+ // // prevent goal checks when we can't walk
+ // if (self.bot_strategytime < time + 0.1)
+ // self.bot_strategytime = time + 0.1;
+ // return;
+ //}
// jump if going toward an obstacle that doesn't look like stairs we
// can walk up directly
@@ -125,14 +139,80 @@
dir = flatdir;
}
dodge = havocbot_dodge();
- dir = normalize(dir + dodge + evadeobstacle + evadelava) * 400;
- makevectors(self.v_angle);
+ dodge = dodge * bound(0,3+skill*0.1,1);
+ evadelava = evadelava * bound(1,3-skill,3); //Noobs fear lava a lot and take more distance from it
+ traceline(self.origin, self.enemy.origin, TRUE, world);
+ if(trace_ent.classname == "player")
+ dir = dir * bound(0,skill/7,1);
+
+ dir = normalize(dir + dodge + evadeobstacle + evadelava);
+
+
+
+ // Emulate keyboard interface;
+ local vector keyboard,flatangle;
+ local float blend;
+ keyboard = self.havocbot_keyboard;
+ if (time >= self.havocbot_keyboardtime)
+ {
+ flatdir=dir; flatdir_z = 0;
+ self.havocbot_keyboardtime =
+ max(
+ self.havocbot_keyboardtime
+ + bound(0,0.05/(skill+self.havocbot_keyboardskill),0.05)
+ +random()*bound(0,0.025/(skill+self.havocbot_keyboardskill),100)
+ , time);
+ keyboard = '0 0 0';
+
+ flatangle = self.v_angle; flatangle_z=0;
+ makevectors(flatangle);
+
+ local float trigger;
+ local vector v_forward_right;
+ local vector v_forward_left;
+ blend = bound(0,skill*0.1,1);
+ trigger = cvar("bot_ai_keyboard_treshold");
+ v_forward_right = normalize(v_forward + v_right);
+ v_forward_left = normalize(v_forward - v_right);
+ // Place in reverse order !! least important direction FIRST
+
+ if (skill > 4.5)
+ {
+ if (flatdir * v_forward_right * -1 > trigger) keyboard = v_forward_right * -1;
+ if (flatdir * v_forward_left * -1 > trigger) keyboard = v_forward_left * -1;
+ }
+ if (skill > 2.5)
+ {
+ if (flatdir * v_forward_right > trigger) keyboard = v_forward_right;
+ if (flatdir * v_forward_left > trigger) keyboard = v_forward_left;
+ if (flatdir * v_forward * 1 > trigger) keyboard = v_forward * -1;
+ }
+ if (skill > 1.5)
+ {
+ if (flatdir * v_right > trigger) keyboard = v_right;
+ if (flatdir * v_right * -1 > trigger) keyboard = v_right * -1;
+ }
+ if (flatdir * v_forward > trigger) keyboard = v_forward;
+ //dprint(ftos(flatdir * v_forward),"\n");
+ keyboard = normalize(keyboard);
+ self.havocbot_keyboard = keyboard;
+ if (self.havocbot_ducktime>time) self.button5=TRUE;
+ }
+ blend = bound(0,vlen(self.goalcurrent.origin-self.origin)/cvar("bot_ai_keyboard_distance"),1); // When getting close move with 360 degree
+ dir = (keyboard * blend + dir * (1-blend))*cvar("sv_maxspeed");
+
self.movement_x = dir * v_forward;
self.movement_y = dir * v_right;
- self.movement_z = dir * v_up;
+ if (self.flags & FL_INWATER) self.movement_z = dir * v_up; else self.movement_z = 0;
+
+ if ((dir * v_up) >= cvar("g_balance_jumpheight")*0.5 && (self.flags & FL_ONGROUND)) self.button2=1;
+ if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill)*0.1,1)) self.button2=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);
+
};
.float havocbot_chooseenemy_finished;
+.float havocbot_stickenemy;
void() havocbot_chooseenemy =
{
local entity head, best;
@@ -143,9 +223,30 @@
self.enemy = world;
return;
}
+ traceline(self.origin+self.view_ofs, self.enemy.origin+self.enemy.view_ofs*0.5,FALSE,world);
+ if (trace_ent.classname != "player")
+ self.havocbot_stickenemy =0;
+ else if ( (trace_ent != self.enemy) || (vlen(self.enemy.origin - self.origin) > 1000) )
+ {
+ self.havocbot_stickenemy =0;
+ if( (self.health < 30) || (self.enemy.health < 0))
+ self.havocbot_chooseenemy_finished = time;
+ }
+ //dprint(ftos(self.havocbot_stickenemy));dprint(etos(self.enemy),"\n");
+ //dprint(ftos(time),"-");dprint(ftos(self.havocbot_chooseenemy_finished),"\n");
+ if (self.havocbot_stickenemy == 1)
+ {
+ // remain tracking him for a shot while (case he went after a small corner or pilar
+ self.havocbot_chooseenemy_finished = time + bound(0,skill*0.1,1)*1.8;
+ return;
+ }
if (time < self.havocbot_chooseenemy_finished)
+ {
+ self.havocbot_stickenemy = 1;
return;
- self.havocbot_chooseenemy_finished = time + cvar("bot_ai_enemydetectioninterval");
+ }
+ self.havocbot_chooseenemy_finished = time + cvar("bot_ai_enemydetectioninterval")*bound(0,(11-skill)*0.1,1);
+ self.havocbot_chooseenemy_finished = time + 0.01;
eye = (self.origin + self.view_ofs);
best = world;
bestrating = 100000000;
@@ -167,12 +268,108 @@
head = head.chain;
}
self.enemy = best;
+ self.havocbot_stickenemy = 1;
};
float(entity e) w_getbestweapon;
+.float havocbot_chooseweapon_timer;
+.float havocbot_chooseweapon_lastbestscore;
void() havocbot_chooseweapon =
{
- self.switchweapon = w_getbestweapon(self);
+ // TODO: clean this up by moving it to weapon code
+ if(self.enemy.classname!="player")
+ {
+ self.switchweapon = w_getbestweapon(self);
+ return;
+ }
+
+ local float rocket ; rocket =-1000;
+ local float nex ; nex =-1000;
+ local float hagar ; hagar =-1000;
+ local float grenade ; grenade =-1000;
+ local float electro ; electro =-1000;
+ local float crylink ; crylink =-1000;
+ local float uzi ; uzi =-1000;
+ local float shotgun ; shotgun =-1000;
+ local float laser ; laser =-1000;
+ local float bestscore; bestscore = 0;
+ local float bestweapon; bestweapon=self.switchweapon;
+ local float distance; distance=bound(10,vlen(self.origin-self.enemy.origin)-200,10000);
+ local float maxdelaytime=0.5;
+ local float spreadpenalty=10;
+ local float distancefromfloor;
+ traceline(self.enemy.origin,self.enemy.origin-'0 0 1000',TRUE,world);
+ distancefromfloor = self.enemy.origin_z - trace_endpos_z;
+ // Formula:
+ // (Damage/Sec * Weapon spefic change to get that damage)
+ // *(Time to get to target * weapon specfic hitchange bonus) / (in a time of maxdelaytime)
+ // *(Spread change of hit) // if it applies
+ // *(Penality for target beeing in air)
+ if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
+ rocket = (cvar("g_balance_rocketlauncher_damage")/cvar("g_balance_rocketlauncher_refire")*0.75)
+ * bound(0,(cvar("g_balance_rocketlauncher_speed")/distance*maxdelaytime),1)*1.5;
+ if (client_hasweapon(self, WEP_NEX, TRUE, FALSE))
+ nex = (cvar("g_balance_nex_damage")/cvar("g_balance_nex_refire")*1.0)
+ * (0.5);
+ if (client_hasweapon(self, WEP_HAGAR, TRUE, FALSE))
+ hagar = (cvar("g_balance_hagar_primary_damage")/cvar("g_balance_hagar_primary_refire")*1.0)
+ * bound(0,(cvar("g_balance_hagar_primary_speed")/distance*maxdelaytime),1)*0.2;
+ if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE, FALSE))
+ grenade = (cvar("g_balance_grenadelauncher_primary_damage")/cvar("g_balance_grenadelauncher_primary_refire")*1.0)
+ * bound(0,(cvar("g_balance_grenadelauncher_primary_speed")/distance*maxdelaytime),1)*1.1;
+ if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE))
+ electro = (cvar("g_balance_electro_primary_damage")/cvar("g_balance_electro_primary_refire")*0.75)
+ * bound(0,(cvar("g_balance_electro_primary_speed")/distance*maxdelaytime),1)*1.0;
+ if (client_hasweapon(self, WEP_CRYLINK, TRUE, FALSE))
+ crylink = (cvar("g_balance_crylink_primary_damage")/cvar("g_balance_crylink_primary_refire")*1.0)
+ * bound(0,(cvar("g_balance_crylink_primary_speed")/distance*maxdelaytime),1)*1.0
+ * bound(0,1/cvar("g_balance_crylink_primary_spread")/distance*spreadpenalty,1);
+ if (client_hasweapon(self, WEP_UZI, TRUE, FALSE))
+ uzi = (cvar("g_balance_uzi_sustained_damage")/cvar("g_balance_uzi_sustained_refire")*1.0)
+ * bound(0,1/cvar("g_balance_uzi_sustained_spread")/distance*spreadpenalty,1)*0.5;
+ if (client_hasweapon(self, WEP_SHOTGUN, TRUE, FALSE))
+ shotgun = (cvar("g_balance_shotgun_primary_damage")*cvar("g_balance_shotgun_primary_bullets")/cvar("g_balance_shotgun_primary_refire")*1.0)
+ * bound(0,1/cvar("g_balance_shotgun_primary_spread")/distance*spreadpenalty,1);
+ if (client_hasweapon(self, WEP_LASER, FALSE, FALSE))
+ laser = (cvar("g_balance_laser_damage")/cvar("g_balance_laser_refire")*1.0)
+ * bound(0,cvar("g_balance_laser_speed")/distance*0.2*maxdelaytime,1);
+ if((self.enemy.flags & FL_ONGROUND)==FALSE){
+ rocket = rocket * (1-bound(0, distancefromfloor/cvar("g_balance_rocketlauncher_radius" ),0.9)); //slight bigger change
+ grenade = grenade * (1-bound(0,distancefromfloor/cvar("g_balance_grenadelauncher_primary_radius"),0.95));
+ electro = electro * (1-bound(0,distancefromfloor/cvar("g_balance_electro_primary_radius" ),0.95));
+ laser = laser * (1-bound(0,distancefromfloor/cvar("g_balance_laser_radius" ),0.95));
+ }
+/*
+ dprint("Floor distance: ",ftos(distancefromfloor),"\n");
+ dprint("Rocket: " , ftos(rocket ), "\n");
+ dprint("Nex: " , ftos(nex ), "\n");
+ dprint("Hagar: " , ftos(hagar ), "\n");
+ dprint("Grenade: ", ftos(grenade ), "\n");
+ dprint("Electro: ", ftos(electro ), "\n");
+ dprint("Crylink: ", ftos(crylink ), "\n");
+ dprint("Uzi: " , ftos(uzi ), "\n");
+ dprint("Shotgun :", ftos(shotgun ), "\n");
+ dprint("Laser :", ftos(laser ), "\n\n");
+*/
+ if (rocket > bestscore){ bestscore = rocket ; bestweapon = WEP_ROCKET_LAUNCHER ;}
+ if (nex > bestscore){ bestscore = nex ; bestweapon = WEP_NEX ;}
+ if (hagar > bestscore){ bestscore = hagar ; bestweapon = WEP_HAGAR ;}
+ if (grenade > bestscore){ bestscore = grenade ; bestweapon = WEP_GRENADE_LAUNCHER ;}
+ if (electro > bestscore){ bestscore = electro ; bestweapon = WEP_ELECTRO ;}
+ if (crylink > bestscore){ bestscore = crylink ; bestweapon = WEP_CRYLINK ;}
+ if (uzi > bestscore){ bestscore = uzi ; bestweapon = WEP_UZI ;}
+ if (shotgun > bestscore){ bestscore = shotgun ; bestweapon = WEP_SHOTGUN ;}
+ if (laser > bestscore){ bestscore = laser ; bestweapon = WEP_LASER ;}
+
+ if(time>self.havocbot_chooseweapon_timer || self.havocbot_chooseweapon_lastbestscore<bestscore/10) //Or when the new damage is SOO much larger ! Or my gun runs out of ammo
+ {
+ self.havocbot_chooseweapon_timer=max(self.havocbot_chooseweapon_timer+cvar("g_balance_weaponswitchdelay")*120*(10-skill)*0.1,time);
+ if( self.havocbot_chooseweapon_lastbestscore*1.5<bestscore*bound(1,1+(skill*skill)*0.01,2))
+ {
+ self.switchweapon = bestweapon;
+ self.havocbot_chooseweapon_lastbestscore=bestscore;
+ }
+ }
};
.float nextaim;
@@ -208,9 +405,20 @@
weapon_action(self.weapon, WR_AIM);
else if (self.goalcurrent)
{
- local vector v;
- v = self.goalcurrent.origin - self.origin;
- //v = self.velocity;
+ local vector now,v,next;//,heading;
+ local float distance,skillblend,distanceblend;
+ now = self.goalcurrent.origin - self.origin;
+ distance = vlen(now);
+ //heading = self.velocity;
+ //dprint(self.goalstack01.classname,etos(self.goalstack01),"\n");
+ if(self.goalstack01 != self && self.goalstack01 != world)
+ next = self.goalstack01.origin - self.origin;
+ else
+ next = now;
+ 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);
+ v = (now * (distanceblend) + next * (1-distanceblend)) * (skillblend) + now * (1-skillblend);
+ //v = now * (distanceblend) + next * (1-distanceblend);
if (self.waterlevel < 2)
v_z = 0;
//dprint("walk at:", vtos(v), "\n");
@@ -224,5 +432,7 @@
{
self.bot_ai = havocbot_ai;
// will be updated by think code
+ //Generate some random skill levels
+ self.havocbot_keyboardskill=random()-0.5;
havocbot_chooserole();
}
Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc 2007-04-20 11:34:00 UTC (rev 2361)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc 2007-04-20 11:34:36 UTC (rev 2362)
@@ -187,11 +187,6 @@
void relocate_spawnpoint()
{
- vector o;
- o = self.origin;
-
- setsize(self, PL_MIN, PL_MAX);
-
// nudge off the floor
setorigin(self, self.origin + '0 0 1');
@@ -202,9 +197,11 @@
return;
}
- // drop the spawn point onto the floor
- // NOTE: a later version might not do this any more
- droptofloor();
+ if(cvar("g_spawnpoints_autodrop"))
+ {
+ setsize(self, PL_MIN, PL_MAX);
+ droptofloor();
+ }
}
// NOTE: DO NOT USE THIS FUNCTION TOO OFTEN.
More information about the nexuiz-commits
mailing list