def random_point_surrounding(position): p = Position(libtcod.random_get_int(0, position.x - 1, position.x + 1), libtcod.random_get_int(0, position.y - 1, position.y + 1)) while p.x == position.x and p.y == position.y: p = Position(libtcod.random_get_int(0, position.x - 1, position.x + 1), libtcod.random_get_int(0, position.y - 1, position.y + 1)) return p
def __init__(self, game): self.name = None self.glyph = None self._pos = Position() self.energy = Energy() self.game = game self.hp = 0 self.base_max_hp = 0 self.base_defense = 0 self.base_power = 0 self.xp = 0 self.level = 1 self.inventory = None
def on_target(self, target): self.game.log.elemental( 'The fireball explodes, burning everything within %d tiles!' % self._radius, Elements.FIRE) for actor in self.game.stage.actors: if actor.pos.distance_to(target.pos) <= self._radius: self.game.log.elemental( '{1} gets burned for %d hit points.' % self._damage, Elements.FIRE, actor) actor.take_damage(self, self._damage, self.actor) # Send events for the UI to render the explosion hit_on = [ Tile.TYPE_FLOOR, Tile.TYPE_TALL_GRASS, Tile.TYPE_CRUSHED_GRASS ] for x in range(target.pos.x - self._radius, target.pos.x + self._radius + 1): for y in range(target.pos.y - self._radius, target.pos.y + self._radius + 1): if target.pos.distance(x, y) <= self._radius: if self.game.stage.map.tile_at(x, y).type in hit_on: self.add_event( Event(Event.TYPE_BOLT, element=Elements.FIRE, position=Position(x, y)))
def __init__(self, name, glyph, on_use=None, equip_slot=None): """An Item can be either usable or equipment, but not both. For a usable item, provide a Spell for on_use. For equipment, provide an equip slot string.""" self.name = name self.glyph = glyph self.pos = Position() self.on_use = on_use self.owner = None self.equip_slot = equip_slot self.power_bonus = 0 self.defense_bonus = 0 self.max_hp_bonus = 0 self.is_equipped = False
def handle_mouse_click(self, mouse): if mouse.rbutton_pressed: self.__cancel() return # Assume it's a left-click pos = Position(mouse.cx, mouse.cy) if self._range is not None: distance = self._game_screen.game.player.pos.distance_to(pos) if distance > self._range: self._game_screen.game.log.notify('Out of range. Select again.') return target = Target(position=pos) if self._game_screen.game.stage.map.is_in_fov(pos): monster = self.__monster_at(pos) target.actor = monster self.ui.pop(target)
def random_point_inside(self): return Position(libtcod.random_get_int(0, self.x1 + 1, self.x2 - 1), libtcod.random_get_int(0, self.y1 + 1, self.y2 - 1))
def center(self): return Position((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2)
class Actor(Noun): def __init__(self, game): self.name = None self.glyph = None self._pos = Position() self.energy = Energy() self.game = game self.hp = 0 self.base_max_hp = 0 self.base_defense = 0 self.base_power = 0 self.xp = 0 self.level = 1 self.inventory = None @property def pos(self): return self._pos @pos.setter def pos(self, other): if self._pos != other: self._pos.copy(other) def needs_input(self): return False def speed(self): return NORMAL_SPEED def get_action(self): action = self.on_get_action() if action: action.bind(self, True) return action def on_get_action(self): raise Exception('implement in subclass') def finish_turn(self, action): self.energy.spend() def create_melee_hit(self): hit = self.on_create_melee_hit() self.modify_hit(hit) return hit def on_create_melee_hit(self): raise Exception('implement in subclass') def modify_hit(self, hit): self.on_modify_hit(hit) def on_modify_hit(self, hit): pass @property def power(self): bonus = 0 if self.inventory: equipped = filter(lambda i: i.is_equipped, self.inventory) bonus = sum(equipment.power_bonus for equipment in equipped) return self.base_power + bonus @property def defense(self): bonus = 0 if self.inventory: equipped = filter(lambda i: i.is_equipped, self.inventory) bonus = sum(equipment.defense_bonus for equipment in equipped) return self.base_defense + bonus @property def max_hp(self): bonus = 0 if self.inventory: equipped = filter(lambda i: i.is_equipped, self.inventory) bonus = sum(equipment.max_hp_bonus for equipment in equipped) return self.base_max_hp + bonus def take_damage(self, action, damage, attacker): self.hp -= damage self.on_damaged(action, damage, attacker) if self.hp <= 0: action.add_event(Event(Event.TYPE_DEATH, actor=self, other=attacker)) attacker.on_killed(self) self.on_death(attacker) def on_give_damage(self, action, defender, damage): pass def on_damaged(self, action, damage, attacker): pass def on_death(self, attacker): pass def on_killed(self, defender): pass def heal(self, amount): # Heal by the given amount, without going over the maximum self.hp += amount if self.hp > self.max_hp: self.hp = self.max_hp def is_alive(self): return self.hp > 0 def required_for_level_up(self): return LEVEL_UP_BASE + self.level * LEVEL_UP_FACTOR def can_level_up(self): return self.xp >= self.required_for_level_up() def level_up(self): required = self.required_for_level_up() self.level += 1 self.xp -= required def is_player(self): return self == self.game.player