테스트

aion-server 4.8

Gitteol
최고관리자 · 1 · 💬 0 클론/새로받기
 4.8 61f661d · 1 commits 새로받기(Pull)
game-server/src/com/aionemu/gameserver/services/siege/FortressSiege.java
package com.aionemu.gameserver.services.siege;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.commons.utils.Rnd;
import com.aionemu.gameserver.configs.main.LoggingConfig;
import com.aionemu.gameserver.configs.main.SiegeConfig;
import com.aionemu.gameserver.dao.SiegeDAO;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.PlayerCommonData;
import com.aionemu.gameserver.model.gameobjects.siege.SiegeNpc;
import com.aionemu.gameserver.model.items.ItemId;
import com.aionemu.gameserver.model.siege.ArtifactLocation;
import com.aionemu.gameserver.model.siege.FortressLocation;
import com.aionemu.gameserver.model.siege.SiegeModType;
import com.aionemu.gameserver.model.siege.SiegeRace;
import com.aionemu.gameserver.model.team.legion.Legion;
import com.aionemu.gameserver.model.team.legion.LegionHistoryAction;
import com.aionemu.gameserver.model.templates.npc.AbyssNpcType;
import com.aionemu.gameserver.model.templates.npc.NpcRating;
import com.aionemu.gameserver.model.templates.siegelocation.SiegeLegionReward;
import com.aionemu.gameserver.model.templates.siegelocation.SiegeMercenaryZone;
import com.aionemu.gameserver.model.templates.spawns.SpawnTemplate;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.services.LegionService;
import com.aionemu.gameserver.services.SiegeService;
import com.aionemu.gameserver.services.abyss.GloryPointsService;
import com.aionemu.gameserver.services.mail.AbyssSiegeLevel;
import com.aionemu.gameserver.services.mail.MailFormatter;
import com.aionemu.gameserver.services.mail.SiegeResult;
import com.aionemu.gameserver.services.player.PlayerService;
import com.aionemu.gameserver.skillengine.SkillEngine;
import com.aionemu.gameserver.spawnengine.SpawnEngine;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.ThreadPoolManager;
import com.aionemu.gameserver.world.World;

/**
 * Object that controls siege of certain fortress. Siege object is not reusable. New siege = new instance.
 * <p/>
 *
 * @author SoulKeeper
 */
public class FortressSiege extends Siege<FortressLocation> {

	private static final Logger log = LoggerFactory.getLogger("SIEGE_LOG");
	private final Map<Integer, MercenaryLocation> activeMercenaryLocs = new ConcurrentHashMap<>();
	private int oldLegionId;

	public FortressSiege(FortressLocation fortress) {
		super(fortress);
	}

	@Override
	public void onSiegeStart() {
		if (LoggingConfig.LOG_SIEGE)
			log.info(this + ": Siege started. Race: " + getSiegeLocation().getRace() + ", legion ID: " + getSiegeLocation().getLegionId());
		// Mark fortress as vulnerable
		getSiegeLocation().setVulnerable(true);

		// Let the world know where the siege is
		broadcastState(getSiegeLocation());

		// Clear fortress from enemys
		getSiegeLocation().clearLocation();

		// Remove all and spawn siege NPCs
		despawnNpcs(getSiegeLocationId());
		spawnNpcs(getSiegeLocationId(), getSiegeLocation().getRace(), SiegeModType.SIEGE);
		initSiegeBoss();
		this.oldLegionId = getSiegeLocation().getLegionId();
		if (getSiegeLocation().getRace() != SiegeRace.BALAUR) {
			initMercenaryZones();
			getSiegeLocation().forEachPlayer(p -> getSiegeLocation().checkForBalanceBuff(p, FortressLocation.SiegeBuffAction.ADD));
			if (getBoss().getLevel() == 65) {
				SiegeRace oppositeRace = getSiegeLocation().getRace() == SiegeRace.ELYOS ? SiegeRace.ASMODIANS : SiegeRace.ELYOS;
				ThreadPoolManager.getInstance().schedule(() -> spawnFactionTroopAssault(oppositeRace), Rnd.get(600, 1800) * 1000); // Faction Balance NPCs
			}
		}
		// Check for Balaur Assault
		if (SiegeConfig.BALAUR_AUTO_ASSAULT)
			BalaurAssaultService.getInstance().onSiegeStart(this);
	}

	/**
	 * Handles an additional assault of race-specific troops (asmo/ely only), to ensure players glory point rewards
	 */
	private void spawnFactionTroopAssault(SiegeRace race) {
		if (!getSiegeLocation().isVulnerable())
			return;

		final int worldId = getSiegeLocation().getWorldId();
		for (SiegeNpc sn : World.getInstance().getLocalSiegeNpcs(getSiegeLocationId())) {
			if (sn.getAbyssNpcType() == AbyssNpcType.ARTIFACT || sn.getRating() == NpcRating.LEGENDARY
				|| sn.getSpawn().getSiegeModType() == SiegeModType.ASSAULT || Rnd.chance() < 35)
				continue;
			final int amount = Rnd.get(1, 2);
			for (int i = 0; i < amount; i++) {
				double angleRadians = Math.toRadians(Rnd.nextFloat(180f));
				float x1 = (float) (sn.getX() + Math.cos(angleRadians) * Rnd.get(1, 2));
				float y1 = (float) (sn.getY() + Math.sin(angleRadians) * Rnd.get(1, 2));
				SpawnTemplate temp = SpawnEngine.newSiegeSpawn(worldId, race == SiegeRace.ELYOS ? Rnd.get(252408, 252412) : Rnd.get(252413, 252417),
					getSiegeLocationId(), race, SiegeModType.ASSAULT, x1, y1, sn.getZ(), (byte) 0);
				SpawnEngine.spawnObject(temp, 1);
			}
		}
	}

	private void initMercenaryZones() {
		List<SiegeMercenaryZone> mercs = getSiegeLocation().getSiegeMercenaryZones(); // can be null if not implemented
		if (mercs == null)
			return;
		for (SiegeMercenaryZone zone : mercs) {
			MercenaryLocation mLoc = new MercenaryLocation(zone, getSiegeLocation().getRace(), getSiegeLocationId());
			activeMercenaryLocs.put(zone.getId(), mLoc);
		}
	}

	@Override
	public void onSiegeFinish() {
		if (LoggingConfig.LOG_SIEGE) {
			SiegeRace oldRace = getSiegeLocation().getRace();
			int oldLegionId = getSiegeLocation().getLegionId();
			if (isBossKilled()) {
				SiegeRaceCounter winner = getSiegeCounter().getWinnerRaceCounter();
				log.info(this + ": Siege finished. Old race: " + oldRace + ", legion ID: " + oldLegionId + " -> New race: " + winner.getSiegeRace()
					+ ", legion ID: " + (winner.getWinnerLegionId() == null ? 0 : winner.getWinnerLegionId()));
			} else {
				log.info(this + ": Siege finished. No winner found. Race: " + oldRace + ", legion ID: " + oldLegionId);
			}
		}

		// Unregister siege boss listeners
		// cleanup :)
		unregisterSiegeBossListeners();

		// despawn protectors and make fortress invulnerable
		SiegeService.getInstance().deSpawnNpcs(getSiegeLocationId());
		// need to remove balance buff before vulnerability is set to false
		getSiegeLocation().forEachPlayer(p -> getSiegeLocation().checkForBalanceBuff(p, FortressLocation.SiegeBuffAction.SIEGE_END_REMOVE));
		getSiegeLocation().setVulnerable(false);
		getSiegeLocation().setUnderShield(false);

		// Guardian deity general was not killed, fortress stays with previous
		if (isBossKilled()) {
			onCapture();
			broadcastUpdate(getSiegeLocation());
		} else {
			onDefended();
			broadcastState(getSiegeLocation());
		}
		getSiegeLocation().adjustFactionBalance(getFactionBalanceAdjustment());

		SiegeService.getInstance().spawnNpcs(getSiegeLocationId(), getSiegeLocation().getRace(), SiegeModType.PEACE);

		// Reward players and owning legion
		SiegeRace winnerRace = getSiegeLocation().getRace();
		if (winnerRace != SiegeRace.BALAUR) {
			SiegeRace loserRace = winnerRace == SiegeRace.ASMODIANS ? SiegeRace.ELYOS : SiegeRace.ASMODIANS;
			SiegeRaceCounter winnerRaceCounter = getSiegeCounter().getRaceCounter(winnerRace);
			SiegeRaceCounter loserRaceCounter = getSiegeCounter().getRaceCounter(loserRace);
			sendRewardsToParticipants(winnerRaceCounter, isBossKilled() ? SiegeResult.OCCUPY : SiegeResult.DEFENDER);
			sendRewardsToParticipants(loserRaceCounter, isBossKilled() ? SiegeResult.FAIL : SiegeResult.EMPTY);
			distributeLegionRewards(winnerRaceCounter);
		} else if (SiegeConfig.SIEGE_REWARD_BALAUR_VICTORY) {
			sendRewardsToParticipants(getSiegeCounter().getRaceCounter(SiegeRace.ASMODIANS), isBossKilled() ? SiegeResult.FAIL : SiegeResult.EMPTY);
			sendRewardsToParticipants(getSiegeCounter().getRaceCounter(SiegeRace.ELYOS), isBossKilled() ? SiegeResult.FAIL : SiegeResult.EMPTY);
		}

		// Update outpost status
		// Certain fortresses are changing outpost ownership
		updateOutpostStatusByFortress(getSiegeLocation());

		// Update data in the DB
		SiegeDAO.updateSiegeLocation(getSiegeLocation());
		if (isBossKilled()) {
			getSiegeLocation().forEachPlayer(p -> {
				if (SiegeRace.getByRace(p.getRace()) == getSiegeLocation().getRace())
					QuestEngine.getInstance().onKill(new QuestEnv(getBoss(), p, 0));
			});
		}
	}

	private void onCapture() {
		SiegeRaceCounter winner = getSiegeCounter().getWinnerRaceCounter();
		SiegeRace winnerRace = winner.getSiegeRace();
		SiegeRace oldRace = getSiegeLocation().getRace();
		Legion oldLegion = oldLegionId == 0 ? null : LegionService.getInstance().getLegion(oldLegionId);

		// Players gain buffs on capture of some fortresses
		applyWorldBuffs(winnerRace, false);
		// Set new fortress and artifact owner race
		getSiegeLocation().setRace(winnerRace);
		getArtifact().setRace(winnerRace);

		// reset occupy count
		getSiegeLocation().setOccupiedCount(winnerRace == SiegeRace.BALAUR ? 0 : 1);

		// If new race is balaur
		if (SiegeRace.BALAUR == winnerRace) {
			getSiegeLocation().setLegionId(0);
			getArtifact().setLegionId(0);
		} else {
			Integer topLegionId = winner.getWinnerLegionId();
			getSiegeLocation().setLegionId(topLegionId != null ? topLegionId : 0);
			getArtifact().setLegionId(topLegionId != null ? topLegionId : 0);
		}

		// announce
		String locL10n = getSiegeLocation().getTemplate().getL10n();
		Legion winnerLegion = getSiegeLocation().getLegionId() == 0 ? null : LegionService.getInstance().getLegion(getSiegeLocation().getLegionId());
		SM_SYSTEM_MESSAGE loserMsg = getLoserMsg(oldRace, oldLegion, locL10n);
		SM_SYSTEM_MESSAGE winnerMsg = getWinnerMsg(winnerRace, winnerLegion, locL10n);
		World.getInstance().forEachPlayer(player -> {
			if (player.getRace().getRaceId() == oldRace.getRaceId())
				PacketSendUtility.sendPacket(player, loserMsg);
			else
				PacketSendUtility.sendPacket(player, winnerMsg);
		});
	}

	private SM_SYSTEM_MESSAGE getWinnerMsg(SiegeRace winnerRace, Legion winnerLegion, String locationName) {
		if (winnerLegion == null)
			return SM_SYSTEM_MESSAGE.STR_ABYSS_WIN_CASTLE(winnerRace.getL10n(), locationName);
		else
			return SM_SYSTEM_MESSAGE.STR_ABYSS_GUILD_WIN_CASTLE(winnerLegion.getName(), locationName);
	}

	private SM_SYSTEM_MESSAGE getLoserMsg(SiegeRace loserRace, Legion oldLegion, String locationName) {
		if (oldLegion == null)
			return SM_SYSTEM_MESSAGE.STR_ABYSS_CASTLE_TAKEN(loserRace.getL10n(), locationName);
		else
			return SM_SYSTEM_MESSAGE.STR_ABYSS_GUILD_CASTLE_TAKEN(oldLegion.getName(), locationName);
	}

	private int getFactionBalanceAdjustment() {
		switch (getSiegeLocation().getRace()) {
			case ELYOS:
				return 1;
			case ASMODIANS:
				return -1;
			case BALAUR:
				int b = getSiegeLocation().getFactionBalance();
				if (b > 0)
					return -1;
				else if (b < 0)
					return 1;
		}
		return 0;
	}

	private void onDefended() {
		// Increase fortress occupied count
		if (getSiegeLocation().getRace() != SiegeRace.BALAUR && getSiegeLocation().getTemplate().getMaxOccupyCount() > 0) {
			getSiegeLocation().increaseOccupiedCount();
		}

		// Players gain buffs for successfully defense / failed capture the fortress
		applyWorldBuffs(getSiegeLocation().getRace(), true);
	}

	private void applyWorldBuffs(SiegeRace winner, boolean isDefense) {
		final int skillId;

		switch (getSiegeLocation().getLocationId()) {
			case 1131:
				skillId = 12147;
				break;
			case 1132:
				skillId = 12148;
				break;
			case 1141:
				skillId = 12149;
				break;
			case 1221:
				skillId = 12075;
				break;
			case 1231:
				skillId = 12076;
				break;
			case 1241:
				skillId = 12077;
				break;
			case 1251:
				skillId = 12074;
				break;
			case 2011:
				skillId = 12155;
				break;
			case 2021:
				skillId = 12156;
				break;
			case 3011:
				skillId = 12157;
				break;
			case 3021:
				skillId = 12158;
				break;
			default:
				return;
		}

		String skillL10n = DataManager.SKILL_DATA.getSkillTemplate(skillId).getL10n();
		SM_SYSTEM_MESSAGE notification = isDefense
			? SM_SYSTEM_MESSAGE.STR_CASTLE_DEFENCE_WIN_BUFF_ON(winner.getL10n(), getSiegeLocation().getTemplate().getL10n(), skillL10n)
			: SM_SYSTEM_MESSAGE.STR_CASTLE_WIN_BUFF_ON(winner.getL10n(), getSiegeLocation().getTemplate().getL10n(), skillL10n);
		World.getInstance().forEachPlayer(player -> {
			if (player.getRace().getRaceId() == winner.getRaceId()) {
				SkillEngine.getInstance().applyEffectDirectly(skillId, player, player);
				PacketSendUtility.sendPacket(player, notification);
			}
		});
	}

	private void distributeLegionRewards(SiegeRaceCounter winnerRaceCounter) {
		int legionId = getSiegeLocation().getLegionId();
		Legion legion = legionId == 0 ? null : LegionService.getInstance().getLegion(legionId);
		if (legion == null) {
			if (LoggingConfig.LOG_SIEGE)
				log.info(this + ": Skipped sending legion rewards because the fortress is not owned by any legion (owner race: "
					+ getSiegeLocation().getRace() + ").");
			return;
		}
		distributeLegionGp(legion, winnerRaceCounter);
		distributeLegionRewards(legion);
	}

	private void distributeLegionGp(Legion legion, SiegeRaceCounter src) {
		int legionGp = getSiegeLocation().getLegionGp();
		if (legionGp <= 0)
			return;
		try {
			Set<Integer> participatedLegionMembers = new HashSet<>(src.getPlayerAbyssPoints().keySet());
			participatedLegionMembers.retainAll(legion.getLegionMembers());

			if (participatedLegionMembers.isEmpty()) {
				if (LoggingConfig.LOG_SIEGE)
					log.info(this + ": Distributed no GP to the members of " + legion + " because no one made AP");
			} else {
				int gp = Math.min(Math.round(legionGp / (float) participatedLegionMembers.size()), SiegeConfig.LEGION_GP_CAP_PER_MEMBER);
				for (int participant : participatedLegionMembers)
					GloryPointsService.increaseGpBy(participant, gp);
				if (LoggingConfig.LOG_SIEGE)
					log.info(this + ": Distributed " + gp + " GP each, to the following members of " + legion + ": " + participatedLegionMembers);
			}
		} catch (Exception e) {
			log.error("Error while distributing legion GP for " + this, e);
		}
	}

	private void distributeLegionRewards(Legion legion) {
		List<SiegeLegionReward> legionRewards = getSiegeLocation().getLegionRewards();
		if (legionRewards == null || legionRewards.isEmpty())
			return;
		try {
			long totalKinah = 0;
			int nonKinahItems = 0;
			PlayerCommonData brigadeGeneral = PlayerService.getOrLoadPlayerCommonData(legion.getBrigadeGeneral());
			for (SiegeLegionReward item : legionRewards) {
				if (item.getItemId() == ItemId.KINAH) {
					long kinah = isBossKilled() ? item.getItemCount() : Math.round(item.getItemCount() * 0.7f);
					legion.getLegionWarehouse().increaseKinah(kinah);
					LegionService.getInstance().addRewardHistory(legion, kinah, isBossKilled() ? LegionHistoryAction.OCCUPATION : LegionHistoryAction.DEFENSE,
						getSiegeLocationId());
					totalKinah += kinah;
				} else {
					nonKinahItems++;
					MailFormatter.sendAbyssRewardMail(getSiegeLocation(), brigadeGeneral, AbyssSiegeLevel.NONE, SiegeResult.PROTECT, System.currentTimeMillis(),
						item.getItemId(), item.getItemCount(), 0);
				}
			}
			if (LoggingConfig.LOG_SIEGE) {
				String msg = "";
				if (totalKinah > 0)
					msg += "Added " + totalKinah + " kinah to the legion warehouse";
				if (nonKinahItems > 0)
					msg += (msg.isEmpty() ? "Sent " : " and sent ") + nonKinahItems + " legion rewards to brigade general " + brigadeGeneral.getName() + " of "
						+ legion + " (see sysmail.log)";
				log.info(this + ": " + msg);
			}
		} catch (Exception e) {
			log.error("Error while distributing legion rewards for " + this, e);
		}
	}

	@Override
	public boolean isEndless() {
		return false;
	}

	@Override
	public void onAbyssPointsAdded(Player player, int abyssPoints) {
		if (getSiegeLocation().isVulnerable() && getSiegeLocation().isInsideLocation(player))
			getSiegeCounter().addAbyssPoints(player, abyssPoints);
	}

	protected ArtifactLocation getArtifact() {
		return SiegeService.getInstance().getFortressArtifact(getSiegeLocationId());
	}

	protected boolean hasArtifact() {
		return getArtifact() != null;
	}

	public MercenaryLocation getMercenaryLocationByZoneId(int zoneId) {
		return activeMercenaryLocs.get(zoneId);
	}
}

📎 첨부파일

댓글 작성 권한이 없습니다.
🏆 포인트 랭킹 TOP 10
순위 닉네임 포인트
1 no_profile 타키야겐지쪽지보내기 자기소개 아이디로 검색 전체게시물 102,949
2 no_profile 동가리쪽지보내기 자기소개 아이디로 검색 전체게시물 63,733
3 no_profile 라프텔쪽지보내기 자기소개 아이디로 검색 전체게시물 51,771
4 no_profile 불멸의행복쪽지보내기 자기소개 아이디로 검색 전체게시물 36,923
5 서번트쪽지보내기 자기소개 아이디로 검색 전체게시물 35,011
6 no_profile 닥터스쪽지보내기 자기소개 아이디로 검색 전체게시물 29,470
7 no_profile 검은고양이쪽지보내기 자기소개 아이디로 검색 전체게시물 29,077
8 no_profile Revolution쪽지보내기 자기소개 아이디로 검색 전체게시물 28,199
9 no_profile 보거스쪽지보내기 자기소개 아이디로 검색 전체게시물 26,731
10 no_profile 호롤롤로쪽지보내기 자기소개 아이디로 검색 전체게시물 17,020
알림 0