Merge branch 'master' into terencehill/bot_waypoints
authorterencehill <piuntn@gmail.com>
Sat, 23 Dec 2017 17:51:09 +0000 (18:51 +0100)
committerterencehill <piuntn@gmail.com>
Sat, 23 Dec 2017 17:51:09 +0000 (18:51 +0100)
# Conflicts:
# qcsrc/common/triggers/trigger/jumppads.qc
# qcsrc/common/triggers/trigger/jumppads.qh

1  2 
qcsrc/common/triggers/trigger/jumppads.qc
qcsrc/common/triggers/trigger/jumppads.qh
qcsrc/server/bot/default/bot.qc

index 999a615cb7c9ac9b835cc275482720e06cbd76ac,4316a0edf356124837c3586928de62e2b6dc4492..d10a1e33037d69ae81b22943c8ab26ed8e5ffe63
@@@ -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
                        // 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
                        // 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 != "")
        {
                        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)
  {
        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.velocity = trigger_push_calculatevelocity(org, t, this.height);
 +                      e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
 -                      tracetoss(e, e);
 -                      if(e.move_movetype == MOVETYPE_NONE)
 -                              waypoint_spawnforteleporter(this, trace_endpos, vlen(trace_endpos - org) / vlen(e.velocity));
+                       e.velocity = trigger_push_calculatevelocity(org, t, this.height, e);
-                               e.velocity = trigger_push_calculatevelocity(new_org, t, this.height);
 +                      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);
 +                              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
                }
        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);
        }
  
index a1260c4e5382fc2d5decb130a34e980bb38ac82f,8615bc66d6a06e4137d102580d3bd5db0fc44f1d..c3b0b339def6c2f0f7b8e5c35f6773c91bcb4aea
@@@ -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);
          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);
  
index f599124db7bbb091e73b94bcbebc7cdfc4a0dbbc,6ea375c0879b19ec945269deb93518e496b4c216..20af7e71984dfdac24a5895ec91b7bf128f03b8b
@@@ -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);
  
                botframe_spawnedwaypoints = true;
                waypoint_loadall();
                if(!waypoint_load_links())
 -                      waypoint_schedulerelinkall();
 +                      waypoint_schedulerelinkall(); // link all the autogenerated waypoints (teleporters)
        }
  
        if (bot_list)