def random_weather(season='fall'): """ Given a season, picks a weighted random weather type from the list of valid weathers. :param season: 'summer', 'autumn', 'winter', or 'spring' :return: A WeatherType object with emits valid in the given season. """ emits = emits_for_season(season) # Build a list of all weathers and the combined weight # of their valid emits weathers = {} total_weight = 0 for emit in emits: if emit.weather.automated: weatherweight = weathers[ emit.weather.id] if emit.weather.id in weathers else 0 weatherweight += emit.weight weathers[emit.weather.id] = weatherweight * emit.weather.multiplier total_weight += emit.weight # Create our picker list picker = WeightedPicker() for k, v in weathers.iteritems(): picker.add_option(k, v) result = picker.pick() weather = WeatherType.objects.get(pk=result) return weather
def at_repeat(self): try: haven = Shardhaven.objects.get(pk=self.obj.db.haven_id) except (Shardhaven.DoesNotExist, Shardhaven.MultipleObjectsReturned): self.stop() return if self.obj.db.last_monster: try: monster = Monster.objects.get(id=self.obj.db.last_monster) except (Monster.DoesNotExist, Monster.MultipleObjectsReturned): self.stop() return else: monsters = Monster.objects.filter( habitats__in=[haven.haven_type], difficulty__lte=haven.difficulty_rating) monster_type = self.obj.ndb.last_monster_type if monster_type: if monster_type == "mook": monsters = monsters.filter(npc_type=Monster.MOOKS) elif monster_type == "boss": monsters = monsters.filter(npc_type=Monster.BOSS) if monsters.count() == 0: self.stop() return picker = WeightedPicker() for monster in monsters.all(): picker.add_option(monster, monster.weight_spawn) monster = picker.pick() mob_instance = monster.create_instance(self.obj) self.obj.msg_contents("{} attacks {}!".format( mob_instance.name, self.obj.ndb.monster_attack)) mob_instance.attack(self.obj.ndb.monster_attack, kill=True) mob_instance.combat.set_switch_chance(40) if haven.auto_combat: cscript = self.obj.ndb.combat_manager for testobj in self.obj.contents: if (testobj.has_account or (hasattr(testobj, "is_character") and testobj.is_character) ) and not testobj.check_permstring("builders"): if not cscript.check_character_is_combatant(testobj): testobj.msg(cscript.add_combatant(testobj, testobj)) if not testobj.is_typeclass( "world.exploration.npcs.BossMonsterNpc" ) and not testobj.is_typeclass( "world.exploration.npcs.MookMonsterNpc"): if mob_instance.combat.state: mob_instance.combat.state.add_foe(testobj) self.stop()
def pick_emit(weathertype, season=None, time=None, intensity=None): """ Given weather conditions, pick a random emit. If a GM-set weather override is present, will always return that value. :param weathertype: A WeatherType object, integer ID, or None. If None, defaults to the first weather type. :param season: 'summer', 'autumn', 'winter', 'spring', or None. If None, defaults to the current IC season. :param time: 'morning', 'afternoon', 'evening', 'night', or None. If None, defaults to the current IC time of day. :param intensity: The intensity of the weather, from 1 to 10. :return: """ # Do we have a GM-set override? custom_weather = ServerConfig.objects.conf('weather_custom', default=None) if custom_weather: return custom_weather if weathertype is None: weathertype = ServerConfig.objects.conf('weather_type_current', default=1) if isinstance(weathertype, int): weathertype = WeatherType.objects.get(pk=weathertype) if not isinstance(weathertype, WeatherType): raise ValueError if intensity is None: intensity = ServerConfig.objects.conf('weather_intensity_current', default=5) emits = weather_emits(weathertype, season=season, time=time, intensity=intensity) if emits.count() == 0: logger.log_err( "Weather: Unable to find any matching emits for {} intensity {} on a {} {}." .format(weathertype.name, intensity, season, time)) return None if emits.count() == 1: return emits[0].text picker = WeightedPicker() for emit in emits: picker.add_option(emit, emit.weight) result = picker.pick() return result.text
def set_alignment_and_affinity(cls, haven, obj): from world.magic.models import Alignment, Affinity align_picker = WeightedPicker() for alignment in haven.alignment_chances.all(): align_picker.add(alignment.alignment, alignment.weight) affinity_picker = WeightedPicker() for affinity in haven.affinity_chances.all(): affinity_picker.add(affinity.affinity, affinity.weight) alignment = align_picker.pick() affinity = affinity_picker.pick() if not alignment: alignment = Alignment.PRIMAL if not affinity: affinity = Affinity.objects.order_by("?").first() obj.db.alignment = alignment.id obj.db.affinity = affinity.id
def create_trinket(cls, haven): name = GeneratedLootFragment.generate_trinket_name() trinket = create.create_object( typeclass="world.exploration.loot.Trinket", key=name) trinket.db.desc = "\nAn ancient trinket, one that feels slightly warm to the touch.\n" quality_picker = WeightedPicker() quality_picker.add_option(4, 25) quality_picker.add_option(5, 45) quality_picker.add_option(6, 30) quality_picker.add_option(7, 10) quality_picker.add_option(8, 3) quality_picker.add_option(9, 1) trinket.db.quality_level = quality_picker.pick() trinket.db.found_shardhaven = haven.name cls.set_alignment_and_affinity(haven, trinket) return trinket
def at_object_receive(self, obj, source_location): if not obj.is_typeclass('typeclasses.characters.Character'): return haven = self.shardhaven if not haven: return entrance_square = haven.entrance if entrance_square is not None and entrance_square.room == self: return if not obj.has_player or not (hasattr(obj, 'is_character') and obj.is_character): return if obj.is_typeclass("world.exploration.npcs.BossMonsterNpc")\ or obj.is_typeclass("world.explorations.npcs.MookMonsterNpc"): return haven_square = self.shardhaven_square recent = False if haven_square is not None: recent = haven_square.visited_recently haven_square.visit(obj) if obj.check_permstring("builders"): return characters = [] for testobj in self.contents: if testobj != obj and (testobj.has_player or (hasattr(testobj, 'is_character') and testobj.is_character)) \ and not testobj.check_permstring("builders"): characters.append(testobj) player_characters = [] monsters = [] for testobj in characters: if not testobj.is_typeclass("world.exploration.npcs.BossMonsterNpc") \ and not testobj.is_typeclass("world.exploration.npcs.MookMonsterNpc"): player_characters.append(testobj) else: monsters.append(testobj) if obj not in player_characters: player_characters.append(obj) if haven_square.monster and not haven_square.monster_defeated and len( monsters) == 0: self.db.last_monster = haven_square.monster.id self.ndb.monster_attack = obj.name self.scripts.add(SpawnMobScript) else: picker = WeightedPicker() # Let's not roll high for EVERY single player # Otherwise we run the risk of a monster showing up every single room. if recent: weight_none = haven.weight_no_monster_backtrack else: weight_none = haven.weight_no_monster if len(monsters) > 0: weight_none *= 4 if haven.auto_combat: cscript = self.ndb.combat_manager if cscript and not cscript.check_character_is_combatant( obj): obj.msg("There is a fight in the room!") obj.msg(cscript.add_combatant(obj, obj)) for mon in monsters: if mon.combat.state: mon.combat.state.add_foe(obj) if len(player_characters) > 1: # Chance of spawn in goes down after the first player. weight_none = weight_none * 2 if len(monsters) > 1: # Chance of spawn in goes down after the first monster. weight_none = weight_none * 2 if obj.ndb.shardhaven_sneak_value: weight_none += (obj.ndb.shardhaven_sneak_value * 10) if obj.ndb.shardhaven_sneak_value > 0: self.msg_contents( "%s sneaks quietly into the room, hoping not to disturb any monsters." % obj.name) elif obj.ndb.shardhaven_sneak_value < 0: self.msg_contents( "%s attempts to sneak into the room, but ends up making more " "noise than if they'd just walked!" % obj.name) obj.ndb.shardhaven_sneak_value = None if weight_none < 0: weight_none = 0 if weight_none > 0: picker.add_option(None, weight_none) picker.add_option("mook", haven.weight_mook_monster) picker.add_option("boss", haven.weight_boss_monster) monster = picker.pick() if monster: self.ndb.last_monster_type = monster self.ndb.monster_attack = obj.name self.scripts.add(SpawnMobScript) if len(characters) > 0: return picker = WeightedPicker() if recent: picker.add_option(None, haven.weight_no_treasure_backtrack) else: picker.add_option(None, haven.weight_no_treasure) picker.add_option("trinket", haven.weight_trinket) picker.add_option("weapon", haven.weight_weapon) treasure = picker.pick() if treasure: if treasure == "trinket": trinket = LootGenerator.create_trinket(haven) trinket.location = self elif treasure == "weapon": weapon_types = (LootGenerator.WPN_BOW, LootGenerator.WPN_SMALL, LootGenerator.WPN_MEDIUM, LootGenerator.WPN_HUGE) weapon = LootGenerator.create_weapon( haven, random.choice(weapon_types)) weapon.location = self if self.ndb.combat_manager: obj.msg("Your party is already in combat! Joining the fight.") obj.msg(self.ndb.combat_manager.add_combatant(obj, obj)) for mob in monsters: if mob.combat and mob.combat.state: mob.combat.state.add_foe(obj)
if monster_type: if monster_type == "mook": monsters = monsters.filter(npc_type=Monster.MOOKS) elif monster_type == "boss": monsters = monsters.filter(npc_type=Monster.BOSS) if monsters.count() == 0: self.stop() return picker = WeightedPicker() for monster in monsters.all(): picker.add_option(monster, monster.weight_spawn) monster = picker.pick() mob_instance = monster.create_instance(self.obj) self.obj.msg_contents("{} attacks {}!".format( mob_instance.name, self.obj.ndb.monster_attack)) mob_instance.attack(self.obj.ndb.monster_attack, kill=True) mob_instance.combat.set_switch_chance(40) if haven.auto_combat: cscript = self.obj.ndb.combat_manager for testobj in self.obj.contents: if (testobj.has_player or (hasattr(testobj, 'is_character') and testobj.is_character)) \ and not testobj.check_permstring("builders"): if not cscript.check_character_is_combatant(testobj): testobj.msg(cscript.add_combatant(testobj, testobj)) if not testobj.is_typeclass('world.exploration.npcs.BossMonsterNpc') \
def create_weapon(cls, haven, wpn_type=None): weapon_types = ( LootGenerator.WPN_SMALL, LootGenerator.WPN_MEDIUM, LootGenerator.WPN_HUGE, LootGenerator.WPN_BOW, ) if not wpn_type: wpn_type = random.choice(weapon_types) picker = WeightedPicker() difficulty = haven.difficulty_rating if difficulty < 3: picker.add_option("steel", 30) picker.add_option("rubicund", 50) picker.add_option("diamondplate", 1) elif difficulty < 5: picker.add_option("steel", 10) picker.add_option("rubicund", 40) picker.add_option("diamondplate", 5) elif difficulty < 8: picker.add_option("rubicund", 30) picker.add_option("diamondplate", 20) picker.add_option("alaricite", 5) else: picker.add_option("rubicund", 10) picker.add_option("diamondplate", 30) picker.add_option("alaricite", 5) material = picker.pick() should_name = material in ["diamondplate", "alaricite"] generator_wpn = GeneratedLootFragment.MEDIUM_WEAPON_TYPE if wpn_type == LootGenerator.WPN_SMALL: generator_wpn = GeneratedLootFragment.SMALL_WEAPON_TYPE elif wpn_type == LootGenerator.WPN_HUGE: generator_wpn = GeneratedLootFragment.HUGE_WEAPON_TYPE elif wpn_type == LootGenerator.WPN_BOW: generator_wpn = GeneratedLootFragment.BOW_WEAPON_TYPE name = GeneratedLootFragment.generate_weapon_name( material, include_name=should_name, wpn_type=generator_wpn) weapon = create.create_object( typeclass="world.exploration.loot.AncientWeapon", key=name) desc = "\n{particle} {adjective} ancient {material} weapon, with {decor} on the {element}.\n" if wpn_type == LootGenerator.WPN_BOW: desc = "\n{particle} {adjective} ancient {material} bow, decorated with {decor}.\n" adjective = GeneratedLootFragment.pick_random_fragment( GeneratedLootFragment.ADJECTIVE) decor = GeneratedLootFragment.pick_random_fragment( GeneratedLootFragment.WEAPON_DECORATION) element = GeneratedLootFragment.pick_random_fragment( GeneratedLootFragment.WEAPON_ELEMENT) particle = a_or_an(adjective).capitalize() desc = desc.replace("{particle}", particle) desc = desc.replace("{material}", material) desc = desc.replace("{adjective}", adjective) desc = desc.replace("{decor}", decor) desc = desc.replace("{element}", element) weapon.db.desc = desc quality_picker = WeightedPicker() quality_picker.add_option(4, 25) quality_picker.add_option(5, 45) quality_picker.add_option(6, 30) quality_picker.add_option(7, 10) quality_picker.add_option(8, 3) quality_picker.add_option(9, 1) weapon.item_data.quality_level = quality_picker.pick() weapon.db.found_shardhaven = haven.name weapon.item_data.recipe = LootGenerator.get_weapon_recipe( material, wpn_type=wpn_type) cls.set_alignment_and_affinity(haven, weapon) return weapon