Beispiel #1
0
        private static void init()
        {
            if (Allocation != null)
            {
                return;
            }

            Allocation          = Memory.Allocate(0x90);
            TempPoint1          = MemoryObject.FromAddress <NiPoint3>(Allocation.Address);
            TempPoint2          = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x10);
            TempNormal          = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x20);
            TempSafety          = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x30);
            TempTransform       = MemoryObject.FromAddress <NiTransform>(Allocation.Address + 0x40);
            TempTransform.Scale = 1.0f;
            TempSafety.X        = 0.0f;
            TempSafety.Y        = 0.0f;
            TempSafety.Z        = 0.0f;

            SetupRaycastMask(new[]
            {
                CollisionLayers.AnimStatic,
                CollisionLayers.Biped,
                CollisionLayers.CharController,
                //CollisionLayers.Clutter,
                CollisionLayers.DebrisLarge,
                CollisionLayers.Ground,
                //CollisionLayers.Props,
                CollisionLayers.Static,
                CollisionLayers.Terrain,
                CollisionLayers.Trap,
                CollisionLayers.Trees,
                CollisionLayers.Unidentified
            });
        }
        internal bool GetOverwriteWeaponNode(TESForm obj, NiPoint3 pt)
        {
            if (!this.IsEnabled)
            {
                return(false);
            }

            if (obj == null || obj.FormId != this.LastTargetFormId)
            {
                return(false);
            }

            var pcam = PlayerCamera.Instance;

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

            var pn = pcam.Node;

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

            var pos = pn.WorldTransform.Position;

            pt.X = pos.X;
            pt.Y = pos.Y;
            pt.Z = pos.Z - 10.0f;
            return(true);
        }
        internal CameraStabilize(CameraMain cameraMain, CameraTarget target)
        {
            if (cameraMain == null)
            {
                throw new ArgumentNullException("cameraMain");
            }

            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            CameraMain = cameraMain;

            if (Allocation == null)
            {
                Allocation = Memory.Allocate(0x60);
            }

            TempPoint           = MemoryObject.FromAddress <NiPoint3>(Allocation.Address);
            TempTransform       = MemoryObject.FromAddress <NiTransform>(Allocation.Address + 0x10);
            TempTransform.Scale = 1.0f;
            TweenPoint          = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x50);

            ForTarget = GetFromTarget(target);
        }
Beispiel #4
0
        internal void Initialize()
        {
            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));

            this.fn_Actor_SetPosition            = NetScriptFramework.Main.GameInfo.GetAddressOf(36319);
            this.fn_BGSSoundDescriptor_PlaySound = NetScriptFramework.Main.GameInfo.GetAddressOf(32301);
            this.fn_TESImageSpaceModifier_Apply  = NetScriptFramework.Main.GameInfo.GetAddressOf(18185);
            this.fn_FlashHudMeter         = NetScriptFramework.Main.GameInfo.GetAddressOf(51907);
            this.fn_GetMagicFailedMessage = NetScriptFramework.Main.GameInfo.GetAddressOf(11295);

            /*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));
             *  }
             * }*/
        }
        private void InitMagicNode()
        {
            if (MagicNodeAllocation != null)
            {
                return;
            }

            const int count = 3;
            const int size  = 0x130;
            const int size2 = 0x10;

            MagicNodeAllocation = Memory.Allocate(size * count + size2 * count);
            MagicNodes          = new NiNode[count];
            MagicTranslates     = new NiPoint3[count];
            var s = Settings.Instance;

            for (var i = 0; i < count; i++)
            {
                var addrOfThis = MagicNodeAllocation.Address + size * i;
                Memory.InvokeCdecl(Plugin.NiNode_ctor, addrOfThis, 0);
                MagicNodes[i] = MemoryObject.FromAddress <NiNode>(addrOfThis);
                MagicNodes[i].IncRef();

                MagicTranslates[i] =
                    MemoryObject.FromAddress <NiPoint3>(MagicNodeAllocation.Address + size * count + size2 * i);
                switch (i)
                {
                case 0:
                    MagicTranslates[i].X = s.MagicLeftOffsetX;
                    MagicTranslates[i].Y = s.MagicLeftOffsetY;
                    MagicTranslates[i].Z = s.MagicLeftOffsetZ;
                    break;

                case 1:
                    MagicTranslates[i].X = s.MagicRightOffsetX;
                    MagicTranslates[i].Y = s.MagicRightOffsetY;
                    MagicTranslates[i].Z = s.MagicRightOffsetZ;
                    break;

                case 2:
                    MagicTranslates[i].X = s.MagicVoiceOffsetX;
                    MagicTranslates[i].Y = s.MagicVoiceOffsetY;
                    MagicTranslates[i].Z = s.MagicVoiceOffsetZ;
                    break;

                default:
                    MagicTranslates[i].X = 0.0f;
                    MagicTranslates[i].Y = 0.0f;
                    MagicTranslates[i].Z = 0.0f;
                    break;
                }
            }
        }
Beispiel #6
0
        internal void AddTweenFrom(long duration, NiPoint3 cur)
        {
            if (this.LastCalculated == null || duration <= 0 || cur == null)
            {
                return;
            }

            long now = IFPVPlugin.Instance.Time;

            this.TweenPoint.CopyFrom(cur);
            this.TweenBegin = now;
            this.TweenEnd   = now + duration;
        }
Beispiel #7
0
        internal override void Apply()
        {
            var alloc = NetScriptFramework.Memory.Allocate(0x20);

            alloc.Pin();

            this.addr_MenuTopicManager = NetScriptFramework.Main.GameInfo.GetAddressOf(514959);
            addr_PickData = NetScriptFramework.Main.GameInfo.GetAddressOf(515446);

            this.TargetHeadTrack      = NetScriptFramework.MemoryObject.FromAddress <NiPoint3>(alloc.Address);
            this.TranslateHeadTrack   = NetScriptFramework.MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x10);
            this.TranslateHeadTrack.X = 0.0f;
            this.TranslateHeadTrack.Y = 2000.0f;
            this.TranslateHeadTrack.Z = 0.0f;

            Events.OnFrame.Register(Event_Frame);
            Events.OnUpdatedPlayerHeadtrack.Register(Event_UpdatedHeadtrack);
            Events.OnUpdateCamera.Register(Event_UpdatedCamera, 100000);
        }
Beispiel #8
0
        internal void ApplyTween(NiPoint3 target, long time)
        {
            if (time >= this.TweenEnd || time < this.TweenBegin || this.TweenPoint == null)
            {
                return;
            }

            float sx    = this.TweenPoint.X;
            float sy    = this.TweenPoint.Y;
            float sz    = this.TweenPoint.Z;
            float tx    = target.X;
            float ty    = target.Y;
            float tz    = target.Z;
            float ratio = (float)(time - this.TweenBegin) / (float)(this.TweenEnd - this.TweenBegin);

            ratio = (float)Utility.ApplyFormula(ratio, TValue.TweenTypes.Linear);

            target.X = (tx - sx) * ratio + sx;
            target.Y = (ty - sy) * ratio + sy;
            target.Z = (tz - sz) * ratio + sz;
        }
        internal void ApplyTween(NiPoint3 target, long time)
        {
            if (time >= TweenEnd || time < TweenBegin || TweenPoint == null)
            {
                return;
            }

            var sx    = TweenPoint.X;
            var sy    = TweenPoint.Y;
            var sz    = TweenPoint.Z;
            var tx    = target.X;
            var ty    = target.Y;
            var tz    = target.Z;
            var ratio = (time - TweenBegin) / (float)(TweenEnd - TweenBegin);

            ratio = (float)Utility.ApplyFormula(ratio, TValue.TweenTypes.Linear);

            target.X = (tx - sx) * ratio + sx;
            target.Y = (ty - sy) * ratio + sy;
            target.Z = (tz - sz) * ratio + sz;
        }
Beispiel #10
0
        private bool IsIFPVMaybe(PlayerCharacter plr, NiPoint3 camPos)
        {
            if (plr == null)
            {
                return(false);
            }

            var root = plr.Node;

            if (root != null)
            {
                var head = root.LookupNodeByName("NPCEyeBone") ?? root.LookupNodeByName("NPC Head [Head]");
                if (head == null || head.WorldTransform.Position.GetDistance(camPos) >= settings.IFPVdist.Value)
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }

            return(true);
        }
Beispiel #11
0
        private void ApplyPositionOffset(NiTransform transform, float x, float y, float z, NiPoint3 result)
        {
            if (x == 0.0f && y == 0.0f && z == 0.0f)
            {
                var tpos = transform.Position;
                if (!result.Equals(tpos))
                {
                    result.CopyFrom(tpos);
                }
                return;
            }

            var pos = this.TempResult.Transform.Position;

            pos.X = x;
            pos.Y = y;
            pos.Z = z;
            transform.Translate(pos, result);
        }
Beispiel #12
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 #13
0
 internal static void CopyFrom(this NiPoint3 pt, NiPoint3 other)
 {
     Memory.Copy(other.Address, pt.Address, 0xC);
 }
Beispiel #14
0
        internal static bool Apply(CameraUpdate update, NiTransform transform, NiPoint3 result)
        {
            init();

            if (update == null || transform == null || result == null)
            {
                return(false);
            }

            if (update.Values.CollisionEnabled.CurrentValue < 0.5)
            {
                return(false);
            }

            var actor = update.Target.Actor;

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

            var cell = actor.ParentCell;

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

            float safety = (float)(update.Values.NearClip.CurrentValue + 1.0);

            if (safety < 1.0f)
            {
                safety = 1.0f;
            }

            float safety2 = Math.Max(0.0f, Settings.Instance.CameraCollisionSafety);

            var tpos = transform.Position;

            TempPoint1.CopyFrom(actor.Position);
            TempPoint1.Z = tpos.Z;

            if (safety2 > 0.0f)
            {
                TempSafety.Y = -safety2 * 0.5f;
                TempTransform.CopyFrom(transform);
                TempTransform.Position.CopyFrom(TempPoint1);
                TempTransform.Translate(TempSafety, TempPoint1);
            }

            TempNormal.X = tpos.X - TempPoint1.X;
            TempNormal.Y = tpos.Y - TempPoint1.Y;
            TempNormal.Z = tpos.Z - TempPoint1.Z;

            float len = TempNormal.Length;

            if (len <= 0.0f)
            {
                return(false);
            }

            TempNormal.Normalize(TempNormal);
            TempNormal.Multiply(len + safety + safety2, TempNormal);

            TempPoint2.X = TempPoint1.X + TempNormal.X;
            TempPoint2.Y = TempPoint1.Y + TempNormal.Y;
            TempPoint2.Z = TempPoint1.Z + TempNormal.Z;

            var ls = TESObjectCELL.RayCast(new RayCastParameters()
            {
                Cell  = cell,
                Begin = new float[] { TempPoint1.X, TempPoint1.Y, TempPoint1.Z },
                End   = new float[] { TempPoint2.X, TempPoint2.Y, TempPoint2.Z }
            });

            if (ls == null || ls.Count == 0)
            {
                return(false);
            }

            RayCastResult     best     = null;
            float             bestDist = 0.0f;
            List <NiAVObject> ignore   = new List <NiAVObject>(3);

            {
                var sk = actor.GetSkeletonNode(true);
                if (sk != null)
                {
                    ignore.Add(sk);
                }
            }
            {
                var sk = actor.GetSkeletonNode(false);
                if (sk != null)
                {
                    ignore.Add(sk);
                }
            }
            if (update.CachedMounted)
            {
                var mount = actor.GetMount();
                if (mount != null)
                {
                    var sk = mount.GetSkeletonNode(false);
                    if (sk != null)
                    {
                        ignore.Add(sk);
                    }
                }
            }

            foreach (var r in ls)
            {
                if (!IsValid(r, ignore))
                {
                    continue;
                }

                float dist = r.Fraction;
                if (best == null)
                {
                    best     = r;
                    bestDist = dist;
                }
                else if (dist < bestDist)
                {
                    best     = r;
                    bestDist = dist;
                }
            }

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

            bestDist *= len + safety + safety2;
            bestDist -= safety + safety2;
            bestDist /= len + safety + safety2;

            // Negative is ok!

            result.X = (TempPoint2.X - TempPoint1.X) * bestDist + TempPoint1.X;
            result.Y = (TempPoint2.Y - TempPoint1.Y) * bestDist + TempPoint1.Y;
            result.Z = (TempPoint2.Z - TempPoint1.Z) * bestDist + TempPoint1.Z;

            return(true);
        }
        internal override void Apply()
        {
            this.NiNode_ctor = NetScriptFramework.Main.GameInfo.GetAddressOf(68936);
            _cachedOffsets   = new int[256];

            ulong vid        = 17693;
            int   baseOffset = 0x5430;

            Events.OnMainMenu.Register(e =>
            {
                if (this._curPlaceNode == null)
                {
                    var alloc = MemoryManager.Allocate(0x130, 0);
                    Memory.InvokeCdecl(this.NiNode_ctor, alloc, 0);
                    this._curPlaceNode = MemoryObject.FromAddress <NiNode>(alloc);
                    this._curPlaceNode.IncRef();

                    alloc             = MemoryManager.Allocate(0x10, 0);
                    this._curPlacePos = MemoryObject.FromAddress <NiPoint3>(alloc);
                    Memory.WriteZero(this._curPlacePos.Address, 0xC);
                }
            }, 0, 1);

            Memory.WriteHook(new HookParameters()
            {
                Address       = NetScriptFramework.Main.GameInfo.GetAddressOf(vid, 0x5CF2 - baseOffset, 0, "0F B6 D9 0F BE C2"),
                IncludeLength = 6,
                ReplaceLength = 6,
                Before        = ctx =>
                {
                    TESObjectWEAP weap = null;
                    Actor actor        = null;

                    int count = ctx.CX.ToUInt8();
                    try
                    {
                        weap = MemoryObject.FromAddress <TESObjectWEAP>(ctx.R12);
                    }
                    catch
                    {
                    }
                    try
                    {
                        actor = MemoryObject.FromAddress <Actor>(ctx.R15);
                    }
                    catch
                    {
                    }

                    int now = count;
                    _mod(weap, actor, ref now);

                    if (now > 255)
                    {
                        now = 255;
                    }

                    if (now != count)
                    {
                        ctx.CX = new IntPtr(now);
                    }
                },
            });

            Memory.WriteHook(new HookParameters()
            {
                Address       = NetScriptFramework.Main.GameInfo.GetAddressOf(vid, 0x603D - baseOffset, 0, "E8"),
                IncludeLength = 5,
                ReplaceLength = 5,
                After         = ctx =>
                {
                    TESObjectWEAP weap = null;
                    Actor actor        = null;
                    int count          = ctx.AX.ToUInt8();

                    try
                    {
                        weap = MemoryObject.FromAddress <TESObjectWEAP>(ctx.R12);
                    }
                    catch
                    {
                    }
                    try
                    {
                        actor = MemoryObject.FromAddress <Actor>(ctx.R15);
                    }
                    catch
                    {
                    }

                    int now = count;
                    _mod(weap, actor, ref now);

                    if (now > 255)
                    {
                        now = 255;
                    }

                    if (now != count)
                    {
                        ctx.AX = new IntPtr(now);
                    }
                },
            });

            Memory.WriteHook(new HookParameters()
            {
                Address       = NetScriptFramework.Main.GameInfo.GetAddressOf(42928, 0xB91B - 0xB360, 0, "E8"),
                IncludeLength = 5,
                ReplaceLength = 5,
                After         = ctx =>
                {
                    if (settings.ForceDrawTime.Value >= 0.0)
                    {
                        ctx.XMM0f = (float)settings.ForceDrawTime.Value;
                    }
                    else
                    {
                        int track = _projTrack;
                        if (track > 0)
                        {
                            track--;
                            _projTrack = track;

                            if (_projStrength.HasValue)
                            {
                                ctx.XMM0f = _projStrength.Value;
                                if (track == 0)
                                {
                                    _projStrength = null;
                                }
                            }
                            else
                            {
                                _projStrength = ctx.XMM0f;
                            }
                        }
                    }
                },
            });

            Memory.WriteHook(new HookParameters()
            {
                Address       = NetScriptFramework.Main.GameInfo.GetAddressOf(vid, 0x621C - baseOffset, 0, "F3 0F 10 44 24 48"),
                IncludeLength = 0, //0x3D - 0x1C,
                ReplaceLength = 0x3D - 0x1C,
                Before        = ctx =>
                {
                    var pos = MemoryObject.FromAddress <NiPoint3>(ctx.BP + 0x68);

                    int index = ctx.SI.ToUInt8();
                    if (index <= 1)
                    {
                        pos.X = Memory.ReadFloat(ctx.SP + 0x48);
                        pos.Y = Memory.ReadFloat(ctx.SP + 0x4C);
                        pos.Z = Memory.ReadFloat(ctx.SP + 0x50);
                        return;
                    }

                    var plr       = PlayerCharacter.Instance;
                    bool isPlayer = plr != null && plr.Cast <PlayerCharacter>() == ctx.R15;
                    if (isPlayer)
                    {
                        _projTrack = index;
                    }
                    else
                    {
                        _projTrack = 0;
                    }

                    float x = 0.0f;
                    float y = 0.0f;
                    _calculate_projectile_offset(index - 1, ref x, ref y);

                    if (this._curPlaceHadNode)
                    {
                        var npos = this._curPlaceNode.WorldTransform.Position;
                        npos.X   = Memory.ReadFloat(ctx.SP + 0x48);
                        npos.Y   = Memory.ReadFloat(ctx.SP + 0x4C);
                        npos.Z   = Memory.ReadFloat(ctx.SP + 0x50);

                        this._curPlacePos.X = x;
                        this._curPlacePos.Y = 0.0f;
                        this._curPlacePos.Z = y;
                        this._curPlaceNode.WorldTransform.Translate(this._curPlacePos, npos);

                        pos.X = npos.X;
                        pos.Y = npos.Y;
                        pos.Z = npos.Z;
                    }
                    else
                    {
                        bool didGet = false;
                        if (isPlayer)
                        {
                            var pcam = PlayerCamera.Instance;
                            if (pcam != null)
                            {
                                var pnode = pcam.Node;
                                if (pnode != null)
                                {
                                    byte[] buf = Memory.ReadBytes(pnode.WorldTransform.Address, 0x34);
                                    Memory.WriteBytes(this._curPlaceNode.WorldTransform.Address, buf);

                                    var tpos            = this._curPlaceNode.WorldTransform.Position;
                                    tpos.X              = Memory.ReadFloat(ctx.SP + 0x48);
                                    tpos.Y              = Memory.ReadFloat(ctx.SP + 0x4C);
                                    tpos.Z              = Memory.ReadFloat(ctx.SP + 0x50);
                                    this._curPlacePos.X = x;
                                    this._curPlacePos.Y = 0.0f;
                                    this._curPlacePos.Z = y;
                                    this._curPlaceNode.WorldTransform.Translate(this._curPlacePos, pos);
                                    didGet = true;
                                }
                            }
                        }

                        if (!didGet)
                        {
                            pos.X = Memory.ReadFloat(ctx.SP + 0x48) + x;
                            pos.Y = Memory.ReadFloat(ctx.SP + 0x4C);
                            pos.Z = Memory.ReadFloat(ctx.SP + 0x50) + y;
                        }
                    }
                }
            });

            Events.OnWeaponFireProjectilePosition.Register(e =>
            {
                if (e.Node != null)
                {
                    byte[] buf = Memory.ReadBytes(e.Node.WorldTransform.Address, 0x34);
                    Memory.WriteBytes(this._curPlaceNode.WorldTransform.Address, buf);
                    this._curPlaceHadNode = true;
                }
                else
                {
                    this._curPlaceHadNode = false;
                }
            }, 50);
        }
        private TESEffectShader ShouldGlow(TESObjectREFR obj, NiPoint3 pos)
        {
            if (obj == null)
            {
                return(null);
            }

            var           form = obj.BaseForm;
            TESObjectBOOK book = null;

            if (form == null || (book = form as TESObjectBOOK) == null || book.IsRead)
            {
                return(null);
            }

            TESObjectCELL cell = null;

            if (obj.Node == null || (cell = obj.ParentCell) == null)
            {
                return(null);
            }

            var tes = TES.Instance;

            if (tes == null)
            {
                return(null);
            }

            if (!Memory.InvokeCdecl(_is_cell_loaded, tes.Cast <TES>(), cell.Cast <TESObjectCELL>(), 0).ToBool())
            {
                return(null);
            }

            var tracker = Tools.BookTracker.Instance;
            var type    = tracker.GetBookType(book);

            if (!type.HasValue)
            {
#if DEBUG_MSG
                NetScriptFramework.Main.WriteDebugMessage("Warning: " + book.ToString() + " does not have a type in tracker!");
#endif
                return(null);
            }

            int mask = 1 << (int)type.Value;
            if ((this._care_mask & mask) == 0)
            {
                return(null);
            }

            if (obj.Position.GetDistance(pos) > 8000.0f)
            {
                return(null);
            }

            var ls = this._shaders[(int)type.Value];
            if (ls.Count == 0)
            {
                return(null);
            }

            if (ls.Count == 1)
            {
                return(ls[0]);
            }

            return(ls[rnd.Next(0, ls.Count)]);
        }