Example #1
0
 def locks(self):
     return LockHandler(self)
Example #2
0
class CraftingRecipe(CachedPropertiesMixin, SharedMemoryModel):
    """
    For crafting, a recipe has a name, description, then materials. A lot of information
    is saved as a parsable text string in the 'result' text field. It'll
    take a form like: "baseval:0;scaling:1" and so on. baseval is a value
    the object has (for armor, say) for minimum quality level, while
    scaling is the increase per quality level to stats. "slot" and "slot limit"
    are used for wearable objects to denote the slot they're worn in and
    how many other objects may be worn in that slot, respectively.
    """

    name = models.CharField(unique=True, max_length=255)
    desc = models.TextField(blank=True)
    # organizations or players that know this recipe
    known_by = models.ManyToManyField("dominion.AssetOwner",
                                      blank=True,
                                      related_name="crafting_recipes")
    materials = models.ManyToManyField("CraftingMaterialType",
                                       blank=True,
                                       through="RequiredMaterial")
    difficulty = models.PositiveSmallIntegerField(default=0)
    additional_cost = models.PositiveIntegerField(default=0)
    # the ability/profession that is used in creating this
    ability = models.CharField(blank=True, max_length=80, db_index=True)
    skill = models.CharField(blank=True, max_length=80, db_index=True)
    # the type of object we're creating
    type = models.CharField(blank=True, max_length=80, db_index=True)
    # level in ability this recipe corresponds to. 1 through 6, usually
    level = models.PositiveSmallIntegerField(default=1)
    allow_adorn = models.BooleanField(default=True)
    lock_storage = models.TextField("locks",
                                    blank=True,
                                    help_text="defined in setup_utils")
    # values for items created by this recipe
    volume = models.IntegerField(
        default=0, help_text="The size of objects created by this recipe.")
    base_value = models.DecimalField(
        default=0.0,
        help_text="Value the recipe uses in different "
        "calculations for typeclass properties.",
        max_digits=6,
        decimal_places=2,
    )
    scaling = models.DecimalField(
        default=0.0,
        help_text="Adjusts calculated value based on item quality",
        max_digits=6,
        decimal_places=2,
    )
    # values for containers
    displayable = models.BooleanField(default=True,
                                      help_text="Used for furniture types")
    display_by_line = models.BooleanField(
        default=True,
        help_text="If true, display inventory by line for container recipe",
    )
    # values for equipment
    slot = models.CharField(max_length=80,
                            blank=True,
                            help_text="Location where clothing/armor is worn")
    slot_limit = models.PositiveSmallIntegerField(
        default=1, help_text="Max number that can be worn")
    fashion_mult = models.DecimalField(
        null=True,
        blank=True,
        help_text="If defined, multiplier for modeling",
        max_digits=6,
        decimal_places=2,
    )
    armor_penalty = models.DecimalField(
        default=0.0,
        help_text="Value for armor impairing movement",
        max_digits=6,
        decimal_places=2,
    )
    weapon_skill = models.CharField(
        max_length=80,
        blank=True,
        help_text="Weapon skill used for weapons made by this recipe",
    )

    def __init__(self, *args, **kwargs):
        super(CraftingRecipe, self).__init__(*args, **kwargs)
        self.locks = LockHandler(self)

    def access(self, accessing_obj, access_type="learn", default=False):
        """
        Determines if another object has permission to access.
        accessing_obj - object trying to access this one
        access_type - type of access sought
        default - what to return if no lock of access_type was found
        """
        return self.locks.check(accessing_obj,
                                access_type=access_type,
                                default=default)

    def org_owners(self):
        return self.known_by.select_related("organization_owner").filter(
            organization_owner__isnull=False)

    org_owners: Iterable = CachedProperty(org_owners, "_org_owners")

    def can_be_learned_by(self, learner):
        """Returns True if learner can learn this recipe, False otherwise"""
        if not self.access(learner):
            return False
        # if we have no orgs that know this recipe, anyone can learn it normally
        if not self.org_owners:
            return True
        # check if they have granted access from any of the orgs that know it
        return any(
            ob.access(learner, access_type="recipe") for ob in self.org_owners)

    def display_reqs(self, dompc=None, full=False):
        """Returns string display for recipe"""
        msg = ""
        if full:
            msg += "{wName:{n %s\n" % self.name
            msg += "{wDescription:{n %s\n" % self.desc
        msg += "{wSilver:{n %s\n" % self.additional_cost

        material_msgs = []
        for material_requirement in self.required_materials.all():
            mat = material_requirement.type
            req_amt = material_requirement.amount
            mat_msg = f"{mat}: {req_amt}"
            if dompc:
                try:
                    pcmat = dompc.assets.owned_materials.get(type=mat)
                    amt = pcmat.amount
                except OwnedMaterial.DoesNotExist:
                    amt = 0
                mat_msg += f"({amt}/{req_amt})"
            material_msgs.append(mat_msg)
        if material_msgs:
            msg += "{wMaterials:{n %s\n" % ", ".join(material_msgs)
        return msg

    @CachedProperty
    def value(self):
        """Returns total cost of all materials used"""
        val = self.additional_cost
        val += RequiredMaterial.objects.filter(recipe=self).total_value()
        return val

    def __str__(self):
        return self.name

    @property
    def attack_type(self):
        if self.weapon_skill == "archery":
            return "ranged"
        return "melee"

    def create_obj(self, typec, key, loc, home, quality, crafter=None):
        if "{" in key and not key.endswith("{n"):
            key += "{n"
        obj = create.create_object(typeclass=typec,
                                   key=key,
                                   location=loc,
                                   home=home)
        CraftingRecord.objects.create(objectdb=obj,
                                      quality_level=quality,
                                      crafted_by=crafter,
                                      recipe=self)
        # will set color name and strip ansi from colorized name for key
        obj.name = key
        return obj
Example #3
0
 def __init__(self, *args, **kwargs):
     super(CraftingRecipe, self).__init__(*args, **kwargs)
     self.locks = LockHandler(self)
Example #4
0
 def __init__(self, lockstring):
     self.lock_storage = ""
     self.locks = LockHandler(self)
     self.locks.add(lockstring)