X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Fhavocbot%2Fhavocbot.qc;h=f0b229bae48e151018ca143584bfef4019522a28;hp=cede62366848b6407f7e8924863290c62a905099;hb=cabba6eeb71f3ca612aa30bb8c7dad9cbc9c0d52;hpb=cd2e3f4efb8e5f3c7db8b6c1654ee2c6a1eea05a diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc index cede623668..f0b229bae4 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@ -44,7 +44,6 @@ void havocbot_ai(entity this) this.havocbot_role(this); // little too far down the rabbit hole } - // TODO: tracewalk() should take care of this job (better path finding under water) // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it if(!(IS_DEAD(this) || STAT(FROZEN, this))) if(!this.goalcurrent) @@ -139,7 +138,9 @@ void havocbot_ai(entity this) vector now,v,next;//,heading; float aimdistance,skillblend,distanceblend,blend; - next = now = ( (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5) - (this.origin + this.view_ofs); + + SET_DESTCOORDS(this.goalcurrent, this.origin, now); + next = now = now - (this.origin + this.view_ofs); aimdistance = vlen(now); //heading = this.velocity; //dprint(this.goalstack01.classname,etos(this.goalstack01),"\n"); @@ -306,12 +307,12 @@ void havocbot_bunnyhop(entity this, vector dir) this.bot_timelastseengoal = 0; } - gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5; + SET_DESTCOORDS(this.goalcurrent, this.origin, gco); bunnyhopdistance = vlen(this.origin - gco); // Run only to visible goals if(IS_ONGROUND(this)) - if(vlen(this.velocity - eZ * this.velocity.z) >= autocvar_sv_maxspeed) // if -really- running + if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed)) // if -really- running if(checkpvs(this.origin + this.view_ofs, this.goalcurrent)) { this.bot_lastseengoal = this.goalcurrent; @@ -413,17 +414,32 @@ void havocbot_bunnyhop(entity this, vector dir) #endif } -.entity goalcurrent_prev; -.float goalcurrent_distance; -.float goalcurrent_distance_time; +// return true when bot isn't getting closer to the current goal +bool havocbot_checkgoaldistance(entity this, vector gco) +{ + float curr_dist = vlen(this.origin - gco); + if(curr_dist > this.goalcurrent_distance) + { + if(!this.goalcurrent_distance_time) + this.goalcurrent_distance_time = time; + else if (time - this.goalcurrent_distance_time > 0.5) + return true; + } + else + { + // reduce it a little bit so it works even with very small approaches to the goal + this.goalcurrent_distance = max(20, curr_dist - 15); + this.goalcurrent_distance_time = 0; + } + return false; +} + void havocbot_movetogoal(entity this) { vector destorg; vector diff; vector dir; vector flatdir; - vector m1; - vector m2; vector evadeobstacle; vector evadelava; float maxspeed; @@ -507,17 +523,25 @@ void havocbot_movetogoal(entity this) // Handling of jump pads if(this.jumppadcount) { - // If got stuck on the jump pad try to reach the farthest visible waypoint - // but with some randomness so it can try out different paths - if(this.aistatus & AI_STATUS_OUT_JUMPPAD) + if(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT) { - if(fabs(this.velocity.z)<50) + this.aistatus |= AI_STATUS_OUT_JUMPPAD; + navigation_poptouchedgoals(this); + return; + } + else if(this.aistatus & AI_STATUS_OUT_JUMPPAD) + { + // If got stuck on the jump pad try to reach the farthest visible waypoint + // but with some randomness so it can try out different paths + if(!this.goalcurrent) { entity newgoal = NULL; - if (vdist(this.origin - this.goalcurrent.origin, <, 150)) - this.aistatus &= ~AI_STATUS_OUT_JUMPPAD; - else IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 1000), + IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 1000), { + if(it.wpflags & WAYPOINTFLAG_TELEPORT) + if(it.origin.z < this.origin.z - 100 && vdist(vec2(it.origin - this.origin), <, 100)) + continue; + traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this); if(trace_fraction < 1) @@ -539,11 +563,22 @@ void havocbot_movetogoal(entity this) } } else - return; + { + gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5; + if (this.origin.z > gco.z && vdist(vec2(this.velocity), <, autocvar_sv_maxspeed)) + this.aistatus &= ~AI_STATUS_OUT_JUMPPAD; + else if(havocbot_checkgoaldistance(this, gco)) + { + navigation_clearroute(this); + this.bot_strategytime = 0; + } + else + return; + } } else { - if(time - this.lastteleporttime > 0.3 && this.velocity.z > 0) + if(time - this.lastteleporttime > 0.2 && this.velocity.z > 0) { vector velxy = this.velocity; velxy_z = 0; if(vdist(velxy, <, autocvar_sv_maxspeed * 0.2)) @@ -716,12 +751,13 @@ void havocbot_movetogoal(entity this) if(autocvar_bot_debug_goalstack) debuggoalstack(this); - m1 = this.goalcurrent.origin + this.goalcurrent.mins; - m2 = this.goalcurrent.origin + this.goalcurrent.maxs; - destorg = this.origin; - destorg.x = bound(m1_x, destorg.x, m2_x); - destorg.y = bound(m1_y, destorg.y, m2_y); - destorg.z = bound(m1_z, destorg.z, m2_z); + SET_DESTCOORDS(this.goalcurrent, this.origin, destorg); + + // in case bot ends up inside the teleport waypoint without touching + // the teleport itself, head to the teleport origin + if(destorg == this.origin) + destorg = this.goalcurrent.origin; + diff = destorg - this.origin; //dist = vlen(diff); dir = normalize(diff); @@ -731,8 +767,8 @@ void havocbot_movetogoal(entity this) //if (this.bot_dodgevector_time < time) { - // this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval"); - // this.bot_dodgevector_jumpbutton = 1; + //this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval"); + //this.bot_dodgevector_jumpbutton = 1; evadeobstacle = '0 0 0'; evadelava = '0 0 0'; @@ -742,18 +778,18 @@ void havocbot_movetogoal(entity this) { if(this.waterlevel>WATERLEVEL_SWIMMING) { - // flatdir_z = 1; + //flatdir_z = 1; this.aistatus |= AI_STATUS_OUT_WATER; } else { + dir = flatdir; if(this.velocity.z >= 0 && !(this.watertype == CONTENT_WATER && gco.z < this.origin.z) && ( !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER) || this.aistatus & AI_STATUS_OUT_WATER)) PHYS_INPUT_BUTTON_JUMP(this) = true; else PHYS_INPUT_BUTTON_JUMP(this) = false; } - dir = normalize(flatdir); } else { @@ -782,33 +818,12 @@ void havocbot_movetogoal(entity this) } // if bot for some reason doesn't get close to the current goal find another one - if(!IS_PLAYER(this.goalcurrent) && !(this.goalcurrent.bot_pickup_respawning && this.goalcurrent_distance < 50)) + if(!this.jumppadcount && !IS_PLAYER(this.goalcurrent) && !(this.goalcurrent.bot_pickup_respawning && this.goalcurrent_distance < 50)) + if(havocbot_checkgoaldistance(this, gco)) { - float curr_dist = vlen(this.origin - this.goalcurrent.origin); - if(this.goalcurrent != this.goalcurrent_prev) - { - this.goalcurrent_prev = this.goalcurrent; - this.goalcurrent_distance = curr_dist; - this.goalcurrent_distance_time = 0; - } - else if(curr_dist > this.goalcurrent_distance) - { - if(!this.goalcurrent_distance_time) - this.goalcurrent_distance_time = time; - else if (time - this.goalcurrent_distance_time > 0.5) - { - this.goalcurrent_prev = NULL; - navigation_clearroute(this); - this.bot_strategytime = 0; - return; - } - } - else - { - // reduce it a little bit so it works even with very small approaches to the goal - this.goalcurrent_distance = max(20, curr_dist - 15); - this.goalcurrent_distance_time = 0; - } + navigation_clearroute(this); + this.bot_strategytime = 0; + return; } // Check for water/slime/lava and dangerous edges @@ -1263,7 +1278,9 @@ float havocbot_moveto(entity this, vector pos) debuggoalstack(this); // Heading - vector dir = ( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ) - (this.origin + this.view_ofs); + vector dir; + SET_DESTCOORDS(this.goalcurrent, this.origin, dir); + dir = dir - (this.origin + this.view_ofs); dir.z = 0; bot_aimdir(this, dir, -1);