def send_quest_giver_offer_reward(self, quest, quest_giver_guid, enable_next=True): # Validate if its active to player and if its an instant complete quest. if quest.entry not in self.active_quests and not QuestHelpers.is_instant_complete_quest(quest): return # If this request is from an active quest (not an automatic instant complete dialog) validate again. if quest.entry in self.active_quests: # While the dialog was open displaying 'Quest Complete' the user destroyed items. # Validate if this quest can be completed. active_quest = self.active_quests[quest.entry] if not active_quest.can_complete_quest(): self.send_cant_take_quest_response(QuestFailedReasons.QUEST_FAILED_MISSING_ITEMS) return quest_title_bytes = PacketWriter.string_to_bytes(quest.Title) display_dialog_text = quest.OfferRewardText dialog_text_bytes = PacketWriter.string_to_bytes(display_dialog_text) data = pack( f'<QI{len(quest_title_bytes)}s{len(dialog_text_bytes)}sI', quest_giver_guid, quest.entry, quest_title_bytes, dialog_text_bytes, 1 if enable_next else 0 # enable_next ) # Emote count, always 4. data += pack('<I', 4) for i in range(1, 5): offer_emote = eval(f'quest.OfferRewardEmote{i}') offer_emote_delay = eval(f'quest.OfferRewardEmoteDelay{i}') data += pack('<2I', offer_emote, offer_emote_delay) if QuestHelpers.has_pick_reward(quest): # Reward choices rew_choice_item_list = list(filter((0).__ne__, QuestHelpers.generate_rew_choice_item_list(quest))) rew_choice_count_list = list(filter((0).__ne__, QuestHelpers.generate_rew_choice_count_list(quest))) data += pack('<I', len(rew_choice_item_list)) for index, item in enumerate(rew_choice_item_list): data += self._gen_item_struct(item, rew_choice_count_list[index]) else: data += pack('<I', 0) # Apart from available rewards to pick from, sometimes there are rewards you will also get, no matter what. if QuestHelpers.has_item_reward(quest): # Required items rew_item_list = list(filter((0).__ne__, QuestHelpers.generate_rew_item_list(quest))) rew_count_list = list(filter((0).__ne__, QuestHelpers.generate_rew_count_list(quest))) data += pack('<I', len(rew_item_list)) for index, item in enumerate(rew_item_list): data += self._gen_item_struct(item, rew_count_list[index]) else: data += pack('<I', 0) # Reward Money, 0.5.3 does not handle spells as a possible reward. CGPlayer_C::OnQuestGiverChooseReward. data += pack('<I', quest.RewOrReqMoney if quest.RewOrReqMoney >= 0 else -quest.RewOrReqMoney) self.player_mgr.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_OFFER_REWARD, data))
def send_quest_giver_quest_details(self, quest_template, quest_giver_guid, activate_accept): # Quest information quest_title = PacketWriter.string_to_bytes(quest_template.Title) quest_details = PacketWriter.string_to_bytes(quest_template.Details) quest_objectives = PacketWriter.string_to_bytes(quest_template.Objectives) data = pack( f'<QI{len(quest_title)}s{len(quest_details)}s{len(quest_objectives)}sI', quest_giver_guid, quest_template.entry, quest_title, quest_details, quest_objectives, 1 if activate_accept else 0 ) # Reward choices rew_choice_item_list = list(filter((0).__ne__, QuestHelpers.generate_rew_choice_item_list(quest_template))) rew_choice_count_list = list(filter((0).__ne__, QuestHelpers.generate_rew_choice_count_list(quest_template))) data += pack('<I', len(rew_choice_item_list)) for index, item in enumerate(rew_choice_item_list): data += self._gen_item_struct(item, rew_choice_count_list[index]) # Reward items rew_item_list = list(filter((0).__ne__, QuestHelpers.generate_rew_item_list(quest_template))) rew_count_list = list(filter((0).__ne__, QuestHelpers.generate_rew_count_list(quest_template))) data += pack('<I', len(rew_item_list)) for index, item in enumerate(rew_item_list): data += self._gen_item_struct(item, rew_count_list[index]) # Reward money data += pack('<I', quest_template.RewOrReqMoney) # Emotes data += pack('<I', 4) for index in range(1, 5): detail_emote = int(eval(f'quest_template.DetailsEmote{index}')) detail_emote_delay = eval(f'quest_template.DetailsEmoteDelay{index}') data += pack('<2I', detail_emote, detail_emote_delay) self.player_mgr.enqueue_packet(PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_QUEST_DETAILS, data))
def send_quest_giver_offer_reward(self, active_quest, quest_giver_guid, enable_next=True): # CGPlayer_C::OnQuestGiverChooseReward quest = active_quest.quest quest_title_bytes = PacketWriter.string_to_bytes(quest.Title) display_dialog_text = quest.OfferRewardText dialog_text_bytes = PacketWriter.string_to_bytes(display_dialog_text) data = pack( f'<QI{len(quest_title_bytes)}s{len(dialog_text_bytes)}sI', quest_giver_guid, active_quest.quest.entry, quest_title_bytes, dialog_text_bytes, 1 if enable_next else 0 # enable_next ) # Emote count, always 4. data += pack('<I', 4) for i in range(1, 5): emote = eval(f'active_quest.quest.OfferRewardEmote{i}') delay = eval(f'active_quest.quest.OfferRewardEmoteDelay{i}') data += pack('<2I', emote, delay) if active_quest.has_pick_reward(): # Reward choices rew_choice_item_list = list( filter((0).__ne__, QuestHelpers.generate_rew_choice_item_list(quest))) rew_choice_count_list = list( filter((0).__ne__, QuestHelpers.generate_rew_choice_count_list(quest))) data += pack('<I', len(rew_choice_item_list)) for index, item in enumerate(rew_choice_item_list): data += self._gen_item_struct(item, rew_choice_count_list[index]) else: data += pack('<I', 0) # Apart from available rewards to pick from, sometimes there are rewards you will also get, no matter what. if active_quest.has_item_reward(): # Required items rew_item_list = list( filter((0).__ne__, QuestHelpers.generate_rew_item_list(quest))) rew_count_list = list( filter((0).__ne__, QuestHelpers.generate_rew_count_list(quest))) data += pack('<I', len(rew_item_list)) for index, item in enumerate(rew_item_list): data += self._gen_item_struct(item, rew_count_list[index]) else: data += pack('<I', 0) # Reward data += pack( '<3I', quest.RewOrReqMoney if quest.RewOrReqMoney >= 0 else -quest.RewOrReqMoney, quest.RewSpell, quest.RewSpellCast, ) self.player_mgr.enqueue_packet( PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_OFFER_REWARD, data))
def send_quest_query_response(self, quest): data = pack(f'<3Ii4I', quest.entry, quest.Method, quest.QuestLevel, quest.ZoneOrSort, quest.Type, quest.NextQuestInChain, quest.RewOrReqMoney, quest.SrcItemId) # Rewards given no matter what. rew_item_list = QuestHelpers.generate_rew_item_list(quest) rew_item_count_list = QuestHelpers.generate_rew_count_list(quest) for index, item in enumerate(rew_item_list): data += pack('<2I', item, rew_item_count_list[index]) # Reward choices. rew_choice_item_list = QuestHelpers.generate_rew_choice_item_list( quest) rew_choice_count_list = QuestHelpers.generate_rew_choice_count_list( quest) for index, item in enumerate(rew_choice_item_list): data += pack('<2I', item, rew_choice_count_list[index]) title_bytes = PacketWriter.string_to_bytes(quest.Title) details_bytes = PacketWriter.string_to_bytes(quest.Details) objectives_bytes = PacketWriter.string_to_bytes(quest.Objectives) end_bytes = PacketWriter.string_to_bytes(quest.EndText) data += pack( f'<I2fI{len(title_bytes)}s{len(details_bytes)}s{len(objectives_bytes)}s{len(end_bytes)}s', quest.PointMapId, quest.PointX, quest.PointY, quest.PointOpt, title_bytes, details_bytes, objectives_bytes, end_bytes, ) # Required kills / Required items count. req_creatures_or_gos = QuestHelpers.generate_req_creature_or_go_list( quest) req_creatures_or_gos_count_list = QuestHelpers.generate_req_creature_or_go_count_list( quest) req_items = QuestHelpers.generate_req_item_list(quest) req_items_count_list = QuestHelpers.generate_req_item_count_list(quest) for index, creature_or_go in enumerate(req_creatures_or_gos): data += pack( '<4IB', creature_or_go if creature_or_go >= 0 else (creature_or_go * -1) | 0x80000000, req_creatures_or_gos_count_list[index], req_items[index], req_items_count_list[index], 0x0 # Unknown, if missing, multiple objective quests will not display properly. ) # Objective texts. req_objective_text_list = QuestHelpers.generate_objective_text_list( quest) for index, objective_text in enumerate(req_objective_text_list): req_objective_text_bytes = PacketWriter.string_to_bytes( req_objective_text_list[index]) data += pack(f'{len(req_objective_text_bytes)}s', req_objective_text_bytes) self.player_mgr.enqueue_packet( PacketWriter.get_packet(OpCode.SMSG_QUEST_QUERY_RESPONSE, data))
def send_quest_giver_quest_details(self, quest_template, quest_giver_guid, activate_accept): # Quest information quest_title = PacketWriter.string_to_bytes(quest_template.Title) quest_details = PacketWriter.string_to_bytes(quest_template.Details) quest_objectives = PacketWriter.string_to_bytes( quest_template.Objectives) data = pack( f'<QI{len(quest_title)}s{len(quest_details)}s{len(quest_objectives)}sI', quest_giver_guid, quest_template.entry, quest_title, quest_details, quest_objectives, 1 if activate_accept else 0) # Reward choices rew_choice_item_list = list( filter((0).__ne__, QuestHelpers.generate_rew_choice_item_list(quest_template))) rew_choice_count_list = list( filter( (0).__ne__, QuestHelpers.generate_rew_choice_count_list(quest_template))) data += pack('<I', len(rew_choice_item_list)) for index, item in enumerate(rew_choice_item_list): data += self._gen_item_struct(item, rew_choice_count_list[index]) # Reward items rew_item_list = list( filter((0).__ne__, QuestHelpers.generate_rew_item_list(quest_template))) rew_count_list = list( filter((0).__ne__, QuestHelpers.generate_rew_count_list(quest_template))) data += pack('<I', len(rew_item_list)) for index, item in enumerate(rew_item_list): data += self._gen_item_struct(item, rew_count_list[index]) # Reward money data += pack('<I', quest_template.RewOrReqMoney) # Required items req_item_list = list( filter((0).__ne__, QuestHelpers.generate_req_item_list(quest_template))) req_count_list = list( filter((0).__ne__, QuestHelpers.generate_req_item_count_list(quest_template))) data += pack('<I', len(req_item_list)) for index, item in enumerate(req_item_list): data += self._gen_item_struct(item, req_count_list[index]) # Required kill / go count req_creature_or_go_list = list( filter( (0).__ne__, QuestHelpers.generate_req_creature_or_go_list(quest_template))) req_creature_or_go_count_list = list( filter((0).__ne__, QuestHelpers.generate_req_creature_or_go_count_list( quest_template))) data += pack('<I', len(req_creature_or_go_list)) for index, creature_or_go in enumerate(req_creature_or_go_list): data += pack( '<2I', creature_or_go if creature_or_go >= 0 else (creature_or_go * -1) | 0x80000000, req_creature_or_go_count_list[index]) self.player_mgr.enqueue_packet( PacketWriter.get_packet(OpCode.SMSG_QUESTGIVER_QUEST_DETAILS, data))