Esempio n. 1
0
    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
Esempio n. 2
0
    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)
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
    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
Esempio n. 6
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 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()
Esempio n. 7
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.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()
Esempio n. 8
0
    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)
Esempio n. 9
0
    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
Esempio n. 10
0
 def load(self):
     MapManager.update_object(self)
Esempio n. 11
0
    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
Esempio n. 12
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()