예제 #1
0
  /*
   * =================
   * fire_lead
   *
   * This is an internal support routine used for bullet/pellet based weapons.
   * =================
   */
  public static void fire_lead(
      edict_t self,
      float[] start,
      float[] aimdir,
      int damage,
      int kick,
      int te_impact,
      int hspread,
      int vspread,
      int mod) {
    trace_t tr;
    float[] dir = {0, 0, 0};
    float[] forward = {0, 0, 0}, right = {0, 0, 0}, up = {0, 0, 0};
    float[] end = {0, 0, 0};
    float r;
    float u;
    float[] water_start = {0, 0, 0};
    boolean water = false;
    int content_mask = Defines.MASK_SHOT | Defines.MASK_WATER;

    tr = GameBase.gi.trace(self.s.origin, null, null, start, self, Defines.MASK_SHOT);
    if (!(tr.fraction < 1.0)) {
      Math3D.vectoangles(aimdir, dir);
      Math3D.AngleVectors(dir, forward, right, up);

      r = Lib.crandom() * hspread;
      u = Lib.crandom() * vspread;
      Math3D.VectorMA(start, 8192, forward, end);
      Math3D.VectorMA(end, r, right, end);
      Math3D.VectorMA(end, u, up, end);

      if ((GameBase.gi.pointcontents.pointcontents(start) & Defines.MASK_WATER) != 0) {
        water = true;
        Math3D.VectorCopy(start, water_start);
        content_mask &= ~Defines.MASK_WATER;
      }

      tr = GameBase.gi.trace(start, null, null, end, self, content_mask);

      // see if we hit water
      if ((tr.contents & Defines.MASK_WATER) != 0) {
        int color;

        water = true;
        Math3D.VectorCopy(tr.endpos, water_start);

        if (!Math3D.VectorEquals(start, tr.endpos)) {
          if ((tr.contents & Defines.CONTENTS_WATER) != 0) {
            if (Lib.strcmp(tr.surface.name, "*brwater") == 0) color = Defines.SPLASH_BROWN_WATER;
            else color = Defines.SPLASH_BLUE_WATER;
          } else if ((tr.contents & Defines.CONTENTS_SLIME) != 0) color = Defines.SPLASH_SLIME;
          else if ((tr.contents & Defines.CONTENTS_LAVA) != 0) color = Defines.SPLASH_LAVA;
          else color = Defines.SPLASH_UNKNOWN;

          if (color != Defines.SPLASH_UNKNOWN) {
            GameBase.gi.WriteByte(Defines.svc_temp_entity);
            GameBase.gi.WriteByte(Defines.TE_SPLASH);
            GameBase.gi.WriteByte(8);
            GameBase.gi.WritePosition(tr.endpos);
            GameBase.gi.WriteDir(tr.plane.normal);
            GameBase.gi.WriteByte(color);
            GameBase.gi.multicast(tr.endpos, Defines.MULTICAST_PVS);
          }

          // change bullet's course when it enters water
          Math3D.VectorSubtract(end, start, dir);
          Math3D.vectoangles(dir, dir);
          Math3D.AngleVectors(dir, forward, right, up);
          r = Lib.crandom() * hspread * 2;
          u = Lib.crandom() * vspread * 2;
          Math3D.VectorMA(water_start, 8192, forward, end);
          Math3D.VectorMA(end, r, right, end);
          Math3D.VectorMA(end, u, up, end);
        }

        // re-trace ignoring water this time
        tr = GameBase.gi.trace(water_start, null, null, end, self, Defines.MASK_SHOT);
      }
    }

    // send gun puff / flash
    if (!((tr.surface != null) && 0 != (tr.surface.flags & Defines.SURF_SKY))) {
      if (tr.fraction < 1.0) {
        if (tr.ent.takedamage != 0) {
          GameCombat.T_Damage(
              tr.ent,
              self,
              self,
              aimdir,
              tr.endpos,
              tr.plane.normal,
              damage,
              kick,
              Defines.DAMAGE_BULLET,
              mod);
        } else {
          if (!"sky".equals(tr.surface.name)) {
            GameBase.gi.WriteByte(Defines.svc_temp_entity);
            GameBase.gi.WriteByte(te_impact);
            GameBase.gi.WritePosition(tr.endpos);
            GameBase.gi.WriteDir(tr.plane.normal);
            GameBase.gi.multicast(tr.endpos, Defines.MULTICAST_PVS);

            if (self.client != null)
              PlayerWeapon.PlayerNoise(self, tr.endpos, Defines.PNOISE_IMPACT);
          }
        }
      }
    }

    // if went through water, determine where the end and make a bubble
    // trail
    if (water) {
      float[] pos = {0, 0, 0};

      Math3D.VectorSubtract(tr.endpos, water_start, dir);
      Math3D.VectorNormalize(dir);
      Math3D.VectorMA(tr.endpos, -2, dir, pos);
      if ((GameBase.gi.pointcontents.pointcontents(pos) & Defines.MASK_WATER) != 0)
        Math3D.VectorCopy(pos, tr.endpos);
      else tr = GameBase.gi.trace(pos, null, null, water_start, tr.ent, Defines.MASK_WATER);

      Math3D.VectorAdd(water_start, tr.endpos, pos);
      Math3D.VectorScale(pos, 0.5f, pos);

      GameBase.gi.WriteByte(Defines.svc_temp_entity);
      GameBase.gi.WriteByte(Defines.TE_BUBBLETRAIL);
      GameBase.gi.WritePosition(water_start);
      GameBase.gi.WritePosition(tr.endpos);
      GameBase.gi.multicast(pos, Defines.MULTICAST_PVS);
    }
  }
예제 #2
0
        public boolean think(edict_t self) {
          edict_t ent;
          edict_t ignore;
          float[] point = {0, 0, 0};
          float[] dir = {0, 0, 0};
          float[] start = {0, 0, 0};
          float[] end = {0, 0, 0};
          int dmg;
          trace_t tr;

          if (GameBase.deathmatch.value != 0) dmg = 5;
          else dmg = 10;

          EdictIterator edit = null;
          while ((edit = GameBase.findradius(edit, self.s.origin, 256)) != null) {
            ent = edit.o;

            if (ent == self) continue;

            if (ent == self.owner) continue;

            if (ent.takedamage == 0) continue;

            if (0 == (ent.svflags & Defines.SVF_MONSTER)
                && (null == ent.client)
                && (Lib.strcmp(ent.classname, "misc_explobox") != 0)) continue;

            Math3D.VectorMA(ent.absmin, 0.5f, ent.size, point);

            Math3D.VectorSubtract(point, self.s.origin, dir);
            Math3D.VectorNormalize(dir);

            ignore = self;
            Math3D.VectorCopy(self.s.origin, start);
            Math3D.VectorMA(start, 2048, dir, end);
            while (true) {
              tr =
                  GameBase.gi.trace(
                      start,
                      null,
                      null,
                      end,
                      ignore,
                      Defines.CONTENTS_SOLID
                          | Defines.CONTENTS_MONSTER
                          | Defines.CONTENTS_DEADMONSTER);

              if (null == tr.ent) break;

              // hurt it if we can
              if ((tr.ent.takedamage != 0)
                  && 0 == (tr.ent.flags & Defines.FL_IMMUNE_LASER)
                  && (tr.ent != self.owner))
                GameCombat.T_Damage(
                    tr.ent,
                    self,
                    self.owner,
                    dir,
                    tr.endpos,
                    Globals.vec3_origin,
                    dmg,
                    1,
                    Defines.DAMAGE_ENERGY,
                    Defines.MOD_BFG_LASER);

              // if we hit something that's not a monster or player we're
              // done
              if (0 == (tr.ent.svflags & Defines.SVF_MONSTER) && (null == tr.ent.client)) {
                GameBase.gi.WriteByte(Defines.svc_temp_entity);
                GameBase.gi.WriteByte(Defines.TE_LASER_SPARKS);
                GameBase.gi.WriteByte(4);
                GameBase.gi.WritePosition(tr.endpos);
                GameBase.gi.WriteDir(tr.plane.normal);
                GameBase.gi.WriteByte(self.s.skinnum);
                GameBase.gi.multicast(tr.endpos, Defines.MULTICAST_PVS);
                break;
              }

              ignore = tr.ent;
              Math3D.VectorCopy(tr.endpos, start);
            }

            GameBase.gi.WriteByte(Defines.svc_temp_entity);
            GameBase.gi.WriteByte(Defines.TE_BFG_LASER);
            GameBase.gi.WritePosition(self.s.origin);
            GameBase.gi.WritePosition(tr.endpos);
            GameBase.gi.multicast(self.s.origin, Defines.MULTICAST_PHS);
          }

          self.nextthink = GameBase.level.time + Defines.FRAMETIME;
          return true;
        }