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;
}
Сразу говрю, что тут у меня скорее всего немного избыточный список типов релейшнов, т.к. это с более свежих хроник - не факт что все из них были в ГФ.