/* * ================= * PF_traceline * * Used for use tracing and shot targeting * Traces are blocked by bbox and exact bsp entityes, and also slide box entities * if the tryents flag is set. * * traceline (vector1, vector2, tryents) * ================= */ static unsafe void PF_traceline() { float * v1 = GetVector(OFS.OFS_PARM0); float * v2 = GetVector(OFS.OFS_PARM1); int nomonsters = (int)GetFloat(OFS.OFS_PARM2); edict_t ent = GetEdict(OFS.OFS_PARM3); Vector3 vec1, vec2; Copy(v1, out vec1); Copy(v2, out vec2); trace_t trace = Server.Move(ref vec1, ref Common.ZeroVector, ref Common.ZeroVector, ref vec2, nomonsters, ent); Progs.GlobalStruct.trace_allsolid = trace.allsolid ? 1 : 0; Progs.GlobalStruct.trace_startsolid = trace.startsolid ? 1 : 0; Progs.GlobalStruct.trace_fraction = trace.fraction; Progs.GlobalStruct.trace_inwater = trace.inwater ? 1 : 0; Progs.GlobalStruct.trace_inopen = trace.inopen ? 1 : 0; Mathlib.Copy(ref trace.endpos, out Progs.GlobalStruct.trace_endpos); Mathlib.Copy(ref trace.plane.normal, out Progs.GlobalStruct.trace_plane_normal); Progs.GlobalStruct.trace_plane_dist = trace.plane.dist; if (trace.ent != null) { Progs.GlobalStruct.trace_ent = Server.EdictToProg(trace.ent); } else { Progs.GlobalStruct.trace_ent = Server.EdictToProg(Server.sv.edicts[0]); } }
/* * =============== * PF_droptofloor * * void() droptofloor * =============== */ static void PF_droptofloor() { edict_t ent = Server.ProgToEdict(Progs.GlobalStruct.self); Vector3 org, mins, maxs; Mathlib.Copy(ref ent.v.origin, out org); Mathlib.Copy(ref ent.v.mins, out mins); Mathlib.Copy(ref ent.v.maxs, out maxs); Vector3 end = org; end.Z -= 256; trace_t trace = Server.Move(ref org, ref mins, ref maxs, ref end, 0, ent); if (trace.fraction == 1 || trace.allsolid) { ReturnFloat(0); } else { Mathlib.Copy(ref trace.endpos, out ent.v.origin); Server.LinkEdict(ent, false); ent.v.flags = (int)ent.v.flags | EdictFlags.FL_ONGROUND; ent.v.groundentity = Server.EdictToProg(trace.ent); ReturnFloat(1); } }
/// <summary> /// ED_ParseEpair /// Can parse either fields or globals returns false if error /// Uze: Warning! value pointer is already with correct offset (value = base + key.ofs)! /// </summary> static unsafe bool ParsePair(void *value, ddef_t key, string s) { void *d = value;// (void *)((int *)base + key->ofs); switch ((etype_t)(key.type & ~DEF_SAVEGLOBAL)) { case etype_t.ev_string: *(int *)d = NewString(s); // - pr_strings; break; case etype_t.ev_float: *(float *)d = Common.atof(s); break; case etype_t.ev_vector: string[] vs = s.Split(' '); ((float *)d)[0] = Common.atof(vs[0]); ((float *)d)[1] = (vs.Length > 1 ? Common.atof(vs[1]) : 0); ((float *)d)[2] = (vs.Length > 2 ? Common.atof(vs[2]) : 0); break; case etype_t.ev_entity: *(int *)d = Server.EdictToProg(Server.EdictNum(Common.atoi(s))); break; case etype_t.ev_field: int f = IndexOfField(s); if (f == -1) { Con.Print("Can't find field {0}\n", s); return(false); } *(int *)d = GetInt32(_FieldDefs[f].ofs); break; case etype_t.ev_function: int func = IndexOfFunction(s); if (func == -1) { Con.Print("Can't find function {0}\n", s); return(false); } *(int *)d = func; // - pr_functions; break; default: break; } return(true); }
/// <summary> /// Host_Kill_f /// </summary> private static void Kill_f() { if (Cmd.Source == cmd_source_t.src_command) { Cmd.ForwardToServer(); return; } if (Server.Player.v.health <= 0) { Server.ClientPrint("Can't suicide -- allready dead!\n"); return; } Progs.GlobalStruct.time = (float)Server.sv.time; Progs.GlobalStruct.self = Server.EdictToProg(Server.Player); Progs.Execute(Progs.GlobalStruct.ClientKill); }
/* * ================= * PF_findradius * * Returns a chain of entities that have origins within a spherical area * * findradius (origin, radius) * ================= */ static unsafe void PF_findradius() { edict_t chain = Server.sv.edicts[0]; float *org = GetVector(OFS.OFS_PARM0); float rad = GetFloat(OFS.OFS_PARM1); Vector3 vorg; Copy(org, out vorg); for (int i = 1; i < Server.sv.num_edicts; i++) { edict_t ent = Server.sv.edicts[i]; if (ent.free) { continue; } if (ent.v.solid == Solids.SOLID_NOT) { continue; } Vector3 v = vorg - (Common.ToVector(ref ent.v.origin) + (Common.ToVector(ref ent.v.mins) + Common.ToVector(ref ent.v.maxs)) * 0.5f); if (v.Length > rad) { continue; } ent.v.chain = Server.EdictToProg(chain); chain = ent; } ReturnEdict(chain); }
/// <summary> /// Host_Spawn_f /// </summary> private static void Spawn_f() { if (Cmd.Source == cmd_source_t.src_command) { Con.Print("spawn is not valid from the console\n"); return; } if (Host.HostClient.spawned) { Con.Print("Spawn not valid -- allready spawned\n"); return; } edict_t ent; // run the entrance script if (Server.sv.loadgame) { // loaded games are fully inited allready // if this is the last client to be connected, unpause Server.sv.paused = false; } else { // set up the edict ent = Host.HostClient.edict; ent.Clear(); //memset(&ent.v, 0, progs.entityfields * 4); ent.v.colormap = Server.NumForEdict(ent); ent.v.team = (Host.HostClient.colors & 15) + 1; ent.v.netname = Progs.NewString(Host.HostClient.name); // copy spawn parms out of the client_t Progs.GlobalStruct.SetParams(Host.HostClient.spawn_parms); // call the spawn function Progs.GlobalStruct.time = (float)Server.sv.time; Progs.GlobalStruct.self = Server.EdictToProg(Server.Player); Progs.Execute(Progs.GlobalStruct.ClientConnect); if ((Sys.GetFloatTime() - Host.HostClient.netconnection.connecttime) <= Server.sv.time) { Con.DPrint("{0} entered the game\n", Host.HostClient.name); } Progs.Execute(Progs.GlobalStruct.PutClientInServer); } // send all current names, colors, and frag counts MsgWriter msg = Host.HostClient.message; msg.Clear(); // send time of update msg.WriteByte(Protocol.svc_time); msg.WriteFloat((float)Server.sv.time); for (int i = 0; i < Server.svs.maxclients; i++) { client_t client = Server.svs.clients[i]; msg.WriteByte(Protocol.svc_updatename); msg.WriteByte(i); msg.WriteString(client.name); msg.WriteByte(Protocol.svc_updatefrags); msg.WriteByte(i); msg.WriteShort(client.old_frags); msg.WriteByte(Protocol.svc_updatecolors); msg.WriteByte(i); msg.WriteByte(client.colors); } // send all current light styles for (int i = 0; i < QDef.MAX_LIGHTSTYLES; i++) { msg.WriteByte(Protocol.svc_lightstyle); msg.WriteByte((char)i); msg.WriteString(Server.sv.lightstyles[i]); } // // send some stats // msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_TOTALSECRETS); msg.WriteLong((int)Progs.GlobalStruct.total_secrets); msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_TOTALMONSTERS); msg.WriteLong((int)Progs.GlobalStruct.total_monsters); msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_SECRETS); msg.WriteLong((int)Progs.GlobalStruct.found_secrets); msg.WriteByte(Protocol.svc_updatestat); msg.WriteByte(QStats.STAT_MONSTERS); msg.WriteLong((int)Progs.GlobalStruct.killed_monsters); // // send a fixangle // Never send a roll angle, because savegames can catch the server // in a state where it is expecting the client to correct the angle // and it won't happen if the game was just loaded, so you wind up // with a permanent head tilt ent = Server.EdictNum(1 + Host.ClientNum); msg.WriteByte(Protocol.svc_setangle); msg.WriteAngle(ent.v.angles.x); msg.WriteAngle(ent.v.angles.y); msg.WriteAngle(0); Server.WriteClientDataToMessage(Server.Player, Host.HostClient.message); msg.WriteByte(Protocol.svc_signonnum); msg.WriteByte(3); Host.HostClient.sendsignon = true; }
/// <summary> /// ED_LoadFromFile /// The entities are directly placed in the array, rather than allocated with /// ED_Alloc, because otherwise an error loading the map would have entity /// number references out of order. /// /// Creates a server's entity / program execution context by /// parsing textual entity definitions out of an ent file. /// /// Used for both fresh maps and savegame loads. A fresh map would also need /// to call ED_CallSpawnFunctions () to let the objects initialize themselves. /// </summary> public static void LoadFromFile(string data) { edict_t ent = null; int inhibit = 0; Progs.GlobalStruct.time = (float)Server.sv.time; // parse ents while (true) { // parse the opening brace data = Common.Parse(data); if (data == null) { break; } if (Common.Token != "{") { Sys.Error("ED_LoadFromFile: found {0} when expecting {", Common.Token); } if (ent == null) { ent = Server.EdictNum(0); } else { ent = Server.AllocEdict(); } data = ParseEdict(data, ent); // remove things from different skill levels or deathmatch if (Host.Deathmatch != 0) { if (((int)ent.v.spawnflags & SpawnFlags.SPAWNFLAG_NOT_DEATHMATCH) != 0) { Server.FreeEdict(ent); inhibit++; continue; } } else if ((Host.CurrentSkill == 0 && ((int)ent.v.spawnflags & SpawnFlags.SPAWNFLAG_NOT_EASY) != 0) || (Host.CurrentSkill == 1 && ((int)ent.v.spawnflags & SpawnFlags.SPAWNFLAG_NOT_MEDIUM) != 0) || (Host.CurrentSkill >= 2 && ((int)ent.v.spawnflags & SpawnFlags.SPAWNFLAG_NOT_HARD) != 0)) { Server.FreeEdict(ent); inhibit++; continue; } // // immediately call spawn function // if (ent.v.classname == 0) { Con.Print("No classname for:\n"); Print(ent); Server.FreeEdict(ent); continue; } // look for the spawn function int func = IndexOfFunction(GetString(ent.v.classname)); if (func == -1) { Con.Print("No spawn function for:\n"); Print(ent); Server.FreeEdict(ent); continue; } Progs.GlobalStruct.self = Server.EdictToProg(ent); Execute(func); } Con.DPrint("{0} entities inhibited\n", inhibit); }
/// <summary> /// RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) /// </summary> public static unsafe void ReturnEdict(edict_t e) { int prog = Server.EdictToProg(e); ReturnInt(prog); }