public static void SV_Physics_Noclip(edict_t ent) { // regular thinking if (!SV_RunThink(ent)) { return; } Mathlib.VectorMA(ref ent.v.angles, (float)host_framtime, ref ent.v.avelocity, out ent.v.angles); Mathlib.VectorMA(ref ent.v.origin, (float)host_framtime, ref ent.v.velocity, out ent.v.origin); SV_LinkEdict(ent, false); }
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_StartSound(edict_t entity, int channel, string sample, int volume, float attenuation) { if (volume < 0 || volume > 255) { Sys_Error("SV_StartSound: volume = {0}", volume); } if (attenuation < 0 || attenuation > 4) { Sys_Error("SV_StartSound: attenuation = {0}", attenuation); } if (channel < 0 || channel > 7) { Sys_Error("SV_StartSound: channel = {0}", channel); } if (sv.datagram.Length > q_shared.MAX_DATAGRAM - 16) { return; } // find precache number for sound int sound_num; for (sound_num = 1; sound_num < q_shared.MAX_SOUNDS && sv.sound_precache[sound_num] != null; sound_num++) { if (sample == sv.sound_precache[sound_num]) { break; } } if (sound_num == q_shared.MAX_SOUNDS || String.IsNullOrEmpty(sv.sound_precache[sound_num])) { Con_Printf("SV_StartSound: {0} not precacheed\n", sample); return; } int ent = NUM_FOR_EDICT(entity); channel = (ent << 3) | channel; int field_mask = 0; if (volume != q_shared.DEFAULT_SOUND_PACKET_VOLUME) { field_mask |= q_shared.SND_VOLUME; } if (attenuation != q_shared.DEFAULT_SOUND_PACKET_ATTENUATION) { field_mask |= q_shared.SND_ATTENUATION; } // directed messages go only to the entity the are targeted on sv.datagram.MSG_WriteByte(q_shared.svc_sound); sv.datagram.MSG_WriteByte(field_mask); if ((field_mask & q_shared.SND_VOLUME) != 0) { sv.datagram.MSG_WriteByte(volume); } if ((field_mask & q_shared.SND_ATTENUATION) != 0) { sv.datagram.MSG_WriteByte((int)(attenuation * 64)); } sv.datagram.MSG_WriteShort(channel); sv.datagram.MSG_WriteByte(sound_num); v3f v; Mathlib.VectorAdd(ref entity.v.mins, ref entity.v.maxs, out v); Mathlib.VectorMA(ref entity.v.origin, 0.5f, ref v, out v); sv.datagram.MSG_WriteCoord(v.x); sv.datagram.MSG_WriteCoord(v.y); sv.datagram.MSG_WriteCoord(v.z); }
public static void SV_Physics_Toss(edict_t ent) { // regular thinking if (!SV_RunThink(ent)) { return; } // if onground, return without moving if (((int)ent.v.flags & q_shared.FL_ONGROUND) != 0) { return; } SV_CheckVelocity(ent); // add gravity if (ent.v.movetype != q_shared.MOVETYPE_FLY && ent.v.movetype != q_shared.MOVETYPE_FLYMISSILE) { SV_AddGravity(ent); } // move angles Mathlib.VectorMA(ref ent.v.angles, (float)host_framtime, ref ent.v.avelocity, out ent.v.angles); // move origin v3f move; Mathlib.VectorScale(ref ent.v.velocity, (float)host_framtime, out move); trace_t trace = PushEntity(ent, ref move); if (trace.fraction == 1) { return; } if (ent.free) { return; } float backoff; if (ent.v.movetype == q_shared.MOVETYPE_BOUNCE) { backoff = 1.5f; } else { backoff = 1; } ClipVelocity(ref ent.v.velocity, ref trace.plane.normal, out ent.v.velocity, backoff); // stop if on ground if (trace.plane.normal.Z > 0.7f) { if (ent.v.velocity.z < 60 || ent.v.movetype != q_shared.MOVETYPE_BOUNCE) { ent.v.flags = (int)ent.v.flags | q_shared.FL_ONGROUND; ent.v.groundentity = EDICT_TO_PROG(trace.ent); ent.v.velocity = default(v3f); ent.v.avelocity = default(v3f); } } // check for in water SV_CheckWaterTransition(ent); }
public static int SV_FlyMove(edict_t ent, float time, trace_t steptrace) { v3f original_velocity = ent.v.velocity; v3f primal_velocity = ent.v.velocity; int numbumps = 4; int blocked = 0; Vector3[] planes = new Vector3[q_shared.MAX_CLIP_PLANES]; int numplanes = 0; float time_left = time; for (int bumpcount = 0; bumpcount < numbumps; bumpcount++) { if (ent.v.velocity.IsEmpty) { break; } v3f end; Mathlib.VectorMA(ref ent.v.origin, time_left, ref ent.v.velocity, out end); trace_t trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid) { // entity is trapped in another solid ent.v.velocity = default(v3f); return(3); } if (trace.fraction > 0) { // actually covered some distance Mathlib.Copy(ref trace.endpos, out ent.v.origin); original_velocity = ent.v.velocity; numplanes = 0; } if (trace.fraction == 1) { break; // moved the entire distance } if (trace.ent == null) { Sys_Error("SV_FlyMove: !trace.ent"); } if (trace.plane.normal.Z > 0.7) { blocked |= 1; // floor if (trace.ent.v.solid == q_shared.SOLID_BSP) { ent.v.flags = (int)ent.v.flags | q_shared.FL_ONGROUND; ent.v.groundentity = EDICT_TO_PROG(trace.ent); } } if (trace.plane.normal.Z == 0) { blocked |= 2; // step if (steptrace != null) { steptrace.CopyFrom(trace); // save for player extrafriction } } // // run the impact function // SV_Impact(ent, trace.ent); if (ent.free) { break; // removed by the impact function } time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= q_shared.MAX_CLIP_PLANES) { // this shouldn't really happen ent.v.velocity = default(v3f); return(3); } planes[numplanes] = trace.plane.normal; numplanes++; // // modify original_velocity so it parallels all of the clip planes // v3f new_velocity = default(v3f); int i, j; for (i = 0; i < numplanes; i++) { ClipVelocity(ref original_velocity, ref planes[i], out new_velocity, 1); for (j = 0; j < numplanes; j++) { if (j != i) { float dot = new_velocity.x * planes[j].X + new_velocity.y * planes[j].Y + new_velocity.z * planes[j].Z; if (dot < 0) { break; // not ok } } } if (j == numplanes) { break; } } if (i != numplanes) { // go along this plane ent.v.velocity = new_velocity; } else { // go along the crease if (numplanes != 2) { ent.v.velocity = default(v3f); return(7); } Vector3 dir = Vector3.Cross(planes[0], planes[1]); float d = dir.X * ent.v.velocity.x + dir.Y * ent.v.velocity.y + dir.Z * ent.v.velocity.z; Mathlib.Copy(ref dir, out ent.v.velocity); Mathlib.VectorScale(ref ent.v.velocity, d, out ent.v.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (Mathlib.DotProduct(ref ent.v.velocity, ref primal_velocity) <= 0) { ent.v.velocity = default(v3f); return(blocked); } } return(blocked); }
public static void SV_Physics_Client(edict_t ent, int num) { if (!svs.clients[num - 1].active) { return; // unconnected slot } // // call standard client pre-think // pr_global_struct.time = (float)sv.time; pr_global_struct.self = EDICT_TO_PROG(ent); PR_ExecuteProgram(pr_global_struct.PlayerPreThink); // // do a move // SV_CheckVelocity(ent); // // decide which move function to call // switch ((int)ent.v.movetype) { case q_shared.MOVETYPE_NONE: if (!SV_RunThink(ent)) { return; } break; case q_shared.MOVETYPE_WALK: if (!SV_RunThink(ent)) { return; } if (!SV_CheckWater(ent) && ((int)ent.v.flags & q_shared.FL_WATERJUMP) == 0) { SV_AddGravity(ent); } SV_CheckStuck(ent); SV_WalkMove(ent); break; case q_shared.MOVETYPE_TOSS: case q_shared.MOVETYPE_BOUNCE: SV_Physics_Toss(ent); break; case q_shared.MOVETYPE_FLY: if (!SV_RunThink(ent)) { return; } SV_FlyMove(ent, (float)host_framtime, null); break; case q_shared.MOVETYPE_NOCLIP: if (!SV_RunThink(ent)) { return; } Mathlib.VectorMA(ref ent.v.origin, (float)host_framtime, ref ent.v.velocity, out ent.v.origin); break; default: Sys_Error("SV_Physics_client: bad movetype {0}", (int)ent.v.movetype); break; } // // call standard player post-think // SV_LinkEdict(ent, true); pr_global_struct.time = (float)sv.time; pr_global_struct.self = EDICT_TO_PROG(ent); PR_ExecuteProgram(pr_global_struct.PlayerPostThink); }