Beispiel #1
0
    def send_attack_state_update(self, damage_info):
        data = pack(
            '<I2QIBIf7I',
            damage_info.hit_info,
            damage_info.attacker.guid,
            damage_info.target.guid,
            damage_info.total_damage,
            # Sub damage count
            1,
            damage_info.damage_school_mask,
            damage_info.total_damage,
            damage_info.damage,
            damage_info.absorb,
            damage_info.target_state,
            damage_info.resist,
            0,
            0,
            damage_info.blocked_amount)
        GridManager.send_surrounding(
            PacketWriter.get_packet(OpCode.SMSG_ATTACKERSTATEUPDATE, data),
            self,
            include_self=self.get_type() == ObjectTypes.TYPE_PLAYER)

        # Damage effects
        self.deal_damage(damage_info.target, damage_info.total_damage)
 def send_update_surrounding(self, update_type=UpdateTypes.UPDATE_FULL):
     update_packet = UpdatePacketFactory.compress_if_needed(
         PacketWriter.get_packet(
             OpCode.SMSG_UPDATE_OBJECT,
             self.get_update_packet(update_type=update_type,
                                    is_self=False)))
     GridManager.send_surrounding(update_packet, self, include_self=False)
Beispiel #3
0
 def send_melee_attack_stop(self, victim_guid):
     # Last uint32 is "deceased"; can be either 1 (self is dead), or 0, (self is alive).
     # Forces the unit to face the corpse and disables clientside
     # turning (UnitFlags.DisableMovement) CGUnit_C::OnAttackStop
     data = pack('<2QI', self.guid, victim_guid, 0 if self.is_alive else 1)
     GridManager.send_surrounding(
         PacketWriter.get_packet(OpCode.SMSG_ATTACKSTOP, data), self)
Beispiel #4
0
    def send_spell_go(self, casting_spell):
        data = [self.unit_mgr.guid, self.unit_mgr.guid,
                casting_spell.spell_entry.ID, 0]  # TODO Flags

        sign = '<2QIH'

        hit_count = 0
        if len(casting_spell.target_results.keys()) > 0:
            hit_count += 1
        sign += 'B'
        data.append(hit_count)

        for target, reason in casting_spell.target_results.items():
            if reason == SpellMissReason.MISS_REASON_NONE:
                data.append(target)
                sign += 'Q'

        data.append(0)  # miss count
        sign += 'B'

        sign += 'H'  # SpellTargetMask
        data.append(casting_spell.spell_target_mask)

        # write initial target
        if casting_spell.spell_target_mask & SpellTargetMask.UNIT == SpellTargetMask.UNIT:
            sign += 'Q'
            data.append(casting_spell.initial_target_unit.guid)

        packed = pack(sign, *data)
        GridManager.send_surrounding(PacketWriter.get_packet(OpCode.SMSG_SPELL_GO, packed), self.unit_mgr,
                                     include_self=self.unit_mgr.get_type() == ObjectTypes.TYPE_PLAYER)
Beispiel #5
0
    def deal_damage(self, target, damage):
        if not target or damage < 1:
            return

        if not self.in_combat:
            self.enter_combat(force_update=True)

        if not target.in_combat:
            target.enter_combat(force_update=True)

        if not target.in_combat:
            target.enter_combat()

        new_health = target.health - damage
        if new_health <= 0:
            target.die(self)
        else:
            target.set_health(new_health)

        update_packet = target.generate_proper_update_packet(
            is_self=target.get_type() == ObjectTypes.TYPE_PLAYER)
        GridManager.send_surrounding(
            update_packet,
            target,
            include_self=target.get_type() == ObjectTypes.TYPE_PLAYER)
Beispiel #6
0
    def update_surrounding(self, destroy=False):
        if destroy:
            grid = GRIDS[self.current_grid]

            for guid, player in list(grid.players.items()):
                if player.guid != self.guid:
                    self.session.request.sendall(player.get_destroy_packet())

        update_packet = UpdatePacketFactory.compress_if_needed(
            PacketWriter.get_packet(
                OpCode.SMSG_UPDATE_OBJECT,
                self.get_update_packet(update_type=UpdateTypes.UPDATE_FULL,
                                       is_self=False)))
        GridManager.send_surrounding(update_packet, self, include_self=False)
        GridManager.send_surrounding(NameQueryHandler.get_query_details(
            self.player),
                                     self,
                                     include_self=True)

        for guid, player in list(
                GridManager.get_surrounding_players(self).items()):
            if self.guid != guid:
                self.session.request.sendall(
                    PacketWriter.get_packet(
                        OpCode.SMSG_UPDATE_OBJECT,
                        player.get_update_packet(
                            update_type=UpdateTypes.UPDATE_FULL,
                            is_self=False)))
                self.session.request.sendall(
                    NameQueryHandler.get_query_details(player.player))
Beispiel #7
0
    def update(self):
        now = time.time()

        if now > self.last_tick > 0:
            elapsed = now - self.last_tick
            self.player.totaltime += elapsed
            self.player.leveltime += elapsed
        self.last_tick = now

        if self.flagged_for_update:
            self.session.request.sendall(
                PacketWriter.get_packet(
                    OpCode.SMSG_UPDATE_OBJECT,
                    self.get_update_packet(update_type=UpdateTypes.UPDATE_FULL,
                                           is_self=True)))

            GridManager.send_surrounding(PacketWriter.get_packet(
                OpCode.SMSG_UPDATE_OBJECT,
                self.get_update_packet(update_type=UpdateTypes.UPDATE_FULL,
                                       is_self=False)),
                                         self,
                                         include_self=False)

            GridManager.update_object(self)

            self.flagged_for_update = False
Beispiel #8
0
    def update_surrounding(self):
        self.send_update_surrounding()
        GridManager.send_surrounding(NameQueryHandler.get_query_details(
            self.player),
                                     self,
                                     include_self=True)

        players, creatures, gobjects = GridManager.get_surrounding_objects(
            self, [
                ObjectTypes.TYPE_PLAYER, ObjectTypes.TYPE_UNIT,
                ObjectTypes.TYPE_GAMEOBJECT
            ])

        for guid, player in players.items():
            if self.guid != guid:
                if guid not in self.objects_in_range:
                    update_packet = UpdatePacketFactory.compress_if_needed(
                        PacketWriter.get_packet(
                            OpCode.SMSG_UPDATE_OBJECT,
                            player.get_update_packet(
                                update_type=UpdateTypes.UPDATE_FULL,
                                is_self=False)))
                    self.session.request.sendall(update_packet)
                    self.session.request.sendall(
                        NameQueryHandler.get_query_details(player.player))
                self.objects_in_range[guid] = {'object': player, 'near': True}

        for guid, creature in creatures.items():
            if guid not in self.objects_in_range:
                update_packet = UpdatePacketFactory.compress_if_needed(
                    PacketWriter.get_packet(
                        OpCode.SMSG_UPDATE_OBJECT,
                        creature.get_update_packet(
                            update_type=UpdateTypes.UPDATE_FULL,
                            is_self=False)))
                self.session.request.sendall(update_packet)
                self.session.request.sendall(creature.query_details())
            self.objects_in_range[guid] = {'object': creature, 'near': True}

        for guid, gobject in gobjects.items():
            if guid not in self.objects_in_range:
                update_packet = UpdatePacketFactory.compress_if_needed(
                    PacketWriter.get_packet(
                        OpCode.SMSG_UPDATE_OBJECT,
                        gobject.get_update_packet(
                            update_type=UpdateTypes.UPDATE_FULL,
                            is_self=False)))
                self.session.request.sendall(update_packet)
                self.session.request.sendall(gobject.query_details())
            self.objects_in_range[guid] = {'object': gobject, 'near': True}

        for guid, object_info in list(self.objects_in_range.items()):
            if not object_info['near']:
                self.session.request.sendall(
                    self.objects_in_range[guid]['object'].get_destroy_packet())
                del self.objects_in_range[guid]
            else:
                self.objects_in_range[guid]['near'] = False
Beispiel #9
0
    def send_move_to(self, waypoints, speed, spline_flag):
        self.reset()
        self.speed = speed

        start_time = int(WorldManager.get_seconds_since_startup() * 1000)

        data = pack('<Q12sIBI', self.unit.guid,
                    self.unit.location.to_bytes(include_orientation=False),
                    start_time, 0, spline_flag)

        waypoints_data = b''
        waypoints_length = len(waypoints)
        last_waypoint = self.unit.location
        total_distance = 0
        total_time = 0
        current_id = 0
        for waypoint in waypoints:
            waypoints_data += waypoint.to_bytes(include_orientation=False)
            current_distance = last_waypoint.distance(waypoint)
            current_time = current_distance / speed
            total_distance += current_distance
            total_time += current_time

            self.pending_waypoints.append(
                PendingWaypoint(current_id, total_time, waypoint))
            last_waypoint = waypoint
            current_id += 1

        data += pack('<2I%us' % len(waypoints_data), int(total_time * 1000),
                     waypoints_length, waypoints_data)

        GridManager.send_surrounding(PacketWriter.get_packet(
            OpCode.SMSG_MONSTER_MOVE, data),
                                     self.unit,
                                     include_self=self.is_player)

        # Player should dismount after some seconds have passed since FP destination is reached (Blizzlike).
        # This is also kind of a hackfix (at least for now) since the client always takes a bit more time to reach
        # the actual destination than the time you specify in SMSG_MONSTER_MOVE.
        if self.is_player and spline_flag == SplineFlags.SPLINEFLAG_FLYING:
            self.total_waypoint_time = total_time + (0.15 * waypoints_length)
        else:
            self.total_waypoint_time = total_time

        # Generate the spline
        spline = MovementSpline()
        spline.flags = spline_flag
        spline.spot = self.unit.location
        spline.guid = self.unit.guid
        spline.facing = self.unit.location.o
        spline.elapsed = 0
        spline.total_time = int(self.total_waypoint_time * 1000)
        spline.points = waypoints
        self.unit.movement_spline = spline

        self.last_position = self.unit.location
        self.should_update_waypoints = True
Beispiel #10
0
 def send_single_item_update(self, world_session, item, is_self):
     update_packet = UpdatePacketFactory.compress_if_needed(PacketWriter.get_packet(
         OpCode.SMSG_UPDATE_OBJECT, item.get_full_update_packet(is_self=False)))
     if is_self:
         world_session.request.sendall(update_packet)
         world_session.request.sendall(item.query_details())
     else:
         GridManager.send_surrounding(update_packet, world_session.player_mgr, include_self=False)
         GridManager.send_surrounding(item.query_details(), world_session.player_mgr,
                                      include_self=False)
    def handle(world_session, socket, reader):
        if len(reader.data) >= 4:  # Avoid handling empty player macro packet
            category = unpack('<I', reader.data[:4])[0]
            if 0x0 <= category <= 0xD:
                voice_packet = PacketWriter.get_packet(OpCode.SMSG_PLAYER_MACRO,
                                                       pack('<QI', world_session.player_mgr.guid,
                                                            category))
                GridManager.send_surrounding(voice_packet, world_session.player_mgr, include_self=True)

        return 0
    def send_move_to(self, waypoints, speed, spline_flag):
        self.reset()
        self.speed = speed

        start_time = int(WorldManager.get_seconds_since_startup() * 1000)

        location_bytes = self.unit.location.to_bytes(include_orientation=False)
        data = pack(f'<Q{len(location_bytes)}sIBI', self.unit.guid,
                    location_bytes, start_time, 0, spline_flag)

        waypoints_data = b''
        waypoints_length = len(waypoints)
        last_waypoint = self.unit.location
        total_distance = 0
        total_time = 0
        current_id = 0
        for waypoint in waypoints:
            waypoints_data += waypoint.to_bytes(include_orientation=False)
            current_distance = last_waypoint.distance(waypoint)
            current_time = current_distance / speed
            total_distance += current_distance
            total_time += current_time

            self.pending_waypoints.append(
                PendingWaypoint(current_id, total_time, waypoint))
            last_waypoint = waypoint
            current_id += 1

        data += pack(f'<2I{len(waypoints_data)}s', int(total_time * 1000),
                     waypoints_length, waypoints_data)

        GridManager.send_surrounding(PacketWriter.get_packet(
            OpCode.SMSG_MONSTER_MOVE, data),
                                     self.unit,
                                     include_self=self.is_player)

        # Player shouldn't instantly dismount after reaching the taxi destination
        if self.is_player and spline_flag == SplineFlags.SPLINEFLAG_FLYING:
            self.total_waypoint_time = total_time + 1.0  # Add 1 extra second
        else:
            self.total_waypoint_time = total_time

        # Generate the spline
        spline = MovementSpline()
        spline.flags = spline_flag
        spline.spot = self.unit.location
        spline.guid = self.unit.guid
        spline.facing = self.unit.location.o
        spline.elapsed = 0
        spline.total_time = int(self.total_waypoint_time * 1000)
        spline.points = waypoints
        self.unit.movement_spline = spline

        self.last_position = self.unit.location
        self.should_update_waypoints = True
Beispiel #13
0
    def handle(world_session, socket, reader):
        # TODO Not working, wrong packet data, or animation not implemented client side?
        player_guid = pack('<Q', world_session.player_mgr.guid)
        mount_anim_packet = PacketWriter.get_packet(
            OpCode.SMSG_MOUNTSPECIAL_ANIM, player_guid)
        GridManager.send_surrounding(PacketWriter.get_packet(
            OpCode.SMSG_TEXT_EMOTE, mount_anim_packet),
                                     world_session.player_mgr,
                                     include_self=True)

        return 0
Beispiel #14
0
 def deal_spell_damage(self, target, damage, school,
                       spell_id):  # TODO Spell hit damage visual?
     data = pack('<IQQIIfiii', 1, self.guid, target.guid, spell_id, damage,
                 damage, school, damage, 0)
     packet = PacketWriter.get_packet(
         OpCode.SMSG_ATTACKERSTATEUPDATEDEBUGINFOSPELL, data)
     GridManager.send_surrounding(
         packet,
         target,
         include_self=target.get_type() == ObjectTypes.TYPE_PLAYER)
     self.deal_damage(target, damage)
Beispiel #15
0
    def change_turn_speed(self, turn_speed=0):
        if turn_speed <= 0:
            turn_speed = config.Unit.Player.Defaults.turn_speed
        self.turn_rate = turn_speed
        data = pack('<f', turn_speed)
        # TODO NOT WORKING
        self.session.request.sendall(
            PacketWriter.get_packet(OpCode.MSG_MOVE_SET_TURN_RATE_CHEAT, data))

        GridManager.send_surrounding(
            PacketWriter.get_packet(OpCode.SMSG_UPDATE_OBJECT,
                                    self.get_movement_update_packet()), self)
Beispiel #16
0
    def change_walk_speed(self, walk_speed=0):
        if walk_speed <= 0:
            walk_speed = config.Unit.Defaults.walk_speed
        elif walk_speed >= 56:
            walk_speed = 56  # Max speed without glitches
        self.walk_speed = walk_speed
        data = pack('<f', walk_speed)
        self.session.request.sendall(
            PacketWriter.get_packet(OpCode.MSG_MOVE_SET_WALK_SPEED, data))

        GridManager.send_surrounding(
            PacketWriter.get_packet(OpCode.SMSG_UPDATE_OBJECT,
                                    self.get_movement_update_packet()), self)
Beispiel #17
0
    def change_speed(self, speed=0):
        if speed <= 0:
            speed = config.Unit.Defaults.run_speed
        elif speed >= 56:
            speed = 56  # Max speed without glitches
        self.running_speed = speed
        data = pack('<f', speed)
        self.session.request.sendall(
            PacketWriter.get_packet(OpCode.SMSG_FORCE_SPEED_CHANGE, data))

        GridManager.send_surrounding(
            PacketWriter.get_packet(OpCode.SMSG_UPDATE_OBJECT,
                                    self.get_movement_update_packet()), self)
Beispiel #18
0
    def receive_damage(self, amount, source=None):
        is_player = self.get_type() == ObjectTypes.TYPE_PLAYER

        new_health = self.health - amount
        if new_health <= 0:
            self.die(killer=source)
        else:
            self.set_health(new_health)

        update_packet = self.generate_proper_update_packet(is_self=is_player)
        GridManager.send_surrounding(update_packet,
                                     self,
                                     include_self=is_player)
Beispiel #19
0
    def change_swim_speed(self, swim_speed=0):
        if swim_speed <= 0:
            swim_speed = config.Unit.Defaults.swim_speed
        elif swim_speed >= 56:
            swim_speed = 56  # Max possible swim speed
        self.swim_speed = swim_speed
        data = pack('<f', swim_speed)
        self.session.request.sendall(
            PacketWriter.get_packet(OpCode.SMSG_FORCE_SWIM_SPEED_CHANGE, data))

        GridManager.send_surrounding(
            PacketWriter.get_packet(OpCode.SMSG_UPDATE_OBJECT,
                                    self.get_movement_update_packet()), self)
Beispiel #20
0
    def send_cast_start(self, casting_spell):
        data = [self.unit_mgr.guid, self.unit_mgr.guid,
                casting_spell.spell_entry.ID, 0, casting_spell.get_base_cast_time(),
                casting_spell.spell_target_mask]

        signature = '<2QIHiH'  # TODO
        if casting_spell.initial_target_unit and casting_spell.spell_target_mask != SpellTargetMask.SELF:  # Some self-cast spells crash client if target is written
            data.append(casting_spell.initial_target_unit.guid)
            signature += 'Q'

        data = pack(signature, *data)
        GridManager.send_surrounding(PacketWriter.get_packet(OpCode.SMSG_SPELL_START, data), self.unit_mgr,
                                     include_self=self.unit_mgr.get_type() == ObjectTypes.TYPE_PLAYER)
Beispiel #21
0
    def teleport(self, map_, location):
        if not DbcDatabaseManager.map_get_by_id(map_):
            return False

        self.is_teleporting = True

        GridManager.send_surrounding(self.get_destroy_packet(), self, include_self=False)

        # Same map and not inside instance
        if self.map_ == map_ and self.map_ <= 1:
            data = pack(
                '<Q9fI',
                self.transport_id,
                self.transport.x,
                self.transport.y,
                self.transport.z,
                self.transport.o,
                location.x,
                location.y,
                location.z,
                location.o,
                0,  # ?
                0  # MovementFlags
            )
            self.session.request.sendall(PacketWriter.get_packet(OpCode.SMSG_MOVE_WORLDPORT_ACK, data))
        # Loading screen
        else:
            data = pack('<I', map_)
            self.session.request.sendall(PacketWriter.get_packet(OpCode.SMSG_TRANSFER_PENDING, data))

            data = pack(
                '<B4f',
                map_,
                location.x,
                location.y,
                location.z,
                location.o
            )

            self.session.request.sendall(PacketWriter.get_packet(OpCode.SMSG_NEW_WORLD, data))

        self.map_ = map_
        self.location.x = location.x
        self.location.y = location.y
        self.location.z = location.z
        self.location.o = location.o

        return True
Beispiel #22
0
    def send_update_surrounding(self,
                                update_packet,
                                include_self=False,
                                create=False):
        if not create:
            self.inventory.send_inventory_update(self.session, is_self=False)
            self.inventory.build_update()

        GridManager.send_surrounding(update_packet,
                                     self,
                                     include_self=include_self)
        if create:
            GridManager.send_surrounding(NameQueryHandler.get_query_details(
                self.player),
                                         self,
                                         include_self=True)
Beispiel #23
0
    def respawn(self, force_update=True):
        super().respawn()

        self.set_health(self.max_health)
        self.set_mana(self.max_power_1)

        self.is_spawned = True
        self.respawn_timer = 0
        self.respawn_time = randint(self.creature_instance.spawntimesecsmin,
                                    self.creature_instance.spawntimesecsmax)

        if force_update:
            GridManager.send_surrounding(
                self.generate_proper_update_packet(create=True),
                self,
                include_self=False)
    def handle_movement_status(world_session, socket, reader):
        movement_fmt = '<QfffffffffI'

        if not world_session.player_mgr.is_teleporting and len(
                reader.data
        ) >= 48:  # Avoid handling malformed movement packets
            try:
                transport_guid, transport_x, transport_y, transport_z, transport_o, x, y, z, o, pitch, flags = \
                    unpack(movement_fmt, reader.data[:48])

                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_orientation = 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

                movement_data = pack('<Q%us' % len(reader.data),
                                     world_session.player_mgr.guid,
                                     reader.data)

                GridManager.send_surrounding(PacketWriter.get_packet(
                    OpCode(reader.opcode), movement_data),
                                             world_session.player_mgr,
                                             include_self=False)
                GridManager.update_object(world_session.player_mgr)
                world_session.player_mgr.sync_player()

                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.flagged_for_update = True

            except (AttributeError, error):
                Logger.error('Error while handling %s, skipping. Data: %s' %
                             (OpCode(reader.opcode), reader.data))

        return 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)
                self.aura_manager.update(elapsed)
                # Movement Updates
                self.movement_manager.update_pending_waypoints(elapsed)
                # Random Movement
                if not self.in_combat and self.creature_instance.movement_type == MovementTypes.WANDER:
                    if len(self.movement_manager.pending_waypoints) == 0:
                        if now > self.last_random_movement + self.random_movement_wait_time:
                            self.movement_manager.move_random(
                                self.spawn_position,
                                self.creature_instance.wander_distance)
                            self.random_movement_wait_time = randint(1, 12)
                            self.last_random_movement = now
            # 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
                    GridManager.send_surrounding(self.get_destroy_packet(),
                                                 self,
                                                 include_self=False)
        self.last_tick = now

        if self.dirty:
            GridManager.send_surrounding(
                self.generate_proper_update_packet(create=False),
                self,
                include_self=False)
            GridManager.update_object(self)
            self.reset_fields()

            self.set_dirty(is_dirty=False)
    def respawn(self):
        super().respawn()

        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.is_spawned = True
        self.respawn_timer = 0
        self.respawn_time = randint(self.creature_instance.spawntimesecsmin,
                                    self.creature_instance.spawntimesecsmax)

        GridManager.send_surrounding(
            self.generate_proper_update_packet(create=True),
            self,
            include_self=False)
Beispiel #27
0
    def loot_item(self, slot):
        if self.current_selection > 0:
            enemy = GridManager.get_surrounding_unit_by_guid(
                self, self.current_selection, include_players=False)
            if enemy and enemy.loot_manager.has_loot():
                loot = enemy.loot_manager.get_loot_in_slot(slot)
                if not loot or not loot.item:
                    self.send_loot_release(enemy.guid)
                    return

                if self.inventory.add_item(
                        item_template=loot.item.item_template,
                        count=loot.quantity,
                        looted=True):
                    enemy.loot_manager.do_loot(slot)
                    data = pack('<B', slot)
                    GridManager.send_surrounding(
                        PacketWriter.get_packet(OpCode.SMSG_LOOT_REMOVED,
                                                data), self)

            if enemy and not enemy.loot_manager.has_loot():
                enemy.set_lootable(False)
Beispiel #28
0
    def end_duel(self, duel_winner_flag, duel_complete_flag, winner):
        if not self.arbiter or self.duel_state == DuelState.DUEL_STATE_FINISHED or not self.players:
            return

        # Set this first to prevent next tick to trigger.
        self.duel_state = DuelState.DUEL_STATE_FINISHED

        if duel_winner_flag == DuelWinner.DUEL_WINNER_KNOCKOUT:
            # TODO: Should trigger EMOTE BEG on loser?
            # TODO: Should root loser for 3 secs?
            pass

        # Send either the duel ended by natural means or if it was canceled/interrupted
        packet = PacketWriter.get_packet(OpCode.SMSG_DUEL_COMPLETE, pack('<B', duel_complete_flag))
        GridManager.send_surrounding(packet, self.arbiter)

        # Was not interrupted, broadcast duel result.
        if duel_complete_flag == DuelComplete.DUEL_FINISHED:
            winner_name_bytes = PacketWriter.string_to_bytes(winner.player.name)
            loser_name_bytes = PacketWriter.string_to_bytes(self.players[winner.guid].target.player.name)
            data = pack(f'<B{len(winner_name_bytes)}s{len(loser_name_bytes)}s', duel_winner_flag, winner_name_bytes,
                        loser_name_bytes)
            packet = PacketWriter.get_packet(OpCode.SMSG_DUEL_WINNER, data)
            GridManager.send_surrounding(packet, self.arbiter)

        packet = PacketWriter.get_packet(OpCode.SMSG_CANCEL_COMBAT)
        for entry in self.players.values():
            entry.player.session.enqueue_packet(packet)
            entry.player.leave_combat()
            self.build_update(entry.player)
            entry.player.set_dirty()

        # Clean up arbiter go and cleanup.
        GridManager.remove_object(self.arbiter)

        # Finally, flush this DualManager instance.
        self.flush()
Beispiel #29
0
 def send_melee_attack_start(self, victim_guid):
     data = pack('<2Q', self.guid, victim_guid)
     GridManager.send_surrounding(
         PacketWriter.get_packet(OpCode.SMSG_ATTACKSTART, data), self)
    def handle_movement_status(world_session, socket, reader):
        # 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)

                GridManager.send_surrounding(PacketWriter.get_packet(
                    OpCode(reader.opcode), movement_data),
                                             world_session.player_mgr,
                                             include_self=False)
                GridManager.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