def cast_combat_skill(self, skill, target): """ Cast a skill in combat. """ if not self.owner: return if not self.owner.ndb.combat_handler: # Onwer is not in combat. return if self.GLOBAL_COOLING_DOWN: # In GCD. self.owner.msg({"msg": LS("This skill is not ready yet!")}) return if self.skills[skill].is_cooling_down(): # Skill is cooling down. self.owner.msg({"msg": LS("This skill is not ready yet!")}) return # Cast skill. result = self.owner.ndb.combat_handler.cast_skill( skill, self.owner.dbref, target) if result: # Cast successed, set GCD if settings.GLOBAL_CD > 0: self.GLOBAL_COOLING_DOWN = True # Set timer. TICKER_HANDLER.add(self, settings.GLOBAL_CD, hook_key="global_cooled_down") return result
def at_object_creation(self): """ Called when the object is first created. """ #Subscribes room to ticker_handler and calls at_hour every tick TICKER_HANDLER.add(self, 60*60, hook_key="at_hour") #60*60 = seconds #Room Attributes related to Light Cycles #whether light cycle phase is active self.db.light_cycle_active = False #light phase duration self.db.light_phase_lengths = {"dawn":2, "day":10, "dusk":2, "night":10} self.db.light_phase_echoes = { "dawn":"", "day":"", "dusk":"", "night":"" } #phase change echoes self.db.light_phase_descs = { "dawn":"", "day":"", "dusk":"", "night":"" } #phase room descriptions self.db.light_phase = "dawn" #current phase self.db.light_phase_time = 2 #time left self.db.light_phase_hour = 0 #time into cycle, starting at dawn self.db.lumens = 30 #temporary default lumens value
def set_combat(self, teams, desc, timeout): """ Add combatant to handler Args: teams: (dict) {<team id>: [<characters>]} desc: (string) combat's description timeout: (int) Total combat time in seconds. Zero means no limit. """ self.desc = desc self.timeout = timeout for team in teams: for character in teams[team]: character.set_team(team) self.characters[character.dbref] = character for character in self.characters.values(): # add the combat handler character.ndb.combat_handler = self # Change the command set. character.cmdset.add(settings.CMDSET_COMBAT) if character.has_player: self.show_combat(character) self.start_combat() if self.timeout: TICKER_HANDLER.add(self.timeout, self.at_timeout, persistent=False)
def auto_cast_skill(self): """ Cast a new skill automatically. """ if not self.can_auto_cast: return if not self.owner: return if not self.owner.is_alive(): return if not self.owner.ndb.combat_handler: # combat is finished, stop ticker TICKER_HANDLER.remove(self.auto_cast_skill_cd, self.owner.auto_cast_skill) return # Choose a skill and the skill's target. result = ChooseSkill.choose(self.owner) if result: skill, target = result self.owner.ndb.combat_handler.prepare_skill( skill, self.owner, target)
def _set_ticker(self, interval, hook_key, stop=False): """ Set how often the given hook key should be "ticked". Args: interval (int): The number of seconds between ticks hook_key (str): The name of the method (on this mob) to call every interval seconds. stop (bool, optional): Just stop the last ticker without starting a new one. With this set, the interval and hook_key arguments are unused. In order to only have one ticker running at a time, we make sure to store the previous ticker subscription so that we can easily find and stop it before setting a new one. The tickerhandler is persistent so we need to remember this across reloads. """ idstring = "tutorial_mob" # this doesn't change last_interval = self.db.last_ticker_interval if last_interval: # we have a previous subscription, kill this first. TICKER_HANDLER.remove(self, last_interval, idstring) self.db.last_ticker_interval = interval if not stop: # set the new ticker TICKER_HANDLER.add(self, interval, idstring, hook_key)
def at_server_start(): """ This is called every time the server starts up, regardless of how it was shut down. """ # Start the main logger begin() # Affect default encoding (it's a security on frozen versions) if getattr(sys, "frozen", False): main.info("Running in frozen mode, try to change the default encoding") try: sys.setdefaultencoding("utf-8") except Exception: main.exception("An error occured while changing encoding.") else: main.info("Setting defaultencoding to utf-8") # Launch the script if it's not running try: script = ScriptDB.objects.get(db_key="event_handler") except ScriptDB.DoesNotExist: script = create_script("typeclasses.scripts.AvEventHandler") main.info("Creating the EventHandler") # Launch tickers ticker_handler.add(3, tickers.vehicles.move) # Load the apps errors = load_apps() for name, error in errors: app.warning("Error while loading {}: {}".format(name, error))
def npc_active_ticks(self, *args, **kwargs): "Ticks after the NPC has been attacked." targets = False # Any targets in the room? # This should probably go below. if self.db.tries_left > 0: for i in self.location.contents: if i in self.db.offended_by: targets = True npc_rules.attack(self, i) self.db.tries_left = 3 return if not targets: for k, v in self.location.db.trails.iteritems(): target_name = str(self.db.offended_by[0]) if k == target_name: destination = self.search(v) self.move_to(destination) for i in self.location.contents: if i in self.db.offended_by: targets = True npc_rules.attack(self, i) self.db.tries_left = 3 break break self.db.tries_left = self.db.tries_left - 1 if self.db.tries_left < 0: self.db.offended_by = [] self.db.tries_left = self.db.tries tickerhandler.remove(self.db.ticker_speed, self.npc_active_ticks) return
def at_object_leave(self, obj, target_location): if utils.inherits_from(obj, Character): for item in self.contents: # if item in room not self if item.dbref != obj.dbref: # if item is of class Character if utils.inherits_from(item, Character): obj.msg("DATA,char_remove," + item.name + item.dbref) item.msg("DATA,char_remove," + obj.name + obj.dbref) # else if item is of class Mob elif utils.inherits_from(item, Mob): obj.msg("DATA,char_remove," + item.name + item.dbref) # else if item is of class Npc elif utils.inherits_from(item, Npc): obj.msg("DATA,char_remove," + item.name + item.dbref) # else (an object) else: obj.msg("DATA,obj_remove," + item.name + item.dbref) if utils.inherits_from(obj, Npc): # An NPC has left pass elif utils.inherits_from(obj, Mob): # A Mob has left pass else: # Else if a PC has left the room if utils.inherits_from(obj, Character): # Any NPCs in the room ? for item in self.contents: if utils.inherits_from(item, Npc): # Notify NPCs that a PC left the room tickerhandler.remove(item,1)
def at_object_receive(self, obj, source_location): if utils.inherits_from(obj, Npc): # An NPC has entered pass else: # Else if a PC has entered if utils.inherits_from(obj, Character): # Cause the character to look around #obj.execute_cmd('look') for item in self.contents: # Any NPCs in the room ? if utils.inherits_from(item, Npc): # Notify NPCs that a PC entered the room item.at_char_entered(obj) tickerhandler.add(item,1) # if item in room not self if item.dbref != obj.dbref: # if item is of class Character if utils.inherits_from(item, Character): obj.msg("DATA,char_add," + item.name + item.dbref) item.msg("DATA,char_add," + obj.name + obj.dbref) # else if item is of class Mob elif utils.inherits_from(item, Mob): obj.msg("DATA,char_add," + item.name + item.dbref) # else if item is of class Npc elif utils.inherits_from(item, Npc): obj.msg("DATA,char_add," + item.name + item.dbref) # else (an object) else: obj.msg("DATA,obj_add," + item.name + item.dbref)
def die(self, killers): """ The monster is killed. Reborn in settings.NPC_REBORN_CD seconds. """ try: super(MudderyMonster, self).die(killers) # delete itself and notify its location location = self.location if self.reborn_cd <= 0: # Can not reborn. delete_object(self.dbref) else: # Remove from its location. self.move_to(None, quiet=True, to_none=True) # Set reborn timer. TICKER_HANDLER.add(self.reborn_cd, self.reborn) if location: for content in location.contents: if content.has_player: content.show_location() except Exception, e: logger.log_tracemsg("die error: %s" % e)
def sample_char(char, archetype, race, focus=None): """Loads sample traits onto a character. Args: char (Character): character to load traits archetype (str): name of base archetype race (str): name of race to become focus Optional(str): focus to apply. if None, default is race's first item in foci collection """ archetypes.apply_archetype(char, archetype, reset=True) char.traits.STR.base += 1 char.traits.PER.base += 1 char.traits.INT.base += 1 char.traits.DEX.base += 1 char.traits.CHA.base += 1 char.traits.VIT.base += 2 char.traits.MAG.base += 2 focus = focus or races.load_race(race).foci[0] races.apply_race(char, race, focus) archetypes.calculate_secondary_traits(char.traits) archetypes.finalize_traits(char.traits) tickerhandler.add(char, 6, hook_key='at_turn_start') skills.apply_skills(char) skills.finalize_skills(char.skills)
def cast_combat_skill(self, skill, target): """ Cast a skill in combat. """ if not self.owner: return if not self.owner.ndb.combat_handler: # Onwer is not in combat. return if self.GLOBAL_COOLING_DOWN: # In GCD. self.owner.msg({"msg":LS("This skill is not ready yet!")}) return if self.skills[skill].is_cooling_down(): # Skill is cooling down. self.owner.msg({"msg":LS("This skill is not ready yet!")}) return # Cast skill. result = self.owner.ndb.combat_handler.cast_skill(skill, self.owner.dbref, target) if result: # Cast successed, set GCD if settings.GLOBAL_CD > 0: self.GLOBAL_COOLING_DOWN = True # Set timer. TICKER_HANDLER.add(self, settings.GLOBAL_CD, hook_key="global_cooled_down") return result
def stop_auto_combat_skill(self): """ Stop auto cast skill. """ self.can_auto_cast = False TICKER_HANDLER.remove(self.auto_cast_skill_cd, self.owner.auto_cast_skill)
def at_post_unpuppet(self, player, session=None): """ We stove away the character when the player goes ooc/logs off, otherwise the character object will remain in the room also after the player logged off ("headless", so to say). Args: player (Player): The player object that just disconnected from this object. session (Session): Session controlling the connection that just disconnected. """ if not self.sessions.count(): tickerhandler.remove(7, self.player_character_ticks) # only remove this char from grid if no sessions control it anymore. if self.location: def message(obj, from_obj): obj.msg( "The form of %s shimmers briefly, then fades away into the ether." % self.get_display_name(obj), from_obj=from_obj) self.location.for_contents(message, exclude=[self], from_obj=self) self.db.prelogout_location = self.location self.location = None
def sample_char(char, archetype, race, focus=None): """Loads sample traits onto a character. Args: char (Character): character to load traits archetype (str): name of base archetype race (str): name of race to become focus Optional(str): focus to apply. if None, default is race's first item in foci collection """ archetypes.apply_archetype(char, archetype, reset=True) char.traits.STR.base += 1 char.traits.PER.base += 1 char.traits.INT.base += 1 char.traits.DEX.base += 1 char.traits.CHA.base += 1 char.traits.VIT.base += 2 char.traits.MAG.base += 2 focus = focus or races.load_race(race).foci[0] races.apply_race(char, race, focus) archetypes.calculate_secondary_traits(char.traits) archetypes.finalize_traits(char.traits) tickerhandler.add(interval=6, callback=char.at_turn_start) skills.apply_skills(char) skills.finalize_skills(char.skills)
def at_post_puppet(self): """ Called just after puppeting has been completed and all Player<->Object links have been established. Note: You can use `self.player` and `self.sessions.get()` to get player and sessions at this point; the last entry in the list from `self.sessions.get()` is the latest Session puppeting this Object. """ self.msg("\nYou become |c%s|n.\n" % self.name) self.msg(self.at_look(self.location)) def message(obj, from_obj): obj.msg( "The form of %s emerges from the ether as %s soul descends to use it." % (self.get_display_name(obj), self.db.genderp), from_obj=from_obj) self.location.for_contents(message, exclude=[self], from_obj=self) self.db.enchantments = [] self.db.regen_rate = 0.1 tickerhandler.add(7, self.player_character_ticks)
def die(self, killers): """ The monster is killed. Reborn in settings.NPC_REBORN_CD seconds. """ try: super(MudderyMonster, self).die(killers) # delete itself and notify its location location = self.location if settings.NPC_REBORN_CD <= 0: # Can not reborn. delete_object(self.dbref) else: # Remove from its location. self.move_to(None, quiet=True, to_none=True) # Set reborn timer. TICKER_HANDLER.add(self, settings.NPC_REBORN_CD, hook_key="reborn") if location: for content in location.contents: if content.has_player: content.show_location() except Exception, e: logger.log_tracemsg("die error: %s" % e)
def at_post_puppet(self, **kwargs): # here we can check to see if this is the first time logging in. if self.attributes.has('new_character'): #enter the chargen state EvMenu(self, "world.chargen.gen", startnode="pick_race", cmdset_mergetype='Replace', cmdset_priority=1, auto_quit=False) self.attributes.remove('new_character') ############### Non-Persistent Tickers #################### TICKER_HANDLER.add(interval=10, callback=self.tick_heal_player, idstring="tick_heal_char", persistent=False) TICKER_HANDLER.add(interval=60, callback=self.save_character, idstring='tick_save_char', persistent=False) ########################################################### self.msg(f"\nYou become |c{self.name.capitalize()}|n") self.execute_cmd('look')
def at_stop(self): "Called just before the script is stopped/destroyed." if self.timeout: TICKER_HANDLER.remove(self.timeout, self.at_timeout) for character in self.characters.values(): # note: the list() call above disconnects list from database self._cleanup_character(character)
def global_cooled_down(self): """ GCD finished. """ self.GLOBAL_COOLING_DOWN = False # Remove the timer. TICKER_HANDLER.remove(self, settings.GLOBAL_CD)
def start_emotechain(self, emote_chain): # Init emote chain self.db.emote_step = 0 self.db.current_emotechain = emote_chain tickerhandler.add(5, self.at_emote) # Send first message immediately self.at_emote()
def ignite(self, lighter): room, held_by = self.find_location() lighter.msg(f"You light {self.name}, igniting it.") room.msg_contents( f"{lighter.get_display_name(self)} lights {self.name}, igniting it.", exclude=lighter) tickerhandler.add(30, self.on_burn_tick, persistent=True)
def doit(self): caller = self.db.caller substance_name = self.db.substance if substance_name in caller.db.effects: del caller.db.effects[substance_name] caller.msg(u"Тебя попустило с %s" % substance_name) tickerhandler.remove(self, self.db.affect_time) self.delete()
def cast_off(self): """ When cast_off, a vessel is subject to movement forces. Current, wind, and even self power like oars. This means a script will start to run updating position constantly based on those forces. """ self.db.adrift = True self.msg_contents("The %s is now adrift." % self.key) tickerhandler.add(3, self.make_way, idstring="adrift")
def cast_off(self): ''' When cast_off, a vessel is subject to movement forces. Current, wind, and even self power like oars. This means a script will start to run updating position constantly based on those forces. ''' self.db.adrift = True self.msg_contents("The %s is now adrift." % self.key) tickerhandler.add(3, self.make_way, idstring="adrift")
def check_defeat(character, id): "Checks if a character is 'defeated'." if character.db.hp['Current'] <= 0: character.msg("You fall down, defeated!") character.db.hp['Current'] = character.db.hp['Max'] character.db.fighting = None tickerhandler.remove(5, skill_combat, persistent=False, idstring=id) update_prompt(character) return
def at_post_puppet(self): self.location.msg_contents("%s has connected" % self.key) loginmsg = "[************--Rumour Monger--************]|/" \ "%s arrives in Mercadia.|/" \ "[*****************************************]|/" % self.key SESSIONS.announce_all(loginmsg) tickerhandler.add(interval=randint(10, 15), callback=self.at_regen, persistent=True) self.execute_cmd("look")
def at_object_creation(self): """ Called when object is first created. We set up a ticker to update this room regularly. """ super(PuppetRoom, self).at_object_creation() TICKER_HANDLER.add(60 * 60, self.start_show, idstring="puppet_show_ticker", persistent=True)
def stand(self): if self.db.position is not 0: self.msg("You stand up.") for Character in self.location.contents: if Character is not self: Character.msg("{} stands up.".format(self.db._sdesc)) cooldown = (10 - (self.db.endurance * .1)) tickerhandler.remove(cooldown, self.rest_tick) self.db.position = 0 else: self.msg("You are already standing.")
def rest(self): if self.db.position is 1: self.msg("You are already resting.") else: for Character in self.location.contents: if Character is not self: Character.msg("{} rests.".format(self.db._sdesc)) cooldown = (10 - (self.db.endurance * .1)) self.msg("You sit down and rest.") self.db.position = 1 tickerhandler.add(cooldown, self.rest_tick)
def menunode_allocate_mana(caller, raw_string): """Mana point allocation menu node.""" char = caller.new_char tr = char.traits manas = ('WM', 'BM') raw_string = raw_string.strip() if raw_string.isdigit() and int(raw_string) <= len(manas): tr[manas[int(raw_string) - 1]].base += 1 remaining = tr.MAG.actual - sum(tr[m].base for m in manas) if remaining: text = "Your |CMagic|n trait is |w{}|n.\n\n".format(tr.MAG.actual) text += "This allows you to allocate that many points to your\n" text += "|wWhite Mana|n and |xBlack Mana|n counters.\n" text += "You have |w{}|n points remaining. ".format(remaining) text += "Select a mana counter to increase:" help = "Magic users spend Mana points when casting spells. Different\n" help += "colors of magic require different colors of mana. The effects of\n" help += "different magics vary by color.\n\n" help += " White - white magic spells are generally support/healing based\n" help += " Black - black magic spells are generally attack-oriented\n\n" help += "The number of points allocated here determines the number of\n" help += "each color mana that will be spawned each turn of the game." options = [{ "desc": _format_trait_opts(tr[m], '|w' if m == 'WM' else '|x'), "goto": "menunode_allocate_mana" } for m in manas] def reset_mana(s): for m in manas: char.traits[m].base = 0 options.append({ "desc": "Start Over", "exec": reset_mana, "goto": "menunode_allocate_mana" }) return (text, help), options else: if tr.MAG.actual > 0: output = "Final Mana Values:\n" output += " |wWhite Mana|n: |w{}|n\n".format(tr.WM.actual) output += " |xBlack Mana|n: |w{}|n\n".format(tr.BM.actual) else: output = "" # TODO: implement spells; add level 0 spell cmdsets here archetypes.calculate_secondary_traits(char.traits) archetypes.finalize_traits(char.traits) tickerhandler.add(interval=6, callback=char.at_turn_start) skills.apply_skills(char) return menunode_allocate_skills(caller, output)
def start_auto_combat_skill(self): """ Start auto cast skill. """ self.can_auto_cast = True # Cast a skill immediately self.auto_cast_skill() # Set timer of auto cast. TICKER_HANDLER.add(self.auto_cast_skill_cd, self.owner.auto_cast_skill)
def at_object_creation(self): """ Called when object is first created. We set up a ticker to update this room regularly. """ super(FunHouseRoom, self).at_object_creation() TICKER_HANDLER.add(10 * 60, self.update_funhouse, idstring="funhouse_ticker", persistent=True)
def at_object_creation(self): """ Called when object is first created. We set up a ticker to update this room regularly. """ super(RookeryRoom, self).at_object_creation() TICKER_HANDLER.add(8 * 60, self.update_rookery, idstring="rookery_ticker", persistent=True)
def start_auto_combat_skill(self): """ Start auto cast skill. """ self.can_auto_cast = True # Cast a skill immediately self.auto_cast_skill() # Set timer of auto cast. TICKER_HANDLER.add(self, settings.AUTO_CAST_SKILL_CD, hook_key="auto_cast_skill")
def start_auto_combat_skill(self): """ Start auto cast skill. """ self.AUTO_CAST_SKILL = True # Cast a skill immediately self.auto_cast_skill() # Set timer. TICKER_HANDLER.add(self, settings.AUTO_CAST_SKILL_CD, hook_key="auto_cast_skill")
def _init_character(self, character): """ This initializes handler back-reference and combat cmdset on a character. It also stops the tickerhandler that normally calls at_turn_start every 6s """ if not character.nattributes.has('combat_handler'): tickerhandler.remove(6, character.at_turn_start) character.ndb.combat_handler = self character.cmdset.add("commands.combat.CombatBaseCmdSet") character.cmdset.add("commands.combat.CombatCmdSet") prompt = _COMBAT_PROMPT.format(tr=character.traits) character.msg(prompt=prompt)
def death(self, room, held_by): tickerhandler.remove(30, self.on_burn_tick, persistent=True) if inherits_from(held_by, "characters.characters.Character"): held_by.msg( f"Your {self.name} torch dies out and it collapses into a tiny pile of ash." ) room.msg_contents( f"{held_by.name}'s {self.name} dies out and it collapses into a tiny pile of ash.", exclude=held_by) else: room.msg_contents( f"{self.name} dies out and it collapses into a tiny pile of ash." ) self.delete()
def reborn(self): """ Reborn after being killed. """ TICKER_HANDLER.remove(self, self.reborn_cd) # Recover all hp. self.db.hp = self.max_hp self.show_status() # Reborn at its home. if self.home: self.move_to(self.home, quiet=True) self.msg({"msg": LS("You are reborn at {c%s{n.") % self.home.get_name()})
def menunode_allocate_mana(caller, raw_string): """Mana point allocation menu node.""" char = caller.new_char tr = char.traits manas = ('WM', 'BM') raw_string = raw_string.strip() if raw_string.isdigit() and int(raw_string) <= len(manas): tr[manas[int(raw_string) - 1]].base += 1 remaining = tr.MAG.actual - sum(tr[m].base for m in manas) if remaining: text = "Your |CMagic|n trait is |w{}|n.\n\n".format(tr.MAG.actual) text += "This allows you to allocate that many points to your\n" text += "|wWhite Mana|n and |xBlack Mana|n counters.\n" text += "You have |w{}|n points remaining. ".format(remaining) text += "Select a mana counter to increase:" help = "Magic users spend Mana points when casting spells. Different\n" help += "colors of magic require different colors of mana. The effects of\n" help += "different magics vary by color.\n\n" help += " White - white magic spells are generally support/healing based\n" help += " Black - black magic spells are generally attack-oriented\n\n" help += "The number of points allocated here determines the number of\n" help += "each color mana that will be spawned each turn of the game." options = [{"desc": _format_trait_opts(tr[m], '|w' if m == 'WM' else '|x'), "goto": "menunode_allocate_mana"} for m in manas] def reset_mana(s): for m in manas: char.traits[m].base = 0 options.append({"desc": "Start Over", "exec": reset_mana, "goto": "menunode_allocate_mana"}) return (text, help), options else: if tr.MAG.actual > 0: output = "Final Mana Values:\n" output += " |wWhite Mana|n: |w{}|n\n".format(tr.WM.actual) output += " |xBlack Mana|n: |w{}|n\n".format(tr.BM.actual) else: output = "" # TODO: implement spells; add level 0 spell cmdsets here archetypes.calculate_secondary_traits(char.traits) archetypes.finalize_traits(char.traits) tickerhandler.add(interval=6, callback=char.at_turn_start) skills.apply_skills(char) return menunode_allocate_skills(caller, output)
def at_tick(self): if self.db.attacking != None: print self.attacking.location # if character in same roome as self and aggressive if self.location == self.db.attacking.location and self.db.count < 10: # attack with probability and after cooldown if (time() - self.db.last_attack) > randint(1, 3): self.execute_cmd("say Graaah, die %s!" % self.db.attacking) rules.roll_challenge(self, self.db.attacking, "combat") self.db.last_attack = time() self.db.count += 1 else: tickerhandler.remove(self, 1) else: tickerhandler.remove(self, 1)
def __init__(self, owner): """ Initialize handler. """ self.owner = owner self.skills = owner.db.skills # TICKER_HANDLER need pk. self.pk = "SKILL" # always begin with GCD self.GLOBAL_COOLING_DOWN = True TICKER_HANDLER.add(self, settings.GLOBAL_CD, hook_key="global_cooled_down") self.AUTO_CAST_SKILL = False self.skill_target = None
def reborn(self): """ Reborn after being killed. """ TICKER_HANDLER.remove(self, settings.NPC_REBORN_CD) # Recover all hp. self.db.hp = self.max_hp # Reborn at its home. if self.home: self.move_to(self.home, quiet=True) for content in self.home.contents: if content.has_player: content.show_location()
def die(self, killers): """ This character is killed. Move it to it's home. """ super(MudderyPlayerCharacter, self).die(killers) self.msg({"msg": LS("You died.")}) if self.reborn_cd <= 0: # Reborn immediately self.reborn() else: # Set reborn timer. TICKER_HANDLER.add(self, self.reborn_cd, hook_key="reborn") self.msg({"msg": LS("You will be reborn at {c%(p)s{n in {c%(s)s{n seconds.") % {'p': self.home.get_name(), 's': self.reborn_cd}})
def at_object_creation(self): """ Called when object is first created. We set up a ticker to update this room regularly. Note that we could in principle also use a Script to manage the ticking of the room; the TickerHandler works fine for simple things like this though. """ super(WeatherRoom, self).at_object_creation() # subscribe ourselves to a ticker to repeatedly call the hook # "update_weather" on this object. The interval is randomized # so as to not have all weather rooms update at the same time. interval = random.randint(50, 70) TICKER_HANDLER.add(interval=interval, callback=self.update_weather, idstring="tutorial") # this is parsed by the 'tutorial' command on TutorialRooms. self.db.tutorial_info = \ "This room has a Script running that has it echo a weather-related message at irregular intervals."
def at_tick(self): tickerhandler.remove(self, self.db.last_ticker_deley_value) self.db.last_ticker_deley_value = random.randint(15, 120) tickerhandler.add(self, self.db.last_ticker_deley_value) if not self.goods: return goods_to_create = self.goods.values() for good in goods_to_create: good_in_inv = self.search(good["name"], location=self, nofound_string="") if not good_in_inv: new_good = create_object(good["typeclass"], good["name"], self, home=self) if not new_good.db.desc: if good["desc"]: new_good.db.desc = good["desc"] new_good.db.coast = good["coast"]
def at_object_creation(self): """ Called only at initial creation. This is a rather silly example since ability scores should vary from Character to Character and is usually set during some character generation step instead. """ # set persistent stats and skills self.db.stats = {'str': 100, 'agi': 100, 'spd': 100, 'dex': 100, 'will': 100, 'edr': 100} self.db.vitals = {'current_hp': float(self.db.stats['will']),'max_hp': float(self.db.stats['will']), 'current_edr': float(self.db.stats['edr']),'max_edr': float(self.db.stats['edr'])} self.db.skills = {'Katanas': {'Basics':50,'Jab':10,'Chop':10},'Dodges': {'Basics':50,'Duck':10,'Jump':10,'Sidestep':10}} self.db.right_hand = {'Holding': None, 'Wielding': None} self.db.left_hand = {'Holding': None, 'Wielding': None} #Define clothes dictionaries for characters. Layer 1 = underclothes, layer 2 = clothes, layers 3+ are armor. #Append is for stuff like medals etc which people can wear. self.db.clothes = {"Head": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Face": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Neck": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Left shoulder": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Right shoulder": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Chest": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Back": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Left arm": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Right arm": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Left hand": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Right hand": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Stomach": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Waist": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Left thigh": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Right thigh": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Left calf": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Right calf": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Left foot": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}, "Right foot": {"Layer 1": None, "Layer 2": None, "Layer 3": None, "Layer 4": None, "Layer 5": None, "Append": None}} tickerhandler.add(60, self.at_tick)
def at_object_creation(self): self.cmdset.add(CmdSetTest) self.db.npc = True self.locks.add("call:false()") self.locks.add("get:false()") self.db.desc = "Среднестатистическая аптекарша." #задаем таймер, рандомно срабратывающий self.db.last_ticker_deley_value = 0 self.db.last_ticker_deley_value = random.randint(15, 120) tickerhandler.add(self, self.db.last_ticker_deley_value) CONV = {"START": {"text": "Добро пожаловать. Чем могу вам помочь?", "links": ["i1", "i1", "i1","i1","END"], "linktexts": ["Купить серу - 3 интренета.", "Купить водород - 5 интернетов.", "Купить бутылку - 5 интернетов.", "Купить вещества - 20 интернетов.", "Ничего"], "keywords": ["1","2","3","4","5"], "selectcmds":[CmdSera,CmdVodorod,CmdBottle,CmdDrugs,None], "callback": None}, "i1": {"text": "Спасибо за покупку. Что нибудь еще?", "links": ["START", "END"], "linktexts":["Еще", "Нет. Все."], "keywords": None, "callback": None}, "i2": {"text": "Этот товар закончился. Скоро обещали привезти.", "links": ["START", "END"], "linktexts": ["Можно тогда...", "Ну ладно. Досвидания."], "keywords": None, "callback": None}, "i3": {"text": "У тебя не хватет интернетов. Подкопи и тогда возвращайся.", "links": ["START", "END"], "linktexts": ["Можно тогда...", "Ну ладно. Досвидания."], "keywords": None, "callback": None}, } self.db.conversation = CONV
def die(self, killers): """ This npc is killed. Reborn in settings.NPC_REBORN_CD seconds. """ super(MudderyNPC, self).die(killers) location = self.location if settings.NPC_REBORN_CD <= 0: # Can not reborn. delete_object(self.dbref) else: # Remove from its location. self.move_to(None, quiet=True, to_none=True) # Set reborn timer. TICKER_HANDLER.add(self, settings.NPC_REBORN_CD, hook_key="reborn") if location: for content in location.contents: if content.has_player: content.show_location()
def _cleanup_character(self, character): """ Remove character from handler and clean it of the back-reference and cmdset. Also re-starts the tickerhandler """ dbref = character.id del self.db.characters[dbref] del self.db.turn_actions[dbref] del self.db.action_count[dbref] for key in [k for k in self.db.distances.keys() if dbref in k]: del self.db.distances[key] character.at_turn_end() del character.ndb.combat_handler if character.cmdset.has_cmdset("combat_cmdset"): character.cmdset.remove("commands.combat.CombatCmdSet") character.cmdset.remove("commands.combat.CombatBaseCmdSet") tickerhandler.add(6, character.at_turn_start) character.msg(prompt=' ')
def at_object_receive(self, new_arrival, source_location): """ When an object enters a room we tell other objects in the room about it by trying to call a hook on them. The Mob object uses this to cheaply get notified of enemies without having to constantly scan for them. Args: new_arrival (Object): the object that just entered this room. source_location (Object): the previous location of new_arrival. """ if self.tags.get('rp', category='flags') and not new_arrival.attributes.has('_sdesc'): sdesc = self.db.messages and self.db.messages.get('species') or new_arrival.key new_arrival.sdesc.add(sdesc) if new_arrival.has_account: # and not new_arrival.is_superuser: # this is a character if self.tags.get('weather', category='flags'): if not self.nattributes.has('weather_time'): self.attempt_weather_update(1.00) # 100% chance of update on initial arrival. tickers = TICKER_HANDLER.all_display() counter = 0 for tick in tickers: if tick[0] == self and tick[1] == 'update_weather': notice = '' counter += 1 show = '20%% chance every %s seconds in ' % tick[3] show += "%s%s" % (tick[0] or "[None]", tick[0] and " (#%s)" % (tick[0].id if hasattr(tick[0], 'id') else '') or '') if counter > 1: notice = '|rExtra Ticker|n - |yadditional|n ' # TODO: Too many weather tickers going, maybe remove extra? channel = ChannelDB.objects.channel_search('MudInfo') if channel[0]: channel[0].msg('* %s\'s %s experience * %s%s' % (new_arrival.key, tick[4], notice, show), keep_log=False) if counter == 0: # No weather ticker! Add a weather ticker. interval = random.randint(12, 30) * 10 TICKER_HANDLER.add(interval=interval, callback=self.update_weather, idstring='Weather') for obj in self.contents_get(exclude=new_arrival): if hasattr(obj, 'at_new_arrival'): obj.at_new_arrival(new_arrival)
def at_object_creation(self): self.cmdset.add(CmdSetTest) self.db.npc = True self.locks.add("call:false()") self.locks.add("get:false()") self.db.desc = "Кондитер. Поход на доктора. Но не доктор." #задаем таймер, рандомно срабратывающий self.db.last_ticker_deley_value = 0 self.db.last_ticker_deley_value = random.randint(15, 120) tickerhandler.add(self, self.db.last_ticker_deley_value) CONV_cond = {"START": {"text": "Добро пожаловать. Чем могу вам помочь?", "links": ["i1", "i1", "END"], "linktexts": ["Купить шоколадные конфеты - 5 интренета.", "Купить трюфели - 5 интернетов.", "Ничего"], "keywords": ["1","2","3"], "selectcmds":[CmdBuyChoco,CmdBuyTruff,None], "callback": None}, "i1": {"text": "Спасибо за покупку. Что нибудь еще?", "links": ["START", "END"], "linktexts":["Еще", "Нет. Все."], "keywords": None, "callback": None}, "i2": {"text": "Этот товар закончился. Скоро обещали привезти.", "links": ["START", "END"], "linktexts": ["Можно тогда...", "Ну ладно. Досвидания."], "keywords": None, "callback": None}, "i3": {"text": "У тебя не хватет интернетов. Подкопи и тогда возвращайся.", "links": ["START", "END"], "linktexts": ["Можно тогда...", "Ну ладно. Досвидания."], "keywords": None, "callback": None}, } self.db.conversation = CONV_cond
def at_object_receive(self, new_arrival, source_location): """ When an object enters a room we tell other objects in the room about it by trying to call a hook on them. The Mob object uses this to cheaply get notified of enemies without having to constantly scan for them. Args: new_arrival (Object): the object that just entered this room. source_location (Object): the previous location of new_arrival. """ if new_arrival.has_player: # and not new_arrival.is_superuser: # this is a character outdoor = self.tags.get('outdoor', category='flags') if outdoor: tickers = TICKER_HANDLER.all_display() counter = 0 for tick in tickers: if tick[0] == self and tick[1] == 'update_weather': notice = '' counter += 1 show = '20%% chance every %s seconds in ' % tick[3] show += "%s%s" % (tick[0] or "[None]", tick[0] and " (#%s)" % (tick[0].id if hasattr(tick[0], "id") else "") or "") if counter > 1: notice = '|rExtra Ticker|n - |yadditional|n ' # Too many weather tickers going, maybe remove extra? channel = ChannelDB.objects.channel_search('MudInfo') if channel[0]: channel[0].msg('* %s\'s %s experience * %s%s' % (new_arrival.key, tick[4], notice, show), keep_log=False) if counter == 0: # No weather ticker - add one. interval = random.randint(50, 70) TICKER_HANDLER.add(interval=interval, callback=self.update_weather, idstring='Weather') for obj in self.contents_get(exclude=new_arrival): if hasattr(obj, "at_new_arrival"): obj.at_new_arrival(new_arrival)
def auto_cast_skill(self): """ Cast a new skill automatically. """ if not self.can_auto_cast: return if not self.owner: return if not self.owner.ndb.combat_handler: # combat is finished, stop ticker TICKER_HANDLER.remove(self, settings.AUTO_CAST_SKILL_CD) return # Get target. choose_new_target = True if self.skill_target: if self.skill_target.is_alive(): choose_new_target = False if choose_new_target: self.skill_target = self.choose_skill_target() if not self.skill_target: # No target. return # Get available skills. available_skills = self.get_available_skills() if not available_skills: # No available skill. return # Random chooses a skill. skill = random.choice(available_skills) if skill: self.cast_skill(skill, self.skill_target)
def func(self): from evennia import TICKER_HANDLER all_subs = TICKER_HANDLER.all_display() if not all_subs: self.caller.msg("No tickers are currently active.") return table = EvTable("interval (s)", "object", "path/methodname", "idstring", "db") for sub in all_subs: table.add_row(sub[3], "%s%s" % (sub[0] or "[None]", sub[0] and " (#%s)" % (sub[0].id if hasattr(sub[0], "id") else "") or ""), sub[1] if sub[1] else sub[2], sub[4] or "[Unset]", "*" if sub[5] else "-") self.caller.msg("|wActive tickers|n:\n" + unicode(table))
def at_object_creation(self): self.db.is_corpse = True self.db.hands = create_object(settings.BASE_OBJECT_TYPECLASS, "hands") #создаем таймер для трупа tickerhandler.add(self, 60*3)
def at_object_creation(self): "called only when the object is first created" TICKER_HANDLER.add(self, 30, hook_key="at_weather_update")