Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
            }
        }
Esempio n. 3
0
        /// <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();
        }
Esempio n. 4
0
        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;
                }
            }
        }