public static void fire_grenade2( edict_t self, float[] start, float[] aimdir, int damage, int speed, float timer, float damage_radius, boolean held) { edict_t grenade; float[] dir = {0, 0, 0}; float[] forward = {0, 0, 0}, right = {0, 0, 0}, up = {0, 0, 0}; Math3D.vectoangles(aimdir, dir); Math3D.AngleVectors(dir, forward, right, up); grenade = GameUtil.G_Spawn(); Math3D.VectorCopy(start, grenade.s.origin); Math3D.VectorScale(aimdir, speed, grenade.velocity); Math3D.VectorMA(grenade.velocity, 200f + Lib.crandom() * 10.0f, up, grenade.velocity); Math3D.VectorMA(grenade.velocity, Lib.crandom() * 10.0f, right, grenade.velocity); Math3D.VectorSet(grenade.avelocity, 300f, 300f, 300f); grenade.movetype = Defines.MOVETYPE_BOUNCE; grenade.clipmask = Defines.MASK_SHOT; grenade.solid = Defines.SOLID_BBOX; grenade.s.effects |= Defines.EF_GRENADE; Math3D.VectorClear(grenade.mins); Math3D.VectorClear(grenade.maxs); grenade.s.modelindex = GameBase.gi.modelindex("models/objects/grenade2/tris.md2"); grenade.owner = self; grenade.touch = Grenade_Touch; grenade.nextthink = GameBase.level.time + timer; grenade.think = Grenade_Explode; grenade.dmg = damage; grenade.dmg_radius = damage_radius; grenade.classname = "hgrenade"; if (held) grenade.spawnflags = 3; else grenade.spawnflags = 1; grenade.s.sound = GameBase.gi.soundindex("weapons/hgrenc1b.wav"); if (timer <= 0.0) Grenade_Explode.think(grenade); else { GameBase.gi.sound( self, Defines.CHAN_WEAPON, GameBase.gi.soundindex("weapons/hgrent1a.wav"), 1, Defines.ATTN_NORM, 0); GameBase.gi.linkentity(grenade); } }
public void touch(edict_t ent, edict_t other, cplane_t plane, csurface_t surf) { float[] origin = {0, 0, 0}; int n; if (other == ent.owner) return; if (surf != null && (surf.flags & Defines.SURF_SKY) != 0) { GameUtil.G_FreeEdict(ent); return; } if (ent.owner.client != null) PlayerWeapon.PlayerNoise(ent.owner, ent.s.origin, Defines.PNOISE_IMPACT); // calculate position for the explosion entity Math3D.VectorMA(ent.s.origin, -0.02f, ent.velocity, origin); if (other.takedamage != 0) { GameCombat.T_Damage( other, ent, ent.owner, ent.velocity, ent.s.origin, plane.normal, ent.dmg, 0, 0, Defines.MOD_ROCKET); } else { // don't throw any debris in net games if (GameBase.deathmatch.value == 0 && 0 == GameBase.coop.value) { if ((surf != null) && 0 == (surf.flags & (Defines.SURF_WARP | Defines.SURF_TRANS33 | Defines.SURF_TRANS66 | Defines.SURF_FLOWING))) { n = Lib.rand() % 5; while (n-- > 0) GameMisc.ThrowDebris(ent, "models/objects/debris2/tris.md2", 2, ent.s.origin); } } } GameCombat.T_RadiusDamage( ent, ent.owner, ent.radius_dmg, other, ent.dmg_radius, Defines.MOD_R_SPLASH); GameBase.gi.WriteByte(Defines.svc_temp_entity); if (ent.waterlevel != 0) GameBase.gi.WriteByte(Defines.TE_ROCKET_EXPLOSION_WATER); else GameBase.gi.WriteByte(Defines.TE_ROCKET_EXPLOSION); GameBase.gi.WritePosition(origin); GameBase.gi.multicast(ent.s.origin, Defines.MULTICAST_PHS); GameUtil.G_FreeEdict(ent); }
public static void fire_grenade( edict_t self, float[] start, float[] aimdir, int damage, int speed, float timer, float damage_radius) { edict_t grenade; float[] dir = {0, 0, 0}; float[] forward = {0, 0, 0}, right = {0, 0, 0}, up = {0, 0, 0}; Math3D.vectoangles(aimdir, dir); Math3D.AngleVectors(dir, forward, right, up); grenade = GameUtil.G_Spawn(); Math3D.VectorCopy(start, grenade.s.origin); Math3D.VectorScale(aimdir, speed, grenade.velocity); Math3D.VectorMA(grenade.velocity, 200f + Lib.crandom() * 10.0f, up, grenade.velocity); Math3D.VectorMA(grenade.velocity, Lib.crandom() * 10.0f, right, grenade.velocity); Math3D.VectorSet(grenade.avelocity, 300, 300, 300); grenade.movetype = Defines.MOVETYPE_BOUNCE; grenade.clipmask = Defines.MASK_SHOT; grenade.solid = Defines.SOLID_BBOX; grenade.s.effects |= Defines.EF_GRENADE; Math3D.VectorClear(grenade.mins); Math3D.VectorClear(grenade.maxs); grenade.s.modelindex = GameBase.gi.modelindex("models/objects/grenade/tris.md2"); grenade.owner = self; grenade.touch = Grenade_Touch; grenade.nextthink = GameBase.level.time + timer; grenade.think = Grenade_Explode; grenade.dmg = damage; grenade.dmg_radius = damage_radius; grenade.classname = "grenade"; GameBase.gi.linkentity(grenade); }
public void touch(edict_t ent, edict_t other, cplane_t plane, csurface_t surf) { if (other == ent.owner) return; if (surf != null && 0 != (surf.flags & Defines.SURF_SKY)) { GameUtil.G_FreeEdict(ent); return; } if (other.takedamage == 0) { if ((ent.spawnflags & 1) != 0) { if (Lib.random() > 0.5f) GameBase.gi.sound( ent, Defines.CHAN_VOICE, GameBase.gi.soundindex("weapons/hgrenb1a.wav"), 1, Defines.ATTN_NORM, 0); else GameBase.gi.sound( ent, Defines.CHAN_VOICE, GameBase.gi.soundindex("weapons/hgrenb2a.wav"), 1, Defines.ATTN_NORM, 0); } else { GameBase.gi.sound( ent, Defines.CHAN_VOICE, GameBase.gi.soundindex("weapons/grenlb1b.wav"), 1, Defines.ATTN_NORM, 0); } return; } ent.enemy = other; Grenade_Explode.think(ent); }
/* * ================= * check_dodge * * This is a support routine used when a client is firing a non-instant * attack weapon. It checks to see if a monster's dodge function should be * called. * ================= */ static void check_dodge(edict_t self, float[] start, float[] dir, int speed) { float[] end = {0, 0, 0}; float[] v = {0, 0, 0}; trace_t tr; float eta; // easy mode only ducks one quarter the time if (GameBase.skill.value == 0) { if (Lib.random() > 0.25) return; } Math3D.VectorMA(start, 8192, dir, end); tr = GameBase.gi.trace(start, null, null, end, self, Defines.MASK_SHOT); if ((tr.ent != null) && (tr.ent.svflags & Defines.SVF_MONSTER) != 0 && (tr.ent.health > 0) && (null != tr.ent.monsterinfo.dodge) && GameUtil.infront(tr.ent, self)) { Math3D.VectorSubtract(tr.endpos, start, v); eta = (Math3D.VectorLength(v) - tr.ent.maxs[0]) / speed; tr.ent.monsterinfo.dodge.dodge(tr.ent, self, eta); } }
/** * Mesh * * @author cwei */ public abstract class Mesh extends Light { // g_mesh.c: triangle model functions /* * ============================================================= * * ALIAS MODELS * * ============================================================= */ static final int NUMVERTEXNORMALS = 162; float[][] r_avertexnormals = Anorms.VERTEXNORMALS; float[] shadevector = {0, 0, 0}; float[] shadelight = {0, 0, 0}; // precalculated dot products for quantized angles static final int SHADEDOT_QUANT = 16; float[][] r_avertexnormal_dots = Anorms.VERTEXNORMAL_DOTS; float[] shadedots = r_avertexnormal_dots[0]; /** * GL_LerpVerts * * @param nverts * @param ov * @param verts * @param move * @param frontv * @param backv */ void GL_LerpVerts(int nverts, int[] ov, int[] v, float[] move, float[] frontv, float[] backv) { FloatBuffer lerp = vertexArrayBuf; lerp.limit((nverts << 2) - nverts); // nverts * 3 int ovv, vv; // PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) { float[] normal; int j = 0; for (int i = 0; i < nverts; i++ /* , v++, ov++, lerp+=4 */) { vv = v[i]; normal = r_avertexnormals[(vv >>> 24) & 0xFF]; ovv = ov[i]; lerp.put( j, move[0] + (ovv & 0xFF) * backv[0] + (vv & 0xFF) * frontv[0] + normal[0] * Defines.POWERSUIT_SCALE); lerp.put( j + 1, move[1] + ((ovv >>> 8) & 0xFF) * backv[1] + ((vv >>> 8) & 0xFF) * frontv[1] + normal[1] * Defines.POWERSUIT_SCALE); lerp.put( j + 2, move[2] + ((ovv >>> 16) & 0xFF) * backv[2] + ((vv >>> 16) & 0xFF) * frontv[2] + normal[2] * Defines.POWERSUIT_SCALE); j += 3; } } else { int j = 0; for (int i = 0; i < nverts; i++ /* , v++, ov++, lerp+=4 */) { ovv = ov[i]; vv = v[i]; lerp.put(j, move[0] + (ovv & 0xFF) * backv[0] + (vv & 0xFF) * frontv[0]); lerp.put( j + 1, move[1] + ((ovv >>> 8) & 0xFF) * backv[1] + ((vv >>> 8) & 0xFF) * frontv[1]); lerp.put( j + 2, move[2] + ((ovv >>> 16) & 0xFF) * backv[2] + ((vv >>> 16) & 0xFF) * frontv[2]); j += 3; } } } private final FloatBuffer colorArrayBuf = Lib.newFloatBuffer(qfiles.MAX_VERTS * 4); private final FloatBuffer vertexArrayBuf = Lib.newFloatBuffer(qfiles.MAX_VERTS * 3); private final FloatBuffer textureArrayBuf = Lib.newFloatBuffer(qfiles.MAX_VERTS * 2); boolean isFilled = false; float[] tmpVec = {0, 0, 0}; float[][] vectors = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0} // 3 mal vec3_t }; // stack variable private final float[] move = {0, 0, 0}; // vec3_t private final float[] frontv = {0, 0, 0}; // vec3_t private final float[] backv = {0, 0, 0}; // vec3_t /** * GL_DrawAliasFrameLerp * * <p>interpolates between two frames and origins FIXME: batch lerp all vertexes */ void GL_DrawAliasFrameLerp(qfiles.dmdl_t paliashdr, float backlerp) { qfiles.daliasframe_t frame = paliashdr.aliasFrames[currententity.frame]; int[] verts = frame.verts; qfiles.daliasframe_t oldframe = paliashdr.aliasFrames[currententity.oldframe]; int[] ov = oldframe.verts; float alpha; if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) alpha = currententity.alpha; else alpha = 1.0f; // PMM - added double shell if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) gl.glDisable(GL_TEXTURE_2D); float frontlerp = 1.0f - backlerp; // move should be the delta back to the previous frame * backlerp Math3D.VectorSubtract(currententity.oldorigin, currententity.origin, frontv); Math3D.AngleVectors(currententity.angles, vectors[0], vectors[1], vectors[2]); move[0] = Math3D.DotProduct(frontv, vectors[0]); // forward move[1] = -Math3D.DotProduct(frontv, vectors[1]); // left move[2] = Math3D.DotProduct(frontv, vectors[2]); // up Math3D.VectorAdd(move, oldframe.translate, move); for (int i = 0; i < 3; i++) { move[i] = backlerp * move[i] + frontlerp * frame.translate[i]; frontv[i] = frontlerp * frame.scale[i]; backv[i] = backlerp * oldframe.scale[i]; } // ab hier wird optimiert GL_LerpVerts(paliashdr.num_xyz, ov, verts, move, frontv, backv); gl.glEnableClientState(GL_VERTEX_ARRAY); gl.glVertexPointer(3, 0, vertexArrayBuf); // PMM - added double damage shell if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) { gl.glColor4f(shadelight[0], shadelight[1], shadelight[2], alpha); } else { gl.glEnableClientState(GL_COLOR_ARRAY); gl.glColorPointer(4, 0, colorArrayBuf); // // pre light everything // FloatBuffer color = colorArrayBuf; float l; int size = paliashdr.num_xyz; int j = 0; for (int i = 0; i < size; i++) { l = shadedots[(verts[i] >>> 24) & 0xFF]; color.put(j, l * shadelight[0]); color.put(j + 1, l * shadelight[1]); color.put(j + 2, l * shadelight[2]); color.put(j + 3, alpha); j += 4; } } gl.glClientActiveTextureARB(TEXTURE0); gl.glTexCoordPointer(2, 0, textureArrayBuf); gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); int pos = 0; int[] counts = paliashdr.counts; ShortBuffer srcIndexBuf = null; FloatBuffer dstTextureCoords = textureArrayBuf; FloatBuffer srcTextureCoords = paliashdr.textureCoordBuf; int dstIndex = 0; int srcIndex = 0; int count; int mode; int size = counts.length; for (int j = 0; j < size; j++) { // get the vertex count and primitive type count = counts[j]; if (count == 0) break; // done srcIndexBuf = paliashdr.indexElements[j]; mode = GL_TRIANGLE_STRIP; if (count < 0) { mode = GL_TRIANGLE_FAN; count = -count; } srcIndex = pos << 1; srcIndex--; for (int k = 0; k < count; k++) { dstIndex = srcIndexBuf.get(k) << 1; dstTextureCoords.put(dstIndex, srcTextureCoords.get(++srcIndex)); dstTextureCoords.put(++dstIndex, srcTextureCoords.get(++srcIndex)); } gl.glDrawElements(mode, srcIndexBuf); pos += count; } // PMM - added double damage shell if ((currententity.flags & (Defines.RF_SHELL_RED | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE | Defines.RF_SHELL_HALF_DAM)) != 0) gl.glEnable(GL_TEXTURE_2D); gl.glDisableClientState(GL_COLOR_ARRAY); } private final float[] point = {0, 0, 0}; /** GL_DrawAliasShadow */ void GL_DrawAliasShadow(qfiles.dmdl_t paliashdr, int posenum) { float lheight = currententity.origin[2] - lightspot[2]; int[] order = paliashdr.glCmds; float height = -lheight + 1.0f; int orderIndex = 0; int index = 0; // TODO shadow drawing with vertex arrays int count; while (true) { // get the vertex count and primitive type count = order[orderIndex++]; if (count == 0) break; // done if (count < 0) { count = -count; gl.glBegin(GL_TRIANGLE_FAN); } else gl.glBegin(GL_TRIANGLE_STRIP); do { index = order[orderIndex + 2] * 3; point[0] = vertexArrayBuf.get(index); point[1] = vertexArrayBuf.get(index + 1); point[2] = vertexArrayBuf.get(index + 2); point[0] -= shadevector[0] * (point[2] + lheight); point[1] -= shadevector[1] * (point[2] + lheight); point[2] = height; gl.glVertex3f(point[0], point[1], point[2]); orderIndex += 3; } while (--count != 0); gl.glEnd(); } } // TODO sync with jogl renderer. hoz // stack variable private final float[] mins = {0, 0, 0}; private final float[] maxs = {0, 0, 0}; /** R_CullAliasModel */ boolean R_CullAliasModel(entity_t e) { qfiles.dmdl_t paliashdr = (qfiles.dmdl_t) currentmodel.extradata; if ((e.frame >= paliashdr.num_frames) || (e.frame < 0)) { VID.Printf( Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such frame " + e.frame + '\n'); e.frame = 0; } if ((e.oldframe >= paliashdr.num_frames) || (e.oldframe < 0)) { VID.Printf( Defines.PRINT_ALL, "R_CullAliasModel " + currentmodel.name + ": no such oldframe " + e.oldframe + '\n'); e.oldframe = 0; } qfiles.daliasframe_t pframe = paliashdr.aliasFrames[e.frame]; qfiles.daliasframe_t poldframe = paliashdr.aliasFrames[e.oldframe]; /* * * compute axially aligned mins and maxs */ if (pframe == poldframe) { for (int i = 0; i < 3; i++) { mins[i] = pframe.translate[i]; maxs[i] = mins[i] + pframe.scale[i] * 255; } } else { float thismaxs, oldmaxs; for (int i = 0; i < 3; i++) { thismaxs = pframe.translate[i] + pframe.scale[i] * 255; oldmaxs = poldframe.translate[i] + poldframe.scale[i] * 255; if (pframe.translate[i] < poldframe.translate[i]) mins[i] = pframe.translate[i]; else mins[i] = poldframe.translate[i]; if (thismaxs > oldmaxs) maxs[i] = thismaxs; else maxs[i] = oldmaxs; } } /* * * compute a full bounding box */ float[] tmp; for (int i = 0; i < 8; i++) { tmp = bbox[i]; if ((i & 1) != 0) tmp[0] = mins[0]; else tmp[0] = maxs[0]; if ((i & 2) != 0) tmp[1] = mins[1]; else tmp[1] = maxs[1]; if ((i & 4) != 0) tmp[2] = mins[2]; else tmp[2] = maxs[2]; } /* * * rotate the bounding box */ tmp = mins; Math3D.VectorCopy(e.angles, tmp); tmp[YAW] = -tmp[YAW]; Math3D.AngleVectors(tmp, vectors[0], vectors[1], vectors[2]); for (int i = 0; i < 8; i++) { Math3D.VectorCopy(bbox[i], tmp); bbox[i][0] = Math3D.DotProduct(vectors[0], tmp); bbox[i][1] = -Math3D.DotProduct(vectors[1], tmp); bbox[i][2] = Math3D.DotProduct(vectors[2], tmp); Math3D.VectorAdd(e.origin, bbox[i], bbox[i]); } int f, mask; int aggregatemask = ~0; // 0xFFFFFFFF for (int p = 0; p < 8; p++) { mask = 0; for (f = 0; f < 4; f++) { float dp = Math3D.DotProduct(frustum[f].normal, bbox[p]); if ((dp - frustum[f].dist) < 0) { mask |= (1 << f); } } aggregatemask &= mask; } if (aggregatemask != 0) { return true; } return false; } // bounding box float[][] bbox = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0} }; // TODO sync with jogl renderer. hoz /** R_DrawAliasModel */ void R_DrawAliasModel(entity_t e) { if ((e.flags & Defines.RF_WEAPONMODEL) == 0) { if (R_CullAliasModel(e)) return; } if ((e.flags & Defines.RF_WEAPONMODEL) != 0) { if (r_lefthand.value == 2.0f) return; } qfiles.dmdl_t paliashdr = (qfiles.dmdl_t) currentmodel.extradata; // // get lighting information // // PMM - rewrote, reordered to handle new shells & mixing // PMM - 3.20 code .. replaced with original way of doing it to keep mod // authors happy // int i; if ((currententity.flags & (Defines.RF_SHELL_HALF_DAM | Defines.RF_SHELL_GREEN | Defines.RF_SHELL_RED | Defines.RF_SHELL_BLUE | Defines.RF_SHELL_DOUBLE)) != 0) { Math3D.VectorClear(shadelight); if ((currententity.flags & Defines.RF_SHELL_HALF_DAM) != 0) { shadelight[0] = 0.56f; shadelight[1] = 0.59f; shadelight[2] = 0.45f; } if ((currententity.flags & Defines.RF_SHELL_DOUBLE) != 0) { shadelight[0] = 0.9f; shadelight[1] = 0.7f; } if ((currententity.flags & Defines.RF_SHELL_RED) != 0) shadelight[0] = 1.0f; if ((currententity.flags & Defines.RF_SHELL_GREEN) != 0) shadelight[1] = 1.0f; if ((currententity.flags & Defines.RF_SHELL_BLUE) != 0) shadelight[2] = 1.0f; } else if ((currententity.flags & Defines.RF_FULLBRIGHT) != 0) { for (i = 0; i < 3; i++) shadelight[i] = 1.0f; } else { R_LightPoint(currententity.origin, shadelight); // player lighting hack for communication back to server // big hack! if ((currententity.flags & Defines.RF_WEAPONMODEL) != 0) { // pick the greatest component, which should be the same // as the mono value returned by software if (shadelight[0] > shadelight[1]) { if (shadelight[0] > shadelight[2]) r_lightlevel.value = 150 * shadelight[0]; else r_lightlevel.value = 150 * shadelight[2]; } else { if (shadelight[1] > shadelight[2]) r_lightlevel.value = 150 * shadelight[1]; else r_lightlevel.value = 150 * shadelight[2]; } } if (gl_monolightmap.string.charAt(0) != '0') { float s = shadelight[0]; if (s < shadelight[1]) s = shadelight[1]; if (s < shadelight[2]) s = shadelight[2]; shadelight[0] = s; shadelight[1] = s; shadelight[2] = s; } } if ((currententity.flags & Defines.RF_MINLIGHT) != 0) { for (i = 0; i < 3; i++) if (shadelight[i] > 0.1f) break; if (i == 3) { shadelight[0] = 0.1f; shadelight[1] = 0.1f; shadelight[2] = 0.1f; } } if ((currententity.flags & Defines.RF_GLOW) != 0) { // bonus items // will pulse // with time float scale; float min; scale = (float) (0.1f * Math.sin(r_newrefdef.time * 7)); for (i = 0; i < 3; i++) { min = shadelight[i] * 0.8f; shadelight[i] += scale; if (shadelight[i] < min) shadelight[i] = min; } } // ================= // PGM ir goggles color override if ((r_newrefdef.rdflags & Defines.RDF_IRGOGGLES) != 0 && (currententity.flags & Defines.RF_IR_VISIBLE) != 0) { shadelight[0] = 1.0f; shadelight[1] = 0.0f; shadelight[2] = 0.0f; } // PGM // ================= shadedots = r_avertexnormal_dots[ ((int) (currententity.angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; float an = (float) (currententity.angles[1] / 180 * Math.PI); shadevector[0] = (float) Math.cos(-an); shadevector[1] = (float) Math.sin(-an); shadevector[2] = 1; Math3D.VectorNormalize(shadevector); // // locate the proper data // c_alias_polys += paliashdr.num_tris; // // draw all the triangles // if ((currententity.flags & Defines.RF_DEPTHHACK) != 0) // hack the // depth range // to prevent // view model // from poking // into walls gl.glDepthRange(gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin)); if ((currententity.flags & Defines.RF_WEAPONMODEL) != 0 && (r_lefthand.value == 1.0f)) { gl.glMatrixMode(GL_PROJECTION); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glScalef(-1, 1, 1); MYgluPerspective(r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height, 4, 4096); gl.glMatrixMode(GL_MODELVIEW); gl.glCullFace(GL_BACK); } gl.glPushMatrix(); e.angles[PITCH] = -e.angles[PITCH]; // sigh. R_RotateForEntity(e); e.angles[PITCH] = -e.angles[PITCH]; // sigh. image_t skin; // select skin if (currententity.skin != null) skin = currententity.skin; // custom player skin else { if (currententity.skinnum >= qfiles.MAX_MD2SKINS) skin = currentmodel.skins[0]; else { skin = currentmodel.skins[currententity.skinnum]; if (skin == null) skin = currentmodel.skins[0]; } } if (skin == null) skin = r_notexture; // fallback... GL_Bind(skin.texnum); // draw it gl.glShadeModel(GL_SMOOTH); GL_TexEnv(GL_MODULATE); if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) { gl.glEnable(GL_BLEND); } if ((currententity.frame >= paliashdr.num_frames) || (currententity.frame < 0)) { VID.Printf( Defines.PRINT_ALL, "R_DrawAliasModel " + currentmodel.name + ": no such frame " + currententity.frame + '\n'); currententity.frame = 0; currententity.oldframe = 0; } if ((currententity.oldframe >= paliashdr.num_frames) || (currententity.oldframe < 0)) { VID.Printf( Defines.PRINT_ALL, "R_DrawAliasModel " + currentmodel.name + ": no such oldframe " + currententity.oldframe + '\n'); currententity.frame = 0; currententity.oldframe = 0; } if (r_lerpmodels.value == 0.0f) currententity.backlerp = 0; GL_DrawAliasFrameLerp(paliashdr, currententity.backlerp); GL_TexEnv(GL_REPLACE); gl.glShadeModel(GL_FLAT); gl.glPopMatrix(); if ((currententity.flags & Defines.RF_WEAPONMODEL) != 0 && (r_lefthand.value == 1.0F)) { gl.glMatrixMode(GL_PROJECTION); gl.glPopMatrix(); gl.glMatrixMode(GL_MODELVIEW); gl.glCullFace(GL_FRONT); } if ((currententity.flags & Defines.RF_TRANSLUCENT) != 0) { gl.glDisable(GL_BLEND); } if ((currententity.flags & Defines.RF_DEPTHHACK) != 0) gl.glDepthRange(gldepthmin, gldepthmax); if (gl_shadows.value != 0.0f && (currententity.flags & (Defines.RF_TRANSLUCENT | Defines.RF_WEAPONMODEL)) == 0) { gl.glPushMatrix(); R_RotateForEntity(e); gl.glDisable(GL_TEXTURE_2D); gl.glEnable(GL_BLEND); gl.glColor4f(0, 0, 0, 0.5f); GL_DrawAliasShadow(paliashdr, currententity.frame); gl.glEnable(GL_TEXTURE_2D); gl.glDisable(GL_BLEND); gl.glPopMatrix(); } gl.glColor4f(1, 1, 1, 1); } }
/* * ================= * 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); } }
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; }