From: terencehill Date: Sat, 23 Dec 2017 17:51:09 +0000 (+0100) Subject: Merge branch 'master' into terencehill/bot_waypoints X-Git-Tag: xonotic-v0.8.5~2378^2~7^2 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=99f5aae787d0e46852e2340594c5cb4805c0f3f3;hp=-c Merge branch 'master' into terencehill/bot_waypoints # Conflicts: # qcsrc/common/triggers/trigger/jumppads.qc # qcsrc/common/triggers/trigger/jumppads.qh --- 99f5aae787d0e46852e2340594c5cb4805c0f3f3 diff --combined qcsrc/common/triggers/trigger/jumppads.qc index 999a615cb7,4316a0edf3..d10a1e3303 --- a/qcsrc/common/triggers/trigger/jumppads.qc +++ b/qcsrc/common/triggers/trigger/jumppads.qc @@@ -25,19 -25,23 +25,20 @@@ REGISTER_NET_LINKED(ENT_CLIENT_TARGET_P tgt - target entity (can be either a point or a model entity; if it is the latter, its midpoint is used) ht - jump height, measured from the higher one of org and tgt's midpoint + pushed_entity - object that is to be pushed Returns: velocity for the jump - the global trigger_push_calculatevelocity_flighttime is set to the total - jump time */ - vector trigger_push_calculatevelocity(vector org, entity tgt, float ht) - + vector trigger_push_calculatevelocity(vector org, entity tgt, float ht, entity pushed_entity) { float grav, sdist, zdist, vs, vz, jumpheight; vector sdir, torg; torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5; - grav = PHYS_GRAVITY(tgt); - if(PHYS_ENTGRAVITY(tgt)) - grav *= PHYS_ENTGRAVITY(tgt); + grav = PHYS_GRAVITY(NULL); + if(pushed_entity && PHYS_ENTGRAVITY(pushed_entity)) + grav *= PHYS_ENTGRAVITY(pushed_entity); zdist = torg.z - org.z; sdist = vlen(torg - org - zdist * '0 0 1'); @@@ -85,7 -89,6 +86,7 @@@ if(zdist == 0) solution_x = solution.y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually) + float flighttime; if(zdist < 0) { // down-jump @@@ -94,14 -97,14 +95,14 @@@ // almost straight line type // jump apex is before the jump // we must take the larger one - trigger_push_calculatevelocity_flighttime = solution.y; + flighttime = solution.y; } else { // regular jump // jump apex is during the jump // we must take the larger one too - trigger_push_calculatevelocity_flighttime = solution.y; + flighttime = solution.y; } } else @@@ -112,17 -115,17 +113,17 @@@ // almost straight line type // jump apex is after the jump // we must take the smaller one - trigger_push_calculatevelocity_flighttime = solution.x; + flighttime = solution.x; } else { // regular jump // jump apex is during the jump // we must take the larger one - trigger_push_calculatevelocity_flighttime = solution.y; + flighttime = solution.y; } } - vs = sdist / trigger_push_calculatevelocity_flighttime; + vs = sdist / flighttime; // finally calculate the velocity return sdir * vs + '0 0 1' * vz; @@@ -135,7 -138,7 +136,7 @@@ bool jumppad_push(entity this, entity t if(this.enemy) { - targ.velocity = trigger_push_calculatevelocity(targ.origin, this.enemy, this.height); + targ.velocity = trigger_push_calculatevelocity(targ.origin, this.enemy, this.height, targ); } else if(this.target && this.target != "") { @@@ -148,7 -151,7 +149,7 @@@ else RandomSelection_AddEnt(e, 1, 1); } - targ.velocity = trigger_push_calculatevelocity(targ.origin, RandomSelection_chosen_ent, this.height); + targ.velocity = trigger_push_calculatevelocity(targ.origin, RandomSelection_chosen_ent, this.height, targ); } else { @@@ -270,37 -273,6 +271,37 @@@ void trigger_push_touch(entity this, en #ifdef SVQC void trigger_push_link(entity this); void trigger_push_updatelink(entity this); +bool trigger_push_testorigin(entity tracetest_ent, entity targ, entity jp, vector org) +{ + setorigin(tracetest_ent, org); + tracetoss(tracetest_ent, tracetest_ent); + if(trace_startsolid) + return false; + + if(!jp.height) + { + // since tracetoss starting from jumppad's origin often fails when target + // is very close to real destination, start it directly from target's + // origin instead + tracetest_ent.velocity.z = 0; + setorigin(tracetest_ent, targ.origin + stepheightvec); + tracetoss(tracetest_ent, tracetest_ent); + if(trace_startsolid) + { + setorigin(tracetest_ent, targ.origin + stepheightvec / 2); + tracetoss(tracetest_ent, tracetest_ent); + if(trace_startsolid) + { + setorigin(tracetest_ent, targ.origin); + tracetoss(tracetest_ent, tracetest_ent); + if(trace_startsolid) + return false; + } + } + } + tracebox(trace_endpos, tracetest_ent.mins, tracetest_ent.maxs, trace_endpos - eZ * 1500, true, tracetest_ent); + return true; +} #endif void trigger_push_findtarget(entity this) { @@@ -311,80 -283,17 +312,80 @@@ if (this.target) { int n = 0; +#ifdef SVQC + vector vel = '0 0 0'; +#endif for(entity t = NULL; (t = find(t, targetname, this.target)); ) { ++n; #ifdef SVQC + if(t.move_movetype != MOVETYPE_NONE) + continue; + entity e = spawn(); - setorigin(e, org); setsize(e, PL_MIN_CONST, PL_MAX_CONST); + e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; - e.velocity = trigger_push_calculatevelocity(org, t, this.height); + e.velocity = trigger_push_calculatevelocity(org, t, this.height, e); - tracetoss(e, e); - if(e.move_movetype == MOVETYPE_NONE) - waypoint_spawnforteleporter(this, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity)); + vel = e.velocity; + vector best_target = '0 0 0'; + vector best_org = '0 0 0'; + vector best_vel = '0 0 0'; + bool valid_best_target = false; + if (trigger_push_testorigin(e, t, this, org)) + { + best_target = trace_endpos; + best_org = org; + best_vel = e.velocity; + valid_best_target = true; + } + + vector new_org; + vector dist = t.origin - org; + if (dist.x || dist.y) // if not perfectly vertical + { + // test trajectory with different starting points, sometimes the trajectory + // starting from the jumppad origin can't reach the real destination + // and destination waypoint ends up near the jumppad itself + vector flatdir = normalize(dist - eZ * dist.z); + vector ofs = flatdir * 0.5 * min(fabs(this.absmax.x - this.absmin.x), fabs(this.absmax.y - this.absmin.y)); + new_org = org + ofs; - e.velocity = trigger_push_calculatevelocity(new_org, t, this.height); ++ e.velocity = trigger_push_calculatevelocity(new_org, t, this.height, e); + vel = e.velocity; + if (vdist(vec2(e.velocity), <, autocvar_sv_maxspeed)) + e.velocity = autocvar_sv_maxspeed * flatdir; + if (trigger_push_testorigin(e, t, this, new_org) && (!valid_best_target || trace_endpos.z > best_target.z + 50)) + { + best_target = trace_endpos; + best_org = new_org; + best_vel = vel; + valid_best_target = true; + } + new_org = org - ofs; - e.velocity = trigger_push_calculatevelocity(new_org, t, this.height); ++ e.velocity = trigger_push_calculatevelocity(new_org, t, this.height, e); + vel = e.velocity; + if (vdist(vec2(e.velocity), <, autocvar_sv_maxspeed)) + e.velocity = autocvar_sv_maxspeed * flatdir; + if (trigger_push_testorigin(e, t, this, new_org) && (!valid_best_target || trace_endpos.z > best_target.z + 50)) + { + best_target = trace_endpos; + best_org = new_org; + best_vel = vel; + valid_best_target = true; + } + } + + if (valid_best_target) + { + if (!(boxesoverlap(this.absmin, this.absmax + eZ * 50, best_target + PL_MIN_CONST, best_target + PL_MAX_CONST))) + { + float velxy = vlen(vec2(best_vel)); + float cost = vlen(vec2(t.origin - best_org)) / velxy; + if(velxy < autocvar_sv_maxspeed) + velxy = autocvar_sv_maxspeed; + cost += vlen(vec2(best_target - t.origin)) / velxy; + waypoint_spawnforteleporter(this, best_target, cost, e); + } + } delete(e); #endif } @@@ -412,13 -321,11 +413,13 @@@ else { entity e = spawn(); - setorigin(e, org); setsize(e, PL_MIN_CONST, PL_MAX_CONST); + e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; + setorigin(e, org); e.velocity = this.movedir; tracetoss(e, e); - waypoint_spawnforteleporter(this, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity)); + if (!(boxesoverlap(this.absmin, this.absmax + eZ * 50, trace_endpos + PL_MIN_CONST, trace_endpos + PL_MAX_CONST))) + waypoint_spawnforteleporter(this, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity), e); delete(e); } diff --combined qcsrc/common/triggers/trigger/jumppads.qh index a1260c4e53,8615bc66d6..c3b0b339de --- a/qcsrc/common/triggers/trigger/jumppads.qh +++ b/qcsrc/common/triggers/trigger/jumppads.qh @@@ -11,6 -11,8 +11,6 @@@ const int NUM_JUMPPADSUSED = 3 .float jumppadcount; .entity jumppadsused[NUM_JUMPPADSUSED]; -float trigger_push_calculatevelocity_flighttime; - #ifdef SVQC void SUB_UseTargets(entity this, entity actor, entity trigger); void trigger_push_use(entity this, entity actor, entity trigger); @@@ -24,10 -26,14 +24,11 @@@ tgt - target entity (can be either a point or a model entity; if it is the latter, its midpoint is used) ht - jump height, measured from the higher one of org and tgt's midpoint + pushed_entity - object that is to be pushed Returns: velocity for the jump - the global trigger_push_calculatevelocity_flighttime is set to the total - jump time */ - vector trigger_push_calculatevelocity(vector org, entity tgt, float ht); - + vector trigger_push_calculatevelocity(vector org, entity tgt, float ht, entity pushed_entity); void trigger_push_touch(entity this, entity toucher); diff --combined qcsrc/server/bot/default/bot.qc index f599124db7,6ea375c087..20af7e7198 --- a/qcsrc/server/bot/default/bot.qc +++ b/qcsrc/server/bot/default/bot.qc @@@ -438,7 -438,7 +438,7 @@@ void bot_clientconnect(entity this else if(this.bot_forced_team==4) this.team = NUM_TEAM_4; else - JoinBestTeam(this, false, true); + JoinBestTeam(this, true); havocbot_setupbot(this); } @@@ -579,8 -579,9 +579,8 @@@ void autoskill(float factor void bot_calculate_stepheightvec() { stepheightvec = autocvar_sv_stepheight * '0 0 1'; - jumpstepheightvec = stepheightvec + - ((autocvar_sv_jumpvelocity * autocvar_sv_jumpvelocity) / (2 * autocvar_sv_gravity)) * '0 0 0.85'; - // 0.75 factor is for safety to make the jumps easy + jumpheight_vec = (autocvar_sv_jumpvelocity ** 2) / (2 * autocvar_sv_gravity) * '0 0 1'; + jumpstepheightvec = stepheightvec + jumpheight_vec * 0.85; // reduce it a bit to make the jumps easy } float bot_fixcount() @@@ -698,19 -699,6 +698,19 @@@ void bot_serverframe( return; } + if(autocvar_skill != skill) + { + float wpcost_update = false; + if(skill >= autocvar_bot_ai_bunnyhop_skilloffset && autocvar_skill < autocvar_bot_ai_bunnyhop_skilloffset) + wpcost_update = true; + if(skill < autocvar_bot_ai_bunnyhop_skilloffset && autocvar_skill >= autocvar_bot_ai_bunnyhop_skilloffset) + wpcost_update = true; + + skill = autocvar_skill; + if (wpcost_update) + waypoint_updatecost_foralllinks(); + } + bot_calculate_stepheightvec(); bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL); @@@ -760,7 -748,7 +760,7 @@@ botframe_spawnedwaypoints = true; waypoint_loadall(); if(!waypoint_load_links()) - waypoint_schedulerelinkall(); + waypoint_schedulerelinkall(); // link all the autogenerated waypoints (teleporters) } if (bot_list)