예제 #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
예제 #2
0
def ability(accessing_obj, accessed_obj, *args, **kwargs):
    """
    Check accessing_obj's rank in an ability to determine lock.
    Usage:
        ability(value)
        ability(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.ability
        val = int(args[0])
    else:
        name = args[0]
        val = int(args[1])
    if name == "all":
        from world.traits.models import Trait

        ability_list = Trait.get_valid_ability_names(Trait.CRAFTING)
    else:
        ability_list = name.split(",")
    for ability_name in ability_list:
        ability_name = ability_name.lower().strip()
        try:
            pab = accessing_obj.traits.get_ability_value(ability_name)
        except AttributeError:
            return False
        if pab >= val:
            return True
    return False
예제 #3
0
def get_ability_cost(caller,
                     ability,
                     adjust_value=None,
                     check_teacher=True,
                     unmodified=False):
    """Uses cost at rank and factors in teacher discounts if they are allowed."""
    from world.traits.models import Trait

    current_rating = caller.traits.get_ability_value(ability)
    if not adjust_value and adjust_value != 0:
        adjust_value = 1
    new_rating = current_rating + adjust_value
    cost = cost_at_rank(ability, current_rating, new_rating)
    crafting_abilities = Trait.get_valid_ability_names(Trait.CRAFTING)
    if ability in crafting_abilities:
        cost /= 2
    if cost < 0:
        return cost
    if unmodified:
        return cost
    # abilities are more expensive the more we have in the same category
    if ability in crafting_abilities:
        for c_ability in crafting_abilities:
            cost += caller.traits.get_ability_value(c_ability)
    # check what discount would be
    if check_teacher:
        if caller.traits.check_training(ability, stype="ability"):
            cost = discounted_cost(caller, cost)
    return cost
예제 #4
0
 def adjust_ability(self, field, value=1):
     if field not in Trait.get_valid_ability_names():
         raise Exception(
             "Error in adjust_ability: %s not found as a valid ability." %
             field)
     current = self.get_ability_value(field)
     self.set_ability_value(field, current + value)
     self.character.db.trainer = None
예제 #5
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))
예제 #6
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
예제 #7
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>")