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 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)
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)
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
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)
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]
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]