Beispiel #1
0
  /** Turns to the movement direction, and walks the current distance if facing it. */
  public static boolean SV_StepDirection(edict_t ent, float yaw, float dist) {
    float[] move = {0, 0, 0};
    float[] oldorigin = {0, 0, 0};
    float delta;

    ent.ideal_yaw = yaw;
    M.M_ChangeYaw(ent);

    yaw = (float) (yaw * Math.PI * 2 / 360);
    move[0] = (float) Math.cos(yaw) * dist;
    move[1] = (float) Math.sin(yaw) * dist;
    move[2] = 0;

    Math3D.VectorCopy(ent.s.origin, oldorigin);
    if (SV_movestep(ent, move, false)) {
      delta = ent.s.angles[Defines.YAW] - ent.ideal_yaw;
      if (delta > 45 && delta < 315) { // not turned far enough, so don't
        // take the step
        Math3D.VectorCopy(oldorigin, ent.s.origin);
      }
      GameBase.gi.linkentity(ent);
      GameBase.G_TouchTriggers(ent);
      return true;
    }
    GameBase.gi.linkentity(ent);
    GameBase.G_TouchTriggers(ent);
    return false;
  }
Beispiel #2
0
  /** R_SetupFrame */
  void R_SetupFrame() {
    r_framecount++;

    //	build the transformation matrix for the given view angles
    Math3D.VectorCopy(r_newrefdef.vieworg, r_origin);

    Math3D.AngleVectors(r_newrefdef.viewangles, vpn, vright, vup);

    //	current viewcluster
    mleaf_t leaf;
    if ((r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) == 0) {
      r_oldviewcluster = r_viewcluster;
      r_oldviewcluster2 = r_viewcluster2;
      leaf = Mod_PointInLeaf(r_origin, r_worldmodel);
      r_viewcluster = r_viewcluster2 = leaf.cluster;

      // check above and below so crossing solid water doesn't draw wrong
      if (leaf.contents == 0) { // look down a bit
        Math3D.VectorCopy(r_origin, temp);
        temp[2] -= 16;
        leaf = Mod_PointInLeaf(temp, r_worldmodel);
        if ((leaf.contents & Defines.CONTENTS_SOLID) == 0 && (leaf.cluster != r_viewcluster2))
          r_viewcluster2 = leaf.cluster;
      } else { // look up a bit
        Math3D.VectorCopy(r_origin, temp);
        temp[2] += 16;
        leaf = Mod_PointInLeaf(temp, r_worldmodel);
        if ((leaf.contents & Defines.CONTENTS_SOLID) == 0 && (leaf.cluster != r_viewcluster2))
          r_viewcluster2 = leaf.cluster;
      }
    }

    for (int i = 0; i < 4; i++) v_blend[i] = r_newrefdef.blend[i];

    c_brush_polys = 0;
    c_alias_polys = 0;

    // clear out the portion of the screen that the NOWORLDMODEL defines
    if ((r_newrefdef.rdflags & Defines.RDF_NOWORLDMODEL) != 0) {
      GL11.glEnable(GL11.GL_SCISSOR_TEST);
      GL11.glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
      GL11.glScissor(
          r_newrefdef.x,
          vid.height - r_newrefdef.height - r_newrefdef.y,
          r_newrefdef.width,
          r_newrefdef.height);
      GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
      GL11.glClearColor(1.0f, 0.0f, 0.5f, 0.5f);
      GL11.glDisable(GL11.GL_SCISSOR_TEST);
    }
  }
Beispiel #3
0
  /** Does not change the entities velocity at all */
  public static trace_t SV_PushEntity(edict_t ent, float[] push) {
    trace_t trace;
    float[] start = {0, 0, 0};
    float[] end = {0, 0, 0};
    int mask;

    Math3D.VectorCopy(ent.s.origin, start);
    Math3D.VectorAdd(start, push, end);

    // FIXME: test this
    // a goto statement was replaced.
    boolean retry = false;

    do {
      if (ent.clipmask != 0) mask = ent.clipmask;
      else mask = Defines.MASK_SOLID;

      trace = GameBase.gi.trace(start, ent.mins, ent.maxs, end, ent, mask);

      Math3D.VectorCopy(trace.endpos, ent.s.origin);
      GameBase.gi.linkentity(ent);

      retry = false;
      if (trace.fraction != 1.0) {
        SV_Impact(ent, trace);

        // if the pushed entity went away and the pusher is still there
        if (!trace.ent.inuse && ent.inuse) {
          // move the pusher back and try again
          Math3D.VectorCopy(start, ent.s.origin);
          GameBase.gi.linkentity(ent);
          // goto retry;
          retry = true;
        }
      }
    } while (retry);

    if (ent.inuse) GameBase.G_TouchTriggers(ent);

    return trace;
  }
Beispiel #4
0
  // FIXME: since we need to test end position contents here, can we avoid
  // doing it again later in catagorize position?
  public static boolean SV_movestep(edict_t ent, float[] move, boolean relink) {
    float dz;
    float[] oldorg = {0, 0, 0};
    float[] neworg = {0, 0, 0};
    float[] end = {0, 0, 0};

    trace_t trace = null; // = new trace_t();
    int i;
    float stepsize;
    float[] test = {0, 0, 0};
    int contents;

    //	   try the move
    Math3D.VectorCopy(ent.s.origin, oldorg);
    Math3D.VectorAdd(ent.s.origin, move, neworg);

    //	   flying monsters don't step up
    if ((ent.flags & (Defines.FL_SWIM | Defines.FL_FLY)) != 0) {
      // try one move with vertical motion, then one without
      for (i = 0; i < 2; i++) {
        Math3D.VectorAdd(ent.s.origin, move, neworg);
        if (i == 0 && ent.enemy != null) {
          if (ent.goalentity == null) ent.goalentity = ent.enemy;
          dz = ent.s.origin[2] - ent.goalentity.s.origin[2];
          if (ent.goalentity.client != null) {
            if (dz > 40) neworg[2] -= 8;
            if (!((ent.flags & Defines.FL_SWIM) != 0 && (ent.waterlevel < 2)))
              if (dz < 30) neworg[2] += 8;
          } else {
            if (dz > 8) neworg[2] -= 8;
            else if (dz > 0) neworg[2] -= dz;
            else if (dz < -8) neworg[2] += 8;
            else neworg[2] += dz;
          }
        }
        trace =
            GameBase.gi.trace(
                ent.s.origin, ent.mins, ent.maxs, neworg, ent, Defines.MASK_MONSTERSOLID);

        // fly monsters don't enter water voluntarily
        if ((ent.flags & Defines.FL_FLY) != 0) {
          if (ent.waterlevel == 0) {
            test[0] = trace.endpos[0];
            test[1] = trace.endpos[1];
            test[2] = trace.endpos[2] + ent.mins[2] + 1;
            contents = GameBase.gi.pointcontents.pointcontents(test);
            if ((contents & Defines.MASK_WATER) != 0) return false;
          }
        }

        // swim monsters don't exit water voluntarily
        if ((ent.flags & Defines.FL_SWIM) != 0) {
          if (ent.waterlevel < 2) {
            test[0] = trace.endpos[0];
            test[1] = trace.endpos[1];
            test[2] = trace.endpos[2] + ent.mins[2] + 1;
            contents = GameBase.gi.pointcontents.pointcontents(test);
            if ((contents & Defines.MASK_WATER) == 0) return false;
          }
        }

        if (trace.fraction == 1) {
          Math3D.VectorCopy(trace.endpos, ent.s.origin);
          if (relink) {
            GameBase.gi.linkentity(ent);
            GameBase.G_TouchTriggers(ent);
          }
          return true;
        }

        if (ent.enemy == null) break;
      }

      return false;
    }

    //	   push down from a step height above the wished position
    if ((ent.monsterinfo.aiflags & Defines.AI_NOSTEP) == 0) stepsize = GameBase.STEPSIZE;
    else stepsize = 1;

    neworg[2] += stepsize;
    Math3D.VectorCopy(neworg, end);
    end[2] -= stepsize * 2;

    trace = GameBase.gi.trace(neworg, ent.mins, ent.maxs, end, ent, Defines.MASK_MONSTERSOLID);

    if (trace.allsolid) return false;

    if (trace.startsolid) {
      neworg[2] -= stepsize;
      trace = GameBase.gi.trace(neworg, ent.mins, ent.maxs, end, ent, Defines.MASK_MONSTERSOLID);
      if (trace.allsolid || trace.startsolid) return false;
    }

    // don't go in to water
    if (ent.waterlevel == 0) {
      test[0] = trace.endpos[0];
      test[1] = trace.endpos[1];
      test[2] = trace.endpos[2] + ent.mins[2] + 1;
      contents = GameBase.gi.pointcontents.pointcontents(test);

      if ((contents & Defines.MASK_WATER) != 0) return false;
    }

    if (trace.fraction == 1) {
      // if monster had the ground pulled out, go ahead and fall
      if ((ent.flags & Defines.FL_PARTIALGROUND) != 0) {
        Math3D.VectorAdd(ent.s.origin, move, ent.s.origin);
        if (relink) {
          GameBase.gi.linkentity(ent);
          GameBase.G_TouchTriggers(ent);
        }
        ent.groundentity = null;
        return true;
      }

      return false; // walked off an edge
    }

    //	   check point traces down for dangling corners
    Math3D.VectorCopy(trace.endpos, ent.s.origin);

    if (!M.M_CheckBottom(ent)) {
      if ((ent.flags & Defines.FL_PARTIALGROUND) != 0) {
        // entity had floor mostly pulled out from underneath it
        // and is trying to correct
        if (relink) {
          GameBase.gi.linkentity(ent);
          GameBase.G_TouchTriggers(ent);
        }
        return true;
      }
      Math3D.VectorCopy(oldorg, ent.s.origin);
      return false;
    }

    if ((ent.flags & Defines.FL_PARTIALGROUND) != 0) {
      ent.flags &= ~Defines.FL_PARTIALGROUND;
    }
    ent.groundentity = trace.ent;
    ent.groundentity_linkcount = trace.ent.linkcount;

    //	   the move is ok
    if (relink) {
      GameBase.gi.linkentity(ent);
      GameBase.G_TouchTriggers(ent);
    }
    return true;
  }
Beispiel #5
0
  /** Toss, bounce, and fly movement. When onground, do nothing. */
  public static void SV_Physics_Toss(edict_t ent) {

    trace_t trace;
    float[] move = {0, 0, 0};
    float backoff;
    edict_t slave;
    boolean wasinwater;
    boolean isinwater;
    float[] old_origin = {0, 0, 0};

    //	   regular thinking
    SV_RunThink(ent);

    // if not a team captain, so movement will be handled elsewhere
    if ((ent.flags & Defines.FL_TEAMSLAVE) != 0) return;

    if (ent.velocity[2] > 0) ent.groundentity = null;

    //	check for the groundentity going away
    if (ent.groundentity != null) if (!ent.groundentity.inuse) ent.groundentity = null;

    //	   if onground, return without moving
    if (ent.groundentity != null) return;

    Math3D.VectorCopy(ent.s.origin, old_origin);

    SV_CheckVelocity(ent);

    //	   add gravity
    if (ent.movetype != Defines.MOVETYPE_FLY && ent.movetype != Defines.MOVETYPE_FLYMISSILE)
      SV_AddGravity(ent);

    //	   move angles
    Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles);

    //	   move origin
    Math3D.VectorScale(ent.velocity, Defines.FRAMETIME, move);
    trace = SV_PushEntity(ent, move);
    if (!ent.inuse) return;

    if (trace.fraction < 1) {
      if (ent.movetype == Defines.MOVETYPE_BOUNCE) backoff = 1.5f;
      else backoff = 1;

      GameBase.ClipVelocity(ent.velocity, trace.plane.normal, ent.velocity, backoff);

      // stop if on ground
      if (trace.plane.normal[2] > 0.7) {
        if (ent.velocity[2] < 60 || ent.movetype != Defines.MOVETYPE_BOUNCE) {
          ent.groundentity = trace.ent;
          ent.groundentity_linkcount = trace.ent.linkcount;
          Math3D.VectorCopy(Globals.vec3_origin, ent.velocity);
          Math3D.VectorCopy(Globals.vec3_origin, ent.avelocity);
        }
      }

      // if (ent.touch)
      //	ent.touch (ent, trace.ent, &trace.plane, trace.surface);
    }

    //	   check for water transition
    wasinwater = (ent.watertype & Defines.MASK_WATER) != 0;
    ent.watertype = GameBase.gi.pointcontents.pointcontents(ent.s.origin);
    isinwater = (ent.watertype & Defines.MASK_WATER) != 0;

    if (isinwater) ent.waterlevel = 1;
    else ent.waterlevel = 0;

    if (!wasinwater && isinwater)
      GameBase.gi.positioned_sound(
          old_origin, ent, Defines.CHAN_AUTO, GameBase.gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
    else if (wasinwater && !isinwater)
      GameBase.gi.positioned_sound(
          ent.s.origin,
          ent,
          Defines.CHAN_AUTO,
          GameBase.gi.soundindex("misc/h2ohit1.wav"),
          1,
          1,
          0);

    //	   move teamslaves
    for (slave = ent.teamchain; slave != null; slave = slave.teamchain) {
      Math3D.VectorCopy(ent.s.origin, slave.s.origin);
      GameBase.gi.linkentity(slave);
    }
  }
Beispiel #6
0
  /** Objects need to be moved back on a failed push, otherwise riders would continue to slide. */
  public static boolean SV_Push(edict_t pusher, float[] move, float[] amove) {
    int i, e;
    edict_t check, block[];
    float[] mins = {0, 0, 0};
    float[] maxs = {0, 0, 0};
    pushed_t p;
    float[] org = {0, 0, 0};
    float[] org2 = {0, 0, 0};
    float[] move2 = {0, 0, 0};
    float[] forward = {0, 0, 0};
    float[] right = {0, 0, 0};
    float[] up = {0, 0, 0};

    // clamp the move to 1/8 units, so the position will
    // be accurate for client side prediction
    for (i = 0; i < 3; i++) {
      float temp;
      temp = move[i] * 8.0f;
      if (temp > 0.0) temp += 0.5;
      else temp -= 0.5;
      move[i] = 0.125f * (int) temp;
    }

    // find the bounding box
    for (i = 0; i < 3; i++) {
      mins[i] = pusher.absmin[i] + move[i];
      maxs[i] = pusher.absmax[i] + move[i];
    }

    //	   we need this for pushing things later
    Math3D.VectorSubtract(Globals.vec3_origin, amove, org);
    Math3D.AngleVectors(org, forward, right, up);

    //	   save the pusher's original position
    GameBase.pushed[GameBase.pushed_p].ent = pusher;
    Math3D.VectorCopy(pusher.s.origin, GameBase.pushed[GameBase.pushed_p].origin);
    Math3D.VectorCopy(pusher.s.angles, GameBase.pushed[GameBase.pushed_p].angles);

    if (pusher.client != null)
      GameBase.pushed[GameBase.pushed_p].deltayaw =
          pusher.client.ps.pmove.delta_angles[Defines.YAW];

    GameBase.pushed_p++;

    //	   move the pusher to it's final position
    Math3D.VectorAdd(pusher.s.origin, move, pusher.s.origin);
    Math3D.VectorAdd(pusher.s.angles, amove, pusher.s.angles);
    GameBase.gi.linkentity(pusher);

    //	   see if any solid entities are inside the final position

    // check= g_edicts + 1;
    for (e = 1; e < GameBase.num_edicts; e++) {
      check = GameBase.g_edicts[e];
      if (!check.inuse) continue;
      if (check.movetype == Defines.MOVETYPE_PUSH
          || check.movetype == Defines.MOVETYPE_STOP
          || check.movetype == Defines.MOVETYPE_NONE
          || check.movetype == Defines.MOVETYPE_NOCLIP) continue;

      if (check.area.prev == null) continue; // not linked in anywhere

      // if the entity is standing on the pusher, it will definitely be
      // moved
      if (check.groundentity != pusher) {
        // see if the ent needs to be tested
        if (check.absmin[0] >= maxs[0]
            || check.absmin[1] >= maxs[1]
            || check.absmin[2] >= maxs[2]
            || check.absmax[0] <= mins[0]
            || check.absmax[1] <= mins[1]
            || check.absmax[2] <= mins[2]) continue;

        // see if the ent's bbox is inside the pusher's final position
        if (SV_TestEntityPosition(check) == null) continue;
      }

      if ((pusher.movetype == Defines.MOVETYPE_PUSH) || (check.groundentity == pusher)) {
        // move this entity
        GameBase.pushed[GameBase.pushed_p].ent = check;
        Math3D.VectorCopy(check.s.origin, GameBase.pushed[GameBase.pushed_p].origin);
        Math3D.VectorCopy(check.s.angles, GameBase.pushed[GameBase.pushed_p].angles);
        GameBase.pushed_p++;

        // try moving the contacted entity
        Math3D.VectorAdd(check.s.origin, move, check.s.origin);
        if (check.client != null) { // FIXME: doesn't rotate monsters?
          check.client.ps.pmove.delta_angles[Defines.YAW] += amove[Defines.YAW];
        }

        // figure movement due to the pusher's amove
        Math3D.VectorSubtract(check.s.origin, pusher.s.origin, org);
        org2[0] = Math3D.DotProduct(org, forward);
        org2[1] = -Math3D.DotProduct(org, right);
        org2[2] = Math3D.DotProduct(org, up);
        Math3D.VectorSubtract(org2, org, move2);
        Math3D.VectorAdd(check.s.origin, move2, check.s.origin);

        // may have pushed them off an edge
        if (check.groundentity != pusher) check.groundentity = null;

        block = SV_TestEntityPosition(check);
        if (block == null) { // pushed ok
          GameBase.gi.linkentity(check);
          // impact?
          continue;
        }

        // if it is ok to leave in the old position, do it
        // this is only relevent for riding entities, not pushed
        // FIXME: this doesn't acount for rotation
        Math3D.VectorSubtract(check.s.origin, move, check.s.origin);
        block = SV_TestEntityPosition(check);

        if (block == null) {
          GameBase.pushed_p--;
          continue;
        }
      }

      // save off the obstacle so we can call the block function
      GameBase.obstacle = check;

      // move back any entities we already moved
      // go backwards, so if the same entity was pushed
      // twice, it goes back to the original position
      for (int ip = GameBase.pushed_p - 1; ip >= 0; ip--) {
        p = GameBase.pushed[ip];
        Math3D.VectorCopy(p.origin, p.ent.s.origin);
        Math3D.VectorCopy(p.angles, p.ent.s.angles);
        if (p.ent.client != null) {
          p.ent.client.ps.pmove.delta_angles[Defines.YAW] = (short) p.deltayaw;
        }
        GameBase.gi.linkentity(p.ent);
      }
      return false;
    }

    //	  FIXME: is there a better way to handle this?
    // see if anything we moved has touched a trigger
    for (int ip = GameBase.pushed_p - 1; ip >= 0; ip--)
      GameBase.G_TouchTriggers(GameBase.pushed[ip].ent);

    return true;
  }
Beispiel #7
0
  public static int SV_FlyMove(edict_t ent, float time, int mask) {
    edict_t hit;
    int bumpcount, numbumps;
    float[] dir = {0.0f, 0.0f, 0.0f};
    float d;
    int numplanes;
    float[][] planes = new float[MAX_CLIP_PLANES][3];
    float[] primal_velocity = {0.0f, 0.0f, 0.0f};
    float[] original_velocity = {0.0f, 0.0f, 0.0f};
    float[] new_velocity = {0.0f, 0.0f, 0.0f};
    int i, j;
    trace_t trace;
    float[] end = {0.0f, 0.0f, 0.0f};
    float time_left;
    int blocked;

    numbumps = 4;

    blocked = 0;
    Math3D.VectorCopy(ent.velocity, original_velocity);
    Math3D.VectorCopy(ent.velocity, primal_velocity);
    numplanes = 0;

    time_left = time;

    ent.groundentity = null;
    for (bumpcount = 0; bumpcount < numbumps; bumpcount++) {
      for (i = 0; i < 3; i++) end[i] = ent.s.origin[i] + time_left * ent.velocity[i];

      trace = GameBase.gi.trace(ent.s.origin, ent.mins, ent.maxs, end, ent, mask);

      if (trace.allsolid) { // entity is trapped in another solid
        Math3D.VectorCopy(Globals.vec3_origin, ent.velocity);
        return 3;
      }

      if (trace.fraction > 0) { // actually covered some distance
        Math3D.VectorCopy(trace.endpos, ent.s.origin);
        Math3D.VectorCopy(ent.velocity, original_velocity);
        numplanes = 0;
      }

      if (trace.fraction == 1) break; // moved the entire distance

      hit = trace.ent;

      if (trace.plane.normal[2] > 0.7) {
        blocked |= 1; // floor
        if (hit.solid == Defines.SOLID_BSP) {
          ent.groundentity = hit;
          ent.groundentity_linkcount = hit.linkcount;
        }
      }
      if (trace.plane.normal[2] == 0.0f) {
        blocked |= 2; // step
      }

      //
      //	   run the impact function
      //
      SV_Impact(ent, trace);
      if (!ent.inuse) break; // removed by the impact function

      time_left -= time_left * trace.fraction;

      // cliped to another plane
      if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't
        // really happen
        Math3D.VectorCopy(Globals.vec3_origin, ent.velocity);
        return 3;
      }

      Math3D.VectorCopy(trace.plane.normal, planes[numplanes]);
      numplanes++;

      //
      //	   modify original_velocity so it parallels all of the clip planes
      //
      for (i = 0; i < numplanes; i++) {
        GameBase.ClipVelocity(original_velocity, planes[i], new_velocity, 1);

        for (j = 0; j < numplanes; j++)
          if ((j != i) && !Math3D.VectorEquals(planes[i], planes[j])) {
            if (Math3D.DotProduct(new_velocity, planes[j]) < 0) break; // not ok
          }
        if (j == numplanes) break;
      }

      if (i != numplanes) { // go along this plane
        Math3D.VectorCopy(new_velocity, ent.velocity);
      } else { // go along the crease
        if (numplanes != 2) {
          //					gi.dprintf ("clip velocity, numplanes ==
          // %i\n",numplanes);
          Math3D.VectorCopy(Globals.vec3_origin, ent.velocity);
          return 7;
        }
        Math3D.CrossProduct(planes[0], planes[1], dir);
        d = Math3D.DotProduct(dir, ent.velocity);
        Math3D.VectorScale(dir, d, ent.velocity);
      }

      //
      //	   if original velocity is against the original velocity, stop dead
      //	   to avoid tiny occilations in sloping corners
      //
      if (Math3D.DotProduct(ent.velocity, primal_velocity) <= 0) {
        Math3D.VectorCopy(Globals.vec3_origin, ent.velocity);
        return blocked;
      }
    }

    return blocked;
  }