def finish_sentence(self, caller, npc, dialogue, sentence_no): """ A sentence finished, do it's action. """ if not caller: return # get dialogue dlg = self.get_dialogue(dialogue) if not dlg: return if sentence_no >= len(dlg["sentences"]): return sentence = self.get_sentence(dialogue, sentence_no) if not sentence: return # do dialogue's action if sentence["action"]: SCRIPT_HANDLER.do_action(caller, npc, sentence["action"]) if sentence["is_last"]: # last sentence self.finish_dialogue(caller, dialogue) if sentence["complete_quest"]: caller.quest_handler.complete(sentence["complete_quest"]) if sentence["provide_quest"]: caller.quest_handler.accept(sentence["provide_quest"])
def complete(self): """ Complete a quest, do its action. """ owner = self.db.owner # get rewards obj_list = self.loot_handler.get_obj_list(owner) if obj_list: # give objects to winner owner.receive_objects(obj_list) # do quest's action action = getattr(self.dfield, "action", None) if action: SCRIPT_HANDLER.do_action(owner, None, action) # remove objective objects obj_list = [] for ordinal in self.objectives: if self.objectives[ordinal]["type"] == defines.OBJECTIVE_OBJECT: obj_list.append({"object": self.objectives[ordinal]["object"], "number": self.objectives[ordinal]["number"]}) if obj_list: owner.remove_objects(obj_list)
def finish_sentence(self, caller, npc, dialogue, sentence): """ A sentence finished, do it's action. """ if not caller: return # get dialogue dlg = self.get_dialogue(dialogue) if not dlg: return if sentence >= len(dlg["sentences"]): return sen = self.get_sentence(dialogue, sentence) if not sen: return # do dialogue's action if sen["action"]: SCRIPT_HANDLER.do_action(caller, npc, sen["action"]) if sentence + 1 >= len(dlg["sentences"]): # last sentence self.finish_dialogue(caller, dialogue) if sen["complete_quest"]: caller.quest.complete(sen["complete_quest"]) if sen["provide_quest"]: caller.quest.accept(sen["provide_quest"])
def can_unlock(self, caller): """ Unlock an exit. """ # Only can unlock exits which match there conditions. return SCRIPT_HANDLER.match_condition(caller, self, self.unlock_condition)
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 SCRIPT_HANDLER.match_condition(self.owner, None, record.condition) 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 = SCRIPT_HANDLER.match_condition(caller, self, self.unlock_condition) 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_info_key()): # If is unlocked, use common appearance. return super(MudderyLockedExit, self).get_appearance(caller) can_unlock = SCRIPT_HANDLER.match_condition(caller, self, self.exit_lock["condition"]) if can_unlock and self.exit_lock["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.exit_lock["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.exit_lock["message_lock"], "cmds": cmds} return info
def complete(self): """ Complete a quest, do its action. """ owner = self.db.owner # do quest's action action = getattr(self.dfield, "action", None) if action: SCRIPT_HANDLER.do_action(owner, None, action) # remove objective objects obj_list = [] for ordinal in self.objectives: if self.objectives[ordinal]["type"] == defines.OBJECTIVE_OBJECT: obj_list.append({"object": self.objectives[ordinal]["object"], "number": self.objectives[ordinal]["number"]}) if obj_list: owner.remove_objects(obj_list)
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 SCRIPT_HANDLER.match_condition(caller, self, self.loot_condition): return [] commands = [{"name": self.loot_verb, "cmd": "loot", "args": self.dbref}] return commands
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 SCRIPT_HANDLER.match_condition(caller, self, condition): 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 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 SCRIPT_HANDLER.match_condition(caller, npc, npc_dlg["condition"]): 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_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 SCRIPT_HANDLER.match_condition(caller, npc, npc_dlg["condition"]): continue # Match dependeces. 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: 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 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 settings.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 SCRIPT_HANDLER.match_condition(caller, self, condition): 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_info_key() info[type].append(appearance) return info
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 SCRIPT_HANDLER.match_condition(caller, npc, npc_dlg["condition"]): 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.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 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 SCRIPT_HANDLER.match_condition(killer, self.owner, event["condition"]): event["function"](event["data"], killer)
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 SCRIPT_HANDLER.match_condition(caller, self, self.loot_condition): return [] commands = [{ "name": self.loot_verb, "cmd": "loot", "args": self.dbref }] return commands
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 SCRIPT_HANDLER.match_condition(caller, npc, next_dlg["condition"]): continue for dep in next_dlg["dependencies"]: if not QUEST_DEP_HANDLER.match_dependency( caller, dep["quest"], dep["type"]): 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 SCRIPT_HANDLER.match_condition(character, self.owner, event["condition"]): # If matches the condition. event["function"](event["data"], character)
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.is_not_accomplished(obj["quest"]): return False if not SCRIPT_HANDLER.match_condition(looter, self, obj["condition"]): 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 SCRIPT_HANDLER.match_condition(killer, self.owner, event["condition"]): function = self.get_function(event["type"]) if function: function(event, killer)
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 SCRIPT_HANDLER.match_condition(looter, self.owner, obj["condition"]): return False return True
def get_sentences(self, caller, npc): """ Get NPC's 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 SCRIPT_HANDLER.match_condition(caller, npc, npc_dlg["condition"]): continue # Match dependeces. 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: 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 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 SCRIPT_HANDLER.match_condition(owner, None, event["condition"]): # If matches the condition, run event on the owner. event["function"](event["data"], owner)
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 SCRIPT_HANDLER.match_condition(character, self.owner, event["condition"]): # 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 = SCRIPT_HANDLER.match_condition(caller, self, self.unlock_condition) 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 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_info_key()): # If is unlocked, use common commands. return super(MudderyLockedExit, self).get_available_commands(caller) cmds = [] can_unlock = SCRIPT_HANDLER.match_condition(caller, self, self.exit_lock["condition"]) if can_unlock: # show unlock command verb = self.exit_lock["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 SCRIPT_HANDLER.match_condition(owner, None, event["condition"]): # If matches the condition, run event on the owner. function = self.get_function(event["type"]) if function: function(event, self)
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 SCRIPT_HANDLER.match_condition(character, self.owner, event["condition"]): # If matches the condition. triggered = True event["function"](event["data"], character) return not triggered
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 SCRIPT_HANDLER.match_condition(character, self.owner, event["condition"]): # If matches the condition. triggered = True function = self.get_function(event["type"]) if function: function(event, character) return not triggered
def can_loot(self, looter, obj): """ help function to decide which objects can be looted. Args: self: (object) this character looter: (object) who loot this character obj: (dict) information of the object which will be looted Returns: (boolean) if this object can be looted or not """ rand = random.random() if rand > obj["odds"]: return False if obj["quest"]: if not looter.quest.is_not_accomplished(obj["quest"]): return False if not SCRIPT_HANDLER.match_condition(looter, self, obj["condition"]): return False return True
def get_next_sentences(self, caller, npc, current_dialogue, current_sentence): """ Get current sentence's next 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 SCRIPT_HANDLER.match_condition(caller, npc, next_dlg["condition"]): continue for dep in next_dlg["dependencies"]: if not QUEST_DEP_HANDLER.match_dependency(caller, dep["quest"], dep["type"]): continue sentences.append(next_dlg["sentences"][0])
def can_unlock(self, caller): """ Unlock an exit. """ # Only can unlock exits which match there conditions. return SCRIPT_HANDLER.match_condition(caller, self, self.exit_lock["condition"])