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)); } }
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, });
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); }
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()); } }
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); }
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() !, });
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); }
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); }
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()); }
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, });
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."); } }
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); }
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); }
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); }
public static string PeekMessageString(this CNWSMessage message, int offset) { byte *ptr = message.m_pnReadBuffer + message.m_nReadBufferPtr + offset; return(StringHelper.ReadNullTerminatedString(ptr)); }
public static string PeekMessageResRef(this CNWSMessage message, int offset) { byte *ptr = message.m_pnReadBuffer + message.m_nReadBufferPtr + offset; return(StringHelper.ReadFixedLengthString(ptr, 16)); }
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)); }
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()); }
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>() !, });