예제 #1
0
 def tick(self):
     """
     Apply one tick of damage
     :return: None
     """
     # Reset actor states (to clear damage effect from previous ticks
     for previous_target in self.actors:
         self._set_actor_state(previous_target, False)
     if self.effectDuration == 0:
         self.end()
     if self.effectDuration > 0:
         # Reduce the remaining duration with one tick.
         self.effectDuration -= 1
         # Find all targets in range
         self._actors = []
         for tile in self.tiles:
             for actor in tile.actors:
                 self.actors.append(actor)
         # apply damage to every target
         for target in self.actors:
             damage_amount = roll_hit_die(self.effectHitDie)
             message(
                 self.source.name.capitalize() + ' hits ' + target.name +
                 ' for ' + str(damage_amount) + ' Damage.', "GAME")
             target.takeDamage(damage_amount, self.source.owner)
             # Modify actor states
             self._set_actor_state(target, True)
예제 #2
0
 def tryDropItem(self, item):
     """
     Player attempts to drop an item.
     This function is meant to be called from the GUI.
     """
     if isinstance(item, Equipment):
         if item.isEquiped:
             message("You can't drop an equiped item.")
             return
     self.dropItem(item)
예제 #3
0
 def unEquipItem(self, item):
     """
     basic implementation of equiping, doesn't take into account
     equipment slots. Should be overridden in subclass implementations.
     """
     #can only unequip if item is equiped
     if item in self.equipedItems:
         self.equipedItems.remove(item)
         item.isEquiped = False
         message(self.name.capitalize() + ' unequips a ' + item.name + '.',
                 "GAME")
예제 #4
0
 def followPortal(self, portal):
     """
     Send player through specified portal.
     """
     #Game message
     message(portal.message, "GAME")
     #Move the player to the destination
     destinationLevel = portal.destinationPortal.level
     destinationTile = portal.destinationPortal.tile
     self.moveToLevel(destinationLevel, destinationTile)
     #change the current level of the game to the destinationlevel
     myGame = destinationLevel.owner
     myGame.current_level = destinationLevel
예제 #5
0
 def pickUpItem(self, item):
     """
     Make this character pick up an item.
     Arguments
         item - the item to be picked up
     """
     # remove the item from its tile and level
     item.removeFromLevel()
     # add the item to the inventory of this character
     self.addItem(item)
     # message
     message(self.name.capitalize() + ' picks up a ' + item.name + '.',
             "GAME")
예제 #6
0
 def takeHeal(self, amount, healer):
     """
     function to heal a given amount of hitpoints
     arguments
        amount - the number of hitpoints to heal
        healer - the source of teh healing
     """
     # Heal by the given amount
     if amount > 0:
         self.currentHitPoints += amount
         message(
             self.name.capitalize() + ' gains ' + str(amount) +
             ' hitpoints from a ' + healer.name + '.', "GAME")
     game_event(self.__class__.__name__, self.json)
예제 #7
0
 def attack(self, target):
     """
     Attack another Character
     Arguments
         target - the Character to be attacked
     """
     # Check if the attack hits
     hitRoll = roll_hit_die("1d100")
     # In case of an equal accuracy and dodge rating there is a 50% chance to hit
     toHit = 100 - (50 + self.accuracy - target.dodge)
     message(
         self.name.capitalize() + ' attacks ' + target.name + ': ' +
         str(hitRoll) + ' vs ' + str(toHit), "COMBAT")
     if hitRoll < toHit:
         # Miss, no damage
         message(
             self.name.capitalize() + ' attacks ' + target.name +
             ' but misses!', "COMBAT")
     else:
         # Hit, there will be damage, bonusDamage depends on how strongly the hit connects
         bonusDamagePercent = (hitRoll - toHit) / 100.0
         damagePercent = 1 + bonusDamagePercent
         # targets armor neutralizes part of the damage
         damage = int(damagePercent * self.damage) - target.armor
         if damage > 0:
             message(
                 self.name.capitalize() + ' attacks ' + target.name +
                 ' and hits for ' + str(damage) + ' Damage (' +
                 str(damagePercent) + ' damage factor)', "COMBAT")
             target.takeDamage(damage, self)
         else:
             message(
                 self.name.capitalize() + ' attacks ' + target.name +
                 ' and hits but it has no effect.', "COMBAT")
예제 #8
0
 def equipItem(self, item):
     """
     basic implementation of equiping, doesn't take into account
     equipment slots. Should be overridden in subclass implementations.
     """
     #can only equip if item is in inventory
     if item in self.inventory.items:
         #can only equip if not yet equiped
         if item not in self.equipedItems:
             self.equipedItems.append(item)
             item.isEquiped = True
             message(
                 self.name.capitalize() + ' equips a ' + item.name + '.',
                 "GAME")
예제 #9
0
 def applyTo(self, target):
     """
     Confuse effect will be applied to target monster.
     :target: Monster object
     :return: None
     """
     if not isinstance(target, WarrensGame.Actors.Monster):
         raise GameError("Can not apply confuse effect to " + str(target))
     confused_turns = self.effectDuration
     WarrensGame.AI.ConfusedMonsterAI(self, target, confused_turns)
     target.level.active_effects.append(self)
     self.actors.append(target)
     message(
         target.name + ' is confused for ' + str(confused_turns) +
         ' turns.', "GAME")
예제 #10
0
    def levelUp(self):
        """
        Increase level of this player
        """
        message("You feel stronger!", "GAME")
        self.json["playerLevel"] += 1
        self.json[
            "nextLevelXp"] = GAME.XP_BASE + GAME.XP_BASE * GAME.XP_FACTOR * (
                self.playerLevel * self.playerLevel - 1)

        self._baseAccuracy += GAME.PLAYER_LEVEL_ACCURACY
        self._baseDodge += GAME.PLAYER_LEVEL_DODGE
        self._baseDamage += GAME.PLAYER_LEVEL_DAMAGE
        self._baseArmor += GAME.PLAYER_LEVEL_ARMOR
        self._baseBody += GAME.PLAYER_LEVEL_BODY
        self._baseMind += GAME.PLAYER_LEVEL_MIND
예제 #11
0
 def takeDamage(self, amount, attacker):
     """
     Function to take damage from an attacker.
     :param amount: the incoming amount of damage
     :param attacker: the attacking Actor
     :return: None
     """
     if self.state_alive:
         # apply damage if possible
         if amount > 0:
             self.currentHitPoints -= amount
         # check for death
         if self.currentHitPoints <= 0:
             message(self.name.capitalize() + ' is killed!', "COMBAT")
             self._killedBy(attacker)
         game_event(self.__class__.__name__, self.json)
예제 #12
0
 def dropItem(self, item):
     """
     Make this character drop an item on the current tile.
     Arguments
         item - the item to be dropped
     """
     #unequip it if required
     if item in self.equipedItems:
         self.unEquipItem(item)
     #if it is in the inventory remove it
     if item in self.inventory.items:
         self.inventory.remove(item)
     #add it to the current tile of the character
     item.moveToLevel(self.level, self.tile)
     #message
     message(self.name.capitalize() + ' drops a ' + item.name + '.', "GAME")
예제 #13
0
    def take_turn(self):
        """
        Make this AI object take one turn.
        For a confused monster the monster will move in a random direction.
        """
        # Try to move in a random direction
        message(self.character.name + ' stumbles around (confused).', "GAME")
        direction = self.random_direction()
        if direction is not None:
            self.character.moveAlongVector(*direction)

        # Switch back to regular AI if confusedTurns are over
        self.confusedTurns -= 1
        if self.confusedTurns == 0:
            self.character.AI = self.originalAI
            self.character.state_confused = False
            message(self.character.name + ' is no longer confused.', "GAME")
예제 #14
0
 def _killedBy(self, attacker):
     """
     This function handles the death of this Character
     """
     if self.state_alive:
         if type(attacker) is Player:
             # Yield experience to the player
             message(attacker.name + ' gains ' + str(self.xpValue) + ' XP.',
                     "GAME")
             attacker.gainXp(self.xpValue)
         if type(attacker) is Monster:
             if attacker.killedByText != '':
                 message(attacker.killedByText, "GAME")
         # Transform this character into a corpse and remove AI
         self.char = '%'
         self.sprite_id = SPRITES.MONSTER_RIP
         self.sprite_overlay_id = None
         self._AI = None
         self.name += " corpse"
         self.json["state_alive"] = False
예제 #15
0
    def take_turn(self):
        """
        Take one turn
        """
        message(
            self.character.name + ' at ' + str(self.character.tile) +
            ' takes turn.', "AI")
        # Only take action if we are in a level
        if self.character.level is None:
            message("   Not in a level, can't take action.", "AI")
            return
        # Only take action if we find a player on our level
        if not self.character.level.player_present:
            message("   No player found on level, staying put", "AI")
            return

        for player in self.character.level.players:
            # Only take action if player is not dead.
            if not player.state_alive:
                message("   Player is dead, no action needed", "AI")
                return
            else:
                # TODO medium: read this from the config file via monsterlibrary
                range_of_sight = 8
                range_of_attack = 2
                distance = distance_between_actors(self.character, player)
                # Only take action if player is within range of sight
                if distance > range_of_sight:
                    message("   Player is out of sight, no action needed",
                            "AI")
                    return
                # Attack if player is within range of attack
                elif distance < range_of_attack:
                    message("   Attacking player", "AI")
                    self.character.attack(player)
                    return
                else:
                    message("   Moving towards player", "AI")
                    self.character.moveTowards(player)
                    return