void HandleGossipSelectOption(GossipSelectOption packet) { if (GetPlayer().PlayerTalkClass.GetGossipMenu().GetItem(packet.GossipIndex) == null) { return; } // Prevent cheating on C# scripted menus if (GetPlayer().PlayerTalkClass.GetInteractionData().SourceGuid != packet.GossipUnit) { return; } Creature unit = null; GameObject go = null; if (packet.GossipUnit.IsCreatureOrVehicle()) { unit = GetPlayer().GetNPCIfCanInteractWith(packet.GossipUnit, NPCFlags.Gossip); if (unit == null) { Log.outDebug(LogFilter.Network, "WORLD: HandleGossipSelectOption - {0} not found or you can't interact with him.", packet.GossipUnit.ToString()); return; } } else if (packet.GossipUnit.IsGameObject()) { go = GetPlayer().GetGameObjectIfCanInteractWith(packet.GossipUnit); if (go == null) { Log.outDebug(LogFilter.Network, "WORLD: HandleGossipSelectOption - {0} not found or you can't interact with it.", packet.GossipUnit.ToString()); return; } } else { Log.outDebug(LogFilter.Network, "WORLD: HandleGossipSelectOption - unsupported {0}.", packet.GossipUnit.ToString()); return; } // remove fake death if (GetPlayer().HasUnitState(UnitState.Died)) { GetPlayer().RemoveAurasByType(AuraType.FeignDeath); } if ((unit && unit.GetScriptId() != unit.LastUsedScriptID) || (go != null && go.GetScriptId() != go.LastUsedScriptID)) { Log.outDebug(LogFilter.Network, "WORLD: HandleGossipSelectOption - Script reloaded while in use, ignoring and set new scipt id"); if (unit != null) { unit.LastUsedScriptID = unit.GetScriptId(); } if (go != null) { go.LastUsedScriptID = go.GetScriptId(); } GetPlayer().PlayerTalkClass.SendCloseGossip(); return; } if (!string.IsNullOrEmpty(packet.PromotionCode)) { if (unit) { unit.GetAI().sGossipSelectCode(GetPlayer(), packet.GossipID, packet.GossipIndex, packet.PromotionCode); if (!Global.ScriptMgr.OnGossipSelectCode(GetPlayer(), unit, GetPlayer().PlayerTalkClass.GetGossipOptionSender(packet.GossipIndex), GetPlayer().PlayerTalkClass.GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode)) { GetPlayer().OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); } } else { go.GetAI().GossipSelectCode(GetPlayer(), packet.GossipID, packet.GossipIndex, packet.PromotionCode); Global.ScriptMgr.OnGossipSelectCode(GetPlayer(), go, GetPlayer().PlayerTalkClass.GetGossipOptionSender(packet.GossipIndex), GetPlayer().PlayerTalkClass.GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode); } } else { if (unit != null) { unit.GetAI().sGossipSelect(GetPlayer(), packet.GossipID, packet.GossipIndex); if (!Global.ScriptMgr.OnGossipSelect(GetPlayer(), unit, GetPlayer().PlayerTalkClass.GetGossipOptionSender(packet.GossipIndex), GetPlayer().PlayerTalkClass.GetGossipOptionAction(packet.GossipIndex))) { GetPlayer().OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); } } else { go.GetAI().GossipSelect(GetPlayer(), packet.GossipID, packet.GossipIndex); if (!Global.ScriptMgr.OnGossipSelect(GetPlayer(), go, GetPlayer().PlayerTalkClass.GetGossipOptionSender(packet.GossipIndex), GetPlayer().PlayerTalkClass.GetGossipOptionAction(packet.GossipIndex))) { GetPlayer().OnGossipSelect(go, packet.GossipIndex, packet.GossipID); } } } }
void m_parsingItemsWorker_DoWork(object sender, DoWorkEventArgs e) { var worker = (BackgroundWorker)sender; var items = (IList <ViewerItem>)e.Argument; var nitems = items.Count; int progress = 0; var protocol = m_viewer.CurrentProtocol; var objects = new SortedDictionary <WowGuid, ObjectGossip>(new WowGuidKindEntryComparer()); var menus = new SortedDictionary <uint, ExtGossipMenu>(); ExtGossipMenu currentMenu = null; WowGuid currentObject = WowGuid.Empty; Action resetCurrent = () => { currentMenu = null; currentObject = WowGuid.Empty; }; var optSelectQueue = new Queue <GossipSelectOption>(); for (int i = 0; i < nitems && !worker.CancellationPending; i++) { var item = items[i]; var packet = item.Packet; var opcodePacket = packet as IPacketWithOpcode; if (opcodePacket == null) { continue; } var opcode = (WowOpcodes)opcodePacket.Opcode; switch (opcode) { #warning Gossip Parser not implemented //case WowOpcodes.CMSG_GOSSIP_HELLO: //case WowOpcodes.CMSG_GAMEOBJ_USE: //case WowOpcodes.CMSG_LIST_INVENTORY: //case WowOpcodes.CMSG_TRAINER_LIST: //{ // using (var reader = new StreamHandler(packet.Data)) // { // optSelectQueue.Enqueue(new GossipSelectOption() // { // Object = reader.ReadGuid(), // MenuId = uint.MaxValue, // OptionId = uint.MaxValue // }); // } // break; //} //case WowOpcodes.CMSG_GOSSIP_SELECT_OPTION: //{ // if (currentMenu != null) // { // using (var reader = new StreamHandler(packet.Data)) // { // var obj = reader.ReadGuid(); // var menuId = reader.ReadUInt32(); // var optionId = reader.ReadUInt32(); // if (currentMenu.Menu.MenuId == menuId) // { // optSelectQueue.Enqueue(new GossipSelectOption() // { // Object = obj, // MenuId = menuId, // OptionId = optionId // }); // } // else // Console.WriteLine("Error: Gossip Menu: currentMenuId != selectedMenuId ({0} != {1})", // currentMenu.Menu.MenuId, menuId); // } // } // else // Console.WriteLine("Error: Gossip Parser: Unexpected CMSG_GOSSIP_SELECT_OPTION (inner)"); // break; //} //case WowOpcodes.SMSG_DESTROY_OBJECT: //{ // var guid = new WowGuid(BitConverter.ToUInt64(packet.Data, 0)); // if (currentObject == guid) // resetCurrent(); // break; //} //case WowOpcodes.SMSG_UPDATE_OBJECT: //{ // using (var reader = new StreamHandler(packet.Data)) // { // var updateData = new UpdateData(reader, true); // foreach (var guid in updateData.DestroyedObjects) // { // if (currentObject == guid) // resetCurrent(); // } // } // break; //} //case WowOpcodes.CMSG_QUESTGIVER_ACCEPT_QUEST: //{ // var guid = new WowGuid(BitConverter.ToUInt64(packet.Data, 0)); // if (optSelectQueue.Count > 0) // { // if (optSelectQueue.Peek().Object == guid) // optSelectQueue.Dequeue(); // else // Console.WriteLine("Error: Gossip Parser: Unexpected {0} (packet #{1})", opcode, i); // } // break; //} //case WowOpcodes.SMSG_TRAINER_LIST: //case WowOpcodes.SMSG_VENDOR_INVENTORY: //case WowOpcodes.SMSG_INVALID_PROMOTION_CODE: //{ // if (optSelectQueue.Count > 0) // optSelectQueue.Dequeue(); // else // Console.WriteLine("Error: Gossip Parser: Unexpected {0} (packet #{1})", opcode, i); // break; //} //case WowOpcodes.SMSG_GOSSIP_COMPLETE: //{ // while (optSelectQueue.Count > 0 && // optSelectQueue.Peek().Object == currentObject && // optSelectQueue.Peek().MenuId == currentMenu.Menu.MenuId) // optSelectQueue.Dequeue(); // resetCurrent(); // break; //} //case WowOpcodes.CMSG_LOADING_SCREEN_NOTIFY: //case WowOpcodes.SMSG_NEW_WORLD: case WowOpcodes.SMSG_LOGIN_VERIFY_WORLD: { resetCurrent(); optSelectQueue.Clear(); break; } default: { var parser = item.Parser; if (parser == null) { protocol.CreateParser(item); parser = item.Parser; } if (parser is GossipMessageParser) { var gossip = (GossipMessageParser)parser; if (!gossip.IsParsed) { gossip.Parse(); } var menu = gossip.Menu; ExtGossipMenu extMenu; if (!menus.TryGetValue(menu.MenuId, out extMenu)) { menus[menu.MenuId] = extMenu = new ExtGossipMenu() { Menu = menu, GossipOptionMenus = new uint[menu.GossipOptions.Length] }; } else { var existingMenu = extMenu.Menu; if (!existingMenu.Equals(menu)) { Console.WriteLine("Error: Gossip Parser: New menu with same id {0}", menu.MenuId); break; } } var guid = gossip.Object; extMenu.Objects.Add(guid); ObjectGossip gossipObject; if (!objects.TryGetValue(guid, out gossipObject)) { objects[guid] = gossipObject = new ObjectGossip() { ObjectType = guid.Kind, ObjectEntry = guid.Entry }; } GossipSelectOption opt = null; while (optSelectQueue.Count > 0) { var optSelect = optSelectQueue.Dequeue(); if (optSelect.Object != guid && optSelect.Object.IsGameObject) { continue; } opt = optSelect; break; } if (opt == null) { Console.WriteLine("Error: Gossip Parser: Unexpected Gossip Message"); break; } if ((opt.MenuId == uint.MaxValue) != (currentMenu == null)) { Console.WriteLine("Error: Gossip Parser: unexpected state of gossip parser, packet = {0}", i); } if (currentMenu == null) { // Just interacted with the object gossipObject.InitialMenus.Add(menu.MenuId); currentObject = guid; } else { if (guid != currentObject) { Console.WriteLine("Error: Gossip Parser: unexpected object"); break; } // Got a gossip message after an option was selected int idx = currentMenu.Menu.GossipOptions.IndexOf(_ => _.OptionId == opt.OptionId); if (idx != -1) { currentMenu.GossipOptionMenus[idx] = menu.MenuId; } else { Console.WriteLine("Error: Gossip Parser: Unable to find option {0} in menu {1}", opt.OptionId, opt.MenuId); } } if (gossipObject.Menus.IndexOf(extMenu) < 0) { gossipObject.Menus.Add(extMenu); } currentMenu = extMenu; } else if (parser is CreatureQueryResponseParser) { var query = (CreatureQueryResponseParser)parser; if (!query.IsParsed) { query.Parse(); } var id = query.Template.Entry; if (id < 0) { continue; } m_creatureTemplates[(uint)id] = query.Template; } else if (parser is GameObjectQueryResponseParser) { var query = (GameObjectQueryResponseParser)parser; if (!query.IsParsed) { query.Parse(); } var id = query.Template.Entry; if (id < 0) { continue; } m_goTemplates[(uint)id] = query.Template; } break; } } int newProgress = 100 * i / nitems; if (newProgress != progress) { worker.ReportProgress(progress = newProgress); } } if (worker.CancellationPending) { m_objects = new KeyValuePair <WowGuid, ObjectGossip> [0]; m_menus = new KeyValuePair <uint, ExtGossipMenu> [0]; return; } // Setup names. foreach (var pair in objects) { var obj = pair.Value; var s = obj.ObjectType.ToString() + " #" + obj.ObjectEntry.ToString(); if (obj.ObjectType == WowGuidKind.GameObject) { GameObjectTemplate go; if (m_goTemplates.TryGetValue(obj.ObjectEntry, out go)) { s += " - " + go.Name[0]; } } else if (obj.ObjectType == WowGuidKind.Unit) { CreatureTemplate npc; if (m_creatureTemplates.TryGetValue(obj.ObjectEntry, out npc)) { s += " - " + npc.Name[0] + (string.IsNullOrEmpty(npc.SubName) ? "" : " <" + npc.SubName + ">"); } } obj.ObjectName = s; } m_objects = objects.ToArray(); m_menus = menus.ToArray(); }