Пример #1
0
        private static int OnHandlePlayerToServerCheatMessage(void *pMessage, void *pPlayer, byte nMinor)
        {
            CNWSMessage message = CNWSMessage.FromPointer(pMessage);

            if (message == null)
            {
                return(Hook.CallOriginal(pMessage, pPlayer, nMinor));
            }

            NwPlayer?player = CNWSPlayer.FromPointer(pPlayer).ToNwPlayer();

            switch ((MessageCheatMinor)nMinor)
            {
            case MessageCheatMinor.RunScript:
                return(HandleRunScriptEvent(message, player) ? Hook.CallOriginal(pMessage, pPlayer, nMinor) : false.ToInt());

            case MessageCheatMinor.RunScriptChunk:
                return(HandleRunScriptChunkEvent(message, player) ? Hook.CallOriginal(pMessage, pPlayer, nMinor) : false.ToInt());

            case MessageCheatMinor.PlayVisualEffect:
                return(HandleVisualEffectEvent(message, player) ? Hook.CallOriginal(pMessage, pPlayer, nMinor) : false.ToInt());

            default:
                return(Hook.CallOriginal(pMessage, pPlayer, nMinor));
            }
        }
Пример #2
0
            private static int OnHandleMapPinSetMapPinAtMessage(void *pMessage, void *pPlayer)
            {
                CNWSMessage message = CNWSMessage.FromPointer(pMessage);
                CNWSPlayer  player  = CNWSPlayer.FromPointer(pPlayer);

                if (player == null)
                {
                    return(Hook.CallOriginal(pMessage, pPlayer));
                }

                // Coordinates
                int   offset = 0;
                float x      = message.PeekMessage <float>(offset);

                offset += sizeof(float);
                float y = message.PeekMessage <float>(offset);

                offset += sizeof(float);
                float z = message.PeekMessage <float>(offset);

                offset += sizeof(float);

                // Note
                string note = message.PeekMessageString(offset);

                OnMapPinAddPin eventData = ProcessEvent(new OnMapPinAddPin
                {
                    Player   = player.ToNwPlayer() !,
                    Position = new Vector3(x, y, z),
                    Note     = note,
                });
Пример #3
0
        private static bool HandleRunScriptChunkEvent(CNWSMessage message, NwPlayer?player)
        {
            int    offset      = 0;
            string scriptChunk = message.PeekMessageString(offset);

            offset += scriptChunk.Length + 4;

            uint oidTarget = message.PeekMessage <uint>(offset);

            if (oidTarget == NwObject.Invalid)
            {
                oidTarget = player?.ControlledCreature;
            }

            offset += sizeof(uint);
            bool wrapIntoMain = (message.PeekMessage <int>(offset) & 0x10).ToBool();

            OnDebugRunScriptChunk eventData = ProcessEvent(new OnDebugRunScriptChunk
            {
                Player       = player,
                ScriptChunk  = scriptChunk,
                Target       = (oidTarget & 0x7FFFFFFF).ToNwObject(),
                WrapIntoMain = wrapIntoMain,
            });

            return(!eventData.Skip);
        }
Пример #4
0
            private static int OnHandlePartyMessage(void *pMessage, void *pPlayer, byte nMinor)
            {
                PartyEventType eventType = (PartyEventType)nMinor;

                if (!Enum.IsDefined(eventType))
                {
                    return(Hook.CallOriginal(pMessage, pPlayer, nMinor));
                }

                CNWSMessage message   = CNWSMessage.FromPointer(pMessage);
                uint        oidTarget = message.PeekMessage <uint>(0) & 0x7FFFFFFF;

                OnPartyEvent eventData = new OnPartyEvent
                {
                    EventType = eventType,
                    Player    = CNWSPlayer.FromPointer(pPlayer).ToNwPlayer() !,
                    Target    = oidTarget.ToNwObject <NwCreature>() !,
                };

                eventData.Result = new Lazy <bool>(() => !eventData.PreventEvent && Hook.CallOriginal(pMessage, pPlayer, nMinor).ToBool());
                ProcessEvent(eventData);

                return(eventData.Result.Value.ToInt());
            }
        }
Пример #5
0
        private static bool HandleVisualEffectEvent(CNWSMessage message, NwPlayer?player)
        {
            int offset = 0;

            uint target = message.PeekMessage <uint>(offset) & 0x7FFFFFFF;

            offset += sizeof(uint);

            ushort visualEffect = message.PeekMessage <ushort>(offset);

            offset += sizeof(ushort);

            float duration = message.PeekMessage <float>(offset);

            offset += sizeof(float);

            Vector3 position = message.PeekMessage <Vector3>(offset);

            OnDebugPlayVisualEffect eventData = new OnDebugPlayVisualEffect
            {
                Player         = player,
                TargetObject   = target.ToNwObject(),
                Effect         = NwGameTables.VisualEffectTable[visualEffect],
                Duration       = TimeSpan.FromSeconds(duration),
                TargetPosition = position,
            };

            return(!eventData.Skip);
        }
Пример #6
0
            private static void OnStartBarter(void *pMessage, void *pPlayer)
            {
                CNWSMessage message = CNWSMessage.FromPointer(pMessage);

                ProcessEvent(new OnBarterStart
                {
                    Initiator = CNWSPlayer.FromPointer(pPlayer).ToNwPlayer() !,
                    Target    = (message.PeekMessage <uint>(0) & 0x7FFFFFFF).ToNwPlayer() !,
                });
Пример #7
0
        private static bool HandleChangeDifficultyEvent(NwPlayer dungeonMaster, CNWSMessage message)
        {
            GameDifficulty       difficulty = (GameDifficulty)message.PeekMessage <int>(0);
            OnDMChangeDifficulty eventData  = ProcessEvent(new OnDMChangeDifficulty
            {
                DungeonMaster = dungeonMaster,
                NewDifficulty = difficulty,
            });

            return(!eventData.Skip);
        }
Пример #8
0
        private static bool HandleGiveEvent <TEvent>(NwPlayer dungeonMaster, CNWSMessage message) where TEvent : DMGiveEvent, new()
        {
            int          amount = message.PeekMessage <int>(0);
            NwGameObject target = (message.PeekMessage <uint>(4) & 0x7FFFFFFF).ToNwObject <NwGameObject>() !;

            TEvent eventData = ProcessEvent(new TEvent
            {
                DungeonMaster = dungeonMaster,
                Amount        = amount,
                Target        = target,
            });

            return(!eventData.Skip);
        }
Пример #9
0
        private bool SendMessage(ChatChannel chatChannel, string message, NwObject speaker, NwPlayer?target)
        {
            uint playerId = target != null ? target.Player.m_nPlayerID : PlayerIdConstants.AllClients;

            if (playerId == PlayerIdConstants.Invalid)
            {
                return(false);
            }

            CNWSMessage messageDispatch = LowLevel.ServerExoApp.GetNWSMessage();

            if (target != null)
            {
                // This means we're sending this to one player only.
                // The normal function broadcasts in an area for talk, shout, and whisper, therefore
                // we need to call these functions directly if we are in those categories.
                switch (chatChannel)
                {
                case ChatChannel.PlayerTalk:
                    return(messageDispatch.SendServerToPlayerChat_Talk(playerId, speaker, message.ToExoString()).ToBool());

                case ChatChannel.DmTalk:
                    return(messageDispatch.SendServerToPlayerChat_DM_Talk(playerId, speaker, message.ToExoString()).ToBool());

                case ChatChannel.DmDm:
                case ChatChannel.PlayerDm:
                    return(messageDispatch.SendServerToPlayerChat_DM_Silent_Shout(playerId, speaker, message.ToExoString()).ToBool());

                case ChatChannel.PlayerShout:
                case ChatChannel.DmShout:
                    return(messageDispatch.SendServerToPlayerChat_Shout(playerId, speaker, message.ToExoString()).ToBool());

                case ChatChannel.PlayerWhisper:
                    return(messageDispatch.SendServerToPlayerChat_Whisper(playerId, speaker, message.ToExoString()).ToBool());

                case ChatChannel.DmWhisper:
                    return(messageDispatch.SendServerToPlayerChat_DM_Whisper(playerId, speaker, message.ToExoString()).ToBool());

                case ChatChannel.PlayerParty:
                case ChatChannel.DmParty:
                    return(messageDispatch.SendServerToPlayerChat_Party(playerId, speaker, message.ToExoString()).ToBool());
                }
            }

            return(messageDispatch.SendServerToPlayerChatMessage((byte)chatChannel, speaker, message.ToExoString(), playerId).ToBool());
        }
Пример #10
0
            private static int OnHandleMapPinDestroyMapPinMessage(void *pMessage, void *pPlayer)
            {
                CNWSMessage message = CNWSMessage.FromPointer(pMessage);
                CNWSPlayer  player  = CNWSPlayer.FromPointer(pPlayer);

                if (player == null)
                {
                    return(Hook.CallOriginal(pMessage, pPlayer));
                }

                // Id
                int id = message.PeekMessage <int>(0);

                OnMapPinDestroyPin eventData = ProcessEvent(new OnMapPinDestroyPin
                {
                    Player = player.ToNwPlayer() !,
                    Id     = id,
                });
Пример #11
0
        private void SendNameUpdate(NwPlayer targetPlayer, NwPlayer observerPlayer)
        {
            bool        success = false;
            CNWSMessage message = LowLevel.ServerExoApp.GetNWSMessage();

            uint observerPlayerId = observerPlayer.PlayerId;

            // The client may crash if we send an object update for a creature that does not exist in its
            // last update object list
            if (!IsCreatureInLastUpdateObjectList(observerPlayer, targetPlayer))
            {
                return;
            }

            if (ShowOverridesToDM || !observerPlayer.IsDM)
            {
                // Write a message notifying an object update.
                message.CreateWriteMessage(0x400, observerPlayerId, 1);

                // We don't need one for our update.
                // However, the appearance update is contingent on receiving a pointer which isn't nullptr.
                CLastUpdateObject lastUpdateObj = CLastUpdateObject.FromPointer((void *)0xDEADBEEF);
                message.WriteGameObjUpdate_UpdateObject(observerPlayer, targetPlayer.ControlledCreature, lastUpdateObj, 0, 0x400);

                byte *data = null;
                uint  size = 0;

                if (message.GetWriteMessage(&data, &size).ToBool() && size != 0)
                {
                    message.SendServerToPlayerMessage(observerPlayerId, (byte)MessageMajor.GameObjectUpdate, (byte)MessageGameObjectUpdateMinor.ObjectList, data, size);
                    success = true;
                }

                if (PlayerListNameType != OverrideNameType.Original)
                {
                    message.SendServerToPlayerPlayerList_All(observerPlayer);
                }
            }

            if (success == false)
            {
                Log.Warn($"Sending name update message for observer {observerPlayer.PlayerName}, target {targetPlayer.PlayerName} failed.");
            }
        }
Пример #12
0
        private static bool HandleDumpLocalsEvent(NwPlayer dungeonMaster, CNWSMessage message)
        {
            DumpLocalsType type = (DumpLocalsType)message.PeekMessage <int>(0);

            NwObject target = type switch
            {
                DumpLocalsType.DumpLocals => (message.PeekMessage <uint>(4) & 0x7FFFFFFF).ToNwObject() !,
                DumpLocalsType.DumpAreaLocals => dungeonMaster.ControlledCreature !.Area !,
                DumpLocalsType.DumpModuleLocals => NwModule.Instance,
                _ => throw new ArgumentOutOfRangeException(),
            };

            OnDMDumpLocals eventData = ProcessEvent(new OnDMDumpLocals
            {
                DungeonMaster = dungeonMaster,
                Type          = type,
                Target        = target,
            });

            return(!eventData.Skip);
        }
Пример #13
0
        private static bool HandleRunScriptEvent(CNWSMessage message, NwPlayer?player)
        {
            int    offset     = 0;
            string scriptName = message.PeekMessageString(offset);

            offset += scriptName.Length + 4;

            uint oidTarget = player?.Player.SatisfiesBuild(8193, 14).ToBool() == true?message.PeekMessage <uint>(offset) : NwObject.Invalid;

            if (oidTarget == NwObject.Invalid)
            {
                oidTarget = player?.ControlledCreature;
            }

            OnDebugRunScript eventData = new OnDebugRunScript
            {
                Player     = player,
                ScriptName = scriptName,
                Target     = (oidTarget & 0x7FFFFFFF).ToNwObject(),
            };

            return(!eventData.Skip);
        }
Пример #14
0
        private static bool HandleGiveAlignmentEvent(NwPlayer dungeonMaster, CNWSMessage message, MessageDungeonMasterMinor alignmentType)
        {
            Alignment alignment = alignmentType switch
            {
                MessageDungeonMasterMinor.GiveGoodAlignment => Alignment.Good,
                MessageDungeonMasterMinor.GiveEvilAlignment => Alignment.Evil,
                MessageDungeonMasterMinor.GiveLawfulAlignment => Alignment.Lawful,
                MessageDungeonMasterMinor.GiveChaoticAlignment => Alignment.Chaotic,
                _ => throw new ArgumentOutOfRangeException(),
            };

            int          amount = message.PeekMessage <int>(0);
            NwGameObject target = (message.PeekMessage <uint>(4) & 0x7FFFFFFF).ToNwObject <NwGameObject>() !;

            OnDMGiveAlignment eventData = ProcessEvent(new OnDMGiveAlignment
            {
                DungeonMaster = dungeonMaster,
                Alignment     = alignment,
                Amount        = amount,
                Target        = target,
            });

            return(!eventData.Skip);
        }
Пример #15
0
        public static string PeekMessageString(this CNWSMessage message, int offset)
        {
            byte *ptr = message.m_pnReadBuffer + message.m_nReadBufferPtr + offset;

            return(StringHelper.ReadNullTerminatedString(ptr));
        }
Пример #16
0
        public static string PeekMessageResRef(this CNWSMessage message, int offset)
        {
            byte *ptr = message.m_pnReadBuffer + message.m_nReadBufferPtr + offset;

            return(StringHelper.ReadFixedLengthString(ptr, 16));
        }
Пример #17
0
        public static T PeekMessage <T>(this CNWSMessage message, int offset) where T : unmanaged
        {
            byte *ptr = message.m_pnReadBuffer + message.m_nReadBufferPtr + offset;

            return(Marshal.PtrToStructure <T>((IntPtr)ptr));
        }
Пример #18
0
        private int OnSendServerToPlayerChatMessage(void *pMessage, ChatChannel nChatMessageType, uint oidSpeaker, void *sSpeakerMessage, uint nTellPlayerId, void *tellName)
        {
            if (!isEventHooked && !customHearingDistances)
            {
                return(sendServerToPlayerChatMessageHook.CallOriginal(pMessage, nChatMessageType, oidSpeaker, sSpeakerMessage, nTellPlayerId, tellName));
            }

            CNWSMessage message        = CNWSMessage.FromPointer(pMessage);
            CExoString  speakerMessage = CExoString.FromPointer(sSpeakerMessage);
            NwObject    speaker        = oidSpeaker.ToNwObject() !;

            bool skipMessage = ProcessEvent(nChatMessageType, speakerMessage.ToString(), speaker, NwPlayer.FromPlayerId(nTellPlayerId));

            if (skipMessage)
            {
                return(false.ToInt());
            }

            if (!customHearingDistances)
            {
                return(sendServerToPlayerChatMessageHook.CallOriginal(pMessage, nChatMessageType, oidSpeaker, sSpeakerMessage, nTellPlayerId, tellName));
            }

            CExoLinkedListInternal playerList = LowLevel.ServerExoApp.m_pcExoAppInternal.m_pNWSPlayerList.m_pcExoLinkedListInternal;

            if (playerList == null)
            {
                return(false.ToInt());
            }

            if (nChatMessageType == ChatChannel.PlayerShout && nwServer.ServerInfo.PlayOptions.DisallowShouting)
            {
                nChatMessageType = ChatChannel.PlayerTalk;
            }

            if (nChatMessageType != ChatChannel.PlayerTalk &&
                nChatMessageType != ChatChannel.PlayerWhisper &&
                nChatMessageType != ChatChannel.DmTalk &&
                nChatMessageType != ChatChannel.DmWhisper)
            {
                return(sendServerToPlayerChatMessageHook.CallOriginal(pMessage, nChatMessageType, oidSpeaker, sSpeakerMessage, nTellPlayerId, tellName));
            }

            NwGameObject?speakerGameObject = speaker as NwGameObject;
            NwArea?      speakerArea       = speakerGameObject?.Area;

            foreach (NwPlayer player in NwModule.Instance.Players)
            {
                NwCreature?controlledCreature = player.ControlledCreature;

                if (controlledCreature == null || speakerArea != null && speakerArea != controlledCreature.Area)
                {
                    continue;
                }

                float hearDistance = GetPlayerChatHearingDistance(player, nChatMessageType);
                if (speakerGameObject != null && controlledCreature.DistanceSquared(speakerGameObject) > hearDistance * hearDistance)
                {
                    continue;
                }

                switch (nChatMessageType)
                {
                case ChatChannel.PlayerTalk:
                    message.SendServerToPlayerChat_Talk(player.Player.m_nPlayerID, speaker, speakerMessage);
                    break;

                case ChatChannel.DmTalk:
                    message.SendServerToPlayerChat_DM_Talk(player.Player.m_nPlayerID, speaker, speakerMessage);
                    break;

                case ChatChannel.PlayerWhisper:
                    message.SendServerToPlayerChat_Whisper(player.Player.m_nPlayerID, speaker, speakerMessage);
                    break;

                case ChatChannel.DmWhisper:
                    message.SendServerToPlayerChat_DM_Whisper(player.Player.m_nPlayerID, speaker, speakerMessage);
                    break;
                }
            }

            return(true.ToInt());
        }
Пример #19
0
        private static bool HandleGiveItemEvent(void *pMessage, void *pPlayer, byte nMinor, int bGroup, NwPlayer dungeonMaster, CNWSMessage message)
        {
            NwGameObject target = (message.PeekMessage <uint>(0) & 0x7FFFFFFF).ToNwObject <NwGameObject>() !;
            uint         itemId = LowLevel.ServerExoApp.GetObjectArray().m_nNextObjectArrayID[0];

            OnDMGiveItemBefore beforeEventData = ProcessEvent(new OnDMGiveItemBefore
            {
                DungeonMaster = dungeonMaster,
                Target        = target,
            });

            bool skipped = beforeEventData.Skip || !Hook.CallOriginal(pMessage, pPlayer, nMinor, bGroup).ToBool();

            if (!skipped)
            {
                ProcessEvent(new OnDMGiveItemAfter
                {
                    DungeonMaster = dungeonMaster,
                    Target        = target,
                    Item          = itemId.ToNwObject <NwItem>() !,
                });