示例#1
0
文件: models.py 项目: cirion/skal
    def odds_against(self, battle):
        sword_strength = 0
        bow_strength = 0
        bashing_strength = 0
        if self.sword:
            sword_strength = self.stat_bonus(Stat.objects.get(name="Swordfighting"))
            if CharacterStat.objects.filter(character=self, stat__name="Swordfighting"):
                sword_strength += level_from_value(
                    CharacterStat.objects.get(character=self, stat__name="Swordfighting").value
                )
        if self.bow:
            bow_strength = self.stat_bonus(Stat.objects.get(name="Archery"))

            if CharacterStat.objects.filter(character=self, stat__name="Archery"):
                bow_strength += level_from_value(CharacterStat.objects.get(character=self, stat__name="Archery").value)
                # Unlike bows and swords, we can use bashing even without an item equipped.
        if self.bashing:
            bashing_strength += self.bashing.amount
        if CharacterStat.objects.filter(character=self, stat__name="Bashing"):
            bashing_strength += level_from_value(CharacterStat.objects.get(character=self, stat__name="Bashing").value)
        if battle.enemy == Battle.ENEMY_RANGED:
            sword_strength = sword_strength - (5 + 0.1 * sword_strength)
            bashing_strength = bashing_strength + (5 + 0.1 * bashing_strength)
        elif battle.enemy == Battle.ENEMY_BASHING:
            sword_strength = sword_strength + (5 + 0.1 * sword_strength)
            bow_strength = bow_strength - (5 + 0.1 * bow_strength)
        else:
            bow_strength = bow_strength + (5 + 0.1 * bow_strength)
            bashing_strength = bashing_strength - (5 + 0.1 * bashing_strength)
        best_strength = 0
        weapon = None
        if bow_strength >= sword_strength and bow_strength >= bashing_strength:
            best_strength = bow_strength
            weapon = self.bow
        elif sword_strength >= bow_strength and sword_strength >= bashing_strength:
            best_strength = bow_strength
            weapon = self.sword
        else:
            best_strength = bashing_strength
            weapon = self.bashing
            # Phew! Now, calculate the delta!
        odds = 0.5 + 0.05 * (best_strength - battle.strength)
        # Can play around with this, but I think there's always a 5% chance of success or failure. (Nice D20 odds.)
        if odds < 0.05:
            odds = 0.05
        elif odds > 0.95:
            odds = 0.95
        return {"odds": odds, "weapon": weapon}
示例#2
0
文件: models.py 项目: cirion/skal
def valid_for_stat_pre_reqs(character, pre_reqs, enforceMax):
    if pre_reqs:
        try:
            for pre_req in pre_reqs:
                if pre_req.minimum > 0:
                    character_stat = CharacterStat.objects.get(character=character.pk, stat=pre_req.stat)
                    level = level_from_value(character_stat.value)
                    level += character.stat_bonus(character_stat.stat)
                    # print "For stat " + character_stat.stat.name + " comparing " + str(level) + ":" + str(level_from_value(level)) + " to " + str(pre_req.minimum)
                    if level < pre_req.minimum:
                        return False
                    elif enforceMax and level_from_value(character_stat.value) > pre_req.maximum:
                        return False
        except CharacterStat.DoesNotExist:
            return False
    return True
示例#3
0
文件: models.py 项目: cirion/skal
 def max_health(self):
     amount = 0
     stats = CharacterStat.objects.filter(character=self, stat__type=Stat.TYPE_SKILL).order_by("-value")
     if stats:
         best_stat = stats[0]
         amount = level_from_value(best_stat.value)
     if amount < 10:
         amount = 10
     return amount
示例#4
0
文件: views.py 项目: cirion/skal
def character(request):
	current_character = Character.objects.get(player=request.user.id)
	titles = CharacterTitle.objects.filter(character = current_character)
	skills = CharacterStat.objects.filter(character = current_character, stat__type= Stat.TYPE_SKILL, value__gte = 10)
	for skill in skills:
		skill.value = level_from_value(skill.value) + current_character.stat_bonus(skill.stat)
	plots = CharacterPlot.objects.filter(character = current_character, plot__visible = True, plot__achievement = False )
	plot_descriptions = list()
	for plot in plots:
		#print "Looking at " + plot.__unicode__() + "  " + str(plot.pk) + " value = " + str(plot.value)
		#for arg in PlotDescription.objects.filter(plot = plot.plot.pk):
		#	print "Candidate " + " " + str(arg.pk) + ":" + arg.__unicode__() + ": " + str(arg.value)
		if PlotDescription.objects.filter(plot = plot.plot.pk, value = plot.value):
			#print "Got a match."
			plot_descriptions.append(PlotDescription.objects.get(plot=plot.plot, value=plot.value))
	achievements = list(CharacterPlot.objects.filter(character = current_character, plot__achievement = True))
	achievements.reverse()
	items = CharacterItem.objects.filter(character = current_character, quantity__gt = 0)
	fame = 0
	if CharacterStat.objects.filter(character = current_character, stat__type= Stat.TYPE_FAME):
		fame = level_from_value(CharacterStat.objects.filter(character = current_character, stat__type= Stat.TYPE_FAME)[0].value)
	esteems = CharacterStat.objects.filter(character = current_character, stat__type = Stat.TYPE_ESTEEM)
	for esteem in esteems:
		esteem.value = level_from_value(esteem.value)
	if current_character.gender == Character.GENDER_MALE:
		title = "Mr."
	else:
		title = "Ms."
	swords = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_SWORD)
	bashing = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_BASHING)
	bows = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_BOW)
	feet = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_FEET)
	cloaks = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_CLOAK)
	clothes = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_CLOTHES)
	gloves = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_GLOVES)
	rings = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_RING)
	neck = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_NECK)
	armors = CharacterItem.objects.filter(character = current_character, item__equipment__type = Equipment.TYPE_ARMOR)
	return render_to_response('lok/character.html', {'character': current_character, 'skills': skills, 'fame': fame, 'items': items, 'plots': plot_descriptions, 'achievements': achievements, 'title': title, 'swords': swords, 'bashing': bashing, 'bows': bows, 'feet': feet, 'cloaks': cloaks, 'clothes': clothes, 'gloves': gloves, 'rings': rings, 'neck': neck, 'armors': armors, 'esteems': esteems, 'titles': titles})
示例#5
0
文件: models.py 项目: cirion/skal
    def update_with_result(self, result, pre_reqs, battle, block_death):
        changes = list()
        if self.actions == Character.MAX_ACTIONS:
            self.refill_time = datetime.utcnow().replace(tzinfo=utc) + timedelta(0, self.recharge_delay_secs)
        self.actions = self.actions - 1

        if battle:
            # Increment the appropriate weapon skills. Always get 2pts in current weapon if it's a challenge, 1pt if it's easy (or someone else is fighting for us)
            odds = self.party.odds_against(battle)
            if odds["odds"] > 1 or odds["character"] != self:
                amount = 1
            else:
                amount = 2
            if odds["weapon"] == self.sword:
                stat = Stat.objects.get(name="Swordfighting")
            elif odds["weapon"] == self.bow:
                stat = Stat.objects.get(name="Archery")
            else:
                stat = Stat.objects.get(name="Bashing")
            if not CharacterStat.objects.filter(character=self, stat=stat):
                charstat = CharacterStat(character=self, stat=stat, value=0)
            else:
                charstat = CharacterStat.objects.get(character=self, stat=stat)
            change = Change(type=Change.TYPE_INCREMENT)
            change.name = stat.name
            change.old = charstat.value
            change.amount = amount
            charstat.value += amount
            change.new = charstat.value
            charstat.save()
            changes.append(change)

        stat_outcomes = StatOutcome.objects.filter(choice=result.pk)
        for outcome in stat_outcomes:
            stat, created = CharacterStat.objects.get_or_create(character=self, stat=outcome.stat)
            if level_from_value(stat.value) < outcome.maximum:
                change = Change(type=Change.TYPE_INCREMENT)
                change.old = stat.value
                oldlevel = level_from_value(stat.value)
                oldvalue = stat.value
                change.name = stat.stat.name
                # If we succeeded using a maxed stat, it can only increase by 1 point.
                if pre_reqs.filter(stat=outcome.stat) and pre_reqs.get(stat=outcome.stat).maximum <= oldlevel:
                    stat.value += 1
                else:
                    stat.value += outcome.amount
                if stat.value < 0:
                    stat.value = 0
                change.amount = stat.value - oldvalue
                newlevel = level_from_value(stat.value)
                stat.save()
                if oldlevel != newlevel:
                    change.type = Change.TYPE_LEVEL
                    change.old = oldlevel
                    change.new = newlevel
                    change.amount = newlevel - oldlevel
                    # ... and give them a free health point if they can use it. Note that we [currently] don't refill all health.
                    if self.current_health < self.max_health():
                        self.current_health += 1
                        self.save()
                else:
                    change.old = value_from_level(oldlevel + 1) - stat.value
                    change.new = oldlevel + 1
                changes.append(change)

        money_outcomes = MoneyOutcome.objects.filter(choice=result.pk)
        for outcome in money_outcomes:
            share = outcome.amount
            if battle and self.party.size() > 1:
                # Divide money among the team.
                share = (int)((outcome.amount * 1.25) / self.party.size())
                for player in self.party.members():
                    if player != self:
                        player.money += share
                        player.save()
                        notice = SocialMessage(
                            to_character=player,
                            description="You received "
                            + str(share)
                            + " royals from "
                            + self.title_name()
                            + "'s battle with "
                            + battle.title
                            + ".",
                        )
                        notice.save()
            change = Change(type=Change.TYPE_MONEY)
            change.old = self.money
            self.money += share
            if outcome.amount == 1:
                change.name = "royal"
            else:
                change.name = "royals"
                # If we hit this test, we probably accidentally made the result amount bigger than the choice amount.
            if self.money < 0:
                self.money = 0
            change.new = self.money
            change.amount = change.new - change.old
            changes.append(change)

        item_outcomes = ItemOutcome.objects.filter(result=result.pk)
        for outcome in item_outcomes:
            change = Change(type=Change.TYPE_ITEM)
            change.name = outcome.item.name
            item, created = CharacterItem.objects.get_or_create(character=self, item=outcome.item)
            change.old = item.quantity
            item.quantity += outcome.amount
            if item.quantity < 0:
                item.quantity = 0
            change.new = item.quantity
            change.amount = change.new - change.old
            item.save()
            changes.append(change)

        health_outcomes = HealthOutcome.objects.filter(result=result.pk)
        for outcome in health_outcomes:
            change = Change(type=Change.TYPE_HEALTH)
            change.name = "health"
            change.old = self.current_health

            # If this was a fight, we have two chances to mitigate damage done. First dodge, then absorb.
            if battle:
                dodge_chance = self.stat_bonus(Stat.objects.get(name="Dodging"))
                if CharacterStat.objects.filter(character=self, stat__name="Dodging"):
                    dodge_chance += level_from_value(
                        CharacterStat.objects.get(character=self, stat__name="Dodging").value
                    )
                    # Hard cap at 80% dodge rate. Should probably eventually turn this to a soft cap that kicks in much earlier. We also check on stat increase, but need to keep a check here as well to prevent someone reaching 100% through use of equipment.
                if dodge_chance > 80:
                    dodge_chance = 80
                if random.random() * 100 < dodge_chance:
                    # They dodged it! No damage done. Let them know how lucky they are.
                    changes.append(Change(type=Change.TYPE_DODGE))
                    outcome.amount = 0

                    # Next, let them absorb the blow if they have armor.
                armor_rating = self.stat_bonus(Stat.objects.get(name="Armor"))
                if armor_rating > 40:
                    armor_rating = 40
                old_outcome = outcome.amount
                outcome.amount = int(outcome.amount * (1.0 - float(armor_rating) * 2))
                if old_outcome != outcome.amount:
                    changes.append(Change(type=Change.TYPE_ABSORBED, amount=old_outcome - outcome.amount))

                    # See if they lucked out and gained an increase in dodge rating.
                if dodge_chance < self.level():
                    # Definitely play around with this! Right now I'm thinking the odds of a dodge increase will range between 1-5%, depending on the ratio between the character's stealth, deviousness and their level.
                    max_dodgy = 0
                    if CharacterStat.objects.filter(character=self, stat__name="Deviousness"):
                        max_dodgy = level_from_value(
                            CharacterStat.objects.get(character=self, stat__name="Deviousness").value
                        )
                    if CharacterStat.objects.filter(character=self, stat__name="Stealth"):
                        stealthy = level_from_value(
                            CharacterStat.objects.get(character=self, stat__name="Stealth").value
                        )
                        if stealthy > max_dodgy:
                            max_dodgy = stealthy
                    odds = 0.01 + (0.04 * (max_dodgy / self.level()))
                    if random.random() < odds:
                        # Congrats! You just got better at dodging!
                        dodgechange = Change(type=Change.TYPE_INCREMENT)
                        dodgechange.name = "Dodging"
                        if not CharacterStat.objects.filter(character=self, stat__name="Dodging"):
                            dodgechange.old = 0
                            stat = CharacterStat(character=self, stat=Stat.objects.get(name="Dodging"), value=10)
                            stat.save()
                        else:
                            stat = CharacterStat.objects.get(character=self, stat__name="Dodging")
                            dodgechange.old = stat.value
                            stat.value += 10
                            stat.save()
                        dodgechange.amount = 10
                        dodgechange.new = stat.value
                        changes.append(dodgechange)

            self.current_health += outcome.amount
            if self.current_health < 1 and block_death:
                self.current_health = 1
            elif self.current_health < 0:
                self.current_health = 0
            elif self.current_health > self.max_health():
                self.current_health = self.max_health()
            if self.current_health != change.old:
                change.new = self.current_health
                change.amount = change.new - change.old
                changes.append(change)

        plot_outcomes = PlotOutcome.objects.filter(result=result.pk)
        for outcome in plot_outcomes:
            change = Change(type=Change.TYPE_PLOT)
            change.name = outcome.plot.description
            plot, created = CharacterPlot.objects.get_or_create(character=self, plot=outcome.plot)
            change.new = outcome.value
            plot.value = outcome.value
            plot.save()
            if plot.plot.achievement:
                changes.append(change)

        location_learn_outcomes = LearnLocationOutcome.objects.filter(choice=result.pk)
        for outcome in location_learn_outcomes:
            change = Change(type=Change.TYPE_LOCATION_LEARNED)
            change.name = outcome.location.name
            location, created = CharacterLocationAvailable.objects.get_or_create(
                character=self, location=outcome.location
            )
            location.save()
            changes.append(change)

        title_outcomes = TitleOutcome.objects.filter(result=result.pk)
        for title_outcome in title_outcomes:
            change = Change(type=Change.TYPE_TITLE)
            change.name = macro(title_outcome.title.title(self), self)
            title, created = CharacterTitle.objects.get_or_create(character=self, title=title_outcome.title)
            title.save()
            changes.append(change)

        if SetLocationOutcome.objects.filter(choice=result.pk):
            outcome = SetLocationOutcome.objects.get(choice=result.pk)
            change = Change(type=Change.TYPE_LOCATION_CHANGED)
            change.name = outcome.location.name
            self.location = outcome.location
            changes.append(change)

        self.total_choices = self.total_choices + 1
        self.save()
        return changes
示例#6
0
文件: models.py 项目: cirion/skal
 def level(self):
     best_stat = CharacterStat.objects.filter(character=self, stat__type=Stat.TYPE_SKILL).order_by("-value")[0]
     return level_from_value(best_stat.value)
示例#7
0
文件: models.py 项目: cirion/skal
 def level(self):
     return level_from_value(self.value)