static void PF_aim() { edict_t ent = G_EDICT(q_shared.OFS_PARM0); float speed = G_FLOAT(q_shared.OFS_PARM1); Vector3 start = ToVector(ref ent.v.origin); start.Z += 20; // try sending a trace straight Vector3 dir; Mathlib.Copy(ref pr_global_struct.v_forward, out dir); Vector3 end = start + dir * 2048; trace_t tr = SV_Move(ref start, ref q_shared.ZeroVector, ref q_shared.ZeroVector, ref end, 0, ent); if (tr.ent != null && tr.ent.v.takedamage == q_shared.DAMAGE_AIM && (teamplay.value == 0 || ent.v.team <= 0 || ent.v.team != tr.ent.v.team)) { G_VECTOR(ref pr_global_struct.v_forward); return; } // try all possible entities Vector3 bestdir = dir; float bestdist = sv_aim.value; edict_t bestent = null; for (int i = 1; i < sv.num_edicts; i++) { edict_t check = sv.edicts[i]; if (check.v.takedamage != q_shared.DAMAGE_AIM) { continue; } if (check == ent) { continue; } if (teamplay.value != 0 && ent.v.team > 0 && ent.v.team == check.v.team) { continue; // don't aim at teammate } v3f tmp; Mathlib.VectorAdd(ref check.v.mins, ref check.v.maxs, out tmp); Mathlib.VectorMA(ref check.v.origin, 0.5f, ref tmp, out tmp); Mathlib.Copy(ref tmp, out end); dir = end - start; Mathlib.Normalize(ref dir); float dist = Vector3.Dot(dir, ToVector(ref pr_global_struct.v_forward)); if (dist < bestdist) { continue; // to far to turn } tr = SV_Move(ref start, ref q_shared.ZeroVector, ref q_shared.ZeroVector, ref end, 0, ent); if (tr.ent == check) { // can shoot at this one bestdist = dist; bestent = check; } } if (bestent != null) { v3f dir2, end2; Mathlib.VectorSubtract(ref bestent.v.origin, ref ent.v.origin, out dir2); float dist = Mathlib.DotProduct(ref dir2, ref pr_global_struct.v_forward); Mathlib.VectorScale(ref pr_global_struct.v_forward, dist, out end2); end2.z = dir2.z; Mathlib.Normalize(ref end2); G_VECTOR(ref end2); } else { G_VECTOR(ref bestdir); } }
public static void SV_WriteEntitiesToClient(edict_t clent, MsgWriter msg) { // find the client's PVS Vector3 org = ToVector(ref clent.v.origin) + ToVector(ref clent.v.view_ofs); byte[] pvs = SV_FatPVS(ref org); // send over all entities (except the client) that touch the pvs for (int e = 1; e < sv.num_edicts; e++) { edict_t ent = sv.edicts[e]; // ignore if not touching a PV leaf if (ent != clent) // clent is ALLWAYS sent { // ignore ents without visible models string mname = GetString(ent.v.model); if (String.IsNullOrEmpty(mname)) { continue; } int i; for (i = 0; i < ent.num_leafs; i++) { if ((pvs[ent.leafnums[i] >> 3] & (1 << (ent.leafnums[i] & 7))) != 0) { break; } } if (i == ent.num_leafs) { continue; // not visible } } if (msg.Capacity - msg.Length < 16) { Con_Printf("packet overflow\n"); return; } // send an update int bits = 0; v3f miss; Mathlib.VectorSubtract(ref ent.v.origin, ref ent.baseline.origin, out miss); if (miss.x < -0.1f || miss.x > 0.1f) { bits |= q_shared.U_ORIGIN1; } if (miss.y < -0.1f || miss.y > 0.1f) { bits |= q_shared.U_ORIGIN2; } if (miss.z < -0.1f || miss.z > 0.1f) { bits |= q_shared.U_ORIGIN3; } if (ent.v.angles.x != ent.baseline.angles.x) { bits |= q_shared.U_ANGLE1; } if (ent.v.angles.y != ent.baseline.angles.y) { bits |= q_shared.U_ANGLE2; } if (ent.v.angles.z != ent.baseline.angles.z) { bits |= q_shared.U_ANGLE3; } if (ent.v.movetype == q_shared.MOVETYPE_STEP) { bits |= q_shared.U_NOLERP; // don't mess up the step animation } if (ent.baseline.colormap != ent.v.colormap) { bits |= q_shared.U_COLORMAP; } if (ent.baseline.skin != ent.v.skin) { bits |= q_shared.U_SKIN; } if (ent.baseline.frame != ent.v.frame) { bits |= q_shared.U_FRAME; } if (ent.baseline.effects != ent.v.effects) { bits |= q_shared.U_EFFECTS; } if (ent.baseline.modelindex != ent.v.modelindex) { bits |= q_shared.U_MODEL; } if (e >= 256) { bits |= q_shared.U_LONGENTITY; } if (bits >= 256) { bits |= q_shared.U_MOREBITS; } // // write the message // msg.MSG_WriteByte(bits | q_shared.U_SIGNAL); if ((bits & q_shared.U_MOREBITS) != 0) { msg.MSG_WriteByte(bits >> 8); } if ((bits & q_shared.U_LONGENTITY) != 0) { msg.MSG_WriteShort(e); } else { msg.MSG_WriteByte(e); } if ((bits & q_shared.U_MODEL) != 0) { msg.MSG_WriteByte((int)ent.v.modelindex); } if ((bits & q_shared.U_FRAME) != 0) { msg.MSG_WriteByte((int)ent.v.frame); } if ((bits & q_shared.U_COLORMAP) != 0) { msg.MSG_WriteByte((int)ent.v.colormap); } if ((bits & q_shared.U_SKIN) != 0) { msg.MSG_WriteByte((int)ent.v.skin); } if ((bits & q_shared.U_EFFECTS) != 0) { msg.MSG_WriteByte((int)ent.v.effects); } if ((bits & q_shared.U_ORIGIN1) != 0) { msg.MSG_WriteCoord(ent.v.origin.x); } if ((bits & q_shared.U_ANGLE1) != 0) { msg.MSG_WriteAngle(ent.v.angles.x); } if ((bits & q_shared.U_ORIGIN2) != 0) { msg.MSG_WriteCoord(ent.v.origin.y); } if ((bits & q_shared.U_ANGLE2) != 0) { msg.MSG_WriteAngle(ent.v.angles.y); } if ((bits & q_shared.U_ORIGIN3) != 0) { msg.MSG_WriteCoord(ent.v.origin.z); } if ((bits & q_shared.U_ANGLE3) != 0) { msg.MSG_WriteAngle(ent.v.angles.z); } } }