def get_progress(self): total_count = 0 # Handle exploration, all bits set if completed. if self.is_exploration_quest() and self.get_quest_state() == QuestState.QUEST_REWARD: return total_count ^ 0xFFFFFFFF # Creature or gameobject. req_creature_or_go = QuestHelpers.generate_req_creature_or_go_list(self.quest) req_creature_or_go_count = QuestHelpers.generate_req_creature_or_go_count_list(self.quest) for index, creature_or_go in enumerate(req_creature_or_go): if req_creature_or_go[index] > 0: current_count = eval(f'self.db_state.mobcount{index + 1}') required = req_creature_or_go_count[index] # Consider how many bits the previous creature required. offset = index * req_creature_or_go_count[index - 1] if index > 0 else 0 for i in range(required): if i < current_count: # Turn on actual kills total_count += (1 & 1) << (1 * i) + offset else: # Fill remaining 0s (Missing kills) total_count += 0 << (1 * i) + offset # Debug, enable this to take a look on whats happening at bit level. # Logger.debug(f'{bin(mob_kills)[2:].zfill(32)}') return total_count
def requires_creature_or_go(self, creature_entry): req_creatures_or_gos = QuestHelpers.generate_req_creature_or_go_list(self.quest) required = creature_entry in req_creatures_or_gos if required: index = req_creatures_or_gos.index(creature_entry) required_kills = QuestHelpers.generate_req_creature_or_go_count_list(self.quest)[index] current_kills = eval(f'self.db_state.mobcount{index + 1}') return current_kills < required_kills return False
def update_creature_go_count(self, creature, value): creature_go_index = QuestHelpers.generate_req_creature_or_go_list(self.quest).index(creature.entry) required = QuestHelpers.generate_req_creature_or_go_count_list(self.quest)[creature_go_index] current = self._get_db_mob_or_go_count(creature_go_index) # Current < Required is already validated on requires_creature_or_go(). self._update_db_creature_go_count(creature_go_index, 1) # Update db memento # Notify the current objective count to the player. data = pack('<4IQ', self.db_state.quest, creature.entry, current + value, required, creature.guid) packet = PacketWriter.get_packet(OpCode.SMSG_QUESTUPDATE_ADD_KILL, data) self.owner.enqueue_packet(packet) # Check if this makes it complete. if self.can_complete_quest(): self.update_quest_state(QuestState.QUEST_REWARD)
def is_instant_complete_quest(self): for reqSource in QuestHelpers.generate_req_source_list(self.quest): if reqSource != 0: return False for reqItem in QuestHelpers.generate_req_item_list(self.quest): if reqItem != 0: return False for reqCreatureGo in QuestHelpers.generate_req_creature_or_go_list( self.quest): if reqCreatureGo != 0: return False for reqSpellCast in QuestHelpers.generate_req_spell_cast_list( self.quest): if reqSpellCast != 0: return False return True
def get_progress(self): total_count = 0 req_creature_or_go = QuestHelpers.generate_req_creature_or_go_list( self.quest) req_creature_or_go_count = QuestHelpers.generate_req_creature_or_go_count_list( self.quest) for index, creature_or_go in enumerate(req_creature_or_go): if req_creature_or_go[index] > 0: current_count = eval(f'self.db_state.mobcount{index + 1}') required = req_creature_or_go_count[index] # Consider how many bits the previous creature required. offset = index * req_creature_or_go_count[ index - 1] if index > 0 else 0 for i in range(0, required): if i < current_count: # Turn on actual kills total_count += (1 & 1) << (1 * i) + offset else: # Fill remaining 0s (Missing kills) total_count += 0 << (1 * i) + offset # Debug, enable this to take a look on whats happening at bit level. # Logger.debug(f'{bin(mob_kills)[2:].zfill(32)}') return total_count
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))