X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Faim.qc;h=024db9237faf5d5d1ac314f7ef0ee380b68beb1a;hb=ee2f4178f1709cbf38b2e865c6c96a7d177bbebf;hp=e7a2e6a7bef1d1ee2c3b4ea80be3fb13516bcb1e;hpb=22a952ce0284640d15f5bb1135f750c3a141f6a4;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/bot/default/aim.qc b/qcsrc/server/bot/default/aim.qc index e7a2e6a7b..024db9237 100644 --- a/qcsrc/server/bot/default/aim.qc +++ b/qcsrc/server/bot/default/aim.qc @@ -1,17 +1,13 @@ #include "aim.qh" -#include - -#include "cvars.qh" - -#include "bot.qh" - #include #include - -#include "../../weapons/weaponsystem.qh" - +#include +#include +#include +#include #include +#include // traces multiple trajectories to find one that will impact the target // 'end' vector is the place it aims for, @@ -170,6 +166,23 @@ void bot_lagfunc(entity this, float t, float f1, float f2, entity e1, vector v1, this.bot_canfire = 1; } +// this function should be called after bot_aim so the aim is reset the next frame +void bot_aim_reset(entity this) +{ + this.bot_mouseaim = this.v_angle; + this.bot_olddesiredang = this.v_angle; + this.bot_aimdir_executed = true; + this.bot_badaimtime = 0; + this.bot_aimthinktime = time; + this.bot_prevaimtime = time; + this.bot_1st_order_aimfilter = '0 0 0'; + this.bot_2nd_order_aimfilter = '0 0 0'; + this.bot_3th_order_aimfilter = '0 0 0'; + this.bot_4th_order_aimfilter = '0 0 0'; + this.bot_5th_order_aimfilter = '0 0 0'; + this.bot_firetimer = 0; +} + void bot_aimdir(entity this, vector v, float maxfiredeviation) { float dist, delta_t, blend; @@ -182,9 +195,18 @@ void bot_aimdir(entity this, vector v, float maxfiredeviation) this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360; this.v_angle_z = 0; + // make work bot_aim_reset even if called before this function + if (this.bot_prevaimtime == time) + return; + // invalid aim dir (can happen when bot overlaps target) if(!v) return; + float skill_save = skill; + // allow turning in a more natural way when bot is walking + if (!this.bot_aimtarg) + skill = max(4, skill); + // get the desired angles to aim at //dprint(" at:", vtos(v)); v = normalize(v); @@ -285,38 +307,43 @@ void bot_aimdir(entity this, vector v, float maxfiredeviation) blendrate = autocvar_bot_ai_aimskill_blendrate; r = max(fixedrate, blendrate); //this.v_angle = this.v_angle + diffang * bound(frametime, r * frametime * (2+skill*skill*0.05-random()*0.05*(10-skill)), 1); - this.v_angle = this.v_angle + diffang * bound(delta_t, r * delta_t * (2 + ((skill + this.bot_mouseskill) ** 3) * 0.005 - random()), 1); - this.v_angle = this.v_angle * bound(0,autocvar_bot_ai_aimskill_mouse,1) + desiredang * bound(0,(1-autocvar_bot_ai_aimskill_mouse),1); - //this.v_angle = this.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1); - //this.v_angle = this.v_angle + diffang * (1/ blendrate); + r = bound(delta_t, r * delta_t * (2 + ((skill + this.bot_mouseskill) ** 3) * 0.005 - random()), 1); + this.v_angle += diffang * (r + (1 - r) * bound(0, 1 - autocvar_bot_ai_aimskill_mouse, 1)); this.v_angle_z = 0; this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360; //dprint(" turn:", vtos(this.v_angle)); - makevectors(this.v_angle); - shotorg = this.origin + this.view_ofs; - shotdir = v_forward; + skill = skill_save; - //dprint(" dir:", vtos(v_forward)); - //te_lightning2(NULL, shotorg, shotorg + shotdir * 100); + if (maxfiredeviation <= 0) + return; - // calculate turn angles again - //diffang = desiredang - this.v_angle; - //diffang_y = diffang_y - floor(diffang_y / 360) * 360; - //if (diffang_y >= 180) - // diffang_y = diffang_y - 360; + if (!autocvar_bot_ai_aimskill_firetolerance) + { + this.bot_firetimer = time + 0.2; + return; + } - //dprint("e ", vtos(diffang), " < ", ftos(maxfiredeviation), "\n"); + makevectors(this.v_angle); + shotorg = this.origin + this.view_ofs; + shotdir = v_forward; // decide whether to fire this time - if (v * shotdir >= cos(maxfiredeviation * DEG2RAD)) - if(vdist(trace_endpos-shotorg, <, 500 + 500 * bound(0, skill + this.bot_aggresskill, 10)) || random()*random()>bound(0,(skill+this.bot_aggresskill)*0.05,1)) - this.bot_firetimer = time + bound(0.1, 0.5-(skill+this.bot_aggresskill)*0.05, 0.5); - //traceline(shotorg,shotorg+shotdir*1000,false,NULL); - //dprint(ftos(maxfiredeviation),"\n"); - //dprint(" diff:", vtos(diffang), "\n"); - - //return this.bot_canfire && (time < this.bot_firetimer); + // v is the calculated trajectory, shotdir is bot view direction + // NOTE: checking if (v * shotdir > cos(maxfiredeviation * DEG2RAD)) would be cheaper + // but it gets evaluated to true even if v and shotdir have nearly opposite direction + vector deviation = vectoangles(v) - vectoangles(shotdir); + while (deviation.x < -180) deviation.x += 360; while (deviation.x > 180) deviation.x -= 360; + while (deviation.y < -180) deviation.y += 360; while (deviation.y > 180) deviation.y -= 360; + if (fabs(deviation.x) < maxfiredeviation && fabs(deviation.y) < maxfiredeviation) + { + traceline(shotorg, shotorg + shotdir * 1000, false, NULL); + if (vdist(trace_endpos - shotorg, <, 500 + 500 * bound(0, skill + this.bot_aggresskill, 10)) + || random() * random() > bound(0, (skill + this.bot_aggresskill) * 0.05, 1)) + { + this.bot_firetimer = time + bound(0.1, 0.5 - (skill + this.bot_aggresskill) * 0.05, 0.5); + } + } } vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay) @@ -325,24 +352,16 @@ vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, flo return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed); } -bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity) +bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity, bool shot_accurate) { - float r, hf, distanceratio; + float hf, distanceratio; vector v; - /* - eprint(this); - dprint("bot_aim(", ftos(shotspeed)); - dprint(", ", ftos(shotspeedupward)); - dprint(", ", ftos(maxshottime)); - dprint(", ", ftos(applygravity)); - dprint(");\n"); - */ - hf = this.dphitcontentsmask; this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; - shotspeed *= W_WeaponSpeedFactor(this); - shotspeedupward *= W_WeaponSpeedFactor(this); + float speed_factor = W_WeaponSpeedFactor(this); + shotspeed *= speed_factor; + shotspeedupward *= speed_factor; if (!shotspeed) { LOG_TRACE("bot_aim: WARNING: weapon ", this.(weaponentity).m_weapon.m_name, " shotspeed is zero!"); @@ -357,10 +376,18 @@ bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeed shotorg = this.origin + this.view_ofs; shotdir = v_forward; v = bot_shotlead(this.bot_aimtargorigin, this.bot_aimtargvelocity, shotspeed, this.bot_aimlatency); + distanceratio = sqrt(bound(0,skill,10000))*0.3*(vlen(v-shotorg)-100)/autocvar_bot_ai_aimskill_firetolerance_distdegrees; distanceratio = bound(0,distanceratio,1); - r = (autocvar_bot_ai_aimskill_firetolerance_maxdegrees-autocvar_bot_ai_aimskill_firetolerance_mindegrees) - * (1-distanceratio) + autocvar_bot_ai_aimskill_firetolerance_mindegrees; + float mindegrees = autocvar_bot_ai_aimskill_firetolerance_mindegrees; + float diffdegrees = autocvar_bot_ai_aimskill_firetolerance_maxdegrees - mindegrees; + if (!shot_accurate) // this shot doesn't require too much accuracy + mindegrees += diffdegrees * 0.25; + else // less skilled bots shoot even if they aren't aiming accurately + mindegrees += (random() > 0.3) ? 0 : diffdegrees * 0.25 * (1 - bound(0, skill / 10, 1)); + diffdegrees = autocvar_bot_ai_aimskill_firetolerance_maxdegrees - mindegrees; + float maxfiredeviation = diffdegrees * (1 - distanceratio) + mindegrees; + if (applygravity && this.bot_aimtarg) { if (!findtrajectorywithleading(shotorg, '0 0 0', '0 0 0', this.bot_aimtarg, shotspeed, shotspeedupward, maxshottime, 0, this)) @@ -369,11 +396,11 @@ bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeed return false; } - bot_aimdir(this, findtrajectory_velocity - shotspeedupward * '0 0 1', r); + bot_aimdir(this, findtrajectory_velocity - shotspeedupward * '0 0 1', maxfiredeviation); } else { - bot_aimdir(this, v - shotorg, r); + bot_aimdir(this, v - shotorg, maxfiredeviation); //dprint("AIM: ");dprint(vtos(this.bot_aimtargorigin));dprint(" + ");dprint(vtos(this.bot_aimtargvelocity));dprint(" * ");dprint(ftos(this.bot_aimlatency + vlen(this.bot_aimtargorigin - shotorg) / shotspeed));dprint(" = ");dprint(vtos(v));dprint(" : aimdir = ");dprint(vtos(normalize(v - shotorg)));dprint(" : ");dprint(vtos(shotdir));dprint("\n"); //traceline(shotorg, shotorg + shotdir * 10000, false, this); //if (trace_ent.takedamage) @@ -390,6 +417,12 @@ bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeed } } + if (time > this.bot_firetimer) + { + this.dphitcontentsmask = hf; + return false; + } + //if (r > maxshottime * shotspeed) // return false; this.dphitcontentsmask = hf;