/// <summary> /// SV_StepDirection /// Turns to the movement direction, and walks the current distance if facing it. /// </summary> static bool StepDirection(edict_t ent, float yaw, float dist) { ent.v.ideal_yaw = yaw; QBuiltins.PF_changeyaw(); yaw = (float)(yaw * Math.PI * 2.0 / 360); v3f move; move.x = (float)Math.Cos(yaw) * dist; move.y = (float)Math.Sin(yaw) * dist; move.z = 0; v3f oldorigin = ent.v.origin; if (MoveStep(ent, ref move, false)) { float delta = ent.v.angles.y - ent.v.ideal_yaw; if (delta > 45 && delta < 315) { // not turned far enough, so don't take the step ent.v.origin = oldorigin; } LinkEdict(ent, true); return(true); } LinkEdict(ent, true); return(false); }
/// <summary> /// SV_MoveToGoal /// </summary> public static void MoveToGoal() { edict_t ent = ProgToEdict(Progs.GlobalStruct.self); edict_t goal = ProgToEdict(ent.v.goalentity); float dist = QBuiltins.GetFloat(OFS.OFS_PARM0); if (((int)ent.v.flags & (EdictFlags.FL_ONGROUND | EdictFlags.FL_FLY | EdictFlags.FL_SWIM)) == 0) { QBuiltins.ReturnFloat(0); return; } // if the next step hits the enemy, return immediately if (ProgToEdict(ent.v.enemy) != sv.edicts[0] && CloseEnough(ent, goal, dist)) { return; } // bump around... if ((Sys.Random() & 3) == 1 || !StepDirection(ent, ent.v.ideal_yaw, dist)) { NewChaseDir(ent, goal, dist); } }
/// <summary> /// PR_LoadProgs /// </summary> public static void LoadProgs() { FreeHandles(); QBuiltins.ClearState(); _DynamicStrings.Clear(); // flush the non-C variable lookup cache for (int i = 0; i < GEFV_CACHESIZE; i++) { _gefvCache[i].field = null; } CRC.Init(out _Crc); byte[] buf = Common.LoadFile("progs.dat"); _Progs = Sys.BytesToStructure <dprograms_t>(buf, 0); if (_Progs == null) { Sys.Error("PR_LoadProgs: couldn't load progs.dat"); } Con.DPrint("Programs occupy {0}K.\n", buf.Length / 1024); for (int i = 0; i < buf.Length; i++) { CRC.ProcessByte(ref _Crc, buf[i]); } // byte swap the header _Progs.SwapBytes(); if (_Progs.version != PROG_VERSION) { Sys.Error("progs.dat has wrong version number ({0} should be {1})", _Progs.version, PROG_VERSION); } if (_Progs.crc != PROGHEADER_CRC) { Sys.Error("progs.dat system vars have been modified, progdefs.h is out of date"); } // Functions _Functions = new dfunction_t[_Progs.numfunctions]; int offset = _Progs.ofs_functions; for (int i = 0; i < _Functions.Length; i++, offset += dfunction_t.SizeInBytes) { _Functions[i] = Sys.BytesToStructure <dfunction_t>(buf, offset); _Functions[i].SwapBytes(); } // strings offset = _Progs.ofs_strings; int str0 = offset; for (int i = 0; i < _Progs.numstrings; i++, offset++) { // count string length while (buf[offset] != 0) { offset++; } } int length = offset - str0; _Strings = Encoding.ASCII.GetString(buf, str0, length); // Globaldefs _GlobalDefs = new ddef_t[_Progs.numglobaldefs]; offset = _Progs.ofs_globaldefs; for (int i = 0; i < _GlobalDefs.Length; i++, offset += ddef_t.SizeInBytes) { _GlobalDefs[i] = Sys.BytesToStructure <ddef_t>(buf, offset); _GlobalDefs[i].SwapBytes(); } // Fielddefs _FieldDefs = new ddef_t[_Progs.numfielddefs]; offset = _Progs.ofs_fielddefs; for (int i = 0; i < _FieldDefs.Length; i++, offset += ddef_t.SizeInBytes) { _FieldDefs[i] = Sys.BytesToStructure <ddef_t>(buf, offset); _FieldDefs[i].SwapBytes(); if ((_FieldDefs[i].type & DEF_SAVEGLOBAL) != 0) { Sys.Error("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); } } // Statements _Statements = new dstatement_t[_Progs.numstatements]; offset = _Progs.ofs_statements; for (int i = 0; i < _Statements.Length; i++, offset += dstatement_t.SizeInBytes) { _Statements[i] = Sys.BytesToStructure <dstatement_t>(buf, offset); _Statements[i].SwapBytes(); } // Swap bytes inplace if needed if (!BitConverter.IsLittleEndian) { offset = _Progs.ofs_globals; for (int i = 0; i < _Progs.numglobals; i++, offset += 4) { SwapHelper.Swap4b(buf, offset); } } GlobalStruct = Sys.BytesToStructure <globalvars_t>(buf, _Progs.ofs_globals); _Globals = new float[_Progs.numglobals - globalvars_t.SizeInBytes / 4]; Buffer.BlockCopy(buf, _Progs.ofs_globals + globalvars_t.SizeInBytes, _Globals, 0, _Globals.Length * 4); _EdictSize = _Progs.entityfields * 4 + dedict_t.SizeInBytes - entvars_t.SizeInBytes; _HGlobals = GCHandle.Alloc(_Globals, GCHandleType.Pinned); _GlobalsAddr = _HGlobals.AddrOfPinnedObject().ToInt64(); _HGlobalStruct = GCHandle.Alloc(Progs.GlobalStruct, GCHandleType.Pinned); _GlobalStructAddr = _HGlobalStruct.AddrOfPinnedObject().ToInt64(); }
private static int _Argc; // pr_argc /// <summary> /// PR_ExecuteProgram /// </summary> public unsafe static void Execute(int fnum) { if (fnum < 1 || fnum >= _Functions.Length) { if (progs.GlobalStruct.self != 0) { Print(server.ProgToEdict(progs.GlobalStruct.self)); } host.Error("PR_ExecuteProgram: NULL function"); } dfunction_t f = _Functions[fnum]; int runaway = 100000; Trace = false; // make a stack frame int exitdepth = _Depth; int ofs; int s = EnterFunction(f); edict_t ed; while (true) { s++; // next statement eval_t *a = (eval_t *)Get(_Statements[s].a); eval_t *b = (eval_t *)Get(_Statements[s].b); eval_t *c = (eval_t *)Get(_Statements[s].c); if (--runaway == 0) { RunError("runaway loop error"); } xFunction.profile++; _xStatement = s; if (Trace) { PrintStatement(ref _Statements[s]); } switch ((OP)_Statements[s].op) { case OP.OP_ADD_F: c->_float = a->_float + b->_float; break; case OP.OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP.OP_SUB_F: c->_float = a->_float - b->_float; break; case OP.OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP.OP_MUL_F: c->_float = a->_float * b->_float; break; case OP.OP_MUL_V: c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2]; break; case OP.OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP.OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP.OP_DIV_F: c->_float = a->_float / b->_float; break; case OP.OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP.OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP.OP_GE: c->_float = (a->_float >= b->_float) ? 1 : 0; break; case OP.OP_LE: c->_float = (a->_float <= b->_float) ? 1 : 0; break; case OP.OP_GT: c->_float = (a->_float > b->_float) ? 1 : 0; break; case OP.OP_LT: c->_float = (a->_float < b->_float) ? 1 : 0; break; case OP.OP_AND: c->_float = (a->_float != 0 && b->_float != 0) ? 1 : 0; break; case OP.OP_OR: c->_float = (a->_float != 0 || b->_float != 0) ? 1 : 0; break; case OP.OP_NOT_F: c->_float = (a->_float != 0) ? 0 : 1; break; case OP.OP_NOT_V: c->_float = (a->vector[0] == 0 && a->vector[1] == 0 && a->vector[2] == 0) ? 1 : 0; break; case OP.OP_NOT_S: c->_float = (a->_string == 0 || String.IsNullOrEmpty(GetString(a->_string))) ? 1 : 0; break; case OP.OP_NOT_FNC: c->_float = (a->function == 0) ? 1 : 0; break; case OP.OP_NOT_ENT: c->_float = (server.ProgToEdict(a->edict) == server.sv.edicts[0]) ? 1 : 0; break; case OP.OP_EQ_F: c->_float = (a->_float == b->_float) ? 1 : 0; break; case OP.OP_EQ_V: c->_float = ((a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2])) ? 1 : 0; break; case OP.OP_EQ_S: c->_float = (GetString(a->_string) == GetString(b->_string)) ? 1 : 0; //!strcmp(pr_strings + a->_string, pr_strings + b->_string); break; case OP.OP_EQ_E: c->_float = (a->_int == b->_int) ? 1 : 0; break; case OP.OP_EQ_FNC: c->_float = (a->function == b->function) ? 1 : 0; break; case OP.OP_NE_F: c->_float = (a->_float != b->_float) ? 1 : 0; break; case OP.OP_NE_V: c->_float = ((a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2])) ? 1 : 0; break; case OP.OP_NE_S: c->_float = (GetString(a->_string) != GetString(b->_string)) ? 1 : 0; //strcmp(pr_strings + a->_string, pr_strings + b->_string); break; case OP.OP_NE_E: c->_float = (a->_int != b->_int) ? 1 : 0; break; case OP.OP_NE_FNC: c->_float = (a->function != b->function) ? 1 : 0; break; case OP.OP_STORE_F: case OP.OP_STORE_ENT: case OP.OP_STORE_FLD: // integers case OP.OP_STORE_S: case OP.OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP.OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP.OP_STOREP_F: case OP.OP_STOREP_ENT: case OP.OP_STOREP_FLD: // integers case OP.OP_STOREP_S: case OP.OP_STOREP_FNC: // pointers ed = EdictFromAddr(b->_int, out ofs); ed.StoreInt(ofs, a); break; case OP.OP_STOREP_V: ed = EdictFromAddr(b->_int, out ofs); ed.StoreVector(ofs, a); break; case OP.OP_ADDRESS: ed = server.ProgToEdict(a->edict); if (ed == server.sv.edicts[0] && server.IsActive) { RunError("assignment to world entity"); } c->_int = MakeAddr(a->edict, b->_int); break; case OP.OP_LOAD_F: case OP.OP_LOAD_FLD: case OP.OP_LOAD_ENT: case OP.OP_LOAD_S: case OP.OP_LOAD_FNC: ed = server.ProgToEdict(a->edict); ed.LoadInt(b->_int, c); break; case OP.OP_LOAD_V: ed = server.ProgToEdict(a->edict); ed.LoadVector(b->_int, c); break; case OP.OP_IFNOT: if (a->_int == 0) { s += _Statements[s].b - 1; // offset the s++ } break; case OP.OP_IF: if (a->_int != 0) { s += _Statements[s].b - 1; // offset the s++ } break; case OP.OP_GOTO: s += _Statements[s].a - 1; // offset the s++ break; case OP.OP_CALL0: case OP.OP_CALL1: case OP.OP_CALL2: case OP.OP_CALL3: case OP.OP_CALL4: case OP.OP_CALL5: case OP.OP_CALL6: case OP.OP_CALL7: case OP.OP_CALL8: _Argc = _Statements[s].op - (int)OP.OP_CALL0; if (a->function == 0) { RunError("NULL function"); } dfunction_t newf = _Functions[a->function]; if (newf.first_statement < 0) { // negative statements are built in functions int i = -newf.first_statement; if (i >= QBuiltins.Count) { RunError("Bad builtin call number"); } QBuiltins.Execute(i); break; } s = EnterFunction(newf); break; case OP.OP_DONE: case OP.OP_RETURN: float *ptr = (float *)_GlobalStructAddr; int sta = _Statements[s].a; ptr[OFS.OFS_RETURN + 0] = *(float *)Get(sta); ptr[OFS.OFS_RETURN + 1] = *(float *)Get(sta + 1); ptr[OFS.OFS_RETURN + 2] = *(float *)Get(sta + 2); s = LeaveFunction(); if (_Depth == exitdepth) { return; // all done } break; case OP.OP_STATE: ed = server.ProgToEdict(progs.GlobalStruct.self); #if FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed.v.nextthink = progs.GlobalStruct.time + 0.1f; #endif if (a->_float != ed.v.frame) { ed.v.frame = a->_float; } ed.v.think = b->function; break; default: RunError("Bad opcode %i", _Statements[s].op); break; } } }