Beispiel #1
0
        private GameObject InstantiateRootNiObject(NiObject obj)
        {
            var gameObject = InstantiateNiObject(obj);

            bool shouldAddMissingColliders, isMarker;

            ProcessExtraData(obj, out shouldAddMissingColliders, out isMarker);

            if ((file.name != null) && IsMarkerFileName(file.name))
            {
                shouldAddMissingColliders = false;
                isMarker = true;
            }

            // Add colliders to the object if it doesn't already contain one.
            if (shouldAddMissingColliders && (gameObject.GetComponentInChildren <Collider>() == null))
            {
                GameObjectUtils.AddMissingMeshCollidersRecursively(gameObject);
            }

            if (isMarker)
            {
                GameObjectUtils.SetLayerRecursively(gameObject, MorrowindEngine.markerLayer);
            }

            return(gameObject);
        }
 void ProcessExtraData(NiObject obj, out bool shouldAddMissingColliders, out bool isMarker)
 {
     shouldAddMissingColliders = true;
     isMarker = false;
     if (obj is NiObjectNET objNET)
     {
         var extraData = objNET.ExtraData.Value >= 0 ? (NiExtraData)_obj.Blocks[objNET.ExtraData.Value] : null;
         while (extraData != null)
         {
             if (extraData is NiStringExtraData strExtraData)
             {
                 if (strExtraData.Str == "NCO" || strExtraData.Str == "NCC")
                 {
                     shouldAddMissingColliders = false;
                 }
                 else if (strExtraData.Str == "MRK")
                 {
                     shouldAddMissingColliders = false;
                     isMarker = true;
                 }
             }
             // Move to the next NiExtraData.
             extraData = extraData.NextExtraData.Value >= 0 ? (NiExtraData)_obj.Blocks[extraData.NextExtraData.Value] : null;
         }
     }
 }
Beispiel #3
0
        private void FixReferences(NiObject obj)
        {
            var fields = obj.GetType().GetFields();

            for (var i = 0; i < fields.Length; i++)
            {
                var fieldInfo = fields[i];

                var fieldType = fieldInfo.FieldType.IsArray ?
                                fieldInfo.FieldType.GetElementType() :
                                fieldInfo.FieldType;

                if (typeof(INiRef).IsAssignableFrom(fieldType))
                {
                    if (fieldInfo.FieldType.IsArray)
                    {
                        var array = (INiRef[])fieldInfo.GetValue(obj);
                        Array.ForEach(array, e => e.SetRef(this));
                    }
                    else
                    {
                        ((INiRef)fieldInfo.GetValue(obj)).SetRef(this);
                    }
                }
            }
        }
Beispiel #4
0
 public int AddBlock(NiObject obj)
 {
     this.blocks.Add(obj);
     this.rawBlocks.Add(new byte[0]);
     this.blockType.Add("");
     this.blockSize.Add(0);
     this.header.AddBlock(this.header, obj);
     return(this.blocks.Count - 1);
 }
Beispiel #5
0
        /// <summary>
        /// Get Objects from Int Array.
        /// </summary>
        /// <param name="points">Pointers</param>
        /// <returns>Objects that the pointers pointed to.</returns>
        public IEnumerable <NiObject> FromIntArray(int[] points)
        {
            var arr = new NiObject[points.Length];

            for (var i = 0; i < points.Length; i++)
            {
                arr[i] = this[points[i]];
            }

            return(arr);
        }
Beispiel #6
0
    private IEnumerable <NiObject> FromIntArray(IReadOnlyList <int> array)
    {
        var list = new NiObject[array.Count];

        for (var i = 0; i < array.Count; i++)
        {
            list[i] = _niFile[array[i]];
        }

        return(list);
    }
Beispiel #7
0
        private bool TryExtractTriShape(NiObject obj, Matrix4 worldMatrix, bool invertTris, bool both, ref Vector3[] vertices, ref Triangle[] outtriangles)
        {
            var shape = obj as NiTriShape;

            if (shape == null)
            {
                return(false);
            }

            eFaceDrawMode mode = FindDrawMode(shape);

            if (mode == eFaceDrawMode.DRAW_CCW_OR_BOTH)
            {
                mode = both ? eFaceDrawMode.DRAW_BOTH : eFaceDrawMode.DRAW_CCW;
            }

            Matrix4 myMatrix = ComputeWorldMatrix(shape) * worldMatrix;

            var data = shape.Data.Object as NiTriShapeData;

            if (data.Triangles.Length == 0)
            {
                return(false);
            }

            vertices = new Vector3[data.Vertices.Length];

            for (int i = 0; i < data.Vertices.Length; i++)
            {
                vertices[i] = Vector3.Transform(data.Vertices[i], myMatrix);
            }

            var triangles = new List <Triangle>();

            // CCW
            if (mode == eFaceDrawMode.DRAW_BOTH || (mode == eFaceDrawMode.DRAW_CCW) != invertTris)
            {
                for (int i = 0; i < data.Triangles.Length; i++)
                {
                    triangles.Add(new Triangle(data.Triangles[i].Z, data.Triangles[i].Y, data.Triangles[i].X));
                }
            }

            // CC
            if (mode == eFaceDrawMode.DRAW_BOTH || (mode == eFaceDrawMode.DRAW_CW) != invertTris)
            {
                triangles.AddRange(data.Triangles);
            }

            outtriangles = triangles.ToArray();
            return(true);
        }
 void AddColliderFromNiObject(NiObject niObject, GameObject gameObject)
 {
     if (niObject.GetType() == typeof(NiTriShape))
     {
         var colliderObj = InstantiateNiTriShape((NiTriShape)niObject, false, true); colliderObj.transform.SetParent(gameObject.transform, false);
     }
     else if (niObject.GetType() == typeof(AvoidNode))
     {
     }
     else
     {
         Log("Unsupported collider NiObject: " + niObject.GetType().Name);
     }
 }
 /// <summary>
 /// Creates a GameObject representation of an NiObject.
 /// </summary>
 /// <returns>Returns the created GameObject, or null if the NiObject does not need its own GameObject.</returns>
 GameObject InstantiateNiObject(NiObject obj)
 {
     if (obj.GetType() == typeof(NiNode))
     {
         return(InstantiateNiNode((NiNode)obj));
     }
     else if (obj.GetType() == typeof(NiBSAnimationNode))
     {
         return(InstantiateNiNode((NiNode)obj));
     }
     else if (obj.GetType() == typeof(NiTriShape))
     {
         return(InstantiateNiTriShape((NiTriShape)obj, true, false));
     }
     else if (obj.GetType() == typeof(RootCollisionNode))
     {
         return(InstantiateRootCollisionNode((RootCollisionNode)obj));
     }
     else if (obj.GetType() == typeof(NiTextureEffect))
     {
         return(null);
     }
     else if (obj.GetType() == typeof(NiBSAnimationNode))
     {
         return(null);
     }
     else if (obj.GetType() == typeof(NiBSParticleNode))
     {
         return(null);
     }
     else if (obj.GetType() == typeof(NiRotatingParticles))
     {
         return(null);
     }
     else if (obj.GetType() == typeof(NiAutoNormalParticles))
     {
         return(null);
     }
     else if (obj.GetType() == typeof(NiBillboardNode))
     {
         return(null);
     }
     else
     {
         throw new NotImplementedException($"Tried to instantiate an unsupported NiObject ({obj.GetType().Name}).");
     }
 }
        GameObject InstantiateRootNiObject(NiObject obj)
        {
            var gameObject = InstantiateNiObject(obj);

            ProcessExtraData(obj, out var shouldAddMissingColliders, out var isMarker);
            if (_obj.Name != null && IsMarkerFileName(_obj.Name))
            {
                shouldAddMissingColliders = false;
                isMarker = true;
            }
            // Add colliders to the object if it doesn't already contain one.
            if (shouldAddMissingColliders && gameObject.GetComponentInChildren <Collider>() == null)
            {
                GameObjectUtils.AddMissingMeshCollidersRecursively(gameObject);
            }
            if (isMarker)
            {
                GameObjectUtils.SetLayerRecursively(gameObject, _markerLayer);
            }
            return(gameObject);
        }
Beispiel #11
0
        private void ProcessExtraData(NiObject obj, out bool shouldAddMissingColliders, out bool isMarker)
        {
            shouldAddMissingColliders = true;
            isMarker = false;

            if (obj is NiObjectNET)
            {
                var objNET    = (NiObjectNET)obj;
                var extraData = (objNET.extraData.value >= 0) ? (NiExtraData)file.blocks[objNET.extraData.value] : null;

                while (extraData != null)
                {
                    if (extraData is NiStringExtraData)
                    {
                        var strExtraData = (NiStringExtraData)extraData;

                        if (strExtraData.str == "NCO" || strExtraData.str == "NCC")
                        {
                            shouldAddMissingColliders = false;
                        }
                        else if (strExtraData.str == "MRK")
                        {
                            shouldAddMissingColliders = false;
                            isMarker = true;
                        }
                    }

                    // Move to the next NiExtraData.
                    if (extraData.nextExtraData.value >= 0)
                    {
                        extraData = (NiExtraData)file.blocks[extraData.nextExtraData.value];
                    }
                    else
                    {
                        extraData = null;
                    }
                }
            }
        }
Beispiel #12
0
        public void Read(string gameDir, string fileName, LogFile logFile)
        {
            MemoryStream memoryStream = new MemoryStream();

            try
            {
                if (File.Exists(gameDir + fileName))
                {
                    try
                    {
                        FileStream fileStream = (FileStream)null;
                        while (fileStream == null)
                        {
                            fileStream = Utils.GetFileStream(new FileInfo(gameDir + fileName), logFile);
                        }
                        BinaryReader binaryReader = new BinaryReader((Stream)fileStream);
                        long         length       = binaryReader.BaseStream.Length;
                        memoryStream.Write(binaryReader.ReadBytes((int)length), 0, (int)length);
                        binaryReader.Close();
                        //logFile.WriteLog(" read " + fileName + " " + length);
                    }
                    catch (Exception ex)
                    {
                        logFile.WriteLog("Error reading " + fileName + " " + ex.Message);
                        logFile.Close();
                        System.Environment.Exit(500);
                    }
                }
                else if (BSAArchive.FileExists(fileName))
                {
                    try
                    {
                        byte[] newfile = BSAArchive.GetFile(fileName);
                        int    length  = newfile.Length;
                        memoryStream.Write(newfile, 0, length);
                    }
                    catch (Exception ex)
                    {
                        logFile.WriteLog("Error reading " + fileName + " from BSA/BA2 " + ex.Message + ex.Source);
                        if (ex.Source.ToLower().Contains("mscorlib"))
                        {
                            logFile.WriteLog("Install Visual C++ Redistributable for Visual Studio 2015 from https://www.microsoft.com/en-us/download/details.aspx?id=48145");
                        }
                        logFile.Close();
                        System.Environment.Exit(501);
                    }
                }
                else
                {
                    logFile.WriteLog(fileName + " not found");
                    logFile.Close();
                    System.Environment.Exit(404);
                }
            }
            catch (Exception ex)
            {
                logFile.WriteLog("Error accessing " + gameDir + fileName + " " + ex.Message);
                logFile.WriteLog("In case Mod Organizer is used, set output path outside of game and MO virtual file system directory");
                logFile.Close();
                System.Environment.Exit(502);
            }
            memoryStream.Position = 0L;
            BinaryReader reader = new BinaryReader((Stream)memoryStream);
            string       error  = "Read error " + fileName;

            try
            {
                this.header.Read(reader);
                var stream = reader.BaseStream;
                for (int index = 0; (long)index < (long)this.header.GetNumBlocks(); ++index)
                {
                    //Console.WriteLine("Reading block " + index + " of " + this.header.GetNumBlocks() + " = " + stream.Position + " = " + this.header.GetBlockTypeAtIndex(index));
                    if (NiFile.classTypes.ContainsKey(this.header.GetBlockTypeAtIndex(index)))
                    {
                        NiObject niObject = (NiObject)Activator.CreateInstance(NiFile.classTypes[this.header.GetBlockTypeAtIndex(index)]);
                        niObject.Read(this.header, reader);
                        this.blocks.Add(niObject);
                        this.rawBlocks.Add(new byte[0]);
                        this.blockType.Add(this.header.GetBlockTypeAtIndex(index));
                        this.blockSize.Add(this.header.GetBlockSizeAtIndex(index));
                    }
                    else
                    {
                        error = "Unsupported block " + index + " " + this.header.GetBlockTypeAtIndex(index) + " in " + gameDir + fileName;
                        //logFile.WriteLog("Unsupported block " + index + " " + this.header.GetBlockTypeAtIndex(index) + " in " + gameDir + fileName);
                        uint blockSizeAtIndex = this.header.GetBlockSizeAtIndex(index);
                        this.blocks.Add((NiObject)null);
                        this.rawBlocks.Add(reader.ReadBytes((int)blockSizeAtIndex));
                        this.blockType.Add(this.header.GetBlockTypeAtIndex(index));
                        this.blockSize.Add(this.header.GetBlockSizeAtIndex(index));
                    }
                }
            }
            catch
            {
                logFile.WriteLog(error);
                //logFile.Close();
                //System.Environment.Exit(501);
            }
            reader.Close();
        }
Beispiel #13
0
        private bool TryExtractTriStrips(NiObject obj, Matrix4 worldMatrix, bool invertTris, bool both, ref Vector3[] vertices, ref Triangle[] outtriangles)
        {
            var strips = obj as NiTriStrips;

            if (strips == null)
            {
                return(false);
            }

            eFaceDrawMode mode = FindDrawMode(strips);

            if (mode == eFaceDrawMode.DRAW_CCW_OR_BOTH)
            {
                mode = both ? eFaceDrawMode.DRAW_BOTH : eFaceDrawMode.DRAW_CCW;
            }

            Matrix4 myMatrix = ComputeWorldMatrix(strips) * worldMatrix;

            var data = strips.Data.Object as NiTriStripsData;

            if (data.Vertices.Length == 0)
            {
                return(false);
            }

            vertices = new Vector3[data.Vertices.Length];

            for (int i = 0; i < data.Vertices.Length; i++)
            {
                vertices[i] = Vector3.Transform(data.Vertices[i], myMatrix);
            }

            var triangles = new List <Triangle>();

            foreach (var points in data.Points)
            {
                // CCW
                if (mode == eFaceDrawMode.DRAW_BOTH || (mode == eFaceDrawMode.DRAW_CCW) != invertTris)
                {
                    ushort a    = points[0];
                    ushort b    = points[0];
                    ushort c    = points[1];
                    bool   flip = false;
                    for (int s = 2; s < points.Length; s++)
                    {
                        a = b;
                        b = c;
                        c = points[s];
                        if (a != b && b != c && c != a)
                        {
                            triangles.Add(!flip ? new Triangle(a, c, b) : new Triangle(a, b, c));
                        }
                        flip = !flip;
                    }
                }

                // CC
                if (mode == eFaceDrawMode.DRAW_BOTH || (mode == eFaceDrawMode.DRAW_CW) != invertTris)
                {
                    ushort a    = points[0];
                    ushort b    = points[0];
                    ushort c    = points[1];
                    bool   flip = false;
                    for (int s = 2; s < points.Length; s++)
                    {
                        a = b;
                        b = c;
                        c = points[s];
                        if (a != b && b != c && c != a)
                        {
                            triangles.Add(!flip ? new Triangle(a, b, c) : new Triangle(a, c, b));
                        }
                        flip = !flip;
                    }
                }
            }

            outtriangles = triangles.ToArray();
            return(true);
        }
Beispiel #14
0
            internal bool Update(float diff, float totalTime)
            {
                if (this.WantState > 0 && !this.TriedToLoadMarker)
                {
                    this.TriedToLoadMarker = true;
                    NiObject.LoadFromFileAsync(new NiObjectLoadParameters()
                    {
                        Callback = p =>
                        {
                            if (p.Success)
                            {
                                var obj = p.Result[0] as NiAVObject;
                                if (obj != null)
                                {
                                    this.Object = obj;
                                    this.Object.IncRef();
                                    this.Object.LocalTransform.Scale = this.MarkerScale;
                                }
                            }
                            this.DidLoadMarker = true;
                        },
                        Count    = 1,
                        FileName = this.MarkerNif
                    });
                }

                if (!this.DidLoadMarker)
                {
                    return(true);
                }

                if (this.WantState > 0 && this.Object != null)
                {
                    this.WantState   = 0;
                    this.CurrentFade = 0.0f;
                    this.WantFade    = 1.0f;
                    this.SetCurrentFade(0.0f);

                    this.AddToWorld();
                }
                else if (this.WantState < 0)
                {
                    this.WantFade = 0.0f;
                }

                if (this.Object != null)
                {
                    this.UpdateFade(diff);
                    this.SetCurrentFade(this.CurrentFade);
                }

                if (this.Object != null && this.IsInWorld() && this.WantState < 0 && this.CurrentFade > 0.0f)
                {
                    this.UpdateObject(totalTime);
                }

                if (this.WantState < 0 && this.CurrentFade <= 0.0f)
                {
                    this.Free();
                    return(false);
                }

                return(true);
            }
Beispiel #15
0
        internal void Initialize()
        {
            if (this.Marker == null && !this.TriedToLoadMarker)
            {
                this.TriedToLoadMarker = true;

                NiObject.LoadFromFileAsync(new NiObjectLoadParameters()
                {
                    Callback = p =>
                    {
                        if (p.Success)
                        {
                            var obj = p.Result[0].As <NiAVObject>();
                            if (obj != null)
                            {
                                this.Marker = obj;
                                this.Marker.IncRef();
                                this.Marker.LocalTransform.Scale = this.Plugin.Settings.MarkerScale;
                            }
                        }
                    },
                    Count    = 1,
                    FileName = this.Plugin.Settings.MarkerNif
                });
            }

            var alloc = Memory.Allocate(0x110);

            alloc.Pin();

            this.TargetMarkerPoint        = MemoryObject.FromAddress <NiPoint3>(alloc.Address);
            this.TargetTeleportPoint      = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x10);
            this.AimVectorPoint           = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x20);
            this.SourceTeleportPoint      = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x30);
            this.CurrentTeleportPoint     = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x40);
            this.AimVectorPointDoubled    = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x50);
            this.ThirdPersonTempTransform = MemoryObject.FromAddress <NiTransform>(alloc.Address + 0x60);
            this.SourceMovePoint          = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x100);

            this.AimVectorPoint.X = 0.0f;
            this.AimVectorPoint.Z = 0.0f;
            this.AimVectorPoint.Y = Math.Max(100.0f, Math.Min(8000.0f, this.Plugin.Settings.MaxDistance));

            this.AimVectorPointDoubled.X = 0.0f;
            this.AimVectorPointDoubled.Z = 0.0f;
            this.AimVectorPointDoubled.Y = 2000.0f + Math.Max(100.0f, Math.Min(8000.0f, this.Plugin.Settings.MaxDistance));

            // Setup GameOffset - Updated PrepareFunction & InstallHook to take this value, I didn't update directly incase some use a different Offset.
            int GameOffset  = 0x0;                                      // Everything is based from 1_5_62
            var GameVersion = NetScriptFramework.Main.Game.GameVersion; // Get the game version

            if (GameVersion[0] == 1 && GameVersion[1] == 5 && GameVersion[2] >= 73 && GameVersion[2] <= 97)
            {
                GameOffset = 0x1F0;                                                                                             // Check for game version 1_5_73 to 1_5_97, update GameOffset
            }
            var debug = CrashLog.Debug;

            DebugInfo.DebugFunctionInfo fn = null;
            if (debug == null || (fn = debug.GetFunctionInfo(36319)) == null)
            {
                throw new InvalidOperationException(this.Plugin.Name + " can't work without a debug library!");
            }

            this.fn_Actor_SetPosition = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset));

            fn = debug.GetFunctionInfo(32301);
            if (fn != null)
            {
                this.fn_BGSSoundDescriptor_PlaySound = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset));
            }

            fn = debug.GetFunctionInfo(18185);
            if (fn != null)
            {
                this.fn_TESImageSpaceModifier_Apply = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset));
            }

            fn = debug.GetFunctionInfo(51907);
            if (fn != null)
            {
                this.fn_FlashHudMeter = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset));
            }

            fn = debug.GetFunctionInfo(11295);
            if (fn != null)
            {
                this.fn_GetMagicFailedMessage = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset));
            }

            /*var cost = this.Plugin.Settings.MagickaCost;
             * if (cost > 0.0f)
             * {
             *  var spell = this.Plugin.Settings.SpellForm;
             *  if (spell != null)
             *  {
             *      var effectItem = Memory.ReadPointer(spell.Address + 0x58);
             *      if (effectItem != IntPtr.Zero)
             *      {
             *          effectItem = Memory.ReadPointer(effectItem);
             *          if (effectItem != IntPtr.Zero)
             *          {
             *              var effect = MemoryObject.FromAddress<EffectSetting>(Memory.ReadPointer(effectItem + 0x10));
             *              if (effect != null)
             *                  Memory.WriteFloat(effect.Address + 0x6C, cost);
             *
             *              Memory.WriteFloat(effectItem + 0x18, cost);
             *          }
             *      }
             *
             *      Memory.WriteInt32(spell.Address + 0xC0, (int)(cost + 0.1f));
             *  }
             * }*/
        }
Beispiel #16
0
 public int AddBlock(NiObject obj)
 {
     this.blocks.Add(obj);
     this.header.AddBlock(obj);
     return(this.blocks.Count - 1);
 }
Beispiel #17
0
        public void Read(string skyrimDir, string fileName, LogFile logFile)
        {
            MemoryStream memoryStream = new MemoryStream();

            if (File.Exists(skyrimDir + fileName))
            {
                try
                {
                    FileStream fileStream = (FileStream)null;
                    while (fileStream == null)
                    {
                        fileStream = Utils.GetFileStream(new FileInfo(skyrimDir + fileName), logFile);
                    }
                    BinaryReader binaryReader = new BinaryReader((Stream)fileStream);
                    long         length       = binaryReader.BaseStream.Length;
                    memoryStream.Write(binaryReader.ReadBytes((int)length), 0, (int)length);
                    binaryReader.Close();
                    //logFile.WriteLog(" read " + fileName + " " + length);
                }
                catch (Exception ex)
                {
                    logFile.WriteLog("Error reading " + fileName + " " + ex.Message);
                    logFile.Close();
                    System.Environment.Exit(500);
                }
            }
            else if (BSAArchive.FileExists(fileName))
            {
                try
                {
                    //logFile.Console.WriteLine(" reading " + fileName + " from BSA");
                    byte[] newfile = BSAArchive.GetFile(fileName);
                    int    length  = newfile.Length;
                    memoryStream.Write(newfile, 0, length);
                    //logFile.WriteLog(" read " + fileName + " " + length + " from BSA");
                }
                catch (Exception ex)
                {
                    logFile.WriteLog("Error reading " + fileName + " from BSA " + ex.Message);
                    logFile.Close();
                    System.Environment.Exit(501);
                }
            }
            else
            {
                logFile.WriteLog(fileName + " not found");
                logFile.Close();
                System.Environment.Exit(404);
            }
            memoryStream.Position = 0L;
            //Console.WriteLine("Reading " + fileName);
            BinaryReader reader = new BinaryReader((Stream)memoryStream);

            this.header.Read(reader);
            for (int index = 0; (long)index < (long)this.header.GetNumBlocks(); ++index)
            {
                if (NiFile.classTypes.ContainsKey(this.header.GetBlockTypeAtIndex(index)))
                {
                    NiObject niObject = (NiObject)Activator.CreateInstance(NiFile.classTypes[this.header.GetBlockTypeAtIndex(index)]);
                    niObject.Read(this.header, reader);
                    this.blocks.Add(niObject);
                }
                else
                {
                    uint blockSizeAtIndex = this.header.GetBlockSizeAtIndex(index);
                    reader.ReadBytes((int)blockSizeAtIndex);
                    this.blocks.Add((NiObject)null);
                }
            }
            reader.Close();
            //Console.WriteLine("done " + fileName);
        }