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 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 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 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 _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_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_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 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 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 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 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 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 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 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 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 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(RookeryRoom, self).at_object_creation() TICKER_HANDLER.add(8 * 60, self.update_rookery, idstring="rookery_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(FunHouseRoom, self).at_object_creation() TICKER_HANDLER.add(10 * 60, self.update_funhouse, idstring="funhouse_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 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 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 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 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 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 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 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 use(self, caller): self.db.caller = caller caller.msg(u"%s плавно распространяется по твоему телу" % self.db.name) popustilo = create_object('typeclasses.substance.Popustilo', key="Эффект от вещества %s на игроке %s" % (self.db.name, caller.name)) popustilo.db.caller = caller popustilo.db.substance = self.db.name popustilo.db.affect_time = self.db.affect_time caller.db.effects[self.db.name] = popustilo tickerhandler.add(popustilo, self.db.affect_time, hook_key='doit') self.delete()
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 at_object_creation(self): "This is called when the object is first created only." self.db.strength = 100 self.db.magic = 100 self.db.dex = 100 self.db.intel = 100 self.db.luck = 100 self.db.defense = 100 self.db.health = 255 self.db.max_health = 255 self.db.level = 1 self.db.xp = 0 self.db.next_level_xp = 100 self.db.attr_points = 1 self.db.gold = 0 TICKER_HANDLER.add(10, self.at_prompt)
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 set_state(self, interval, hook_key, stop=False): idstring = self.key + "-" + str(self.id) last_interval = self.db.last_ticker_interval last_hook_key = self.db.last_hook_key if last_interval and last_hook_key: # we have a previous subscription, kill this first. tickerhandler.remove(interval=last_interval, callback=getattr(self, last_hook_key), idstring=idstring) self.db.last_ticker_interval = interval self.db.last_hook_key = hook_key if not stop: # set the new ticker tickerhandler.add(interval=interval, callback=getattr(self, hook_key), idstring=idstring)
def at_object_creation(self): """ Called when object is first created. We set up a ticker to update this room regularly. """ super(WeatherRoom, self).at_object_creation() weather_choice = random.randint(0, 1) if weather_choice == 0: self.current_weather_type = RAINY_STRINGS else: self.current_weather_type = SUNNY_STRINGS TICKER_HANDLER.add(30 * 60, self.update_weather, idstring="weather_ticker", persistent=True)
def func(self): "implements the actual functionality" caller = self.caller target = caller.search(self.target) # Checks for valid target if not can_hit(caller, target): return # Set fighting variable on both character and target. Add combatants to the combat list. # Also check if one character is already fighting (todo) set_fighting(caller, target) # Begin Combat caller.msg("You are fighting {}".format(target)) tickerhandler.add(5, rules.do_hit, persistent=False, idstring="Combat_Ticker") do_hit()
def at_object_receive(self, moved_obj, source_location, **kwargs): """ Called after an object has been moved into this object. Args: moved_obj (Object): The object moved into this one source_location (Object): Where `moved_object` came from. Note that this could be `None`. **kwargs (dict): Arbitrary, optional arguments for users overriding the call (unused by default). """ super(AmbientRoom, self).at_object_receive() if self.db.ambient_switch: # If player enters and not already, connect to ticker if moved_obj.has_account and not self.db.connected_to_ticker: tickerhandler.add(self.db.ambient_interval, self.display_ambient_msg(), persistent=True) self.db.connected_to_ticker = True
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_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 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_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 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_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 at_object_creation(self): "called only when the object is first created" TICKER_HANDLER.add(self, 30, hook_key="at_weather_update")
def at_object_creation(self): #set up hook for self-healing heartbeat TICKER_HANDLER.add(self,10,hook_key="health_ticker") #set up desc attributes self.db.eyes = "blank" self.db.hair = "no" self.db.height_feet = 6 self.db.height_inches = 0 self.db.weight = 0 self.db.sex = "Male" #set up bodyparts available self.db.bodyparts = {"head":{ "desc": "", "hp": 1, "weartype": ["hat","helmet"] }, "left arm":{ "desc": "", "hp": 1, "weartype": [None] }, "left hand":{ "desc": "", "hp": 1, "weartype": ["glove","ring","bracelet"] }, "right arm":{ "desc": "", "hp": 1, "weartype": [None] }, "right hand":{ "desc": "", "hp": 1, "weartype": ["glove","ring","bracelet"] }, "torso":{ "desc": "", "hp": 5, "weartype": ["shirt", "jacket", "cloak", "armor"] }, "left leg":{ "desc": "", "hp": 1, "weartype": ["pants"] }, "left foot":{ "desc": "", "hp": 1, "weartype": ["boot"] }, "right leg":{ "desc": "", "hp": 1, "weartype": ["pants"] }, "right foot":{ "desc": "", "hp": 1, "weartype": ["boot"] } } #set up basic character stats self.db.maxHP = 10 self.db.maxSP = 0 self.db.curHP = 10 self.db.curSP = 0 self.db.times_trained = 0 self.db.level = 0 self.db.regen_rate = 1 self.db.sp_regen_rate = 1 self.db.dodgerating = 1 #Major, character-wide benefits. Affects everything self.db.atts = {"str": 1, "dex": 1, "con": 1, "int": 1, "wis": 1, "cha": 1} #Major, long-term benefits to characters. Wings. Ritual-magic giving #until-logout buffs, etc. Elemental magic that gives the ability to cast #spells at the drop of a hat. Etc. This has a more complicated setup #than the other attributes for the characters. #Each attribute has an Affect Level multiplier that directly effects how #much this affects your level. Typically, the numbers will be 0, .5, or 1, #though more complicated additions are possible in the code. 0 would mean that #that particular ability does not affect your level, no matter how much you put #in to it. A good example of this would be gun modification. Ritual Magic has a #.5 multiplier, because while the effects of its various skills are powerful and #long-lasting, they can't be used directly in combat. Elemental magic, on the other #hand, has a direct effect on combat through the many combative spells that it holds, #and so it has a multiplier of 1, and if it seems like not enough, I may even #decide to increase it to a level above 1, to 1.25 or even 1.5. Every attribute has 5 #"levels" that in general describe how powerful the individual abilities #are underneath that level. Each "level" has a ratiing, which directly gives #points to be spent in that level. There will be some skill synergy #implemented where you get additional points in these levels based #on knowledge skills. Underneath each level is a list of skills. These #are increased with xp, but only up to the number of points that you have #to spend on that level. Basically: # Ability # --Affect Level <multiplier> # --Basic # ----Basic Level: <number> # ----Basic Points: <number> # ----Skills # ------Skill #1: <number> # ------Skill #2: <number> # ------Skill #3: <number> # ------...etc # --Normal # --...etc self.db.abils = { "ritual magic":{ "affects level": .5, "basic":{ "level": 0, "points": 0, "powers":{ "minor boost": 0, "minor shield": 0, "sunvisor": 0 } }, "normal":{ "level": 0, "points": 0, "powers":{ "boost": 0, "shield": 0, "sunshade": 0 } }, "intermediate":{ "level": 0, "points": 0, "powers": { } }, "advanced":{ "level": 0, "points": 0, "powers":{ } }, "master":{ "level": 0, "points": 0, "powers":{ } } }, "elemental magic":{ "affects level": 1, "basic":{ "level": 0, "points": 0, "powers": { "flame dart": 0, "dazzle": 0 } }, "normal":{ "level": 0, "points": 0, "powers":{ } }, "intermediate":{ "level": 0, "points": 0, "powers":{ } }, "advanced":{ "level": 0, "points": 0, "powers":{ } }, "master":{ "level": 0, "points": 0, "powers":{ } } } } #The ability to do stuff. Pick locks. Work with a computer. Balance a checkbook. self.db.skills = {"programming": 0, "martial arts": 0, "melee": 0, "brawling": 0, } #The ability to know things. History. Magical theory. Scientific theory. self.db.knowledges = {"computer science": 0, "magical theory": 0, "history": 0, "demonic lore": 0} #Current job is where you work. Jobs db is a list of dictionaries, describing the #stats of each job that you have held. Couch potato is the default job, and pays #$100 per week. self.db.current_job = "Couch Potato" self.db.jobs = [{"job_title": "Couch Potato", "payscale": 100.00, "job_level": 1, "job_xp": 0}] #How much experience you have, and how much you have spent. Total xp is calculate at runtime self.db.experience = {"current": 0, "spent": 0}
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)