private void PacketHandler_0x3A_DialogUse(Object obj, ClientPacket packet) { var user = (User) obj; if (user.CheckSquelch(0x38, null)) { Logger.InfoFormat("{0}: squelched (dialog use)", user.Name); return; } var header = packet.ReadDialogHeader(); var objectType = packet.ReadByte(); var objectID = packet.ReadUInt32(); var pursuitID = packet.ReadUInt16(); var pursuitIndex = packet.ReadUInt16(); Logger.DebugFormat("objectType {0}, objectID {1}, pursuitID {2}, pursuitIndex {3}", objectType, objectID, pursuitID, pursuitIndex); Logger.DebugFormat("active dialog via state object: pursuitID {0}, pursuitIndex {1}", user.DialogState.CurrentPursuitId, user.DialogState.CurrentPursuitIndex); if (pursuitID == user.DialogState.CurrentPursuitId && pursuitIndex == user.DialogState.CurrentPursuitIndex) { // If we get a packet back with the same index and ID, the dialog has been closed. Logger.DebugFormat("Dialog closed, resetting dialog state"); user.DialogState.EndDialog(); return; } if ((pursuitIndex > user.DialogState.CurrentPursuitIndex + 1) || (pursuitIndex < user.DialogState.CurrentPursuitIndex - 1)) { Logger.ErrorFormat("Dialog index is outside of acceptable limits (next/prev)"); return; } WorldObject wobj; if (user.World.Objects.TryGetValue(objectID, out wobj)) { VisibleObject clickTarget = wobj as VisibleObject; // Was the previous button clicked? Handle that first if (pursuitIndex == user.DialogState.CurrentPursuitIndex - 1) { Logger.DebugFormat("Handling prev: client passed index {0}, current index is {1}", pursuitIndex, user.DialogState.CurrentPursuitIndex); if (user.DialogState.SetDialogIndex(clickTarget, pursuitID, pursuitIndex)) { user.DialogState.ActiveDialog.ShowTo(user, clickTarget); return; } } // Is the active dialog an input or options dialog? if (user.DialogState.ActiveDialog is OptionsDialog) { var paramsLength = packet.ReadByte(); var option = packet.ReadByte(); var dialog = user.DialogState.ActiveDialog as OptionsDialog; dialog.HandleResponse(user, option, clickTarget); } if (user.DialogState.ActiveDialog is TextDialog) { var paramsLength = packet.ReadByte(); var response = packet.ReadString8(); var dialog = user.DialogState.ActiveDialog as TextDialog; dialog.HandleResponse(user, response, clickTarget); } // Did the handling of a response result in our active dialog sequence changing? If so, exit. if (user.DialogState.CurrentPursuitId != pursuitID) { Logger.DebugFormat("Dialog has changed, exiting"); return; } if (user.DialogState.SetDialogIndex(clickTarget, pursuitID, pursuitIndex)) { Logger.DebugFormat("Pursuit index is now {0}", pursuitIndex); user.DialogState.ActiveDialog.ShowTo(user, clickTarget); return; } else { Logger.DebugFormat("Sending close packet"); var p = new ServerPacket(0x30); p.WriteByte(0x0A); p.WriteByte(0x00); user.Enqueue(p); user.DialogState.EndDialog(); } } }
private void PacketHandler_0x39_NPCMainMenu(Object obj, ClientPacket packet) { var user = (User) obj; if (user.CheckSquelch(0x38, null)) { Logger.InfoFormat("{0}: squelched (NPC main menu)", user.Name); return; } // We just ignore the header, because, really, what exactly is a 16-bit encryption // key plus CRC really doing for you var header = packet.ReadDialogHeader(); var objectType = packet.ReadByte(); var objectId = packet.ReadUInt32(); var pursuitId = packet.ReadUInt16(); Logger.DebugFormat("main menu packet: ObjectType {0}, ID {1}, pursuitID {2}", objectType, objectId, pursuitId); // Sanity checks WorldObject wobj; if (Game.World.Objects.TryGetValue(objectId, out wobj)) { // Are we handling a global sequence? DialogSequence pursuit; VisibleObject clickTarget = wobj as VisibleObject; if (pursuitId < Constants.DIALOG_SEQUENCE_SHARED) { // Does the sequence exist in the global catalog? try { pursuit = Game.World.GlobalSequences[pursuitId]; } catch { Logger.ErrorFormat("{0}: pursuit ID {1} doesn't exist in the global catalog?", wobj.Name, pursuitId); return; } } else if (pursuitId >= Constants.DIALOG_SEQUENCE_HARDCODED) { if (!(wobj is Merchant)) { Logger.ErrorFormat("{0}: attempt to use hardcoded merchant menu item on non-merchant", wobj.Name, pursuitId); return; } var menuItem = (MerchantMenuItem) pursuitId; var merchant = (Merchant) wobj; MerchantMenuHandler handler; if (!merchantMenuHandlers.TryGetValue(menuItem, out handler)) { Logger.ErrorFormat("{0}: merchant menu item {1} doesn't exist?", wobj.Name, menuItem); return; } if (!merchant.Jobs.HasFlag(handler.RequiredJob)) { Logger.ErrorFormat("{0}: merchant does not have required job {1}", wobj.Name, handler.RequiredJob); return; } handler.Callback(user, merchant, packet); return; } else { // This is a local pursuit try { pursuit = clickTarget.Pursuits[pursuitId - Constants.DIALOG_SEQUENCE_SHARED]; } catch { Logger.ErrorFormat("{0}: local pursuit {1} doesn't exist?", wobj.Name, pursuitId); return; } } Logger.DebugFormat("{0}: showing initial dialog for Pursuit {1} ({2})", clickTarget.Name, pursuit.Id, pursuit.Name); user.DialogState.StartDialog(clickTarget, pursuit); pursuit.ShowTo(user, clickTarget); } else { Logger.WarnFormat("specified object ID {0} doesn't exist?", objectId); return; } }