def update(self, now): if now > self.last_tick > 0: elapsed = now - self.last_tick if self.is_spawned and self.initialized: # Logic for Trap GameObjects (type 6). if self.has_observers() and self.gobject_template.type == GameObjectTypes.TYPE_TRAP: self.trap_manager.update(elapsed) # Logic for Fishing node. if self.has_observers() and self.gobject_template.type == GameObjectTypes.TYPE_FISHINGNODE: self.fishing_node_manager.update(elapsed) # SpellManager update. self.spell_manager.update(now) # Check if this game object should be updated yet or not. if self.has_pending_updates(): MapManager.update_object(self, has_changes=True) self.reset_fields_older_than(now) # Not spawned but initialized. elif self.initialized: self.respawn_timer += elapsed if self.respawn_timer >= self.respawn_time: if self.summoner: self.despawn(destroy=True) else: self.respawn() self.last_tick = now
def update(self): now = time.time() if now > self.last_tick > 0: elapsed = now - self.last_tick if self.is_alive: # Spell/aura updates self.spell_manager.update(now, elapsed) self.aura_manager.update(elapsed) # Movement Updates self.movement_manager.update_pending_waypoints(elapsed) # Random Movement self._perform_random_movement(now) # Combat movement self._perform_combat_movement(now) # Attack update if self.combat_target and self.is_within_interactable_distance(self.combat_target): self.attack_update(elapsed) # Dead else: self.respawn_timer += elapsed if self.respawn_timer >= self.respawn_time: self.respawn() # Destroy body when creature is about to respawn elif self.is_spawned and self.respawn_timer >= self.respawn_time * 0.8: self.is_spawned = False MapManager.send_surrounding(self.get_destroy_packet(), self, include_self=False) self.last_tick = now if self.dirty: MapManager.send_surrounding(self.generate_proper_update_packet(create=False), self, include_self=False) MapManager.update_object(self) self.reset_fields() self.set_dirty(is_dirty=False)
def update(self, now): if now > self.last_tick > 0: elapsed = now - self.last_tick if self.is_spawned: # Logic for Trap GameObjects (type 6). if self.gobject_template.type == GameObjectTypes.TYPE_TRAP: self.trap_manager.update(elapsed) # Check if this game object should be updated yet or not. if self.has_pending_updates(): MapManager.update_object(self, check_pending_changes=True) self.reset_fields_older_than(now) # SpellManager update. self.spell_manager.update(now) # Not spawned. else: self.respawn_timer += elapsed if self.respawn_timer >= self.respawn_time: if self.is_summon: self.despawn(destroy=True) else: self.respawn() self.last_tick = now
def update(self, now): if now > self.last_tick > 0: elapsed = now - self.last_tick if self.is_alive and self.is_spawned: # Regeneration. self.regenerate(elapsed) # Spell/aura updates self.spell_manager.update(now) self.aura_manager.update(now) # Movement Updates self.movement_manager.update_pending_waypoints(elapsed) # Random Movement self._perform_random_movement(now) # Combat movement self._perform_combat_movement() # Attack update if self.combat_target and self.is_within_interactable_distance(self.combat_target): self.attack_update(elapsed) # Dead elif not self.is_alive: self.respawn_timer += elapsed if self.respawn_timer >= self.respawn_time: self.respawn() # Destroy body when creature is about to respawn. elif self.is_spawned and self.respawn_timer >= self.respawn_time * 0.8: self.despawn(destroy=self.is_summon) # Check if this creature object should be updated yet or not. if self.has_pending_updates(): MapManager.update_object(self, check_pending_changes=True) self.reset_fields_older_than(now) self.last_tick = now
def update(self, now): if now > self.last_tick > 0: elapsed = now - self.last_tick if self.is_alive and self.is_spawned and self.initialized: # Time to live. if self.time_to_live_timer > 0: self.time_to_live_timer -= elapsed # Regeneration. self.regenerate(elapsed) # Spell/Aura Update. self.spell_manager.update(now) self.aura_manager.update(now) # Movement Updates. self.movement_manager.update_pending_waypoints(elapsed) if self.has_moved: self._on_relocation() self.set_has_moved(False) # Random Movement, if visible to players. if self.has_observers(): self._perform_random_movement(now) # Combat Movement. self._perform_combat_movement() # AI. if self.object_ai: self.object_ai.update_ai(elapsed) # Attack Update. if self.combat_target and self.is_within_interactable_distance( self.combat_target): self.attack_update(elapsed) # Not in combat, check if threat manager can resolve a target. elif self.threat_manager: target = self.threat_manager.resolve_target() if target: is_melee = self.is_within_interactable_distance(target) self.attack(target, is_melee=is_melee) # Dead elif not self.is_alive and self.initialized: self.respawn_timer += elapsed if self.respawn_timer >= self.respawn_time: self.respawn() # Destroy body when creature is about to respawn. elif self.is_spawned and self.respawn_timer >= self.respawn_time * 0.8: if self.summoner: self.despawn(destroy=True) else: self.despawn() # Time to live expired, destroy. if self.time_to_live_timer < -1: self.despawn(destroy=True) # Check if this creature object should be updated yet or not. elif self.has_pending_updates(): MapManager.update_object(self, has_changes=True) self.reset_fields_older_than(now) self.last_tick = now
def update_pending_waypoints(self, elapsed): if not self.should_update_waypoints: return self.total_waypoint_timer += elapsed self.waypoint_timer += elapsed # Set elapsed time to the current movement spline data. if self.unit.movement_spline: if self.unit.movement_spline.elapsed < self.unit.movement_spline.total_time: self.unit.movement_spline.elapsed += elapsed * 1000 if self.unit.movement_spline.elapsed > self.unit.movement_spline.total_time: self.unit.movement_spline.elapsed = self.unit.movement_spline.total_time waypoint_length = len(self.pending_waypoints) if waypoint_length > 0: current_waypoint = self.pending_waypoints[0] if self.total_waypoint_timer >= current_waypoint.expected_timestamp: new_position = current_waypoint.location self.last_position = new_position self.waypoint_timer = 0 self.pending_waypoints.pop(0) # Guess current position based on speed and time. else: guessed_distance = self.unit.movement_spline.speed * self.waypoint_timer # If player is flying, don't take terrain Z into account to generate the position. if self.is_player and self.unit.movement_spline and \ self.unit.movement_spline.flags == SplineFlags.SPLINEFLAG_FLYING: map_id = -1 else: map_id = self.unit.map_ new_position = self.last_position.get_point_in_between( guessed_distance, current_waypoint.location, map_id=map_id) if new_position: self.waypoint_timer = 0 self.last_position = new_position.copy() self.unit.location.x = new_position.x self.unit.location.y = new_position.y self.unit.location.z = new_position.z MapManager.update_object(self.unit) if self.is_player and self.unit.pending_taxi_destination: self.unit.taxi_manager.update_flight_state() else: # Path finished. if self.total_waypoint_timer >= self.total_waypoint_time: if self.is_player and self.unit.pending_taxi_destination: self.unit.set_taxi_flying_state(False, set_dirty=True) self.unit.teleport(self.unit.map_, self.unit.pending_taxi_destination, is_instant=True) self.unit.pending_taxi_destination = None self.unit.taxi_manager.update_flight_state() self.reset()
def update_pending_waypoints(self, elapsed): if not self.should_update_waypoints: return self.total_waypoint_timer += elapsed self.waypoint_timer += elapsed # Set elapsed time to the current movement spline data if self.unit.movement_spline: if self.unit.movement_spline.elapsed < self.unit.movement_spline.total_time: self.unit.movement_spline.elapsed += elapsed * 1000 if self.unit.movement_spline.elapsed > self.unit.movement_spline.total_time: self.unit.movement_spline.elapsed = self.unit.movement_spline.total_time waypoint_length = len(self.pending_waypoints) if waypoint_length > 0: current_waypoint = self.pending_waypoints[0] if self.total_waypoint_timer > current_waypoint.expected_timestamp: new_position = current_waypoint.location self.last_position = new_position self.waypoint_timer = 0 self.pending_waypoints.pop(0) # Guess current position based on speed and time else: guessed_distance = self.speed * self.waypoint_timer # If player is flying, don't take terrain Z into account to generate the position. if self.is_player and self.unit.movement_spline.flags == SplineFlags.SPLINEFLAG_FLYING: map_id = -1 else: map_id = self.unit.map_ new_position = self.last_position.get_point_in_between( guessed_distance, current_waypoint.location, map_id=map_id) if new_position: self.unit.location.x = new_position.x self.unit.location.y = new_position.y self.unit.location.z = new_position.z MapManager.update_object(self.unit) else: # Path finished if self.total_waypoint_timer > self.total_waypoint_time: if self.is_player and self.unit.pending_taxi_destination: self.unit.unit_flags &= ~(UnitFlags.UNIT_FLAG_FROZEN | UnitFlags.UNIT_FLAG_TAXI_FLIGHT) self.unit.set_uint32(UnitFields.UNIT_FIELD_FLAGS, self.unit.unit_flags) self.unit.unmount() self.unit.teleport(self.unit.map_, self.unit.pending_taxi_destination) self.unit.pending_taxi_destination = None self.reset()
def respawn(self): super().respawn() # Set all property values before making this creature visible. self.location = self.spawn_position.copy() self.set_health(self.max_health) self.set_mana(self.max_power_1) self.loot_manager.clear() self.set_lootable(False) if self.killed_by and self.killed_by.group_manager: self.killed_by.group_manager.clear_looters_for_victim(self) self.killed_by = None self.respawn_timer = 0 self.respawn_time = randint(self.creature_instance.spawntimesecsmin, self.creature_instance.spawntimesecsmax) # Update its cell position if needed (Died far away from spawn location cell) MapManager.update_object(self) # Make this creature visible to its surroundings. MapManager.respawn_object(self)
def update(self): now = time.time() if now > self.last_tick > 0: elapsed = now - self.last_tick if self.is_spawned: # Check "dirtiness" to determine if this game object should be updated yet or not. if self.dirty: MapManager.send_surrounding( self.generate_proper_update_packet(create=False), self, include_self=False) MapManager.update_object(self) if self.reset_fields_older_than(now): self.set_dirty(is_dirty=False) # Not spawned. else: self.respawn_timer += elapsed if self.respawn_timer >= self.respawn_time and not self.is_summon: self.respawn() self.last_tick = now
def load(self): MapManager.update_object(self)
def handle_movement_status(world_session, socket, reader: PacketReader) -> int: # Avoid handling malformed movement packets, or handling them while no player or player teleporting. if world_session.player_mgr and len(reader.data) >= 48: try: transport_guid, transport_x, transport_y, transport_z, transport_o, x, y, z, o, pitch, flags = \ unpack('<Q9fI', reader.data[:48]) # Hacky way to prevent random teleports when colliding with elevators # Also acts as a rudimentary teleport cheat detection if not world_session.player_mgr.pending_taxi_destination and world_session.player_mgr.location.distance( x=x, y=y, z=z) > 64: Logger.anticheat( f'Preventing coordinate desync from player {world_session.player_mgr.player.name} ({world_session.player_mgr.guid}).' ) world_session.player_mgr.teleport( world_session.player_mgr.map_, world_session.player_mgr.location) return 0 # Send movement info to SpellManager until movement handling is merged to update system if flags & 0xF != 0: # MoveFlags.MOVEFLAG_MOVE_MASK | MoveFlags.MOVEFLAG_STRAFE_MASK world_session.player_mgr.spell_manager.flag_as_moved() world_session.player_mgr.transport_id = transport_guid world_session.player_mgr.transport.x = transport_x world_session.player_mgr.transport.y = transport_y world_session.player_mgr.transport.z = transport_z world_session.player_mgr.transport.o = transport_o world_session.player_mgr.location.x = x world_session.player_mgr.location.y = y world_session.player_mgr.location.z = z world_session.player_mgr.location.o = o world_session.player_mgr.pitch = pitch world_session.player_mgr.movement_flags = flags if flags & MoveFlags.MOVEFLAG_SPLINE_MOVER: world_session.player_mgr.movement_spline = MovementManager.MovementSpline.from_bytes( reader.data[48:]) movement_data = pack(f'<Q{len(reader.data)}s', world_session.player_mgr.guid, reader.data) MapManager.send_surrounding(PacketWriter.get_packet( OpCode(reader.opcode), movement_data), world_session.player_mgr, include_self=False) MapManager.update_object(world_session.player_mgr) world_session.player_mgr.sync_player() # Get up if you jump while not standing if reader.opcode == OpCode.MSG_MOVE_JUMP and \ world_session.player_mgr.stand_state != StandState.UNIT_DEAD and \ world_session.player_mgr.stand_state != StandState.UNIT_STANDING: world_session.player_mgr.stand_state = StandState.UNIT_STANDING world_session.player_mgr.set_dirty() except (AttributeError, error): Logger.error( f'Error while handling {OpCode(reader.opcode).name}, skipping. Data: {reader.data}' ) return 0
def update_pending_waypoints(self, elapsed): if not self.should_update_waypoints: return self.total_waypoint_timer += elapsed self.waypoint_timer += elapsed # Set elapsed time to the current movement spline data. if self.unit.movement_spline: if self.unit.movement_spline.elapsed < self.unit.movement_spline.total_time: self.unit.movement_spline.elapsed += elapsed * 1000 if self.unit.movement_spline.elapsed > self.unit.movement_spline.total_time: self.unit.movement_spline.elapsed = self.unit.movement_spline.total_time waypoint_length = len(self.pending_waypoints) if waypoint_length > 0: current_waypoint = self.pending_waypoints[0] if self.total_waypoint_timer >= current_waypoint.expected_timestamp: new_position = current_waypoint.location self.last_position = new_position self.waypoint_timer = 0 self.pending_waypoints.pop(0) # Guess current position based on speed and time. else: guessed_distance = self.unit.movement_spline.speed * self.waypoint_timer # If player is flying, don't guess in between locations, use waypoints only. if self.is_player and self.unit.movement_spline and \ self.unit.movement_spline.flags == SplineFlags.SPLINEFLAG_FLYING: return map_id = self.unit.map_ # Guess the unit new position. new_position = self.last_position.get_point_in_between(guessed_distance, current_waypoint.location, map_id=map_id) if new_position: self.waypoint_timer = 0 self.last_position = new_position.copy() self.unit.location.x = new_position.x self.unit.location.y = new_position.y self.unit.location.z = new_position.z self.unit.set_has_moved(True) MapManager.update_object(self.unit) # TODO: Logic below should be removed once we have some kind of navmesh. # this temporarily allows units to return without getting stuck in walls forever. # Append combat movements so this unit can use them to return to spawn point if evading. if not self.is_player and self.unit.in_combat and not self.unit.is_evading: self.unit.evading_waypoints.append(new_position.copy()) if self.is_player and self.unit.pending_taxi_destination: self.unit.taxi_manager.update_flight_state() else: # Path finished. if self.total_waypoint_timer >= self.total_waypoint_time: if self.is_player and self.unit.pending_taxi_destination: self.unit.set_taxi_flying_state(False) self.unit.teleport(self.unit.map_, self.unit.pending_taxi_destination, is_instant=True) self.unit.pending_taxi_destination = None self.unit.taxi_manager.update_flight_state() if not self.is_player: if self.unit.is_evading: self.unit.is_evading = False self.reset()