Rogue 248 Опубликовано 15 марта, 2020 Почему-то на осаде замка творится дичь с иконками, они рандомно добавляются. Откуда они вообще бродкастятся? Новых релейшенов для осад не добавляли в гф, а у старых такие же байткоды. Откуда клиент узнает, какого цвета делать иконку и активную/неактивную? Кроме самого релейшена ничего не пересылают. Причем на клиент для разных иконок приходят разные числа, но откуда они берутся - непонятно, набор релейшенов то не менялся. Спойлер Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Rogue 248 Опубликовано 15 марта, 2020 (изменено) Хотя в принципе оно все верно показывается, если персы сделают что-нибудь, то иконка меняется на верную. Но вот на самом персонаже показывается неактивная иконка, это та, которая через юзеринфо приходит. Спойлер Изменено 15 марта, 2020 пользователем Rogue Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 16 марта, 2020 Приходят не "разные числа" а битовая маска. Ну а копать? ищи начиная с пакета RelationChanged, где идет формирование этой маски и что с ней не так. Еще как вариант возможно не шлется вовремя при входе/выходе в зоны или телепорте - тут можно долго гадать. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Rogue 248 Опубликовано 16 марта, 2020 (изменено) 59 минут назад, Gaikotsu сказал: Приходят не "разные числа" а битовая маска. Ну а копать? ищи начиная с пакета RelationChanged, где идет формирование этой маски и что с ней не так. Еще как вариант возможно не шлется вовремя при входе/выходе в зоны или телепорте - тут можно долго гадать. У меня больше подозрение закралось, что там надо всю систему релейшенов переносить. Там например появились куча левых типа 4 штук для пати и патилидера и прочие. Я так понимаю, маска собирается за счет проверки по всем этим релейшенам, которые в клиенте есть. Если проверок на эти "левые" не хватает, то маска наверное другая будет на выходе. С другой стороны оно бы не показывало верные значки, вместо просто неактивных. Тобишь когда к нам на клиент идет релейшенченжд обычный то все в порядке. А вот когда в юзеринфо маска приходит на твоего перса, то там лажа какая-то. Изменено 16 марта, 2020 пользователем Rogue Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Rogue 248 Опубликовано 19 марта, 2020 (изменено) Вообще вот смотрю на овере они просто в юзеринфо прямо делают getUserRelation на чара и не парятся. У меня же там хардкоженые конструкции по типу if (_activeChar.getSiegeState() == 1) _relation |= 0x180; if (_activeChar.getSiegeState() == 2) _relation |= 0x80; Но вот любая попытка сделать так же терпит фиаско, ибо символ не найден)) Хотя нужные методы и импорты есть, хз че ему надо. Изменено 19 марта, 2020 пользователем Rogue Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 19 марта, 2020 package l2p.gameserver.enums; public enum Relation { BATTLE_ZONE(1 << 0), PVP(1 << 1), PK(1 << 2), PARTY_MEMBER(1 << 3), // party member PARTY_LEADER(1 << 4), // true if is party leader HAS_PARTY(1 << 5), // true if is in party CLAN_MEMBER(1 << 6), // true if is in clan CLAN_LEADER(1 << 7), // true if is clan leader CLAN_MATE(1 << 8), // true if is in same clan IN_SIEGE(1 << 9), // true if in siege SIEGE_ATTACKER(1 << 10), // true when attacker SIEGE_ALLY(1 << 11), // blue siege icon, cannot have if red SIEGE_ENEMY(1 << 12), // true when red icon, doesn't matter with blue UNK_13(1 << 13), CLAN_WAR_1_SIDED(1 << 14), // single sword CLAN_WAR_2_SIDED(1 << 15), // double sword ALLY_MEMBER(1 << 16), // clan is in alliance ALLY_LEADER(1 << 17), // ally leader DUEL_ENEMY(1 << 18), TERRITORY_WAR(1 << 19), // in erritory war TERRITORY_WAR_ENEMY(1 << 20), // territory war enemy? BLOCK_CHECKER_BLUE(1 << 21), // block checker blue? BLOCK_CHECKER_RED(1 << 22), // block checker red? PVP_BLUE(1 << 23), // blue sword PVP_RED(1 << 24), // red sword PVP_MASTER(1 << 25); // blue/red sword + this = blue/red crown private final int _mask; Relation(int mask) { _mask = mask; } public int getMask() { return _mask; } } package l2p.gameserver.network.s2c; import static l2p.gameserver.network.s2c.ExSetCompassZoneCode.ZONE_PVP_FLAG; import java.util.ArrayList; import java.util.List; import l2p.gameserver.enums.ClanUnitType; import l2p.gameserver.enums.Relation; import l2p.gameserver.enums.TeamType; import l2p.gameserver.managers.games.HandysBlockCheckerManager; import l2p.gameserver.managers.games.HandysBlockCheckerManager.ArenaParticipantsHolder; import l2p.gameserver.model.Party; import l2p.gameserver.model.Playable; import l2p.gameserver.model.Player; import l2p.gameserver.model.clan.Clan; import l2p.gameserver.model.entity.events.GlobalEvent; public class RelationChanged extends L2GameServerPacket { public static final byte SEND_ONE = (byte) 0x00; public static final byte SEND_DEFAULT = (byte) 0x01; public static final byte SEND_MULTI = (byte) 0x04; private RelationData _single; private List<RelationData> _multi; private byte _mask = (byte) 0x00; public static class RelationData { int _objId; int _relation; int _autoAttackable; int _karma; int _pvpFlag; } public RelationChanged() { _mask |= SEND_MULTI; _multi = new ArrayList<RelationData>(); } public RelationChanged(Playable playable, boolean autoAttackable, int relation) { _mask |= SEND_ONE; _single = new RelationData(); _single._objId = playable.getObjectId(); _single._relation = relation; _single._autoAttackable = autoAttackable ? 1 : 0; _single._karma = playable.getKarma(); _single._pvpFlag = playable.getPvpFlag(); } public void add(RelationData data) { _multi.add(data); } @Override protected void writeImpl() { writeC(0xCE); writeC(_mask); if (_multi == null || _multi.isEmpty()) { writeRelation(_single); } else { writeH(_multi.size()); for (RelationData data : _multi) writeRelation(data); } } private void writeRelation(RelationData data) { writeD(data._objId); if ((_mask & SEND_DEFAULT) == 0) { writeD(data._relation); writeC(data._autoAttackable); writeD(data._karma); writeC(data._pvpFlag); } } /** * @param targetPlayable игрок, отношение к которому изменилось * @param activeChar игрок, которому будет отослан пакет с результатом */ public static L2GameServerPacket update(Player sendTo, Playable targetPlayable, Player activeChar) { if (sendTo == null || targetPlayable == null || activeChar == null) return null; Player targetPlayer = targetPlayable.getPlayer(); int relation = targetPlayer == null ? 0 : getRelation(targetPlayer, activeChar); return new RelationChanged(targetPlayable, targetPlayable.isTargetable() && targetPlayable.isAutoAttackable(activeChar, null), relation); } private static int getRelation(Player player, Player target) { int result = 0; if ((player.getZoneMask() & ZONE_PVP_FLAG) == ZONE_PVP_FLAG) result |= Relation.BATTLE_ZONE.getMask(); if (player.getPvpFlag() != 0) result |= Relation.PVP.getMask(); if (player.getKarma() < 0) result |= Relation.PK.getMask(); Clan clan1 = player.getClan(); Clan clan2 = target.getClan(); if (clan1 != null) { result |= Relation.CLAN_MEMBER.getMask(); if (player.isClanLeader()) result |= Relation.CLAN_LEADER.getMask(); if (clan1 == clan2) result |= Relation.CLAN_MATE.getMask(); if (clan1.getAllianceId() != 0) { result |= Relation.ALLY_MEMBER.getMask(); if (clan1.getAlliance().getLeader() == clan1 && player.isClanLeader()) result |= Relation.ALLY_LEADER.getMask(); } } if (clan1 != null && clan2 != null) { if (target.getUnitType() != ClanUnitType.ACADEMY && player.getUnitType() != ClanUnitType.ACADEMY && target.getChaosFestivalMode() < 2 && player.getChaosFestivalMode() < 2) { if (clan2.isAtWarWith(clan1)) { result |= Relation.CLAN_WAR_1_SIDED.getMask(); if (clan1.isAtWarWith(clan2)) result |= Relation.CLAN_WAR_2_SIDED.getMask(); } } } Party party = player.getParty(); if (party != null) { if (party == target.getParty()) result |= Relation.HAS_PARTY.getMask(); result |= Relation.PARTY_MEMBER.getMask(); if (party.isLeader(player)) result |= Relation.PARTY_LEADER.getMask(); } if (player.getBlockCheckerArena() != -1) { ArenaParticipantsHolder holder = HandysBlockCheckerManager.getInstance().getHolder(player.getBlockCheckerArena()); int team = holder.getPlayerTeam(player); if (team == 0) { result |= Relation.BLOCK_CHECKER_RED.getMask(); result |= Relation.PVP_RED.getMask(); } else if (team == 1) { result |= Relation.BLOCK_CHECKER_BLUE.getMask(); result |= Relation.PVP_BLUE.getMask(); } } if (player.getPvPEventMode() > 0) { int mode = player.getPvPEventMode(); TeamType team = player.getTeam(); if (mode == 2) { if (team == TeamType.RED) result |= Relation.PVP_RED.getMask(); else if (team == TeamType.BLUE) result |= Relation.PVP_BLUE.getMask(); } else { if (team != TeamType.NONE) result |= Relation.PVP_RED.getMask(); } } for (GlobalEvent e : player.getEvents()) result = e.getRelation(player, target, result); return result; } } Ну и дополняется маска еще в глобал эвентах, упаравляющих разными видами осад Например вот так public int getRelation(Player thisPlayer, Player targetPlayer, int result) { Clan clan1 = thisPlayer.getClan(); Clan clan2 = targetPlayer.getClan(); if (clan1 == null || clan2 == null) return result; SiegeEvent<?, ?> siegeEvent2 = targetPlayer.getEvent(SiegeEvent.class); if (this == siegeEvent2) { result |= Relation.IN_SIEGE.getMask(); if ((thisPlayer.getZoneMask() & ExSetCompassZoneCode.ZONE_SIEGE_FLAG) != ExSetCompassZoneCode.ZONE_SIEGE_FLAG) return result; SiegeClanObject siegeClan1 = getSiegeClan(SiegeEvent.ATTACKERS, clan1); SiegeClanObject siegeClan2 = getSiegeClan(SiegeEvent.ATTACKERS, clan2); if (siegeClan1 == null && siegeClan2 == null || siegeClan1 != null && siegeClan2 != null && isAttackersInAlly()) result |= Relation.SIEGE_ALLY.getMask(); else result |= Relation.SIEGE_ENEMY.getMask(); if (siegeClan1 != null) result |= Relation.SIEGE_ATTACKER.getMask(); } return result; } Сразу говрю, что тут у меня скорее всего немного избыточный список типов релейшнов, т.к. это с более свежих хроник - не факт что все из них были в ГФ. 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Rogue 248 Опубликовано 19 марта, 2020 (изменено) Спасибо за код конечно, но тут чтобы это адаптировать придется все ядро переписывать)) Релейшены работают нормально и корректно, как я выяснил. Проблема именно в том, чтобы достать нужное значение в пакете юзер инфо, проблема именно с локальным чаром по иконке. Изменено 19 марта, 2020 пользователем Rogue Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Rogue 248 Опубликовано 19 марта, 2020 В принципе просто заменю в клиенте эти неактивные иконки на активные и все, у меня все равно этих пенальти нет. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Gaikotsu 620 Опубликовано 19 марта, 2020 (изменено) а, ты про пенальти на получение славы при убийстве противников на осаде? того, что должно препятствовать фарму славы на одних и тех же целях нонстопом? кстати то, чтобы вовремя визуально обновлялся статус этого пенальти делается тоже влегкую. просто заведи таск, который будет запускаться в момент назначения пенальти и при выполнении при истечении времени пенальти (а для надежности даже чуть попозже, на пару сотен мс) будет просто вызывать броадкаст CharInfo для своевременного обновления видимого статуса. у меня именно так это работает. Изменено 19 марта, 2020 пользователем Gaikotsu Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты