Example #1
0
        public unsafe void GetBonePosition(Edict edict, int bone, out Vector origin, out Vector angles)
        {
            EngineFuncs.pfnGetBonePosition(edict.Data, bone, out origin, out angles);

            //TODO: engine never sets angles
            angles = new Vector();
        }
Example #2
0
        public unsafe void Free(Edict edict)
        {
            if (edict?.Free != false)
            {
                return;
            }

            var index = EntityIndex(edict);

            if (HighestInUse == index)
            {
                //Recalculate
                //if this is the last entity then we won't find a new highest
                HighestInUse = -1;

                for (var i = index - 1; i >= 0; --i)
                {
                    if (!EdictByIndex(i).Free)
                    {
                        HighestInUse = i;
                        break;
                    }
                }
            }

            EngineFuncs.pfnRemoveEntity(edict.Data);
        }
Example #3
0
        public static void ScriptEntityCancel(Edict pentCine)
        {
            // make sure they are a scripted_sequence
            if (FClassnameIs(pentCine, CLASSNAME))
            {
                CCineMonster pCineTarget = GetClassPtr((CCineMonster)VARS(pentCine));
                // make sure they have a monster in mind for the script
                BaseEntity   pEntity = pCineTarget.m_hTargetEnt;
                CBaseMonster pTarget = null;
                if (pEntity != null)
                {
                    pTarget = pEntity.MyMonsterPointer();
                }

                if (pTarget)
                {
                    // make sure their monster is actually playing a script
                    if (pTarget.m_MonsterState == MONSTERSTATE_SCRIPT)
                    {
                        // tell them do die
                        pTarget.m_scriptState = CCineMonster.SCRIPT_CLEANUP;
                        // do it now
                        pTarget.CineCleanup();
                    }
                }
            }
        }
Example #4
0
        public unsafe void GetAttachment(Edict edict, int attachment, out Vector origin, out Vector angles)
        {
            EngineFuncs.pfnGetAttachment(edict.Data, attachment, out origin, out angles);

            //TODO: engine never sets angles
            angles = new Vector();
        }
Example #5
0
        public BaseEntity CreateInstance(EntityInfo info, Edict edict)
        {
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            try
            {
                var entity = (BaseEntity)Activator.CreateInstance(info.EntityClass);

                edict.PrivateData = entity;

                entity.pev = edict.Vars;

                entity.ClassName = info.PreferredName;

                //Inform of creation
                entity.OnCreate();

                return(entity);
            }
            catch (Exception e)
            {
                Log.Message($"Couldn't create entity \"{info.PreferredName}\":");
                Log.Exception(e);

                //On failure always free the edict
                //This will also free the entity instance if it has been assigned
                EntityDictionary.Free(edict);

                return(null);
            }
        }
Example #6
0
        public void Blocked(Edict pentBlocked, Edict pentOther)
        {
            var blocked = pentBlocked.Entity();

            var other = pentOther.Entity();

            blocked?.Blocked(other);
        }
Example #7
0
        public int Spawn(Edict pent)
        {
            var pEntity = pent.Entity();

            if (pEntity != null)
            {
                // Initialize these or entities who don't link to the world won't have anything in here
                pEntity.AbsMin = pEntity.Origin - new Vector(1, 1, 1);
                pEntity.AbsMax = pEntity.Origin + new Vector(1, 1, 1);

                pEntity.Spawn();

                // Try to get the pointer again, in case the spawn function deleted the entity.
                // UNDONE: Spawn() should really return a code to ask that the entity be deleted, but
                // that would touch too much code for me to do that right now.
                pEntity = pent.Entity();

                if (pEntity != null)
                {
                    if (!Engine.GameRules.IsAllowedToSpawn(pEntity))
                    {
                        return(-1);  // return that this entity should be deleted
                    }
                    if (0 != (pEntity.Flags & EntFlags.KillMe))
                    {
                        return(-1);
                    }
                }

                // Handle global stuff here
                if (pEntity != null && !string.IsNullOrEmpty(pEntity.GlobalName))
                {
                    var pGlobal = Globals.GlobalState.EntityFromTable(pEntity.GlobalName);
                    if (pGlobal != null)
                    {
                        // Already dead? delete
                        if (pGlobal.State == GlobalEState.Dead)
                        {
                            return(-1);
                        }
                        else if (Engine.Globals.MapName != pGlobal.LevelName)
                        {
                            pEntity.MakeDormant();  // Hasn't been moved to this level yet, wait but stay alive
                        }
                        // In this level & not dead, continue on as normal
                    }
                    else
                    {
                        // Spawned entities default to 'On'
                        Globals.GlobalState.EntityAdd(pEntity.GlobalName, Engine.Globals.MapName, GlobalEState.On);
                        //				Log.Alert(AlertType.Console, $"Added global entity {pEntity.ClassName} ({pEntity.GlobalName})\n");
                    }
                }
            }

            return(0);
            //TODO: define return codes
        }
Example #8
0
        public unsafe int EntityIndex(Edict edict)
        {
            if (edict == null)
            {
                throw new ArgumentNullException(nameof(edict));
            }

            return(EntityIndex(edict.Data));
        }
Example #9
0
        public unsafe IInfoBuffer GetClientPhysicsInfoBuffer(Edict pClient)
        {
            if (!ServerAPIUtils.IsClient(pClient, EntityDictionary, Globals))
            {
                throw new ArgumentException("Edict must be a client", nameof(pClient));
            }

            return(new ClientPhysicsInfoBuffer(EngineFuncs, pClient.Data, EntityDictionary.EntityIndex(pClient)));
        }
Example #10
0
        public unsafe IntPtr GetUnmanagedClientPhysicsInfoBuffer(Edict pClient)
        {
            if (!ServerAPIUtils.IsClient(pClient, EntityDictionary, Globals))
            {
                throw new ArgumentException("Edict must be a client", nameof(pClient));
            }

            return(EngineFuncs.pfnGetPhysicsInfoString(pClient.Data));
        }
Example #11
0
 public void OnFreeEntPrivateData(Edict pEnt)
 {
     if (pEnt.PrivateData != null)
     {
         //Inform of destruction
         pEnt.Entity().OnDestroy();
         //Mark the private data as freed, and set the managed instance to be garbage collected
         pEnt.PrivateData = null;
     }
 }
Example #12
0
        /// <summary>
        /// Called when a new client connects (unsquelches its entity for everyone)
        /// </summary>
        /// <param name="edict"></param>
        public void ClientConnected(Edict edict)
        {
            var index = EntUtils.EntIndex(edict) - 1;

            var data = Players[index];

            // Clear out everything we use for deltas on this guy.
            data.WantEnable         = true;
            data.SentGameRulesMasks = new BitVector32();
            data.SentBanMasks       = new BitVector32();
        }
Example #13
0
        internal static bool IsClient(Edict edict, IEntityDictionary entityDictionary, IGlobalVars globalVars)
        {
            if (edict == null)
            {
                return(false);
            }

            var index = entityDictionary.EntityIndex(edict);

            return(0 < index && index <= globalVars.MaxClients);
        }
Example #14
0
        public void SetAbsBox(Edict pent)
        {
            var entity = pent.TryGetEntity();

            if (entity == null)
            {
                throw new InvalidOperationException($"Error: Entity \"{pent.Vars.ClassName}\" (index {EntUtils.EntIndex(pent)}) has no entity instance assigned for SetAbsBox call");
            }

            entity.SetObjectCollisionBox();
        }
Example #15
0
        public void Use(Edict pentUsed, Edict pentOther)
        {
            var used = pentUsed.Entity();

            var other = pentOther.Entity();

            if (used != null && (used.Flags & EntFlags.KillMe) == 0)
            {
                used.Use(other, other, UseType.Toggle, 0);
            }
        }
        public unsafe INetworkMessage Begin(MsgDest msg_dest, int msg_type, Edict ed = null)
        {
            if (CurrentMessage != null)
            {
                throw new InvalidOperationException("Cannot start a network message while another message is active");
            }

            EngineFuncs.pfnMessageBegin(msg_dest, msg_type, IntPtr.Zero, ed.Data);

            CurrentMessage = new NetworkMessage(EngineFuncs, this);

            return(CurrentMessage);
        }
Example #17
0
        public void KeyValue(Edict pentKeyvalue, KeyValueData pkvd)
        {
            //Log.Message($"Entity {EntityDictionary.EntityIndex(pentKeyvalue)}/{EntityDictionary.Max} KeyValue ClassName=\"{pkvd.ClassName}\" Key=\"{pkvd.KeyName}\" Value=\"{pkvd.Value}\"");

            if (pkvd.KeyName == "classname")
            {
                if (pentKeyvalue.PrivateData == null)
                {
                    Log.Message($"Creating entity \"{pkvd.Value}\"");

                    //Create the entity instance
                    EntityRegistry.CreateInstance <BaseEntity>(pentKeyvalue);

                    Log.Message("Created entity");
                }
                else
                {
                    var ent = (BaseEntity)pentKeyvalue.PrivateData;

                    //This should never happen
                    if (pkvd.Value != ent.ClassName)
                    {
                        throw new InvalidOperationException($"Second occurence of classname keyvalue has different value (Expected: {ent.ClassName}, actual:{pkvd.Value})");
                    }

                    pkvd.Handled = true;
                    return;
                }
            }

            if (pentKeyvalue.PrivateData == null)
            {
                throw new InvalidOperationException($"Cannot set keyvalue \"{pkvd.KeyName}={pkvd.Value}\" on null entity of class {pkvd.ClassName}");
            }

            pkvd.Handled = false;

            var entity = (BaseEntity)pentKeyvalue.PrivateData;

            //TODO: uniformly handle keyvalue initialization

            switch (pkvd.KeyName)
            {
            case "classname":
            {
                entity.ClassName = pkvd.Value;
                pkvd.Handled     = true;
                break;
            }
            }
        }
Example #18
0
        public void Think(Edict pent)
        {
            var thinker = pent.Entity();

            if (thinker != null)
            {
                if ((thinker.Flags & EntFlags.Dormant) != 0)
                {
                    Log.Alert(AlertType.Error, $"Dormant entity {thinker.ClassName} is thinking!!");
                }

                thinker.Think();
            }
        }
Example #19
0
        internal unsafe EntityDictionary(EngineFuncs engineFuncs)
        {
            EngineFuncs = engineFuncs ?? throw new ArgumentNullException(nameof(engineFuncs));

            var size = Marshal.SizeOf <Edict.Native>();

            var dummyNative = Marshal.AllocHGlobal(size);

            //Zero memory using a zero initialized array
            var bytes = new byte[size];

            Marshal.Copy(bytes, 0, dummyNative, size);

            EmptyEdict = new Edict((Edict.Native *)dummyNative.ToPointer());
        }
Example #20
0
        public void PutInServer(Edict pEntity)
        {
            var player = EntityRegistry.CreateInstance <BasePlayer>(pEntity);

            player.SetCustomDecalFrames(-1); // Assume none;

            // Allocate a CBasePlayer for pev, and call spawn
            player.Spawn();

            // Reset interpolation during first frame
            player.Effects |= EntityEffects.NoInterp;

            player.pev.UserInt1 = 0;   // disable any spec modes
            player.pev.UserInt2 = 0;
        }
Example #21
0
        public void Touch(Edict pentTouched, Edict pentOther)
        {
            if (TouchDisabled)
            {
                return;
            }

            var touched = pentTouched.Entity();

            var other = pentOther.Entity();

            if (touched != null && other != null && ((touched.Flags | other.Flags) & EntFlags.KillMe) == 0)
            {
                touched.Touch(other);
            }
        }
Example #22
0
 public void EmitSound(Edict entity, SoundChannel channel, string sample, float volume, float attenuation, SoundFlags flags, int pitch)
 {
     if (sample?.FirstOrDefault() == '!')
     {
         if (Sentences.GetSentenceIndex(sample, out var name) >= 0)
         {
             EmitSound2(entity, channel, name, volume, attenuation, flags, pitch);
         }
         else
         {
             Log.Alert(AlertType.AIConsole, $"Unable to find ^{sample} in sentences.txt");
         }
     }
     else
     {
         EmitSound2(entity, channel, sample, volume, attenuation, flags, pitch);
     }
 }
Example #23
0
        public void SetModel(Edict edict, string modelName)
        {
            if (modelName == null)
            {
                throw new ArgumentNullException(nameof(modelName));
            }

            //TODO: brush models should be precached manaully to match the engine
            //TODO: use a default model so it will always succeed
            if (!BrushModelNameRegex.IsMatch(modelName) && EngineServer.ModelCache.Find(modelName) == null)
            {
                throw new NotPrecachedException($"Model \"{modelName}\" not precached");
            }

            //The engine sets the model name using what we've passed in
            var pooled = StringPool.GetPooledString(modelName);

            EngineFuncs.pfnSetModel(edict.Data, pooled);
        }
Example #24
0
        public unsafe object GetModel(Edict edict)
        {
            if (edict == null)
            {
                return(null);
            }

            var modelName = edict.Vars.ModelName;

            if (!string.IsNullOrEmpty(modelName))
            {
                return(null);
            }

            if (Models.TryGetValue(modelName, out var model))
            {
                return(model);
            }

            var nativeData = EngineFuncs.pfnGetModelPtr(edict.Data);

            if (modelName.StartsWith('*'))
            {
                //BSP model
            }
            else if (modelName.EndsWith(".mdl"))
            {
                //Studio model
                model = new StudioHeader((StudioHeader.Native *)nativeData.ToPointer());
            }
            else if (modelName.EndsWith(".spr"))
            {
                //Sprite
            }

            if (model != null)
            {
                Models.Add(modelName, model);
            }

            return(model);
        }
Example #25
0
        public void Command(Edict pEntity, ICommand command)
        {
            // Is the client spawned yet?
            var player = pEntity.TryGetEntity <BasePlayer>();

            if (player == null)
            {
                return;
            }

            var commandName = command.Name;

            //TODO: implement commands

            if (commandName == PlayerUtils.SayCommandName)
            {
                PlayerUtils.HostSay(player, command, false);
            }
            else if (commandName == PlayerUtils.SayTeamCommandName)
            {
                PlayerUtils.HostSay(player, command, true);
            }
            else if (commandName == "closemenus")
            {
                // just ignore it
            }
            else if (Engine.GameRules.ClientCommand(player, command))
            {
                // MenuSelect returns true only if the command is properly handled,  so don't print a warning
            }
            else
            {
                // check the length of the command (prevents crash)
                // max total length is 192 ...and we're adding a string below ("Unknown command: %s\n")
                var printableName = commandName.Length > 127 ? commandName.Substring(0, 127) : commandName;

                // tell the user they entered an unknown command
                PlayerUtils.ClientPrint(player, HudPrint.Console, $"Unknown command: {printableName}\n");
            }
        }
Example #26
0
        public void SetupVisibility(Edict pViewEntity, Edict pClient, out IntPtr pvs, out IntPtr pas)
        {
            var client = pClient.Entity();

            // Find the client's PVS
            var view = pViewEntity?.TryGetEntity() ?? client;

            if ((client.Flags & EntFlags.Proxy) != 0)
            {
                pvs = IntPtr.Zero;    // the spectator proxy sees
                pas = IntPtr.Zero;    // and hears everything
                return;
            }

            var org = view.Origin + view.ViewOffset;

            if ((view.Flags & EntFlags.Ducking) != 0)
            {
                org += (WorldConstants.HULL_MIN - WorldConstants.DUCK_HULL_MIN);
            }

            pvs = EngineServer.SetFatPVS(org);
            pas = EngineServer.SetFatPAS(org);
        }
Example #27
0
        public void UpdateClientData(Edict ent, bool sendWeapons, ClientData cd)
        {
            if (ent == null || ent.PrivateData == null)
            {
                return;
            }

            var player = ent.TryGetEntity <BasePlayer>();

            BasePlayer originalPlayer = null;

            // if user is spectating different player in First person, override some vars
            if (player?.pev.UserInt1 == (int)ObserverMode.InEye && player.m_hObserverTarget)
            {
                originalPlayer = player;
                player         = player.m_hObserverTarget;
            }

            cd.Flags  = player.Flags;
            cd.Health = player.Health;

            cd.ViewModel = EngineModel.IndexOf(player.ViewModelName);

            cd.WaterLevel = player.WaterLevel;
            cd.WaterType  = player.WaterType;
            cd.Weapons    = player.pev.Weapons;

            // Vectors
            cd.Origin     = player.Origin;
            cd.Velocity   = player.Velocity;
            cd.ViewOffset = player.ViewOffset;
            cd.PunchAngle = player.PunchAngle;

            cd.InDuck        = player.pev.InDuck;
            cd.TimeStepSound = player.pev.TimeStepSound;
            cd.DuckTime      = player.pev.DuckTime;
            cd.SwimTime      = player.pev.SwimTime;
            cd.WaterJumpTime = (int)player.pev.TeleportTime;

            cd.SetPhysInfo(EngineServer.GetUnmanagedClientPhysicsInfoBuffer(ent));

            cd.MaxSpeed    = player.pev.MaxSpeed;
            cd.FieldOfView = player.pev.FieldOfView;
            cd.WeaponAnim  = player.pev.WeaponAnim;

            cd.PushMSec = player.pev.PushMSec;

            //Spectator mode
            if (originalPlayer != null)
            {
                // don't use spec vars from chased player
                cd.UserInt1 = originalPlayer.pev.UserInt1;
                cd.UserInt2 = originalPlayer.pev.UserInt2;
            }
            else
            {
                cd.UserInt1 = player.pev.UserInt1;
                cd.UserInt2 = player.pev.UserInt2;
            }

#if CLIENT_WEAPONS
            if (sendWeapons && player != null)
            {
                cd.NextAttack = player.m_flNextAttack;
                cd.UserFloat2 = player.m_flNextAmmoBurn;
                cd.UserFloat3 = player.m_flAmmoStartCharge;

                cd.UserVector1 = new Vector(
                    player.ammo_9mm,
                    player.ammo_357,
                    player.ammo_argrens
                    );

                cd.AmmoNails   = player.ammo_bolts;
                cd.AmmoShells  = player.ammo_buckshot;
                cd.AmmoRockets = player.ammo_rockets;
                cd.AmmoCells   = player.ammo_uranium;
                var vector2 = cd.UserVector2;
                vector2.x      = player.ammo_hornets;
                cd.UserVector2 = vector2;

                if (player.m_pActiveItem != null)
                {
                    BasePlayerWeapon gun = player.m_pActiveItem as BasePlayerWeapon;

                    if (gun?.IsPredicted() == true)
                    {
                        //TODO:
#if false
                        ItemInfo II;
                        memset(&II, 0, sizeof(II));
                        gun.GetItemInfo(&II);

                        cd.m_iId = II.iId;

                        cd.vuser3.z = gun.m_iSecondaryAmmoType;
                        cd.vuser4.x = gun.m_iPrimaryAmmoType;
                        cd.vuser4.y = player.m_rgAmmo[gun.m_iPrimaryAmmoType];
                        cd.vuser4.z = player.m_rgAmmo[gun.m_iSecondaryAmmoType];

                        if (player.m_pActiveItem.m_iId == WEAPON_RPG)
                        {
                            cd.vuser2.y = ((Rpg)player.m_pActiveItem).m_fSpotActive;
                            cd.vuser2.z = ((Rpg)player.m_pActiveItem).m_cActiveRockets;
                        }
#endif
                    }
                }
            }
#endif
        }
Example #28
0
 public void CreateBaseline(bool isPlayer, int eindex, EntityState baseline, Edict entity, int playermodelindex, in Vector playerMins, in Vector playerMaxs)
Example #29
0
        public bool AddToFullPack(EntityState state, int e, Edict ent, Edict host, HostFlags hostFlags, bool isPlayer, IntPtr pSet)
        {
            //Never add entities that aren't in use
            if (ent.Free)
            {
                return(false);
            }

            var entity     = ent.Entity();
            var hostEntity = host.Entity();

            // don't send if flagged for NODRAW and it's not the host getting the message
            if ((entity.Effects & EntityEffects.NoDraw) != 0 &&
                (entity != hostEntity))
            {
                return(false);
            }

            // Ignore ents without valid / visible models
            if (entity.ModelIndex == 0 || string.IsNullOrEmpty(entity.ModelName))
            {
                return(false);
            }

            // Don't send spectators to other players
            if ((entity.Flags & EntFlags.Spectator) != 0 && (entity != hostEntity))
            {
                return(false);
            }

            // Ignore if not the host and not touching a PVS/PAS leaf
            // If pSet is NULL, then the test will always succeed and the entity will be added to the update
            if (entity != hostEntity)
            {
                if (!EngineServer.CheckVisibility(ent, pSet))
                {
                    return(false);
                }
            }

            // Don't send entity to local client if the client says it's predicting the entity itself.
            if ((entity.Flags & EntFlags.SkipLocalHost) != 0)
            {
                if ((hostFlags & HostFlags.SkipLocalEnts) != 0 && (entity.Owner == hostEntity))
                {
                    return(false);
                }
            }

            if (hostEntity.GroupInfo != 0)
            {
                Trace.PushGroupTrace(hostEntity.GroupInfo, GroupOp.And);

                try
                {
                    Trace.GetGroupTrace(out var currentMask, out var currentOp);

                    // Should always be set, of course
                    if (entity.GroupInfo != 0)
                    {
                        if (currentOp == GroupOp.And)
                        {
                            if ((entity.GroupInfo & hostEntity.GroupInfo) == 0)
                            {
                                return(false);
                            }
                        }
                        else if (currentOp == GroupOp.NAnd)
                        {
                            if ((entity.GroupInfo & hostEntity.GroupInfo) != 0)
                            {
                                return(false);
                            }
                        }
                    }
                }
                finally
                {
                    //There is a bug in the SDK that can cause the last group trace to remain if it failed the tests above
                    Trace.PopGroupTrace();
                }
            }

            //This is done by the wrapper since there's no memset in managed code
            //memset(state, 0, sizeof( * state) );

            // Assign index so we can track this entity from frame to frame and
            //  delta from it.
            state.Number     = e;
            state.EntityType = EntityType.Normal;

            // Flag custom entities.
            if ((entity.Flags & EntFlags.CustomEntity) != 0)
            {
                state.EntityType = EntityType.Beam;
            }

            //
            // Copy state data
            //

            // Round animtime to nearest millisecond
            state.AnimTime = (float)((int)(1000.0 * entity.AnimationTime) / 1000.0);

            state.Origin = entity.Origin;
            state.Angles = entity.Angles;
            state.Mins   = entity.Mins;
            state.Maxs   = entity.Maxs;

            state.EndPos   = entity.EndPosition;
            state.StartPos = entity.StartPosition;

            state.ImpactTime = entity.ImpactTime;
            state.StartTime  = entity.StartTime;

            state.ModelIndex = entity.ModelIndex;

            state.Frame = entity.Frame;

            state.Skin    = (short)entity.Skin;
            state.Effects = entity.Effects;

            // This non-player entity is being moved by the game .dll and not the physics simulation system
            //  make sure that we interpolate it's position on the client if it moves
            if (!isPlayer &&
                entity.AnimationTime != 0 &&
                entity.Velocity[0] == 0 &&
                entity.Velocity[1] == 0 &&
                entity.Velocity[2] == 0)
            {
                state.EFlags |= EntityStateFlags.SLerp;
            }

            state.Scale    = entity.Scale;
            state.Solid    = entity.Solid;
            state.ColorMap = entity.ColorMap;

            state.MoveType  = entity.MoveType;
            state.Sequence  = entity.Sequence;
            state.FrameRate = entity.FrameRate;
            state.Body      = entity.Body;

            for (var i = 0; i < 4; ++i)
            {
                state.SetController(i, entity.GetController(i));
            }

            for (var i = 0; i < 2; ++i)
            {
                state.SetBlending(i, entity.GetBlending(i));
            }

            state.RenderMode   = entity.RenderMode;
            state.RenderAmount = (int)entity.RenderAmount;
            state.RenderEffect = entity.RenderEffect;

            state.RenderColor = new Color24
            {
                r = (byte)entity.RenderColor.x,
                g = (byte)entity.RenderColor.y,
                b = (byte)entity.RenderColor.z
            };

            state.AimEnt = 0;
            if (entity.AimEntity != null)
            {
                state.AimEnt = entity.AimEntity.EntIndex();
            }

            state.Owner = 0;
            if (entity.Owner != null)
            {
                var owner = entity.Owner.EntIndex();

                // Only care if owned by a player
                if (owner >= 1 && owner <= Globals.MaxClients)
                {
                    state.Owner = owner;
                }
            }

            // HACK:  Somewhat...
            // Class is overridden for non-players to signify a breakable glass object ( sort of a class? )
            if (!isPlayer)
            {
                state.PlayerClass = entity.PlayerClass;
            }

            // Special stuff for players only
            if (isPlayer)
            {
                state.BaseVelocity = entity.BaseVelocity;

                state.WeaponModel  = EngineModel.IndexOf(entity.WeaponModelName);
                state.GaitSequence = entity.GaitSequence;
                state.Spectator    = (entity.Flags & EntFlags.Spectator) != 0;
                state.Friction     = entity.Friction;

                state.Gravity = entity.Gravity;
                //		state.Team			= entity.Team;
                //
                state.UseHull = (entity.Flags & EntFlags.Ducking) != 0 ? 1 : 0;
                state.Health  = (int)entity.Health;
            }

            return(true);
        }
        public unsafe INetworkMessage Begin(MsgDest msg_dest, int msg_type, Vector pOrigin, Edict ed = null)
        {
            if (CurrentMessage != null)
            {
                throw new InvalidOperationException("Cannot start a network message while another message is active");
            }

            var originAddress = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Vector)));

            try
            {
                Marshal.StructureToPtr(pOrigin, originAddress, false);
                EngineFuncs.pfnMessageBegin(msg_dest, msg_type, originAddress, ed.Data);
            }
            finally
            {
                Marshal.FreeHGlobal(originAddress);
            }

            CurrentMessage = new NetworkMessage(EngineFuncs, this);

            return(CurrentMessage);
        }