Inheritance: mnodebase_t
示例#1
0
        /// <summary>
        /// PF_checkclient
        /// Returns a client (or object that has a client enemy) that would be a
        /// valid target.
        ///
        /// If there are more than one valid options, they are cycled each frame
        ///
        /// If (self.origin + self.viewofs) is not in the PVS of the current target,
        /// it is not returned at all.
        ///
        /// name checkclient ()
        /// </summary>
        static void PF_checkclient()
        {
            // find a new check if on a new frame
            if (Server.sv.time - Server.sv.lastchecktime >= 0.1)
            {
                Server.sv.lastcheck     = PF_newcheckclient(Server.sv.lastcheck);
                Server.sv.lastchecktime = Server.sv.time;
            }

            // return check if it might be visible
            edict_t ent = Server.EdictNum(Server.sv.lastcheck);

            if (ent.free || ent.v.health <= 0)
            {
                ReturnEdict(Server.sv.edicts[0]);
                return;
            }

            // if current entity can't possibly see the check entity, return 0
            edict_t self = Server.ProgToEdict(Progs.GlobalStruct.self);
            Vector3 view = Common.ToVector(ref self.v.origin) + Common.ToVector(ref self.v.view_ofs);
            mleaf_t leaf = Mod.PointInLeaf(ref view, Server.sv.worldmodel);
            int     l    = Array.IndexOf(Server.sv.worldmodel.leafs, leaf) - 1;

            if ((l < 0) || (_CheckPvs[l >> 3] & (1 << (l & 7))) == 0)
            {
                _NotVisCount++;
                ReturnEdict(Server.sv.edicts[0]);
                return;
            }

            // might be able to see it
            _InVisCount++;
            ReturnEdict(ent);
        }
示例#2
0
 public void Clear()
 {
     this.leaf = null;
     this.leafnext = null;
     this.entity = null;
     this.entnext = null;
 }
示例#3
0
        // S_UpdateAmbientSounds
        static void UpdateAmbientSounds()
        {
            if (!_Ambient)
            {
                return;
            }

            // calc ambient sound levels
            if (Client.Cl.worldmodel == null)
            {
                return;
            }

            mleaf_t l = Mod.PointInLeaf(ref _ListenerOrigin, Client.Cl.worldmodel);

            if (l == null || _AmbientLevel.Value == 0)
            {
                for (int i = 0; i < Ambients.NUM_AMBIENTS; i++)
                {
                    _Channels[i].sfx = null;
                }

                return;
            }

            for (int i = 0; i < Ambients.NUM_AMBIENTS; i++)
            {
                channel_t chan = _Channels[i];
                chan.sfx = _AmbientSfx[i];

                float vol = _AmbientLevel.Value * l.ambient_sound_level[i];
                if (vol < 8)
                {
                    vol = 0;
                }

                // don't adjust volume too fast
                if (chan.master_vol < vol)
                {
                    chan.master_vol += (int)(Host.FrameTime * _AmbientFade.Value);
                    if (chan.master_vol > vol)
                    {
                        chan.master_vol = (int)vol;
                    }
                }
                else if (chan.master_vol > vol)
                {
                    chan.master_vol -= (int)(Host.FrameTime * _AmbientFade.Value);
                    if (chan.master_vol < vol)
                    {
                        chan.master_vol = (int)vol;
                    }
                }

                chan.leftvol = chan.rightvol = chan.master_vol;
            }
        }
示例#4
0
        /// <summary>
        /// SV_FindTouchedLeafs
        /// </summary>
        static void FindTouchedLeafs(edict_t ent, mnodebase_t node)
        {
            if (node.contents == Contents.CONTENTS_SOLID)
            {
                return;
            }

            // add an efrag if the node is a leaf

            if (node.contents < 0)
            {
                if (ent.num_leafs == Progs.MAX_ENT_LEAFS)
                {
                    return;
                }

                mleaf_t leaf    = (mleaf_t)node;
                int     leafnum = Array.IndexOf(sv.worldmodel.leafs, leaf) - 1;

                ent.leafnums[ent.num_leafs] = (short)leafnum;
                ent.num_leafs++;
                return;
            }

            // NODE_MIXED
            mnode_t  n          = (mnode_t)node;
            mplane_t splitplane = n.plane;
            int      sides      = Mathlib.BoxOnPlaneSide(ref ent.v.absmin, ref ent.v.absmax, splitplane);

            // recurse down the contacted sides
            if ((sides & 1) != 0)
            {
                FindTouchedLeafs(ent, n.children[0]);
            }

            if ((sides & 2) != 0)
            {
                FindTouchedLeafs(ent, n.children[1]);
            }
        }
示例#5
0
        /// <summary>
        /// R_RecursiveWorldNode
        /// </summary>
        private static void RecursiveWorldNode(mnodebase_t node)
        {
            if (node.contents == Contents.CONTENTS_SOLID)
            {
                return;         // solid
            }
            if (node.visframe != _VisFrameCount)
            {
                return;
            }
            if (CullBox(ref node.mins, ref node.maxs))
            {
                return;
            }

            int c;

            // if a leaf node, draw stuff
            if (node.contents < 0)
            {
                mleaf_t      pleaf = (mleaf_t)node;
                msurface_t[] marks = pleaf.marksurfaces;
                int          mark  = pleaf.firstmarksurface;
                c = pleaf.nummarksurfaces;

                if (c != 0)
                {
                    do
                    {
                        marks[mark].visframe = _FrameCount;
                        mark++;
                    } while(--c != 0);
                }

                // deal with model fragments in this leaf
                if (pleaf.efrags != null)
                {
                    StoreEfrags(pleaf.efrags);
                }

                return;
            }

            // node is just a decision point, so go down the apropriate sides

            mnode_t n = (mnode_t)node;

            // find which side of the node we are on
            mplane_t plane = n.plane;
            double   dot;

            switch (plane.type)
            {
            case Planes.PLANE_X:
                dot = _ModelOrg.X - plane.dist;
                break;

            case Planes.PLANE_Y:
                dot = _ModelOrg.Y - plane.dist;
                break;

            case Planes.PLANE_Z:
                dot = _ModelOrg.Z - plane.dist;
                break;

            default:
                dot = Vector3.Dot(_ModelOrg, plane.normal) - plane.dist;
                break;
            }

            int side = (dot >= 0 ? 0 : 1);

            // recurse down the children, front side first
            RecursiveWorldNode(n.children[side]);

            // draw stuff
            c = n.numsurfaces;

            if (c != 0)
            {
                msurface_t[] surf   = client.cl.worldmodel.surfaces;
                int          offset = n.firstsurface;

                if (dot < 0 - QDef.BACKFACE_EPSILON)
                {
                    side = Surf.SURF_PLANEBACK;
                }
                else if (dot > QDef.BACKFACE_EPSILON)
                {
                    side = 0;
                }

                for ( ; c != 0; c--, offset++)
                {
                    if (surf[offset].visframe != _FrameCount)
                    {
                        continue;
                    }

                    // don't backface underwater surfaces, because they warp
                    if ((surf[offset].flags & Surf.SURF_UNDERWATER) == 0 && ((dot < 0) ^ ((surf[offset].flags & Surf.SURF_PLANEBACK) != 0)))
                    {
                        continue;               // wrong side
                    }
                    // if sorting by texture, just store it out
                    if (_glTexSort.Value != 0)
                    {
                        if (!_IsMirror || surf[offset].texinfo.texture != client.cl.worldmodel.textures[_MirrorTextureNum])
                        {
                            surf[offset].texturechain = surf[offset].texinfo.texture.texturechain;
                            surf[offset].texinfo.texture.texturechain = surf[offset];
                        }
                    }
                    else if ((surf[offset].flags & Surf.SURF_DRAWSKY) != 0)
                    {
                        surf[offset].texturechain = _SkyChain;
                        _SkyChain = surf[offset];
                    }
                    else if ((surf[offset].flags & Surf.SURF_DRAWTURB) != 0)
                    {
                        surf[offset].texturechain = _WaterChain;
                        _WaterChain = surf[offset];
                    }
                    else
                    {
                        DrawSequentialPoly(surf[offset]);
                    }
                }
            }

            // recurse down the back side
            RecursiveWorldNode(n.children[side == 0 ? 1 : 0]);
        }
示例#6
0
        /// <summary>
        /// R_SplitEntityOnNode
        /// </summary>
        static void SplitEntityOnNode(mnodebase_t node)
        {
            if (node.contents == Contents.CONTENTS_SOLID)
            {
                return;
            }

            // add an efrag if the node is a leaf
            if (node.contents < 0)
            {
                if (_EfragTopNode == null)
                {
                    _EfragTopNode = node as mnode_t;
                }

                mleaf_t leaf = (mleaf_t)(object)node;

                // grab an efrag off the free list
                EFrag ef = Client.Cl.free_efrags;
                if (ef == null)
                {
                    Con.Print("Too many efrags!\n");
                    return;     // no free fragments...
                }
                Client.Cl.free_efrags = Client.Cl.free_efrags.entnext;

                ef.entity = _AddEnt;

                // add the entity link
                // *lastlink = ef;
                if (_LastObj is Entity)
                {
                    ((Entity)_LastObj).efrag = ef;
                }
                else
                {
                    ((EFrag)_LastObj).entnext = ef;
                }
                _LastObj   = ef; // lastlink = &ef->entnext;
                ef.entnext = null;

                // set the leaf links
                ef.leaf     = leaf;
                ef.leafnext = leaf.efrags;
                leaf.efrags = ef;

                return;
            }

            // NODE_MIXED
            mnode_t n = node as mnode_t;

            if (n == null)
            {
                return;
            }

            mplane_t splitplane = n.plane;
            int      sides      = Mathlib.BoxOnPlaneSide(ref _EMins, ref _EMaxs, splitplane);

            if (sides == 3)
            {
                // split on this plane
                // if this is the first splitter of this bmodel, remember it
                if (_EfragTopNode == null)
                {
                    _EfragTopNode = n;
                }
            }

            // recurse down the contacted sides
            if ((sides & 1) != 0)
            {
                SplitEntityOnNode(n.children[0]);
            }

            if ((sides & 2) != 0)
            {
                SplitEntityOnNode(n.children[1]);
            }
        }
示例#7
0
        /// <summary>
        /// R_NewMap
        /// </summary>
        public static void NewMap()
        {
            for (int i = 0; i < 256; i++)
                _LightStyleValue[i] = 264;		// normal light value

            _WorldEntity.Clear();
            _WorldEntity.model = Client.cl.worldmodel;

            // clear out efrags in case the level hasn't been reloaded
            // FIXME: is this one short?
            for (int i = 0; i < Client.cl.worldmodel.numleafs; i++)
                Client.cl.worldmodel.leafs[i].efrags = null;

            _ViewLeaf = null;
            ClearParticles();

            BuildLightMaps();

            // identify sky texture
            _SkyTextureNum = -1;
            _MirrorTextureNum = -1;
            model_t world = Client.cl.worldmodel;
            for (int i = 0; i < world.numtextures; i++)
            {
                if (world.textures[i] == null)
                    continue;
                if (world.textures[i].name != null)
                {
                    if (world.textures[i].name.StartsWith("sky"))
                        _SkyTextureNum = i;
                    if (world.textures[i].name.StartsWith("window02_1"))
                        _MirrorTextureNum = i;
                }
                world.textures[i].texturechain = null;
            }
        }
示例#8
0
        /// <summary>
        /// R_SetupFrame
        /// </summary>
        static void SetupFrame()
        {
            // don't allow cheats in multiplayer
            if (Client.cl.maxclients > 1)
                Cvar.Set("r_fullbright", "0");

            AnimateLight();

            _FrameCount++;

            // build the transformation matrix for the given view angles
            Render.Origin = _RefDef.vieworg;

            Mathlib.AngleVectors(ref _RefDef.viewangles, out ViewPn, out ViewRight, out ViewUp);

            // current viewleaf
            _OldViewLeaf = _ViewLeaf;
            _ViewLeaf = Mod.PointInLeaf(ref Render.Origin, Client.cl.worldmodel);

            View.SetContentsColor(_ViewLeaf.contents);
            View.CalcBlend();

            _CacheThrash = false;
            _BrushPolys = 0;
            _AliasPolys = 0;
        }
示例#9
0
        static int PF_newcheckclient(int check)
        {
            // cycle to the next one

            if (check < 1)
            {
                check = 1;
            }

            if (check > Server.svs.maxclients)
            {
                check = Server.svs.maxclients;
            }

            int i = check + 1;

            if (check == Server.svs.maxclients)
            {
                i = 1;
            }

            edict_t ent;

            for (; ; i++)
            {
                if (i == Server.svs.maxclients + 1)
                {
                    i = 1;
                }

                ent = Server.EdictNum(i);

                if (i == check)
                {
                    break;  // didn't find anything else
                }

                if (ent.free)
                {
                    continue;
                }

                if (ent.v.health <= 0)
                {
                    continue;
                }

                if (((int)ent.v.flags & EdictFlags.FL_NOTARGET) != 0)
                {
                    continue;
                }

                // anything that is a client, or has a client as an enemy
                break;
            }

            // get the PVS for the entity
            Vector3 org  = Common.ToVector(ref ent.v.origin) + Common.ToVector(ref ent.v.view_ofs);
            mleaf_t leaf = Mod.PointInLeaf(ref org, Server.sv.worldmodel);

            byte[] pvs = Mod.LeafPVS(leaf, Server.sv.worldmodel);
            Buffer.BlockCopy(pvs, 0, _CheckPvs, 0, pvs.Length);

            return(i);
        }
示例#10
0
        /// <summary>
        /// Mod_LeafPVS
        /// </summary>
        public static byte[] LeafPVS(mleaf_t leaf, model_t model)
        {
            if (leaf == model.leafs[0])
                return _Novis;

            return DecompressVis(leaf.compressed_vis, leaf.visofs, model);
        }
示例#11
0
        /// <summary>
        /// Mod_LoadLeafs
        /// </summary>
        static void LoadLeafs(ref lump_t l)
        {
            if ((l.filelen % dleaf_t.SizeInBytes) != 0)
                Sys.Error("MOD_LoadBmodel: funny lump size in {0}", _LoadModel.name);

            int count = l.filelen / dleaf_t.SizeInBytes;
            mleaf_t[] dest = new mleaf_t[count];

            for (int i = 0; i < dest.Length; i++)
                dest[i] = new mleaf_t();

            _LoadModel.leafs = dest;
            _LoadModel.numleafs = count;

            for (int i = 0, offset = l.fileofs; i < count; i++, offset += dleaf_t.SizeInBytes)
            {
                dleaf_t src = Sys.BytesToStructure<dleaf_t>(_ModBase, offset);

                dest[i].mins.X = Common.LittleShort(src.mins[0]);
                dest[i].mins.Y = Common.LittleShort(src.mins[1]);
                dest[i].mins.Z = Common.LittleShort(src.mins[2]);

                dest[i].maxs.X = Common.LittleShort(src.maxs[0]);
                dest[i].maxs.Y = Common.LittleShort(src.maxs[1]);
                dest[i].maxs.Z = Common.LittleShort(src.maxs[2]);

                int p = Common.LittleLong(src.contents);
                dest[i].contents = p;

                dest[i].marksurfaces = _LoadModel.marksurfaces;
                dest[i].firstmarksurface = Common.LittleShort((short)src.firstmarksurface);
                dest[i].nummarksurfaces = Common.LittleShort((short)src.nummarksurfaces);

                p = Common.LittleLong(src.visofs);
                if (p == -1)
                    dest[i].compressed_vis = null;
                else
                {
                    dest[i].compressed_vis = _LoadModel.visdata; // loadmodel->visdata + p;
                    dest[i].visofs = p;
                }
                dest[i].efrags = null;

                for (int j = 0; j < 4; j++)
                    dest[i].ambient_sound_level[j] = src.ambient_level[j];

                // gl underwater warp
                // Uze: removed underwater warp as too ugly
                //if (dest[i].contents != Contents.CONTENTS_EMPTY)
                //{
                //    for (int j = 0; j < dest[i].nummarksurfaces; j++)
                //        dest[i].marksurfaces[dest[i].firstmarksurface + j].flags |= Surf.SURF_UNDERWATER;
                //}
            }
        }