Exemplo n.º 1
0
def cost_at_rank(skill, current_rating, new_rating):
    """Returns the total cost when given a current rating and the new rating."""
    from world.traits.models import Trait

    cost = 0
    if new_rating > current_rating:
        while current_rating < new_rating:
            current_rating += 1
            if (skill in Trait.get_valid_skill_names(Trait.COMBAT)
                    or skill in Trait.get_valid_ability_names()):
                mult = COMBAT_SKILL_COST_MULT
            else:
                mult = NON_COMBAT_SKILL_COST_MULT
            if current_rating >= 6 and skill in Trait.get_valid_skill_names():
                base = LEGENDARY_COST
                mult //= 10
            else:
                base = current_rating
            cost += base * mult
        return cost
    if new_rating < current_rating:
        while current_rating > new_rating:
            if (skill in Trait.get_valid_skill_names(Trait.COMBAT)
                    or skill in Trait.get_valid_ability_names()):
                cost -= current_rating * COMBAT_SKILL_COST_MULT
            else:
                cost -= current_rating * NON_COMBAT_SKILL_COST_MULT
            current_rating -= 1
        return cost
    return cost
Exemplo n.º 2
0
 def adjust_skill(self, field, value=1):
     if field not in Trait.get_valid_skill_names():
         raise Exception(
             "Error in adjust_skill: %s not found as a valid skill." %
             field)
     current = self.get_skill_value(field)
     self.set_skill_value(field, current + value)
     self.character.db.trainer = None
     if field in Trait.get_valid_skill_names(Trait.CRAFTING):
         abilitylist = _parent_abilities_[field]
         for ability in abilitylist:
             if ability not in self.abilities:
                 self.set_ability_value(ability, 1)
Exemplo n.º 3
0
 def create_knack(self):
     """Attempts to create a new knack"""
     desc = self.rhs
     if not desc:
         raise self.error_class("You must provide a description.")
     try:
         stat, skill, name = (
             self.lhslist[0],
             self.lhslist[1],
             ", ".join(self.lhslist[2:]),
         )
     except IndexError:
         raise self.error_class("You must provide a stat and skill.")
     if not name:
         raise self.error_class("You must provide a name.")
     if self.caller.mods.get_knack_by_name(name):
         raise self.error_class("You already have a knack by that name.")
     stat, skill = stat.lower(), skill.lower()
     if stat not in Trait.get_valid_stat_names():
         raise self.error_class("{} is not a valid stat.".format(stat))
     if skill not in Trait.get_valid_skill_names():
         raise self.error_class("{} is not a valid skill.".format(skill))
     if any(
         [
             knack
             for knack in self.caller.mods.knacks
             if knack.stat == stat and knack.skill == skill
         ]
     ):
         raise self.error_class(
             "You already have a knack for that skill and stat combination."
         )
     self.caller.pay_xp(self.new_knack_cost)
     self.caller.mods.create_knack(name, stat, skill, desc)
     self.msg("You create a knack called '{}' for {}+{}.".format(name, stat, skill))
Exemplo n.º 4
0
def get_highest_crafting_skill(character):
    """Returns the highest crafting skill for character"""
    from world.traits.models import Trait

    skills = character.traits.skills
    return max(
        Trait.get_valid_skill_names(Trait.CRAFTING) + ["artwork"],
        key=lambda x: skills.get(x, 0),
    )
Exemplo n.º 5
0
 def skills(self, skills_dict: Dict[str, int]):
     self.wipe_all_skills()
     for skill, value in skills_dict.items():
         trait = Trait.get_instance_by_name(skill)
         if not trait:
             names = ", ".join(Trait.get_valid_skill_names())
             raise InvalidTrait(
                 f"No trait found by '{skill}'. Valid: {names}")
         self._cache["skill"][skill] = self.character.trait_values.create(
             trait=trait, value=value)
Exemplo n.º 6
0
    def do_spoof_roll(self):
        args = self.lhs if self.rhs else self.args
        syntax_error = (
            "Usage: <stat>/<value> [+ <skill>/<value>] at difficulty=<npc name>"
        )

        # Split string at ' at '
        args, diff_rating = self._extract_difficulty(args, syntax_error)

        # Split string at '+', if possible, and strip.
        stat_str, skill_str = self._extract_stat_skill_string(
            args, syntax_error)

        # Get Stat value
        stat, stat_value = self._get_values(stat_str)
        if stat and stat not in Trait.get_valid_stat_names():
            raise self.error_class(f"{stat} is not a valid stat name.")

        if stat_value < 1 or stat_value > self.STAT_LIMIT:
            raise self.error_class(
                f"Stats must be between 1 and {self.STAT_LIMIT}.")

        # Get skill value, if applicable (None if not)
        skill = None
        skill_value = None
        if skill_str:
            skill, skill_value = self._get_values(skill_str)
            if skill and skill not in Trait.get_valid_skill_names():
                raise self.error_class(f"{skill} is not a valid skill name.")

            if skill_value < 1 or skill_value > self.SKILL_LIMIT:
                raise self.error_class(
                    f"Skills must be between 1 and {self.SKILL_LIMIT}.")

        # Will be None if not self.rhs, which is what we want.
        npc_name = self.rhs

        can_crit = "crit" in self.switches
        is_flub = "flub" in self.switches

        BaseCheckMaker.perform_check_for_character(
            self.caller,
            roll_class=SpoofRoll,
            stat=stat,
            stat_value=stat_value,
            skill=skill,
            skill_value=skill_value,
            rating=diff_rating,
            npc_name=npc_name,
            can_crit=can_crit,
            is_flub=is_flub,
        )
Exemplo n.º 7
0
 def get_stat_and_skill_from_args(self, stats_string):
     skill = None
     try:
         stat, skill = stats_string.split("+")
         stat = stat.strip().lower()
         skill = skill.strip().lower()
     except (TypeError, ValueError):
         stat = stats_string.strip().lower()
     if stat not in Trait.get_valid_stat_names():
         raise self.error_class(f"{stat} is not a valid stat name.")
     if skill and skill not in Trait.get_valid_skill_names():
         raise self.error_class(f"{skill} is not a valid skill name.")
     return stat, skill
Exemplo n.º 8
0
    def clues_shared_modifier_seed(self):
        """Seed value for clue sharing costs"""
        from world.traits.models import Trait

        seed = 0
        pc = self.char_ob
        for stat in Trait.get_valid_stat_names(Trait.SOCIAL):
            seed += pc.traits.get_stat_value(stat)
        # do not be nervous. I love you. <3
        seed += sum([
            pc.traits.get_skill_value(ob)
            for ob in Trait.get_valid_skill_names(Trait.SOCIAL)
        ])
        seed += pc.traits.get_skill_value("investigation") * 3
        return seed
Exemplo n.º 9
0
def get_partial_match(args, s_type):
    from world.traits.models import Trait

    # helper function for finding partial string match of stat/skills
    if s_type == "stat":
        word_list = Trait.get_valid_stat_names()
    elif s_type == "skill":
        word_list = Trait.get_valid_skill_names()
    else:
        return
    matches = []
    for word in word_list:
        if word.startswith(args):
            matches.append(word)
    return matches
Exemplo n.º 10
0
 def display_traits(self):
     caller = self.caller
     caller.msg("{wCurrent Teacher:{n %s" % caller.db.trainer)
     caller.msg("{wUnspent XP:{n %s" % caller.db.xp)
     caller.msg("{wLifetime Earned XP:{n %s" % caller.db.total_xp)
     all_stats = ", ".join(Trait.get_valid_stat_names())
     caller.msg("\n{wStat names:{n")
     caller.msg(all_stats)
     caller.msg("\n{wSkill names:{n")
     caller.msg(", ".join(Trait.get_valid_skill_names()))
     caller.msg("\n{wDominion skill names:{n")
     caller.msg(", ".join(skill for skill in stats_and_skills.DOM_SKILLS))
     caller.msg("\n{wAbility names:{n")
     crafting = Trait.get_valid_ability_names(Trait.CRAFTING)
     abilities = caller.traits.abilities
     abilities = set(abilities.keys()) | set(crafting)
     if caller.check_permstring("builder"):
         caller.msg(", ".join(Trait.get_valid_ability_names()))
     else:
         caller.msg(", ".join(ability for ability in abilities))
Exemplo n.º 11
0
    def set_roll(self, action):
        """Sets a stat and skill for action or assistant"""

        try:
            stat, skill = self.rhslist
            stat = stat.lower()
            skill = skill.lower()
        except (ValueError, TypeError, AttributeError):
            self.msg("Usage: @action/roll <action #>=<stat>,<skill>")
            return
        if (
            stat not in Trait.get_valid_stat_names()
            or skill not in Trait.get_valid_skill_names()
        ):
            self.msg("You must provide a valid stat and skill.")
            return
        field_name = "stat_used"
        self.set_action_field(action, field_name, stat, verbose_name="stat")
        field_name = "skill_used"
        return self.set_action_field(action, field_name, skill, verbose_name="skill")
Exemplo n.º 12
0
def skill(accessing_obj, accessed_obj, *args, **kwargs):
    """
    Check accessing_obj's rank in an skill to determine lock.
    Usage:
        skill(value)
        skill(ability_name, value)
    If only value is given, ability must be a property in accessed_obj
    that returns ability_name.
    """
    if not args:
        return False
    if len(args) == 1:
        if args[0] == "all":
            return True
        name = accessed_obj.skill
        val = int(args[0])
    else:
        name = args[0]
        val = int(args[1])
    if name == "all":
        from world.traits.models import Trait

        skill_list = Trait.get_valid_skill_names(Trait.CRAFTING)
    else:
        skill_list = name.split(",")
    if accessing_obj.char_ob:
        accessing_obj = accessing_obj.char_ob
    for skill_name in skill_list:
        skill_name = skill_name.lower().strip()
        try:
            pab = accessing_obj.traits.get_skill_value(skill_name)
            if pab >= val:
                return True
        except AttributeError:
            return False
    return False
Exemplo n.º 13
0
    ASSISTANT: assistant_stats,
    CHAMPION: guard_stats,
    ANIMAL: animal_stats,
    SMALL_ANIMAL: small_animal_stats,
}
primary_stats = {
    GUARD: Trait.get_valid_stat_names(Trait.PHYSICAL),
    THUG: Trait.get_valid_stat_names(Trait.PHYSICAL),
    SPY: Trait.get_valid_stat_names(Trait.SOCIAL),
    ASSISTANT: Trait.get_valid_stat_names(Trait.MENTAL),
    CHAMPION: Trait.get_valid_stat_names(Trait.PHYSICAL),
    ANIMAL: Trait.get_valid_stat_names(Trait.PHYSICAL),
    SMALL_ANIMAL: Trait.get_valid_stat_names(Trait.PHYSICAL),
}

guard_skills = dict([(key, 0) for key in Trait.get_valid_skill_names(Trait.COMBAT)])
guard_skills.update({"ride": 0, "leadership": 0, "war": 0})
spy_skills = dict([(key, 0) for key in Trait.get_valid_skill_names(Trait.SOCIAL)])
spy_skills.update({"streetwise": 0, "investigation": 0})
assistant_skills = dict(
    [(key, 0) for key in Trait.get_valid_skill_names(Trait.GENERAL)]
)
assistant_skills.update({"etiquette": 0, "diplomacy": 0})
animal_skills = {
    "athletics": 1,
    "brawl": 1,
    "dodge": 1,
    "stealth": 0,
    "survival": 2,
    "legerdemain": 0,
    "performance": 0,
Exemplo n.º 14
0
    def func(self):
        """Execute command."""
        caller = self.caller
        switches = self.switches
        # try to handle possible caching errors
        caller.attributes._cache.pop("currently_training-None", None)
        caller.attributes._cache.pop("num_trained-None", None)
        caller.refresh_from_db()
        if not self.args:
            self.msg(
                "Currently training: %s" %
                ", ".join(str(ob) for ob in self.currently_training(caller)))
            self.msg("You can train %s targets." % self.max_trainees(caller))
            return
        if not self.lhs or not self.rhs or not self.switches:
            caller.msg(
                "Usage: train/[stat or skill] <character to train>=<name of stat or skill to train>"
            )
            return
        additional_cost = 0
        if "retainer" in self.switches:
            player = caller.player.search(self.lhs)
            from world.dominion.models import Agent

            if len(self.rhslist) < 2:
                rhs = self.rhs
            else:
                rhs = self.rhslist[0]
                try:
                    additional_cost = int(self.rhslist[1])
                except ValueError:
                    self.msg("Additional AP must be a number.")
                    return
            try:
                if rhs.isdigit():
                    targ = player.retainers.get(id=rhs).dbobj
                else:
                    targ = player.retainers.get(name__iexact=rhs).dbobj
                if not targ or not targ.pk:
                    raise Agent.DoesNotExist
            except (Agent.DoesNotExist, AttributeError):
                self.msg("Could not find %s's retainer named %s." %
                         (player, rhs))
                return
            caller_msg = "You have trained %s." % targ
            targ_msg = ""
        else:
            targ = caller.search(self.lhs)
            if not targ:
                caller.msg("No one to train by the name of %s." % self.lhs)
                return
            if not targ.player:
                caller.msg(
                    "Use the /retainer switch to train non-player-characters.")
                return
            if "stat" in switches:
                stat = self.rhs.lower()
                if not self.check_attribute_name(Trait.get_valid_stat_names(),
                                                 "stat"):
                    return
                if not self.check_attribute_value(
                        caller.traits.get_stat_value(stat),
                        targ.traits.get_stat_value(stat)):
                    return
            elif "skill" in switches:
                skill = self.rhs.lower()
                if not self.check_attribute_name(Trait.get_valid_skill_names(),
                                                 "skill"):
                    return
                if not self.check_attribute_value(
                        caller.traits.get_skill_value(skill),
                        targ.traits.get_skill_value(skill),
                ):
                    return
            elif "ability" in switches:
                ability = self.rhs.lower()
                if not self.check_attribute_name(
                        Trait.get_valid_ability_names(), "ability"):
                    return
                if not self.check_attribute_value(
                        caller.traits.get_ability_value(ability),
                        targ.traits.get_ability_value(ability),
                ):
                    return
            else:
                caller.msg(
                    "Usage: train/[stat or skill] <character>=<stat or skill name>"
                )
                return
            caller_msg = (
                "You have provided training to %s for them to increase their %s."
                % (targ.name, self.rhs))
            targ_msg = "%s has provided you training, helping you increase your %s." % (
                caller.name,
                self.rhs,
            )
        if not targ.can_be_trained_by(caller):
            return
        if not self.pay_ap_cost(caller, additional_cost):
            return
        targ.post_training(caller,
                           trainer_msg=caller_msg,
                           targ_msg=targ_msg,
                           ap_spent=additional_cost)
        return
Exemplo n.º 15
0
 def func(self):
     """
     Allows the character to check their xp, and spend it if they use
     the /spend switch and meet the requirements.
     """
     caller = self.caller
     dompc = None
     resource = None
     set_specialization = False
     spec_warning = False
     if self.cmdstring == "learn":
         self.switches.append("spend")
     if not self.args:
         # Just display our xp
         self.display_traits()
         return
     if "transfer" in self.switches:
         self.transfer_xp()
         return
     args = self.args.lower()
     # get cost already factors in if we have a trainer, so no need to check
     if args in Trait.get_valid_stat_names():
         cost = stats_and_skills.get_stat_cost(caller, args)
         current = caller.traits.get_stat_value(args)
         if not caller.traits.check_stat_can_be_raised(args):
             caller.msg("%s is already at its maximum." % args)
             return
         stype = "stat"
     elif args in Trait.get_valid_skill_names():
         current = caller.traits.get_skill_value(args)
         if current >= 6:
             caller.msg("%s is already at its maximum." % args)
             return
         if (current >= 5 and
                 stats_and_skills.get_skill_cost_increase(caller) <= -1.0):
             caller.msg(
                 "You cannot buy a legendary skill while you still have catchup xp remaining."
             )
             return
         cost = stats_and_skills.get_skill_cost(caller, args)
         stype = "skill"
     elif args in stats_and_skills.DOM_SKILLS:
         try:
             dompc = caller.player.Dominion
             current = getattr(dompc, args)
             resource = stats_and_skills.get_dom_resource(args)
             if current >= 10:
                 caller.msg("%s is already at its maximum." % args)
                 return
             cost = stats_and_skills.get_dom_cost(caller, args)
             stype = "dom"
         except AttributeError:
             caller.msg("Dominion object not found.")
             return
     elif args in Trait.get_valid_ability_names():
         # if we don't have it, determine if we can learn it
         current = caller.traits.get_ability_value(args)
         if not current:
             if args in Trait.get_valid_ability_names(Trait.CRAFTING):
                 # check if we have valid skill:
                 if args == "tailor" and "sewing" not in caller.traits.skills:
                     caller.msg("You must have sewing to be a tailor.")
                     return
                 if (args == "weaponsmith" or args == "armorsmith"
                     ) and "smithing" not in caller.traits.skills:
                     caller.msg("You must have smithing to be a %s." % args)
                     return
                 if args == "apothecary" and "alchemy" not in caller.traits.skills:
                     caller.msg(
                         "You must have alchemy to be an apothecary.")
                     return
                 if (args == "leatherworker"
                         and "tanning" not in caller.traits.skills):
                     caller.msg(
                         "You must have tanning to be a leatherworker.")
                     return
                 if (args == "carpenter"
                         and "woodworking" not in caller.traits.skills):
                     caller.msg(
                         "You must have woodworking to be a carpenter.")
                     return
                 if args == "jeweler" and "smithing" not in caller.traits.skills:
                     caller.msg("You must have smithing to be a jeweler.")
                     return
                 spec_warning = True
             elif not caller.check_permstring(args):
                 caller.msg("You do not have permission to learn %s." %
                            args)
                 return
             else:
                 spec_warning = False
         if current >= 6:
             caller.msg("%s is already at its maximum." % args)
             return
         if args in Trait.get_valid_ability_names(Trait.CRAFTING):
             spec_warning = True
         if current == 5:
             if any(key for key, value in caller.traits.abilities.items()
                    if key in Trait.get_valid_ability_names(Trait.CRAFTING)
                    and value >= 6):
                 caller.msg(
                     "You have already chosen a crafting specialization.")
                 return
             else:
                 set_specialization = True
                 spec_warning = False
         stype = "ability"
         cost = stats_and_skills.get_ability_cost(caller, args)
     else:
         caller.msg("'%s' wasn't identified as a stat, ability, or skill." %
                    self.args)
         return
     if "cost" in self.switches:
         caller.msg("Cost for %s: %s" % (self.args, cost))
         return
     if "spend" in self.switches:
         # ap_cost = 5 * (current + 1)
         # if not self.player.pay_action_points(ap_cost):
         #     self.msg("You do not have enough action points to spend xp on that.")
         #     return
         if stype == "dom":
             if cost > getattr(dompc.assets, resource):
                 msg = "Unable to buy influence in %s. The cost is %s, " % (
                     args,
                     cost,
                 )
                 msg += "and you have %s %s resources available." % (
                     getattr(dompc.assets, resource),
                     resource,
                 )
                 caller.msg(msg)
                 return
         elif cost > caller.db.xp:
             caller.msg(
                 "Unable to raise %s. The cost is %s, and you have %s xp." %
                 (args, cost, caller.db.xp))
             return
         if stype == "stat":
             caller.adjust_xp(-cost)
             caller.traits.adjust_stat(args)
             caller.msg("You have increased your %s to %s." %
                        (args, current + 1))
             return
         if stype == "skill":
             caller.adjust_xp(-cost)
             caller.traits.adjust_skill(args)
             skill_history = caller.db.skill_history or {}
             spent_list = skill_history.get(args, [])
             spent_list.append(cost)
             skill_history[args] = spent_list
             caller.db.skill_history = skill_history
             caller.msg("You have increased your %s to %s." %
                        (args, current + 1))
             if current + 1 == 6:  # legendary rating
                 inform_staff("%s has bought a rank 6 of %s." %
                              (caller, args))
             return
         if stype == "ability":
             if set_specialization:
                 caller.msg("You have set your primary ability to be %s." %
                            args)
             if spec_warning:
                 caller.msg(
                     "{wNote: The first crafting ability raised to 6 will be your specialization.{n"
                 )
             caller.adjust_xp(-cost)
             caller.traits.adjust_ability(args)
             ability_history = caller.db.ability_history or {}
             spent_list = ability_history.get(args, [])
             spent_list.append(cost)
             ability_history[args] = spent_list
             caller.db.ability_history = ability_history
             caller.msg("You have increased your %s to %s." %
                        (args, current + 1))
             return
         if stype == "dom":
             # charge them influence
             setattr(dompc.assets, resource,
                     getattr(dompc.assets, resource) - cost)
             caller.traits.adjust_dom(args)
             caller.msg(
                 "You have increased your %s influence for a cost of %s %s resources."
                 % (args, resource, cost))
             caller.refresh_from_db()
             return
         return
     # invalid or no switch + arguments
     caller.msg("Usage: xp/spend <stat, ability or skill>")
Exemplo n.º 16
0
    def get_attr_from_args(self, agent, category="stat"):
        """
        Helper method that returns the attr that the player is buying
        or displays a failure message and returns None.
        """

        if not self.check_categories(category):
            return
        rhs = self.rhs
        if category == "level" and not rhs:
            rhs = agent.type_str
        if not rhs:
            if category == "ability":
                self.msg(
                    "Ability must be one of the following: %s"
                    % ", ".join(agent.buyable_abilities)
                )
                return
            self.msg("You must provide the name of what you want to purchase.")
            return
        attr = rhs.lower()
        if category == "stat":
            stat_names = Trait.get_valid_stat_names()
            if attr not in stat_names:
                self.msg(
                    "When buying a stat, it must be one of the following: %s"
                    % ", ".join(stat_names)
                )
                return
            return attr
        if category == "skill":
            skill_names = Trait.get_valid_skill_names()
            if attr not in skill_names:
                self.msg(
                    "When buying a skill, it must be one of the following: %s"
                    % ", ".join(skill_names)
                )
                return
            return attr
        if category == "ability":
            if attr not in agent.buyable_abilities:
                self.msg(
                    "Ability must be one of the following: %s"
                    % ", ".join(agent.buyable_abilities)
                )
                return
            return attr
        if category == "level":
            if attr not in self.retainer_types:
                self.msg(
                    "The type of level to buy must be one of the following: %s"
                    % ", ".join(self.retainer_types)
                )
                return
            return "%s_level" % attr
        if category == "armor":
            return "armor"
        if category == "weapon":
            try:
                cats = ("weapon_damage", "difficulty_mod")
                attr = self.rhslist[0]
                if attr not in cats:
                    self.msg("Must specify one of the following: %s" % ", ".join(cats))
                    return
            except IndexError:
                self.msg("Must specify a weapon field, and the weapon category.")
                return
            return attr