class InfernoTower(PulseTower): '''a pulse tower that shoots infernos''' name = "Inferno Tower" colour = 'orange' cool_down_steps = 5 base_cost = 100 level_cost = 80 range = PlusRange(0.5, 1.5) def step(self, units): """Fires pulses""" self.cool_down.step() if not self.cool_down.is_done(): return None target = self.get_unit_in_range(units.enemies) if target is None: return None self.cool_down.start() infernos = [] for direction in Inferno.DIRECTIONS: inferno = Inferno(self.position, int(self.cell_size), direction) inferno.move_by(Point2D(*direction) * (.4 * self.cell_size)) infernos.append(inferno) return infernos
class PulseTower(AbstractTower): """A tower that sends slow moving pulses out that damage all enemies in their path""" name = 'Pulse Tower' colour = '#6183B4' # Glaucous cool_down_steps = 20 base_cost = 60 level_cost = 45 range = PlusRange(0.5, 1.5) def step(self, units): """Fires pulses""" self.cool_down.step() if not self.cool_down.is_done(): return None target = self.get_unit_in_range(units.enemies) if target is None: return None self.cool_down.start() pulses = [] for direction in Pulse.DIRECTIONS: pulse = Pulse(self.position, self.cell_size, direction) pulse.move_by(Point2D(*direction) * (.4 * self.cell_size)) pulses.append(pulse) return pulses
class EnergyTower(AbstractTower): """A tower that sends slow moving energies out that damage all enemies in their path""" name = 'Energy Tower' colour = 'Yellow' cool_down_steps = 5 base_cost = 40 level_cost = 30 range = PlusRange(0.5, 1.5) def __init__(self, cell_size: int, grid_size=(.9, .9), rotation=math.pi * .25, base_damage=90, level: int = 1): super().__init__(cell_size, grid_size=grid_size, rotation=rotation, base_damage=base_damage, level=level) self._target: InvincibleEnemy = None def _get_target(self, units) -> Union[InvincibleEnemy, None]: """Returns previous target, else selects new one if previous is invalid Invalid target is one of: - dead - out-of-range Return: AbstractEnemy: Returns previous target, unless it is non-existent or invalid (see above), Otherwise, selects & returns new target if a valid one can be found, Otherwise, returns None """ if self._target is None \ or self._target.is_dead() \ or not self.is_position_in_range(self._target.position): self._target = self.get_unit_in_range(units) return self._target def step(self, units): """Fires energies""" self.cool_down.step() if not self.cool_down.is_done(): return None target = self.get_unit_in_range(units.enemies) if target is None: return None self.cool_down.start() energies = [] for direction in Energy.DIRECTIONS: energy = Energy(self.position, self.cell_size, direction) energy.move_by(Point2D(*direction) * (0.4 * self.cell_size)) energies.append(energy) return energies