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
  /** A moving object that doesn't obey physics. */
  public static void SV_Physics_Noclip(edict_t ent) {
    //	   regular thinking
    if (!SV_RunThink(ent)) return;

    Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles);
    Math3D.VectorMA(ent.s.origin, Defines.FRAMETIME, ent.velocity, ent.s.origin);

    GameBase.gi.linkentity(ent);
  }
Beispiel #3
0
  /** GL_DrawParticles */
  void GL_DrawParticles(int num_particles) {
    float origin_x, origin_y, origin_z;

    Math3D.VectorScale(vup, 1.5f, up);
    Math3D.VectorScale(vright, 1.5f, right);

    GL_Bind(r_particletexture.texnum);
    GL11.glDepthMask(false); // no z buffering
    GL11.glEnable(GL11.GL_BLEND);
    GL_TexEnv(GL11.GL_MODULATE);

    GL11.glBegin(GL11.GL_TRIANGLES);

    FloatBuffer sourceVertices = particle_t.vertexArray;
    IntBuffer sourceColors = particle_t.colorArray;
    float scale;
    int color;
    for (int j = 0, i = 0; i < num_particles; i++) {
      origin_x = sourceVertices.get(j++);
      origin_y = sourceVertices.get(j++);
      origin_z = sourceVertices.get(j++);

      // hack a scale up to keep particles from disapearing
      scale =
          (origin_x - r_origin[0]) * vpn[0]
              + (origin_y - r_origin[1]) * vpn[1]
              + (origin_z - r_origin[2]) * vpn[2];

      scale = (scale < 20) ? 1 : 1 + scale * 0.004f;

      color = sourceColors.get(i);

      GL11.glColor4ub(
          (byte) ((color) & 0xFF),
          (byte) ((color >> 8) & 0xFF),
          (byte) ((color >> 16) & 0xFF),
          (byte) ((color >>> 24)));
      // first vertex
      GL11.glTexCoord2f(0.0625f, 0.0625f);
      GL11.glVertex3f(origin_x, origin_y, origin_z);
      // second vertex
      GL11.glTexCoord2f(1.0625f, 0.0625f);
      GL11.glVertex3f(origin_x + up[0] * scale, origin_y + up[1] * scale, origin_z + up[2] * scale);
      // third vertex
      GL11.glTexCoord2f(0.0625f, 1.0625f);
      GL11.glVertex3f(
          origin_x + right[0] * scale, origin_y + right[1] * scale, origin_z + right[2] * scale);
    }
    GL11.glEnd();

    GL11.glDisable(GL11.GL_BLEND);
    GL11.glColor4f(1, 1, 1, 1);
    GL11.glDepthMask(true); // back to normal Z buffering
    GL_TexEnv(GL11.GL_REPLACE);
  }
Beispiel #4
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 #5
0
  /** R_DrawSpriteModel */
  void R_DrawSpriteModel(entity_t e) {
    float alpha = 1.0F;

    qfiles.dsprframe_t frame;
    qfiles.dsprite_t psprite;

    // don't even bother culling, because it's just a single
    // polygon without a surface cache

    psprite = (qfiles.dsprite_t) currentmodel.extradata;

    e.frame %= psprite.numframes;

    frame = psprite.frames[e.frame];

    if ((e.flags & Defines.RF_TRANSLUCENT) != 0) alpha = e.alpha;

    if (alpha != 1.0F) GL11.glEnable(GL11.GL_BLEND);

    GL11.glColor4f(1, 1, 1, alpha);

    GL_Bind(currentmodel.skins[e.frame].texnum);

    GL_TexEnv(GL11.GL_MODULATE);

    if (alpha == 1.0) GL11.glEnable(GL11.GL_ALPHA_TEST);
    else GL11.glDisable(GL11.GL_ALPHA_TEST);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glTexCoord2f(0, 1);
    Math3D.VectorMA(e.origin, -frame.origin_y, vup, point);
    Math3D.VectorMA(point, -frame.origin_x, vright, point);
    GL11.glVertex3f(point[0], point[1], point[2]);

    GL11.glTexCoord2f(0, 0);
    Math3D.VectorMA(e.origin, frame.height - frame.origin_y, vup, point);
    Math3D.VectorMA(point, -frame.origin_x, vright, point);
    GL11.glVertex3f(point[0], point[1], point[2]);

    GL11.glTexCoord2f(1, 0);
    Math3D.VectorMA(e.origin, frame.height - frame.origin_y, vup, point);
    Math3D.VectorMA(point, frame.width - frame.origin_x, vright, point);
    GL11.glVertex3f(point[0], point[1], point[2]);

    GL11.glTexCoord2f(1, 1);
    Math3D.VectorMA(e.origin, -frame.origin_y, vup, point);
    Math3D.VectorMA(point, frame.width - frame.origin_x, vright, point);
    GL11.glVertex3f(point[0], point[1], point[2]);

    GL11.glEnd();

    GL11.glDisable(GL11.GL_ALPHA_TEST);
    GL_TexEnv(GL11.GL_REPLACE);

    if (alpha != 1.0F) GL11.glDisable(GL11.GL_BLEND);

    GL11.glColor4f(1, 1, 1, 1);
  }
Beispiel #6
0
  /** R_SetFrustum */
  void R_SetFrustum() {
    // rotate VPN right by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90f - r_newrefdef.fov_x / 2f));
    // rotate VPN left by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[1].normal, vup, vpn, 90f - r_newrefdef.fov_x / 2f);
    // rotate VPN up by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[2].normal, vright, vpn, 90f - r_newrefdef.fov_y / 2f);
    // rotate VPN down by FOV_X/2 degrees
    Math3D.RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90f - r_newrefdef.fov_y / 2f));

    for (int i = 0; i < 4; i++) {
      frustum[i].type = Defines.PLANE_ANYZ;
      frustum[i].dist = Math3D.DotProduct(r_origin, frustum[i].normal);
      frustum[i].signbits = (byte) SignbitsForPlane(frustum[i]);
    }
  }
Beispiel #7
0
  /** Bmodel objects don't interact with each other, but push all box objects. */
  public static void SV_Physics_Pusher(edict_t ent) {
    float[] move = {0, 0, 0};
    float[] amove = {0, 0, 0};
    edict_t part, mv;

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

    // make sure all team slaves can move before commiting
    // any moves or calling any think functions
    // if the move is blocked, all moved objects will be backed out
    //	  retry:
    GameBase.pushed_p = 0;
    for (part = ent; part != null; part = part.teamchain) {
      if (part.velocity[0] != 0
          || part.velocity[1] != 0
          || part.velocity[2] != 0
          || part.avelocity[0] != 0
          || part.avelocity[1] != 0
          || part.avelocity[2] != 0) { // object
        // is
        // moving
        Math3D.VectorScale(part.velocity, Defines.FRAMETIME, move);
        Math3D.VectorScale(part.avelocity, Defines.FRAMETIME, amove);

        if (!SV_Push(part, move, amove)) break; // move was blocked
      }
    }
    if (GameBase.pushed_p > Defines.MAX_EDICTS)
      SV_GAME.PF_error(Defines.ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted");

    if (part != null) {
      // the move failed, bump all nextthink times and back out moves
      for (mv = ent; mv != null; mv = mv.teamchain) {
        if (mv.nextthink > 0) mv.nextthink += Defines.FRAMETIME;
      }

      // if the pusher has a "blocked" function, call it
      // otherwise, just stay in place until the obstacle is gone
      if (part.blocked != null) part.blocked.blocked(part, GameBase.obstacle);
    } else { // the move succeeded, so call all think functions
      for (part = ent; part != null; part = part.teamchain) {
        SV_RunThink(part);
      }
    }
  }
Beispiel #8
0
  /** R_CullBox Returns true if the box is completely outside the frustum */
  final boolean R_CullBox(float[] mins, float[] maxs) {
    assert (mins.length == 3 && maxs.length == 3) : "vec3_t bug";

    if (r_nocull.value != 0) return false;

    for (int i = 0; i < 4; i++) {
      if (Math3D.BoxOnPlaneSide(mins, maxs, frustum[i]) == 2) return true;
    }
    return false;
  }
Beispiel #9
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 #10
0
  /** R_DrawBeam */
  void R_DrawBeam(entity_t e) {
    oldorigin[0] = e.oldorigin[0];
    oldorigin[1] = e.oldorigin[1];
    oldorigin[2] = e.oldorigin[2];

    origin[0] = e.origin[0];
    origin[1] = e.origin[1];
    origin[2] = e.origin[2];

    normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
    normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
    normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];

    if (Math3D.VectorNormalize(normalized_direction) == 0.0f) return;

    Math3D.PerpendicularVector(perpvec, normalized_direction);
    Math3D.VectorScale(perpvec, e.frame / 2, perpvec);

    for (int i = 0; i < 6; i++) {
      Math3D.RotatePointAroundVector(
          start_points[i], normalized_direction, perpvec, (360.0f / NUM_BEAM_SEGS) * i);

      Math3D.VectorAdd(start_points[i], origin, start_points[i]);
      Math3D.VectorAdd(start_points[i], direction, end_points[i]);
    }

    GL11.glDisable(GL11.GL_TEXTURE_2D);
    GL11.glEnable(GL11.GL_BLEND);
    GL11.glDepthMask(false);

    float r = (d_8to24table[e.skinnum & 0xFF]) & 0xFF;
    float g = (d_8to24table[e.skinnum & 0xFF] >> 8) & 0xFF;
    float b = (d_8to24table[e.skinnum & 0xFF] >> 16) & 0xFF;

    r *= 1 / 255.0f;
    g *= 1 / 255.0f;
    b *= 1 / 255.0f;

    GL11.glColor4f(r, g, b, e.alpha);

    GL11.glBegin(GL11.GL_TRIANGLE_STRIP);

    float[] v;

    for (int i = 0; i < NUM_BEAM_SEGS; i++) {
      v = start_points[i];
      GL11.glVertex3f(v[0], v[1], v[2]);
      v = end_points[i];
      GL11.glVertex3f(v[0], v[1], v[2]);
      v = start_points[(i + 1) % NUM_BEAM_SEGS];
      GL11.glVertex3f(v[0], v[1], v[2]);
      v = end_points[(i + 1) % NUM_BEAM_SEGS];
      GL11.glVertex3f(v[0], v[1], v[2]);
    }
    GL11.glEnd();

    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glDisable(GL11.GL_BLEND);
    GL11.glDepthMask(true);
  }
Beispiel #11
0
  // FIXME: hacked in for E3 demo
  public static void SV_AddRotationalFriction(edict_t ent) {
    int n;
    float adjustment;

    Math3D.VectorMA(ent.s.angles, Defines.FRAMETIME, ent.avelocity, ent.s.angles);
    adjustment = Defines.FRAMETIME * Defines.sv_stopspeed * Defines.sv_friction;
    for (n = 0; n < 3; n++) {
      if (ent.avelocity[n] > 0) {
        ent.avelocity[n] -= adjustment;
        if (ent.avelocity[n] < 0) ent.avelocity[n] = 0;
      } else {
        ent.avelocity[n] += adjustment;
        if (ent.avelocity[n] > 0) ent.avelocity[n] = 0;
      }
    }
  }
Beispiel #12
0
  public static void SV_NewChaseDir(edict_t actor, edict_t enemy, float dist) {
    float deltax, deltay;
    float d[] = {0, 0, 0};
    float tdir, olddir, turnaround;

    // FIXME: how did we get here with no enemy
    if (enemy == null) {
      Com.DPrintf("SV_NewChaseDir without enemy!\n");
      return;
    }
    olddir = Math3D.anglemod((int) (actor.ideal_yaw / 45) * 45);
    turnaround = Math3D.anglemod(olddir - 180);

    deltax = enemy.s.origin[0] - actor.s.origin[0];
    deltay = enemy.s.origin[1] - actor.s.origin[1];
    if (deltax > 10) d[1] = 0;
    else if (deltax < -10) d[1] = 180;
    else d[1] = DI_NODIR;
    if (deltay < -10) d[2] = 270;
    else if (deltay > 10) d[2] = 90;
    else d[2] = DI_NODIR;

    //	   try direct route
    if (d[1] != DI_NODIR && d[2] != DI_NODIR) {
      if (d[1] == 0) tdir = d[2] == 90 ? 45 : 315;
      else tdir = d[2] == 90 ? 135 : 215;

      if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) return;
    }

    //	   try other directions
    if (((Lib.rand() & 3) & 1) != 0 || Math.abs(deltay) > Math.abs(deltax)) {
      tdir = d[1];
      d[1] = d[2];
      d[2] = tdir;
    }

    if (d[1] != DI_NODIR && d[1] != turnaround && SV_StepDirection(actor, d[1], dist)) return;

    if (d[2] != DI_NODIR && d[2] != turnaround && SV_StepDirection(actor, d[2], dist)) return;

    /* there is no direct path to the player, so pick another direction */

    if (olddir != DI_NODIR && SV_StepDirection(actor, olddir, dist)) return;

    if ((Lib.rand() & 1) != 0) /* randomly determine direction of search */ {
      for (tdir = 0; tdir <= 315; tdir += 45)
        if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) return;
    } else {
      for (tdir = 315; tdir >= 0; tdir -= 45)
        if (tdir != turnaround && SV_StepDirection(actor, tdir, dist)) return;
    }

    if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist)) return;

    actor.ideal_yaw = olddir; // can't move

    // if a bridge was pulled out from underneath a monster, it may not have
    // a valid standing position at all

    if (!M.M_CheckBottom(actor)) SV_FixCheckBottom(actor);
  }
Beispiel #13
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 #14
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 #15
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 #16
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;
  }