Exemplo n.º 1
0
 def can_use(self, target=None, **kwargs):
     if not super(RepairAbility, self).can_use(target, **kwargs):
         return False
     
     if vectors.distance(self.actor.pos, target.pos) > self.max_range:
         return False
     
     if self.min_range > 0:
         if vectors.distance(self.actor.pos, target.pos) < self.min_range:
             return False
     
     if self.actor.team != target.team:
         return False
     
     # Is the ally still under construction?
     if target.completion < 100:
         return False
     
     # Is the ally hurt?
     if target.hp >= target.max_hp:
         return False
     
     # Finally, can we afford it?
     cost = teams.multiply_cost(target._part_repair_cost, self.repair_rate)
     if not self.actor.team_obj.can_afford(cost):
         return False
     
     return True
Exemplo n.º 2
0
    def can_use(self, target=None, **kwargs):
        if not super(RepairAbility, self).can_use(target, **kwargs):
            return False

        if vectors.distance(self.actor.pos, target.pos) > self.max_range:
            return False

        if self.min_range > 0:
            if vectors.distance(self.actor.pos, target.pos) < self.min_range:
                return False

        if self.actor.team != target.team:
            return False

        # Is the ally still under construction?
        if target.completion < 100:
            return False

        # Is the ally hurt?
        if target.hp >= target.max_hp:
            return False

        # Finally, can we afford it?
        cost = teams.multiply_cost(target._part_repair_cost, self.repair_rate)
        if not self.actor.team_obj.can_afford(cost):
            return False

        return True
Exemplo n.º 3
0
    def run_ai(self):
        if self.micro_orders == []:
            cmd, pos, target = self.current_order
        else:
            cmd, pos, target = self.micro_orders[0]

        self._passive_ai()
        self._attack_ai()
        self._help_ai()

        if cmd == "stop" or cmd == "hold position":
            self.velocity = [0, 0, 0]

            if target == 0:
                self.next_order()

        elif cmd == "move":
            self._move_ai(pos)

            if vectors.distance(self.pos, pos) <= vectors.total_velocity(self.velocity):
                self.pos = pos
                self.velocity = [0, 0, 0]
                self.next_order()

        elif cmd == "attack":
            target = self.get_first_target()

            # If we have a target, lets move closer to it
            if target != None:
                # First, are we within optimum range of our target?
                # If not then we need to get closer
                target_distance = vectors.distance(self.pos, target.pos)
                if target_distance > self.optimum_attack_range:
                    attack_pos = vectors.get_midpoint(self.pos, target.pos, self.optimum_attack_range)
                    self._move_ai(attack_pos)
                else:
                    # If we are close enough then we can slow down
                    self._decelerate_ai()

        elif cmd == "aid":
            if target == None:
                target = self.get_first_ally()

            # If we have a target, lets move closer to it
            if target != None:
                dist = vectors.distance(self.pos, target.pos)

                if dist > self.optimum_heal_range:
                    target_pos = vectors.get_midpoint(self.pos, target.pos, self.optimum_heal_range)
                    self._move_ai(target_pos)
                else:
                    self._decelerate_ai()

        else:
            raise Exception("No handler for cmd %s (pos: %s, target: %s)" % (cmd, pos, target))

        # Do we have something to build?
        if self.build_queue != []:
            pass
Exemplo n.º 4
0
 def explode(self, actors):
     for a in actors:
         if vectors.distance(self.pos, a.pos) <= self.blast_radius:
             actor_lib.apply_damage(a, dissipate(
                 self.damage, vectors.distance(self.pos, a.pos),
                 self.blast_radius, self.dissipation_func)
             )
     return self.generate_effect()
Exemplo n.º 5
0
 def __init__(self, actor, ability_data={}):
     super(Ability, self).__init__()
     self.actor = actor
     self.facing = [0,0]
     
     self.set_stats(ability_data)
     self.charge = self.required_charge
     
     self._effect_offset_distance = vectors.distance(self.effect_offset)
     self._effect_offset_angle = vectors.angle(self.effect_offset)
     
     self._img_offset_distance = vectors.distance(self.image_offset)
     self._img_offset_angle = vectors.angle(self.image_offset)
Exemplo n.º 6
0
    def __init__(self, actor, ability_data={}):
        super(Ability, self).__init__()
        self.actor = actor
        self.facing = [0, 0]

        self.set_stats(ability_data)
        self.charge = self.required_charge

        self._effect_offset_distance = vectors.distance(self.effect_offset)
        self._effect_offset_angle = vectors.angle(self.effect_offset)

        self._img_offset_distance = vectors.distance(self.image_offset)
        self._img_offset_angle = vectors.angle(self.image_offset)
Exemplo n.º 7
0
 def can_use(self, target=None, **kwargs):
     """Called to see if the ability can be used"""
     if self.charge < self.required_charge:
         return False
     
     if vectors.distance(self.actor.pos, target.pos) > self.max_range:
         return False
     
     if self.min_range > 0:
         if vectors.distance(self.actor.pos, target.pos) < self.min_range:
             return False
     
     return True
Exemplo n.º 8
0
    def can_use(self, target=None, **kwargs):
        if not super(WeaponAbility, self).can_use(target, **kwargs):
            return False

        if vectors.distance(self.actor.pos, target.pos) > self.max_range:
            return False

        if self.min_range > 0:
            if vectors.distance(self.actor.pos, target.pos) < self.min_range:
                return False

        if self.actor.team == target.team:
            return False

        return True
Exemplo n.º 9
0
 def can_use(self, target=None, **kwargs):
     if not super(WeaponAbility, self).can_use(target, **kwargs):
         return False
     
     if vectors.distance(self.actor.pos, target.pos) > self.max_range:
         return False
     
     if self.min_range > 0:
         if vectors.distance(self.actor.pos, target.pos) < self.min_range:
             return False
     
     if self.actor.team == target.team:
         return False
     
     return True
Exemplo n.º 10
0
    def _accelerate_ai(self, target):
        dist = vectors.distance(self.pos, target)

        if dist > self.max_velocity:
            self.velocity = vectors.move_to_vector(vectors.angle(self.pos, target), self.max_velocity)
        else:
            self.velocity = vectors.move_to_vector(vectors.angle(self.pos, target), dist)
Exemplo n.º 11
0
 def generate_bullet(self, target):
     # Set correct origin
     offset_angle = vectors.bound_angle(
         vectors.add_vectors(self._effect_offset_angle, self.facing)
     )
     
     origin_pos = vectors.add_vectors(self.get_offset_pos(use_effect_offset=True), self.actor.pos)
     
     # Get actual velocity we'll be using
     if type(target) == list or type(target) == tuple:
         direction = vectors.angle(origin_pos, target)
         target_pos = target
     else:
         direction = vectors.angle(origin_pos, target.pos)
         target_pos = target.pos
     
     velocity = vectors.move_to_vector(direction, self.bullet['velocity'])
     velocity[2] = math_lib.calc_trajectory(0.1, vectors.distance(origin_pos, target_pos), self.bullet['velocity'])
     
     the_bullet = bullets.Shell(
         pos=origin_pos,
         velocity=velocity,
         image = self.bullet['image'],
         size = self.bullet['size'],
         blast_radius = self.bullet['blast_radius'],
         damage = self.bullet['damage'],
         dissipation_func = self.bullet.get('dissipation_func', "linear"),
     )
     self.actor.bullets.append(the_bullet)
Exemplo n.º 12
0
    def generate_bullet(self, target):
        # Set correct origin
        offset_angle = vectors.bound_angle(
            vectors.add_vectors(self._effect_offset_angle, self.facing))

        origin_pos = vectors.add_vectors(
            self.get_offset_pos(use_effect_offset=True), self.actor.pos)

        # Get actual velocity we'll be using
        if type(target) == list or type(target) == tuple:
            direction = vectors.angle(origin_pos, target)
            target_pos = target
        else:
            direction = vectors.angle(origin_pos, target.pos)
            target_pos = target.pos

        velocity = vectors.move_to_vector(direction, self.bullet['velocity'])
        velocity[2] = math_lib.calc_trajectory(
            0.1, vectors.distance(origin_pos, target_pos),
            self.bullet['velocity'])

        the_bullet = bullets.Shell(
            pos=origin_pos,
            velocity=velocity,
            image=self.bullet['image'],
            size=self.bullet['size'],
            blast_radius=self.bullet['blast_radius'],
            damage=self.bullet['damage'],
            dissipation_func=self.bullet.get('dissipation_func', "linear"),
        )
        self.actor.bullets.append(the_bullet)
Exemplo n.º 13
0
 def run_ai(self):
     if self.micro_orders == []:
         cmd, pos, target = self.current_order
     else:
         cmd, pos, target = self.micro_orders[0]
     
     self._attack_ai()
     
     if cmd == "stop" or cmd == "hold position":
         self.velocity = [0,0,0]
         
         if target == 0:
             self.next_order()
     
     elif cmd == "move" or cmd == "reverse":
         dist = vectors.distance(self.pos, pos)
         self.velocity = vectors.move_to_vector(vectors.angle(self.pos, pos), self.max_velocity)
         
         if dist <= vectors.total_velocity(self.velocity):
             self.pos = pos
             self.velocity = [0,0,0]
             self.next_order()
         
     else:
         raise Exception("No handler for cmd %s (pos: %s, target: %s)" % (cmd, pos, target))
Exemplo n.º 14
0
 def __init__(self, filepath, columns=1, rows=1, animation_rate = 0.5, rotate_about=None):
     super(Animation, self).__init__()
     
     if columns < 1:
         raise Exception("Cannot have fewer than 1 column in an animation")
     
     if rows < 1:
         raise Exception("Cannot have fewer than 1 row in an animation")
     
     self.images = []
     self.animation_rate = animation_rate
     
     img = pygame.image.load(filepath)
     r = img.get_rect()
     
     # Break it down into tiles, save the tiles
     tile_width = r.width / columns
     tile_height = r.height / rows
     
     for y in range(rows):
         for x in range(columns):
             tile = pygame.Surface((tile_width, tile_height), SRCALPHA)
             tile.blit(img, (0,0), (x * tile_width, y * tile_height, tile_width, tile_height))
             
             self.images.append(tile)
     
     # Default the rotate about point
     if rotate_about == None:
         rotate_about = 0, 0, 0
     
     # centre_offset is a distance and angle
     self.centre_offset = (
         vectors.distance(rotate_about),
         vectors.angle(rotate_about),
     )
Exemplo n.º 15
0
 def update_actor(self, the_actor):
     the_actor.enemy_targets = []
     
     for a in self.enemy_actors:
         dist = vectors.distance(a.pos, the_actor.pos)
         
         if dist <= the_actor.max_attack_range:
             the_actor.enemy_targets.append(a)
Exemplo n.º 16
0
    def update_actor(self, the_actor):
        the_actor.enemy_targets = []

        for a in self.enemy_actors:
            dist = vectors.distance(a.pos, the_actor.pos)

            if dist <= the_actor.max_attack_range:
                the_actor.enemy_targets.append(a)
Exemplo n.º 17
0
    def _accelerate_ai(self, target):
        dist = vectors.distance(self.pos, target)

        if dist > self.max_velocity:
            self.velocity = vectors.move_to_vector(
                vectors.angle(self.pos, target), self.max_velocity)
        else:
            self.velocity = vectors.move_to_vector(
                vectors.angle(self.pos, target), dist)
Exemplo n.º 18
0
    def test_distance(self):
        vals = (
            # 2D
            ([0, 0], [0, 0], 0),
            ([1, 1], [0, 0], 1.41),
            ([3, 4], [0, 0], 5),
            ([3, 0], [0, 0], 3),

            # 3D
            ([0, 0, 0], [0, 0, 0], 0),
            ([1, 1, 1], [0, 0, 0], 1.73),
            ([3, 4, 0], [0, 0, 0], 5),
            ([3, 0, 4], [0, 0, 0], 5),
        )

        for a, b, expected in vals:
            self.assertAlmostEqual(vectors.distance(a, b), expected, places=2)
Exemplo n.º 19
0
 def test_distance(self):
     vals = (
         # 2D
         ([0,0], [0,0], 0),
         ([1,1], [0,0], 1.41),
         ([3,4], [0,0], 5),
         ([3,0], [0,0], 3),
         
         # 3D
         ([0,0,0], [0,0,0], 0),
         ([1,1,1], [0,0,0], 1.73),
         ([3,4,0], [0,0,0], 5),
         ([3,0,4], [0,0,0], 5),
     )
     
     for a, b, expected in vals:
         self.assertAlmostEqual(vectors.distance(a, b), expected, places=2)
Exemplo n.º 20
0
    def __init__(self,
                 filepath,
                 columns=1,
                 rows=1,
                 animation_rate=0.5,
                 rotate_about=None):
        super(Animation, self).__init__()

        if columns < 1:
            raise Exception("Cannot have fewer than 1 column in an animation")

        if rows < 1:
            raise Exception("Cannot have fewer than 1 row in an animation")

        self.images = []
        self.animation_rate = animation_rate

        img = pygame.image.load(filepath)
        r = img.get_rect()

        # Break it down into tiles, save the tiles
        tile_width = r.width / columns
        tile_height = r.height / rows

        for y in range(rows):
            for x in range(columns):
                tile = pygame.Surface((tile_width, tile_height), SRCALPHA)
                tile.blit(
                    img, (0, 0),
                    (x * tile_width, y * tile_height, tile_width, tile_height))

                self.images.append(tile)

        # Default the rotate about point
        if rotate_about == None:
            rotate_about = 0, 0, 0

        # centre_offset is a distance and angle
        self.centre_offset = (
            vectors.distance(rotate_about),
            vectors.angle(rotate_about),
        )
Exemplo n.º 21
0
 def generate_bullet(self, target):
     if type(target) == list or type(target) == tuple:
         direction = vectors.angle(self.actor.pos, target)
         target_pos = target
     else:
         direction = vectors.angle(self.actor.pos, target.pos)
         target_pos = target.pos
     
     velocity = vectors.move_to_vector(direction, self.bullet['velocity'])
     velocity[2] = math_lib.calc_trajectory(0.1, vectors.distance(self.actor.pos, target_pos), self.bullet['velocity'])
     
     the_bullet = bullets.Shell(
         pos=self.actor.pos,
         velocity=velocity,
         image = self.bullet['image'],
         size = self.bullet['size'],
         blast_radius = self.bullet['blast_radius'],
         damage = self.bullet['damage'],
         dissipation_func = self.bullet.get('dissipation_func', "linear"),
     )
     self.actor.bullets.append(the_bullet)
Exemplo n.º 22
0
 def inspect_bases(self):
     # First find out which buildings we are missing
     for base_name, base_data in self.bases.items():
         base_area = (
             base_data['location'][0] - base_data['size'][0],
             base_data['location'][1] - base_data['size'][1],
             
             base_data['location'][0] + base_data['size'][0],
             base_data['location'][1] + base_data['size'][1],
         )
         
         buildings_needed = set(base_data['buildings'])
         
         # Reset this now
         base_data['current_buildings'] = []
         
         # Get all buildings within this base
         found_buildings = {}
         total_needed = {}
         for b in buildings_needed:
             found_buildings[b] = 0
             total_needed[b] = 0
         
         for b in base_data['buildings']:
             total_needed[b] += 1
         
         # Loop through all actors and see what we've got
         for i, a in self.own_actors.items():
             if actor_lib.is_inside(a, base_area):
                 if a.actor_type in buildings_needed:
                     found_buildings[a.actor_type] += 1
                     
                     if a.completion >= 100:
                         base_data['current_buildings'].append(a.oid)
         
         # Now also loop through all the buildings_in_progress
         # Use a range loop so we can update the list as we go
         for i in range(len(base_data['buildings_in_progress'])-1, -1, -1):
             b, ttl = base_data['buildings_in_progress'][i]
             
             if ttl <= 0:
                 del(base_data['buildings_in_progress'][i])
                 continue
             
             base_data['buildings_in_progress'][i][1] -= 1
             
             if b in found_buildings:
                 found_buildings[b] += 1
         
         # Now find out what we are missing
         missing = {}
         for b in buildings_needed:
             m = total_needed[b] - found_buildings[b]
             if m > 0:
                 missing[b] = m
         
         # None missing? We can stop looking around now
         if missing == {}:
             continue
         
         # Now find out which builders we can use
         # Narrow down our list of builders so we don't later iterate over
         # non-builders more than once
         builders = []
         builders_used = []
         for aid, a in self.own_actors.items():
             if self.actor_types[a.actor_type]['can_construct']:
                 if a.current_order[0] == "stop":
                     builders.append(a)
         
         # Now we work out which buildings we can build and who is closest to it
         for building_type, amount in missing.items():
             for i in range(amount):
                 target_pos = base_data['location']
                 
                 closest_builder = None, 9999999
                 for b in builders:
                     if b in builders_used: continue
                     if actor_lib.can_build(
                         builder_type = self.actor_types[b.actor_type],
                         item_type = self.actor_types[building_type],
                         build_lists = self.build_lists,
                     ):
                         # If they are closest we want them to go build it
                         dist = vectors.distance(target_pos, b.pos)
                         
                         if dist < closest_builder[1]:
                             closest_builder = b, dist
                 
                 # Now remove them from the pool and issue the build order
                 if closest_builder[0] != None:
                     builders_used.append(closest_builder[0])
                     self.issue_orders(closest_builder[0].oid, cmd="build", pos=target_pos, target=building_type)
                     
                     base_data['buildings_in_progress'].append([building_type, buildings_in_progress_ttl])
Exemplo n.º 23
0
    def inspect_bases(self):
        # First find out which buildings we are missing
        for base_name, base_data in self.bases.items():
            base_area = (
                base_data['location'][0] - base_data['size'][0],
                base_data['location'][1] - base_data['size'][1],
                base_data['location'][0] + base_data['size'][0],
                base_data['location'][1] + base_data['size'][1],
            )

            buildings_needed = set(base_data['buildings'])

            # Reset this now
            base_data['current_buildings'] = []

            # Get all buildings within this base
            found_buildings = {}
            total_needed = {}
            for b in buildings_needed:
                found_buildings[b] = 0
                total_needed[b] = 0

            for b in base_data['buildings']:
                total_needed[b] += 1

            # Loop through all actors and see what we've got
            for i, a in self.own_actors.items():
                if actor_lib.is_inside(a, base_area):
                    if a.actor_type in buildings_needed:
                        found_buildings[a.actor_type] += 1

                        if a.completion >= 100:
                            base_data['current_buildings'].append(a.oid)

            # Now also loop through all the buildings_in_progress
            # Use a range loop so we can update the list as we go
            for i in range(
                    len(base_data['buildings_in_progress']) - 1, -1, -1):
                b, ttl = base_data['buildings_in_progress'][i]

                if ttl <= 0:
                    del (base_data['buildings_in_progress'][i])
                    continue

                base_data['buildings_in_progress'][i][1] -= 1

                if b in found_buildings:
                    found_buildings[b] += 1

            # Now find out what we are missing
            missing = {}
            for b in buildings_needed:
                m = total_needed[b] - found_buildings[b]
                if m > 0:
                    missing[b] = m

            # None missing? We can stop looking around now
            if missing == {}:
                continue

            # Now find out which builders we can use
            # Narrow down our list of builders so we don't later iterate over
            # non-builders more than once
            builders = []
            builders_used = []
            for aid, a in self.own_actors.items():
                if self.actor_types[a.actor_type]['can_construct']:
                    if a.current_order[0] == "stop":
                        builders.append(a)

            # Now we work out which buildings we can build and who is closest to it
            for building_type, amount in missing.items():
                for i in range(amount):
                    target_pos = base_data['location']

                    closest_builder = None, 9999999
                    for b in builders:
                        if b in builders_used: continue
                        if actor_lib.can_build(
                                builder_type=self.actor_types[b.actor_type],
                                item_type=self.actor_types[building_type],
                                build_lists=self.build_lists,
                        ):
                            # If they are closest we want them to go build it
                            dist = vectors.distance(target_pos, b.pos)

                            if dist < closest_builder[1]:
                                closest_builder = b, dist

                    # Now remove them from the pool and issue the build order
                    if closest_builder[0] != None:
                        builders_used.append(closest_builder[0])
                        self.issue_orders(closest_builder[0].oid,
                                          cmd="build",
                                          pos=target_pos,
                                          target=building_type)

                        base_data['buildings_in_progress'].append(
                            [building_type, buildings_in_progress_ttl])
Exemplo n.º 24
0
    def run_ai(self):
        if self.micro_orders == []:
            cmd, pos, target = self.current_order
        else:
            cmd, pos, target = self.micro_orders[0]

        self._passive_ai()
        self._attack_ai()
        self._help_ai()

        if cmd == "stop" or cmd == "hold position":
            self.velocity = [0, 0, 0]

            if target == 0:
                self.next_order()

        elif cmd == "move":
            self._move_ai(pos)

            if vectors.distance(self.pos, pos) <= vectors.total_velocity(
                    self.velocity):
                self.pos = pos
                self.velocity = [0, 0, 0]
                self.next_order()

        elif cmd == "attack":
            target = self.get_first_target()

            # If we have a target, lets move closer to it
            if target != None:
                # First, are we within optimum range of our target?
                # If not then we need to get closer
                target_distance = vectors.distance(self.pos, target.pos)
                if target_distance > self.optimum_attack_range:
                    attack_pos = vectors.get_midpoint(
                        self.pos, target.pos, self.optimum_attack_range)
                    self._move_ai(attack_pos)
                else:
                    # If we are close enough then we can slow down
                    self._decelerate_ai()

        elif cmd == "aid":
            if target == None:
                target = self.get_first_ally()

            # If we have a target, lets move closer to it
            if target != None:
                dist = vectors.distance(self.pos, target.pos)

                if dist > self.optimum_heal_range:
                    target_pos = vectors.get_midpoint(self.pos, target.pos,
                                                      self.optimum_heal_range)
                    self._move_ai(target_pos)
                else:
                    self._decelerate_ai()

        else:
            raise Exception("No handler for cmd %s (pos: %s, target: %s)" %
                            (cmd, pos, target))

        # Do we have something to build?
        if self.build_queue != []:
            pass