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
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
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
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
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))
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
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>")