예제 #1
0
    def act(self,
            action,
            facing_loc=None,
            repeating=False,
            force_restart=True):
        """
		@param repeating: maps to fife, currently broken: http://fife.trac.cvsdude.com/engine/ticket/708
		@param force_restart: whether to always restart, even if action is already displayed
		"""
        if not self.has_action(action):
            action = 'idle'

        if not force_restart and self._action == action:
            return

        # TODO This should not happen, this is a fix for the component introduction
        # Should be fixed as soon as we move concrete object to a component as well
        # which ensures proper initialization order for loading and initing
        if self._instance is not None:
            if facing_loc is None:
                facing_loc = self._instance.getFacingLocation()
            UnitClass.ensure_action_loaded(self._action_set_id, action)  # lazy
            self._instance.act(action + "_" + str(self._action_set_id),
                               facing_loc, repeating)
        self._action = action
예제 #2
0
	def act(self, action, facing_loc=None, repeating=False, force_restart=True):
		"""
		@param repeating: maps to fife, currently broken: http://github.com/fifengine/fifengine/issues/708
		@param force_restart: whether to always restart, even if action is already displayed
		"""
		if not self.has_action(action):
			action = 'idle'

		if not force_restart and self._action == action:
			return

		self._action = action

		# TODO This should not happen, this is a fix for the component introduction
		# Should be fixed as soon as we move concrete object to a component as well
		# which ensures proper initialization order for loading and initing
		if self._instance is None:
			return

		if facing_loc is None:
			facing_loc = self._instance.getFacingLocation()
		UnitClass.ensure_action_loaded(self._action_set_id, action) # lazy
		if (Fife.getVersion() >= (0, 3, 6)):
			if repeating:
				self._instance.actRepeat(action+"_"+str(self._action_set_id), facing_loc)
			else:
				self._instance.actOnce(action+"_"+str(self._action_set_id), facing_loc)
		else:
			self._instance.act(action+"_"+str(self._action_set_id), facing_loc, repeating)
		ActionChanged.broadcast(self, action)
예제 #3
0
	def act(self, action, facing_loc=None, repeating=False, force_restart=True):
		"""
		@param repeating: maps to fife instance method actRepeat or actOnce
		@param force_restart: whether to always restart, even if action is already displayed
		"""
		if not self.has_action(action):
			action = 'idle'

		if not force_restart and self._action == action:
			return

		self._action = action

		# TODO This should not happen, this is a fix for the component introduction
		# Should be fixed as soon as we move concrete object to a component as well
		# which ensures proper initialization order for loading and initing
		if self._instance is None:
			return

		if facing_loc is None:
			facing_loc = self._instance.getFacingLocation()
		UnitClass.ensure_action_loaded(self._action_set_id, action) # lazy
		if (Fife.getVersion() >= (0, 3, 6)):
			if repeating:
				self._instance.actRepeat(action + "_" + str(self._action_set_id), facing_loc)
			else:
				self._instance.actOnce(action + "_" + str(self._action_set_id), facing_loc)
		else:
			self._instance.act(action + "_" + str(self._action_set_id), facing_loc, repeating)
		ActionChanged.broadcast(self, action)
	def act(self, action, facing_loc=None, repeating=False, force_restart=True):
		"""
		@param repeating: maps to fife instance method actRepeat or actOnce
		@param force_restart: whether to always restart, even if action is already displayed
		"""
		if not self.has_action(action):
			action = 'idle'

		if not force_restart and self._action == action:
			return

		self._action = action

		# TODO This should not happen, this is a fix for the component introduction
		# Should be fixed as soon as we move concrete object to a component as well
		# which ensures proper initialization order for loading and initing
		if self._instance is None:
			return

		if facing_loc is None:
			facing_loc = self._instance.getFacingLocation()
		UnitClass.ensure_action_loaded(self._action_set_id, action) # lazy
		if repeating:
			self._instance.actRepeat(action + "_" + str(self._action_set_id), facing_loc)
		else:
			self._instance.actOnce(action + "_" + str(self._action_set_id), facing_loc)
예제 #5
0
	def act(self, action, facing_loc=None, repeating=False):
		if not self.has_action(action):
			action = 'idle'
		# TODO This should not happen, this is a fix for the component introduction
		# Should be fixed as soon as we move concrete object to a component as well
		# which ensures proper initialization order for loading and initing
		if self._instance is not None:
			if facing_loc is None:
				facing_loc = self._instance.getFacingLocation()
			UnitClass.ensure_action_loaded(self._action_set_id, action) # lazy
			self._instance.act(action+"_"+str(self._action_set_id), facing_loc, repeating)
		self._action = action
예제 #6
0
	def act(self, action, facing_loc=None, repeating=False, force_restart=True):
		"""
		@param repeating: maps to fife, currently broken: http://fife.trac.cvsdude.com/engine/ticket/708
		@param force_restart: whether to always restart, even if action is already displayed
		"""
		if not self.has_action(action):
			action = 'idle'

		if not force_restart and self._action == action:
			return

		# TODO This should not happen, this is a fix for the component introduction
		# Should be fixed as soon as we move concrete object to a component as well
		# which ensures proper initialization order for loading and initing
		if self._instance is not None:
			if facing_loc is None:
				facing_loc = self._instance.getFacingLocation()
			UnitClass.ensure_action_loaded(self._action_set_id, action) # lazy
			self._instance.act(action+"_"+str(self._action_set_id), facing_loc, repeating)
		self._action = action
	def test_unitclass(self):
		t = UnitClass(1, {
			'baseclass': 'unit.Unit',
			'name': 'UnitName',
			'radius': 0,
			'components': [],
			'actionsets': []
		})

		self.assertEqual(t.__name__, 'Unit[1]')
		self.assertEqual(t.class_name, 'Unit')
		self.assertEqual(t.name, 'UnitName')
		self.assertEqual(t.id, 1)
예제 #8
0
    def _move_tick(self, resume=False):
        """Called by the scheduler, moves the unit one step for this tick.
		"""
        assert self._next_target is not None

        if self._fife_location1 is None:
            # this data structure is needed multiple times, only create once
            self._fife_location1 = fife.Location(
                self._instance.getLocationRef().getLayer())
            self._fife_location2 = fife.Location(
                self._instance.getLocationRef().getLayer())

        if resume:
            self.__is_moving = True
        else:
            #self.log.debug("%s move tick from %s to %s", self, self.last_position, self._next_target)
            self.last_position = self.position
            self.position = self._next_target
            self._changed()

        # try to get next step, handle a blocked path
        while self._next_target == self.position:
            try:
                self._next_target = self.path.get_next_step()
            except PathBlockedError:
                # if we are trying to resume and it isn't possible then we need to raise it again
                if resume:
                    raise

                self.log.debug("path is blocked")
                self.log.debug("owner: %s", self.owner)
                self.__is_moving = False
                self._next_target = self.position
                if self.blocked_callbacks:
                    self.log.debug(
                        'PATH FOR UNIT %s is blocked. Calling blocked_callback',
                        self)
                    self.blocked_callbacks.execute()
                else:
                    # generic solution: retry in 2 secs
                    self.log.debug(
                        'PATH FOR UNIT %s is blocked. Retry in 2 secs', self)
                    # technically, the ship doesn't move, but it is in the process of moving,
                    # as it will continue soon in general. Needed in border cases for add_move_callback
                    self.__is_moving = True
                    Scheduler().add_new_object(self._move_tick, self,
                                               GAME_SPEED.TICKS_PER_SECOND * 2)
                self.log.debug("Unit %s: path is blocked, no way around", self)
                return

        if self._next_target is None:
            self._movement_finished()
            return
        else:
            self.__is_moving = True

        #setup movement
        move_time = self.get_unit_velocity()
        UnitClass.ensure_action_loaded(
            self._action_set_id, self._move_action)  # lazy load move action

        self._exact_model_coords1.set(self.position.x, self.position.y, 0)
        self._fife_location1.setExactLayerCoordinates(
            self._exact_model_coords1)
        self._exact_model_coords2.set(self._next_target.x, self._next_target.y,
                                      0)
        self._fife_location2.setExactLayerCoordinates(
            self._exact_model_coords2)
        self._route = fife.Route(self._fife_location1, self._fife_location2)
        # TODO/HACK the *5 provides slightly less flickery behavior of the moving
        # objects. This should be fixed properly by using the fife pathfinder for
        # the entire route and task
        location_list = fife.LocationList([self._fife_location2] * 5)
        # It exists for FIFE 0.3.4 compat. See #1993.
        if Fife.getVersion() == (0, 3, 4):
            location_list.thisown = 0
            self._route.thisown = 0
        self._route.setPath(location_list)

        self.act(self._move_action)
        diagonal = self._next_target.x != self.position.x and self._next_target.y != self.position.y
        speed = float(self.session.timer.get_ticks(1)) / move_time[0]
        action = self._instance.getCurrentAction().getId()
        self._instance.follow(action, self._route, speed)

        #self.log.debug("%s registering move tick in %s ticks", self, move_time[int(diagonal)])
        Scheduler().add_new_object(self._move_tick, self,
                                   move_time[int(diagonal)])

        # check if a conditional callback becomes true
        for cond in self._conditional_callbacks.keys(
        ):  # iterate of copy of keys to be able to delete
            if cond():
                # start callback when this function is done
                Scheduler().add_new_object(self._conditional_callbacks[cond],
                                           self)
                del self._conditional_callbacks[cond]
	def _move_tick(self, resume=False):
		"""Called by the scheduler, moves the unit one step for this tick.
		"""
		assert self._next_target is not None

		if self._fife_location is None:
			# this data structure is needed multiple times, only create once
			self._fife_location = fife.Location(self._instance.getLocationRef().getLayer())

		if resume:
			self.__is_moving = True
		else:
			#self.log.debug("%s move tick from %s to %s", self, self.last_position, self._next_target)
			self.last_position = self.position
			self.position = self._next_target
			self._exact_model_coords.set(self.position.x, self.position.y, 0)
			self._fife_location.setExactLayerCoordinates(self._exact_model_coords)
			# it's safe to use location here (thisown is 0, set by swig, and setLocation uses reference)
			self._instance.setLocation(self._fife_location)
			self._changed()

		# try to get next step, handle a blocked path
		while self._next_target == self.position:
			try:
				self._next_target = self.path.get_next_step()
			except PathBlockedError:
				# if we are trying to resume and it isn't possible then we need to raise it again
				if resume:
					raise

				self.log.debug("path is blocked")
				self.log.debug("owner: %s", self.owner)
				self.__is_moving = False
				self._next_target = self.position
				if self.blocked_callbacks:
					self.log.debug('PATH FOR UNIT %s is blocked. Calling blocked_callback', self)
					self.blocked_callbacks.execute()
					"""
					# TODO: This is supposed to delegate control over the behaviour of the unit to the owner.
					#       It is currently not used in a meaningful manner and possibly will be removed,
					#       as blocked_callback solves this problem more elegantly.
					#       Also, this sometimes triggers for collectors, who are supposed to use the
					#       generic solution. Only uncomment this code if this problem is fixed, else
					#       collectors will get stuck.
				elif self.owner is not None and hasattr(self.owner, "notify_unit_path_blocked"):
					self.log.debug('PATH FOR UNIT %s is blocked. Delegating to owner %s', self, self.owner)
					self.owner.notify_unit_path_blocked(self)
					"""
				else:
					# generic solution: retry in 2 secs
					self.log.debug('PATH FOR UNIT %s is blocked. Retry in 2 secs', self)
					# technically, the ship doesn't move, but it is in the process of moving,
					# as it will continue soon in general. Needed in border cases for add_move_callback
					self.__is_moving = True
					Scheduler().add_new_object(self._move_tick, self,
					                           GAME_SPEED.TICKS_PER_SECOND * 2)
				self.log.debug("Unit %s: path is blocked, no way around", self)
				return

		if self._next_target is None:
			self._movement_finished()
			return
		else:
			self.__is_moving = True

		#setup movement

		# WORK IN PROGRESS
		move_time = self.get_unit_velocity()

		#location = fife.Location(self._instance.getLocation().getLayer())
		self._exact_model_coords.set(self._next_target.x, self._next_target.y, 0)
		self._fife_location.setExactLayerCoordinates(self._exact_model_coords)

		UnitClass.ensure_action_loaded(self._action_set_id, self._move_action) # lazy load move action

		# it's safe to use location here (thisown is 0, set by swig, and setLocation uses reference)
		self._instance.move(self._move_action+"_"+str(self._action_set_id), self._fife_location,
												float(self.session.timer.get_ticks(1)) / move_time[0])
		# coords per sec

		diagonal = self._next_target.x != self.position.x and self._next_target.y != self.position.y
		#self.log.debug("%s registering move tick in %s ticks", self, move_time[int(diagonal)])
		Scheduler().add_new_object(self._move_tick, self, move_time[int(diagonal)])

		# check if a conditional callback becomes true
		for cond in self._conditional_callbacks.keys(): # iterate of copy of keys to be able to delete
			if cond():
				# start callback when this function is done
				Scheduler().add_new_object(self._conditional_callbacks[cond], self)
				del self._conditional_callbacks[cond]
	def _move_tick(self, resume=False):
		"""Called by the scheduler, moves the unit one step for this tick.
		"""
		assert self._next_target is not None

		if self._fife_location1 is None:
			# this data structure is needed multiple times, only create once
			self._fife_location1 = fife.Location(self._instance.getLocationRef().getLayer())
			self._fife_location2 = fife.Location(self._instance.getLocationRef().getLayer())

		if resume:
			self.__is_moving = True
		else:
			#self.log.debug("%s move tick from %s to %s", self, self.last_position, self._next_target)
			self.last_position = self.position
			self.position = self._next_target
			self._changed()

		# try to get next step, handle a blocked path
		while self._next_target == self.position:
			try:
				self._next_target = self.path.get_next_step()
			except PathBlockedError:
				# if we are trying to resume and it isn't possible then we need to raise it again
				if resume:
					raise

				self.log.debug("path is blocked")
				self.log.debug("owner: %s", self.owner)
				self.__is_moving = False
				self._next_target = self.position
				if self.blocked_callbacks:
					self.log.debug('PATH FOR UNIT %s is blocked. Calling blocked_callback', self)
					self.blocked_callbacks.execute()
				else:
					# generic solution: retry in 2 secs
					self.log.debug('PATH FOR UNIT %s is blocked. Retry in 2 secs', self)
					# technically, the ship doesn't move, but it is in the process of moving,
					# as it will continue soon in general. Needed in border cases for add_move_callback
					self.__is_moving = True
					Scheduler().add_new_object(self._move_tick, self,
					                           GAME_SPEED.TICKS_PER_SECOND * 2)
				self.log.debug("Unit %s: path is blocked, no way around", self)
				return

		if self._next_target is None:
			self._movement_finished()
			return
		else:
			self.__is_moving = True

		# HACK: 2 different pathfinding systems are being used here and they
		# might not always match.
		# If the graphical location is too far away from the actual location,
		# then forcefully synchronize the locations.
		# This fixes the symptoms from issue #2859
		# https://github.com/unknown-horizons/unknown-horizons/issues/2859
		pos = fife.ExactModelCoordinate(self.position.x, self.position.y, 0)
		fpos = self.fife_instance.getLocationRef().getExactLayerCoordinates()
		if (pos - fpos).length() > 1.5:
			self.fife_instance.getLocationRef().setExactLayerCoordinates(pos)

		#setup movement
		move_time = self.get_unit_velocity()
		UnitClass.ensure_action_loaded(self._action_set_id, self._move_action) # lazy load move action

		self._exact_model_coords1.set(self.position.x, self.position.y, 0)
		self._fife_location1.setExactLayerCoordinates(self._exact_model_coords1)
		self._exact_model_coords2.set(self._next_target.x, self._next_target.y, 0)
		self._fife_location2.setExactLayerCoordinates(self._exact_model_coords2)
		self._route = fife.Route(self._fife_location1, self._fife_location2)
		# TODO/HACK the *5 provides slightly less flickery behavior of the moving
		# objects. This should be fixed properly by using the fife pathfinder for
		# the entire route and task
		location_list = fife.LocationList([self._fife_location2] * 5)
		self._route.setPath(location_list)

		self.act(self._move_action)
		diagonal = self._next_target.x != self.position.x and self._next_target.y != self.position.y
		speed = float(self.session.timer.get_ticks(1)) / move_time[0]
		action = self._instance.getCurrentAction().getId()
		self._instance.follow(action, self._route, speed)

		#self.log.debug("%s registering move tick in %s ticks", self, move_time[int(diagonal)])
		Scheduler().add_new_object(self._move_tick, self, move_time[int(diagonal)])

		# check if a conditional callback becomes true
		for cond in list(self._conditional_callbacks.keys()): # iterate of copy of keys to be able to delete
			if cond():
				# start callback when this function is done
				Scheduler().add_new_object(self._conditional_callbacks[cond], self)
				del self._conditional_callbacks[cond]
예제 #11
0
	def _move_tick(self, resume=False):
		"""Called by the scheduler, moves the unit one step for this tick.
		"""
		assert self._next_target is not None

		if self._fife_location1 is None:
			# this data structure is needed multiple times, only create once
			self._fife_location1 = fife.Location(self._instance.getLocationRef().getLayer())
			self._fife_location2 = fife.Location(self._instance.getLocationRef().getLayer())

		if resume:
			self.__is_moving = True
		else:
			#self.log.debug("%s move tick from %s to %s", self, self.last_position, self._next_target)
			self.last_position = self.position
			self.position = self._next_target
			self._changed()

		# try to get next step, handle a blocked path
		while self._next_target == self.position:
			try:
				self._next_target = self.path.get_next_step()
			except PathBlockedError:
				# if we are trying to resume and it isn't possible then we need to raise it again
				if resume:
					raise

				self.log.debug("path is blocked")
				self.log.debug("owner: %s", self.owner)
				self.__is_moving = False
				self._next_target = self.position
				if self.blocked_callbacks:
					self.log.debug('PATH FOR UNIT %s is blocked. Calling blocked_callback', self)
					self.blocked_callbacks.execute()
				else:
					# generic solution: retry in 2 secs
					self.log.debug('PATH FOR UNIT %s is blocked. Retry in 2 secs', self)
					# technically, the ship doesn't move, but it is in the process of moving,
					# as it will continue soon in general. Needed in border cases for add_move_callback
					self.__is_moving = True
					Scheduler().add_new_object(self._move_tick, self,
					                           GAME_SPEED.TICKS_PER_SECOND * 2)
				self.log.debug("Unit %s: path is blocked, no way around", self)
				return

		if self._next_target is None:
			self._movement_finished()
			return
		else:
			self.__is_moving = True

		#setup movement
		move_time = self.get_unit_velocity()
		UnitClass.ensure_action_loaded(self._action_set_id, self._move_action) # lazy load move action

		self._exact_model_coords1.set(self.position.x, self.position.y, 0)
		self._fife_location1.setExactLayerCoordinates(self._exact_model_coords1)
		self._exact_model_coords2.set(self._next_target.x, self._next_target.y, 0)
		self._fife_location2.setExactLayerCoordinates(self._exact_model_coords2)
		self._route = fife.Route(self._fife_location1, self._fife_location2)
		# TODO/HACK the *5 provides slightly less flickery behavior of the moving
		# objects. This should be fixed properly by using the fife pathfinder for
		# the entire route and task
		self._route.setPath(fife.LocationList([self._fife_location2]*5))
		self._route.setRouteStatus(3)  #fife.RouteStatus.ROUTE_SOLVED)

		diagonal = self._next_target.x != self.position.x and self._next_target.y != self.position.y
		action = self._move_action+"_"+str(self._action_set_id)
		speed = float(self.session.timer.get_ticks(1)) / move_time[0]
		self._instance.follow(action, self._route, speed)

		#self.log.debug("%s registering move tick in %s ticks", self, move_time[int(diagonal)])
		Scheduler().add_new_object(self._move_tick, self, move_time[int(diagonal)])

		# check if a conditional callback becomes true
		for cond in self._conditional_callbacks.keys(): # iterate of copy of keys to be able to delete
			if cond():
				# start callback when this function is done
				Scheduler().add_new_object(self._conditional_callbacks[cond], self)
				del self._conditional_callbacks[cond]