def match_condition(self, quest_key): """ Check if the quest matches its condition. Args: quest_key: (string) quest's key Returns: (boolean) result """ # Get quest's record. model_names = OBJECT_KEY_HANDLER.get_models(quest_key) if not model_names: return False for model_name in model_names: model_quest = apps.get_model(settings.WORLD_DATA_APP, model_name) try: record = model_quest.objects.get(key=quest_key) return STATEMENT_HANDLER.match_condition( record.condition, self.owner, None) except ObjectDoesNotExist: continue except AttributeError: continue return True
def get_appearance(self, caller): """ This is a convenient hook for a 'look' command to call. """ # Get name and description. if caller.is_exit_unlocked(self.get_data_key()): # If is unlocked, use common appearance. return super(MudderyLockedExit, self).get_appearance(caller) can_unlock = STATEMENT_HANDLER.match_condition(self.unlock_condition, caller, self) if can_unlock and self.auto_unlock: # Automatically unlock the exit when a character looking at it. caller.unlock_exit(self) # If is unlocked, use common appearance. return super(MudderyLockedExit, self).get_appearance(caller) cmds = [] if can_unlock: # show unlock command verb = self.unlock_verb if not verb: verb = LS("Unlock") cmds = [{"name": verb, "cmd": "unlock_exit", "args": self.dbref}] info = {"dbref": self.dbref, "name": self.name, "desc": self.locked_desc, "cmds": cmds} return info
def get_appearance(self, caller): """ This is a convenient hook for a 'look' command to call. """ # Get name and description. if caller.is_exit_unlocked(self.get_data_key()): # If is unlocked, use common appearance. return super(MudderyLockedExit, self).get_appearance(caller) can_unlock = STATEMENT_HANDLER.match_condition(self.unlock_condition, caller, self) if can_unlock and self.auto_unlock: # Automatically unlock the exit when a character looking at it. caller.unlock_exit(self) # If is unlocked, use common appearance. return super(MudderyLockedExit, self).get_appearance(caller) cmds = [] if can_unlock: # show unlock command verb = self.unlock_verb if not verb: verb = _("Unlock") cmds = [{"name": verb, "cmd": "unlock_exit", "args": self.dbref}] info = {"dbref": self.dbref, "name": self.name, "desc": self.locked_desc, "cmds": cmds} return info
def can_unlock(self, caller): """ Unlock an exit. """ # Only can unlock exits which match there conditions. return STATEMENT_HANDLER.match_condition(self.unlock_condition, caller, self)
def get_surroundings(self, caller): """ This is a convenient hook for a 'look' command to call. """ # get name, description, commands and all objects in it info = { "exits": [], "npcs": [], "things": [], "players": [], "offlines": [] } visible = (cont for cont in self.contents if cont != caller and cont.access(caller, "view")) if GAME_SETTINGS.get("solo_mode"): visible = (cont for cont in visible if not cont.has_player) for cont in visible: # only show objects that match the condition condition = getattr(cont.dfield, "condition", None) if condition: if not STATEMENT_HANDLER.match_condition( condition, caller, self): continue type = self.get_surrounding_type(cont) if type: appearance = {} if type == "npcs": # add quest status if hasattr(cont, "have_quest"): provide_quest, complete_quest = cont.have_quest(caller) appearance["provide_quest"] = provide_quest appearance["complete_quest"] = complete_quest elif type == "exits": # get exits destination if cont.destination: dest = { "name": cont.destination.get_name(), "position": cont.destination.position } appearance["destination"] = dest elif type == "offlines": continue appearance["dbref"] = cont.dbref appearance["name"] = cont.get_name() appearance["key"] = cont.get_data_key() info[type].append(appearance) return info
def get_available_commands(self, caller): """ This returns a list of available commands. "args" must be a string without ' and ", usually it is self.dbref. """ if not STATEMENT_HANDLER.match_condition(self.loot_condition, caller, self): return [] commands = [{"name": self.loot_verb, "cmd": "loot", "args": self.dbref}] return commands
def get_desc(self, caller): """ This returns object's descriptions on different conditions. """ desc_conditions = DESC_HANDLER.get(self.get_data_key()) if desc_conditions: for item in desc_conditions: if STATEMENT_HANDLER.match_condition(item["condition"], caller, self): return item["desc"] return self.db.desc
def get_npc_sentences(self, caller, npc): """ Get NPC's sentences that can show to the caller. Args: caller: (object) the character who want to start a talk. npc: (object) the NPC that the character want to talk to. Returns: sentences: (list) a list of available sentences. """ if not caller: return if not npc: return sentences = [] # Get npc's dialogues. for dlg_key in npc.dialogues: # Get all dialogues. npc_dlg = self.get_dialogue(dlg_key) if not npc_dlg: continue # Match conditions. if not STATEMENT_HANDLER.match_condition(npc_dlg["condition"], caller, npc): continue # Match dependencies. match = True for dep in npc_dlg["dependencies"]: status = QUEST_STATUS_SET.get(dep["type"]) if not status.match(caller, dep["quest"]): match = False break if not match: continue if npc_dlg["sentences"]: # If has sentence, use it. sentences.append(npc_dlg["sentences"][0]) if not sentences: # Use default sentences. # Default sentences should not have condition and dependencies. for dlg_key in npc.default_dialogues: npc_dlg = self.get_dialogue(dlg_key) if npc_dlg: sentences.append(npc_dlg["sentences"][0]) return self.create_output_sentences(sentences, caller, npc)
def dialogue_have_quest(self, caller, npc, dialogue, accomplished_quests): """ Find quests by recursion. """ provide_quest = False complete_quest = False # check if the dialogue is available npc_dlg = self.get_dialogue(dialogue) if not npc_dlg: return (provide_quest, complete_quest) if not STATEMENT_HANDLER.match_condition(npc_dlg["condition"], caller, npc): return (provide_quest, complete_quest) match = True for dep in npc_dlg["dependencies"]: if not QUEST_DEP_HANDLER.match_dependency(caller, dep["quest"], dep["type"]): match = False break if not match: return (provide_quest, complete_quest) # find quests in its sentences for sen in npc_dlg["sentences"]: if sen["complete_quest"] in accomplished_quests: complete_quest = True return (provide_quest, complete_quest) if not provide_quest and sen["provide_quest"]: quest_key = sen["provide_quest"] if caller.quest_handler.can_provide(quest_key): provide_quest = True if not accomplished_quests: return (provide_quest, complete_quest) for dlg_key in npc_dlg["nexts"]: # get next dialogue provide, complete = self.dialogue_have_quest( caller, npc, dlg_key, accomplished_quests) provide_quest = (provide_quest or provide) complete_quest = (complete_quest or complete) if complete_quest: break if not accomplished_quests: if provide_quest: break return (provide_quest, complete_quest)
def is_visible(self, caller): """ If this object is visible to the caller. Return: boolean: visible """ if not self.condition: return True return STATEMENT_HANDLER.match_condition(self.condition, caller, self)
def get_npc_sentences(self, caller, npc): """ Get NPC's sentences that can show to the caller. Args: caller: (object) the character who want to start a talk. npc: (object) the NPC that the character want to talk to. Returns: sentences: (list) a list of available sentences. """ if not caller: return if not npc: return sentences = [] # Get npc's dialogues. for dlg_key in npc.dialogues: # Get all dialogues. npc_dlg = self.get_dialogue(dlg_key) if not npc_dlg: continue # Match conditions. if not STATEMENT_HANDLER.match_condition(npc_dlg["condition"], caller, npc): continue # Match dependencies. match = True for dep in npc_dlg["dependencies"]: status = QUEST_STATUS_SET.get(dep["type"]) if not status.match(caller, dep["quest"]): match = False break if not match: continue if npc_dlg["sentences"]: # If has sentence, use it. sentences.append(npc_dlg["sentences"][0]) if not sentences: # Use default sentences. # Default sentences should not have condition and dependencies. for dlg_key in npc.default_dialogues: npc_dlg = self.get_dialogue(dlg_key) if npc_dlg: sentences.append(npc_dlg["sentences"][0]) return sentences
def dialogue_have_quest(self, caller, npc, dialogue): """ Find quests by recursion. """ provide_quest = False finish_quest = False # check if the dialogue is available npc_dlg = self.get_dialogue(dialogue) if not npc_dlg: return (provide_quest, finish_quest) if not STATEMENT_HANDLER.match_condition(npc_dlg["condition"], caller, npc): return (provide_quest, finish_quest) match = True for dep in npc_dlg["dependencies"]: status = QUEST_STATUS_SET.get(dep["type"]) if not status.match(caller, dep["quest"]): match = False break if not match: return (provide_quest, finish_quest) # find quests in its sentences for sen in npc_dlg["sentences"]: for quest_key in sen["finish_quest"]: if caller.quest_handler.is_accomplished(quest_key): finish_quest = True return (provide_quest, finish_quest) if not provide_quest and sen["provide_quest"]: for quest_key in sen["provide_quest"]: if caller.quest_handler.can_provide(quest_key): provide_quest = True return (provide_quest, finish_quest) for dlg_key in npc_dlg["nexts"]: # get next dialogue provide, finish = self.dialogue_have_quest(caller, npc, dlg_key) provide_quest = (provide_quest or provide) finish_quest = (finish_quest or finish) if finish_quest: break if not caller.quest_handler.get_accomplished_quests(): if provide_quest: break return (provide_quest, finish_quest)
def dialogue_have_quest(self, caller, npc, dialogue, accomplished_quests): """ Find quests by recursion. """ provide_quest = False complete_quest = False # check if the dialogue is available npc_dlg = self.get_dialogue(dialogue) if not npc_dlg: return (provide_quest, complete_quest) if not STATEMENT_HANDLER.match_condition(npc_dlg["condition"], caller, npc): return (provide_quest, complete_quest) match = True for dep in npc_dlg["dependencies"]: if not QUEST_DEP_HANDLER.match_dependency(caller, dep["quest"], dep["type"]): match = False break; if not match: return (provide_quest, complete_quest) # find quests in its sentences for sen in npc_dlg["sentences"]: if sen["complete_quest"] in accomplished_quests: complete_quest = True return (provide_quest, complete_quest) if not provide_quest and sen["provide_quest"]: quest_key = sen["provide_quest"] if caller.quest_handler.can_provide(quest_key): provide_quest = True if not accomplished_quests: return (provide_quest, complete_quest) for dlg_key in npc_dlg["nexts"]: # get next dialogue provide, complete = self.dialogue_have_quest(caller, npc, dlg_key, accomplished_quests) provide_quest = (provide_quest or provide) complete_quest = (complete_quest or complete) if complete_quest: break if not accomplished_quests: if provide_quest: break return (provide_quest, complete_quest)
def get_next_sentences(self, caller, npc, current_dialogue, current_sentence): """ Get current sentence's next sentences. Args: caller: (object) the character who want to start a talk. npc: (object) the NPC that the character want to talk to. dialogue: (string) the key of the currrent dialogue. sentence: (int) the number of current sentence. Returns: sentences: (list) a list of available sentences. """ if not caller: return # Get current dialogue. dlg = self.get_dialogue(current_dialogue) if not dlg: return sentences = [] try: # If has next sentence, use next sentence. sentences.append(dlg["sentences"][current_sentence + 1]) except Exception as e: # Else get next dialogues. for dlg_key in dlg["nexts"]: # Get next dialogue. next_dlg = self.get_dialogue(dlg_key) if not next_dlg: continue if not next_dlg["sentences"]: continue if not STATEMENT_HANDLER.match_condition( next_dlg["condition"], caller, npc): continue for dep in next_dlg["dependencies"]: status = QUEST_STATUS_SET.get(dep["type"]) if not status.match(caller, dep["quest"]): continue sentences.append(next_dlg["sentences"][0]) return self.create_output_sentences(sentences, caller, npc)
def can_loot(self, looter, obj): """ help function to decide which objects can be looted. """ rand = random.random() if obj["odds"] < rand: return False if obj["quest"]: if not looter.quest_handler.is_not_accomplished(obj["quest"]): return False if not STATEMENT_HANDLER.match_condition(obj["condition"], looter, self.owner): return False return True
def at_character_kill(self, killers): """ Called when a character kills others. This event is set on the character who is killed, and take effect on the killer! """ if defines.EVENT_TRIGGER_KILL in self.events: for event in self.events[defines.EVENT_TRIGGER_KILL]: # If has kill event. for killer in killers: if self.can_bypass(killer): continue if STATEMENT_HANDLER.match_condition(event["condition"], killer, self.owner): function = self.get_function(event["type"]) if function: function(event, killer)
def get_next_sentences(self, caller, npc, current_dialogue, current_sentence): """ Get current sentence's next sentences. Args: caller: (object) the character who want to start a talk. npc: (object) the NPC that the character want to talk to. dialogue: (string) the key of the currrent dialogue. sentence: (int) the number of current sentence. Returns: sentences: (list) a list of available sentences. """ if not caller: return # Get current dialogue. dlg = self.get_dialogue(current_dialogue) if not dlg: return sentences = [] try: # If has next sentence, use next sentence. sentences.append(dlg["sentences"][current_sentence + 1]) except Exception, e: # Else get next dialogues. for dlg_key in dlg["nexts"]: # Get next dialogue. next_dlg = self.get_dialogue(dlg_key) if not next_dlg: continue if not next_dlg["sentences"]: continue if not STATEMENT_HANDLER.match_condition(next_dlg["condition"], caller, npc): continue for dep in next_dlg["dependencies"]: status = QUEST_STATUS_SET.get(dep["type"]) if not status.match(caller, dep["quest"]): continue sentences.append(next_dlg["sentences"][0])
def at_character_move_in(self, character): """ Called when a character moves in the event handler's owner, usually a room. """ if not character: return if self.can_bypass(character): return if defines.EVENT_TRIGGER_ARRIVE in self.events: for event in self.events[defines.EVENT_TRIGGER_ARRIVE]: # If has arrive event. if STATEMENT_HANDLER.match_condition(event["condition"], character, self.owner): # If matches the condition. function = self.get_function(event["type"]) if function: function(event, character)
def get_available_commands(self, caller): """ This returns a list of available commands. "args" must be a string without ' and ", usually it is self.dbref. """ if caller.is_exit_unlocked(self.get_data_key()): # If is unlocked, use common commands. return super(MudderyLockedExit, self).get_available_commands(caller) cmds = [] can_unlock = STATEMENT_HANDLER.match_condition(self.unlock_condition, caller, self) if can_unlock: # show unlock command verb = self.unlock_verb if not verb: verb = _("Unlock") cmds = [{"name": verb, "cmd": "unlock", "args": self.dbref}] return cmds
def get_available_commands(self, caller): """ This returns a list of available commands. "args" must be a string without ' and ", usually it is self.dbref. """ if caller.is_exit_unlocked(self.get_data_key()): # If is unlocked, use common commands. return super(MudderyLockedExit, self).get_available_commands(caller) cmds = [] can_unlock = STATEMENT_HANDLER.match_condition(self.unlock_condition, caller, self) if can_unlock: # show unlock command verb = self.unlock_verb if not verb: verb = LS("Unlock") cmds = [{"name": verb, "cmd": "unlock", "args": self.dbref}] return cmds
def at_character_die(self): """ Called when a character is killed. """ owner = self.owner if not owner: return if self.can_bypass(owner): return if defines.EVENT_TRIGGER_DIE in self.events: for event in self.events[defines.EVENT_TRIGGER_DIE]: #If has die event. if STATEMENT_HANDLER.match_condition(event["condition"], owner, None): # If matches the condition, run event on the owner. function = self.get_function(event["type"]) if function: function(event, self)
def match_condition(self, quest_key): """ Check if the quest matches its condition. Args: quest_key: (string) quest's key Returns: (boolean) result """ # Get quest's record. model_name = TYPECLASS("QUEST").model_name if not model_name: return False model_quest = apps.get_model(settings.WORLD_DATA_APP, model_name) try: record = model_quest.objects.get(key=quest_key) return STATEMENT_HANDLER.match_condition(record.condition, self.owner, None) except Exception, e: logger.log_errmsg("Can't get quest %s's condition: %s" % (quest_key, e))
def at_action(self, character, obj): """ Called when a character act to an object. """ if not character: return True if self.can_bypass(character): return True triggered = False if defines.EVENT_TRIGGER_ACTION in self.events: for event in self.events[defines.EVENT_TRIGGER_ACTION]: # If has traverse event. if STATEMENT_HANDLER.match_condition(event["condition"], character, self.owner): # If matches the condition. triggered = True function = self.get_function(event["type"]) if function: function(event, character) return not triggered
def trigger(self, event_type, character, obj): """ Trigger an event. Args: event_type: (string) event's type. character: (object) the character who trigger this event. obj: (object) the event object. Return: triggered: (boolean) if an event is triggered. """ if not character: return False if self.can_bypass(character): return False if event_type not in self.events: return False # Get all event's of this type. event_list = self.events[event_type] candidates = [ e for e in event_list if not character.is_event_closed(e["key"]) and STATEMENT_HANDLER.match_condition(e["condition"], character, obj) ] rand = random.random() for event in candidates: if rand < event["odds"]: func = EVENT_ACTION_SET.func(event["action"]) if func: func(event["key"], character, obj) return True rand -= event["odds"]
def at_character_traverse(self, character): """ Called before a character traverses an exit. If returns true, the character can pass the exit, else the character can not pass the exit. """ if not character: return True if self.can_bypass(character): return True triggered = False if defines.EVENT_TRIGGER_TRAVERSE in self.events: for event in self.events[defines.EVENT_TRIGGER_TRAVERSE]: # If has traverse event. if STATEMENT_HANDLER.match_condition(event["condition"], character, self.owner): # If matches the condition. triggered = True function = self.get_function(event["type"]) if function: function(event, character) return not triggered
def trigger(self, event_type, character, target): """ Trigger an event. Return: triggered: (boolean) if an event is triggered. """ if not character: return False if self.can_bypass(character): return False if event_type not in self.events: return False for event in self.events[event_type]: # Check condition. if STATEMENT_HANDLER.match_condition(event["condition"], character, target): function = EVENT_ACTION_SET.get(event["type"]) if function: function(event, character)
def trigger(self, event_type, character, obj): """ Trigger an event. Args: event_type: (string) event's type. character: (object) the character who trigger this event. obj: (object) the event object. Return: triggered: (boolean) if an event is triggered. """ if not character: return False if self.can_bypass(character): return False if event_type not in self.events: return False # Get all event's of this type. event_list = self.events[event_type] candidates = [e for e in event_list if not character.is_event_closed(e["key"]) and STATEMENT_HANDLER.match_condition(e["condition"], character, obj)] rand = random.random() for event in candidates: if rand < event["odds"]: func = EVENT_ACTION_SET.func(event["action"]) if func: func(event["key"], character, obj) return True rand -= event["odds"]