694 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			694 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * This file is part of the L2J Mobius project.
 | |
|  * 
 | |
|  * This program is free software: you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License as published by
 | |
|  * the Free Software Foundation, either version 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  * 
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 | |
|  * General Public License for more details.
 | |
|  * 
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| package instances.IstinaCavern;
 | |
| 
 | |
| import java.util.Comparator;
 | |
| import java.util.Map;
 | |
| import java.util.concurrent.ConcurrentHashMap;
 | |
| 
 | |
| import com.l2jmobius.Config;
 | |
| import com.l2jmobius.gameserver.enums.CategoryType;
 | |
| import com.l2jmobius.gameserver.enums.Movie;
 | |
| import com.l2jmobius.gameserver.model.AggroInfo;
 | |
| import com.l2jmobius.gameserver.model.DamageDoneInfo;
 | |
| import com.l2jmobius.gameserver.model.Location;
 | |
| import com.l2jmobius.gameserver.model.StatsSet;
 | |
| import com.l2jmobius.gameserver.model.actor.L2Attackable;
 | |
| import com.l2jmobius.gameserver.model.actor.L2Character;
 | |
| import com.l2jmobius.gameserver.model.actor.L2Npc;
 | |
| import com.l2jmobius.gameserver.model.actor.instance.L2DoorInstance;
 | |
| import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
 | |
| import com.l2jmobius.gameserver.model.holders.SkillHolder;
 | |
| import com.l2jmobius.gameserver.model.instancezone.Instance;
 | |
| import com.l2jmobius.gameserver.model.skills.Skill;
 | |
| import com.l2jmobius.gameserver.network.NpcStringId;
 | |
| import com.l2jmobius.gameserver.network.serverpackets.ExSendUIEvent;
 | |
| import com.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
 | |
| import com.l2jmobius.gameserver.network.serverpackets.PlaySound;
 | |
| import com.l2jmobius.gameserver.util.Util;
 | |
| 
 | |
| import instances.AbstractInstance;
 | |
| 
 | |
| /**
 | |
|  * Istina Cavern instance zone.
 | |
|  * @author St3eT
 | |
|  */
 | |
| public final class IstinaCavern extends AbstractInstance
 | |
| {
 | |
| 	// NPCs
 | |
| 	private static final int RUMIESE = 33151;
 | |
| 	private static final int RUMIESE_INSTANCE = 33293;
 | |
| 	private static final int INVISIBLE_NPC = 18919;
 | |
| 	private static final int BALLISTA = 19021;
 | |
| 	private static final int EXTREME_MINION = 23125;
 | |
| 	private static final int[] ISTINA =
 | |
| 	{
 | |
| 		29195, // Istina (Common)
 | |
| 		29196, // Istina (Extreme)
 | |
| 	};
 | |
| 	// Skills
 | |
| 	private static final SkillHolder ERUPTION_1 = new SkillHolder(14222, 1);
 | |
| 	private static final SkillHolder ERUPTION_2 = new SkillHolder(14223, 1);
 | |
| 	private static final SkillHolder ISTINA_ERUPTION_SKILL = new SkillHolder(14221, 1);
 | |
| 	// Items
 | |
| 	private static final int CONTROL_DEVICE = 17608; // Energy Control Device
 | |
| 	private static final int REWARD_BOX_COMMON = 30371; // Box Containing Magic Power
 | |
| 	private static final int REWARD_BOX_EXTREME = 30374; // Magic Filled Box
 | |
| 	// Locations
 | |
| 	private static final Location DEFEAT_ISTINA_LOC = new Location(-177120, 148782, -11384, 49140);
 | |
| 	private static final Location RUMIESE_LOC = new Location(-177001, 147844, -11380, 47684);
 | |
| 	private static final Location BATTLE_LOC = new Location(-177111, 146802, -11384);
 | |
| 	// Misc
 | |
| 	private static final int PERFECT_SCORE_1 = 30000000;
 | |
| 	private static final int PERFECT_SCORE_2 = 300000000;
 | |
| 	private static final int TEMPLATE_ID_COMMON = 169;
 | |
| 	private static final int TEMPLATE_ID_EXTREME = 170;
 | |
| 	
 | |
| 	public IstinaCavern()
 | |
| 	{
 | |
| 		addStartNpc(RUMIESE);
 | |
| 		addTalkId(RUMIESE, RUMIESE_INSTANCE);
 | |
| 		addFirstTalkId(RUMIESE_INSTANCE);
 | |
| 		addAttackId(ISTINA);
 | |
| 		addAttackId(BALLISTA);
 | |
| 		addSpellFinishedId(ISTINA);
 | |
| 		addSpellFinishedId(INVISIBLE_NPC);
 | |
| 		addSpawnId(INVISIBLE_NPC, BALLISTA);
 | |
| 	}
 | |
| 	
 | |
| 	@Override
 | |
| 	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
 | |
| 	{
 | |
| 		String htmltext = null;
 | |
| 		final Instance instance = npc.getInstanceWorld();
 | |
| 		if (isIstinaInstance(instance))
 | |
| 		{
 | |
| 			switch (event)
 | |
| 			{
 | |
| 				case "leaveInstance":
 | |
| 				{
 | |
| 					teleportPlayerOut(player, instance);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "battleTeleport":
 | |
| 				{
 | |
| 					player.teleToLocation(BATTLE_LOC);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "giveDevice":
 | |
| 				{
 | |
| 					if (!hasQuestItems(player, CONTROL_DEVICE))
 | |
| 					{
 | |
| 						giveItems(player, CONTROL_DEVICE, 1);
 | |
| 						htmltext = "33293-06.html";
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						htmltext = "33293-07.html";
 | |
| 					}
 | |
| 				}
 | |
| 				case "giveReward":
 | |
| 				{
 | |
| 					if (instance.isStatus(3))
 | |
| 					{
 | |
| 						if (npc.getVariables().getBoolean("PLAYER_" + player.getObjectId(), true))
 | |
| 						{
 | |
| 							giveItems(player, (isExtremeMode(instance) ? REWARD_BOX_EXTREME : REWARD_BOX_COMMON), 1);
 | |
| 							npc.getVariables().set("PLAYER_" + player.getObjectId(), false);
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							htmltext = "33293-08.html";
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if (event.equals("enterInstanceCommon"))
 | |
| 			{
 | |
| 				enterInstance(player, npc, TEMPLATE_ID_COMMON);
 | |
| 			}
 | |
| 			else if (event.equals("enterInstanceExtreme"))
 | |
| 			{
 | |
| 				enterInstance(player, npc, TEMPLATE_ID_EXTREME);
 | |
| 			}
 | |
| 		}
 | |
| 		return htmltext;
 | |
| 	}
 | |
| 	
 | |
| 	@Override
 | |
| 	public void onTimerEvent(String event, StatsSet params, L2Npc npc, L2PcInstance player)
 | |
| 	{
 | |
| 		final Instance instance = npc.getInstanceWorld();
 | |
| 		if (isIstinaInstance(instance))
 | |
| 		{
 | |
| 			final StatsSet npcParams = npc.getParameters();
 | |
| 			final StatsSet npcVars = npc.getVariables();
 | |
| 			switch (event)
 | |
| 			{
 | |
| 				case "DEATH_TIMER":
 | |
| 				{
 | |
| 					final L2Character mostHated = ((L2Attackable) npc).getMostHated();
 | |
| 					if ((mostHated != null) && npc.isInsideRadius(mostHated, 15000, false, true))
 | |
| 					{
 | |
| 						final SkillHolder death1 = npcParams.getSkillHolder("Istina_Death_Skill01");
 | |
| 						final SkillHolder death2 = npcParams.getSkillHolder("Istina_Death_Skill02");
 | |
| 						
 | |
| 						if (mostHated.isInCategory(CategoryType.TANKER_GROUP))
 | |
| 						{
 | |
| 							addSkillCastDesire(npc, mostHated, (mostHated.isAffectedBySkill(death1) ? death2 : death1), 23);
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							addSkillCastDesire(npc, mostHated, death2, 23);
 | |
| 						}
 | |
| 					}
 | |
| 					getTimers().addTimer("DEATH_TIMER", 35000, npc, null);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "DEATH_CHECK_TIMER":
 | |
| 				{
 | |
| 					final SkillHolder death1 = npcParams.getSkillHolder("Istina_Death_Skill01");
 | |
| 					final SkillHolder death2 = npcParams.getSkillHolder("Istina_Death_Skill02");
 | |
| 					final L2Character mostHated = ((L2Attackable) npc).getMostHated();
 | |
| 					
 | |
| 					if ((mostHated != null) && npc.isInsideRadius(mostHated, 15000, false, true) && mostHated.isInCategory(CategoryType.TANKER_GROUP) && mostHated.isAffectedBySkill(death1))
 | |
| 					{
 | |
| 						addSkillCastDesire(npc, mostHated, death2, 23);
 | |
| 					}
 | |
| 					break;
 | |
| 				}
 | |
| 				case "REFLECT_TIMER":
 | |
| 				{
 | |
| 					if (!isExtremeMode(instance))
 | |
| 					{
 | |
| 						showOnScreenMsg(instance, NpcStringId.ISTINA_SPREADS_THE_REFLECTING_PROTECTIVE_SHEET, ExShowScreenMessage.TOP_CENTER, 4000);
 | |
| 					}
 | |
| 					final SkillHolder reflect = npcParams.getSkillHolder("Istina_Refraction_Skill");
 | |
| 					npc.setTarget(npc);
 | |
| 					npc.doCast(reflect.getSkill());
 | |
| 					instance.broadcastPacket(new PlaySound(1, "Npcdialog1.istina_voice_02", 0, 0, 0, 0, 0));
 | |
| 					getTimers().addTimer("REFLECT_TIMER", 90000 + getRandom(15000), npc, null);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "REFLECT_CHECK_TIMER":
 | |
| 				{
 | |
| 					if (npc.isAffectedBySkill(npcParams.getSkillHolder("Istina_Refraction_Skill")))
 | |
| 					{
 | |
| 						getTimers().addTimer("REFLECT_CHECK_TIMER", 1000, npc, null);
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						npc.setDisplayEffect(2);
 | |
| 					}
 | |
| 					break;
 | |
| 				}
 | |
| 				case "LOW_ERUPTION_TIMER":
 | |
| 				{
 | |
| 					final L2Attackable istina = (L2Attackable) npc;
 | |
| 					if ((istina.getHateList() != null) && (istina.getHateList().size() > 0))
 | |
| 					{
 | |
| 						final L2Character target = istina.getHateList().stream().sorted((o1, o2) -> (int) o1.calculateDistance(o2, true, false)).findFirst().orElse(null);
 | |
| 						if (target != null)
 | |
| 						{
 | |
| 							final L2Npc eruption = addSpawn(INVISIBLE_NPC, Util.getRandomPosition(target, 50, 50), false, 0, false, instance.getId());
 | |
| 							eruption.getVariables().set("ERUPTION_TARGET", target);
 | |
| 						}
 | |
| 					}
 | |
| 					getTimers().addTimer("LOW_ERUPTION_TIMER", 15000, npc, null);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "ERUPTION_TIMER":
 | |
| 				{
 | |
| 					addSkillCastDesire(npc, npc, ISTINA_ERUPTION_SKILL, 23);
 | |
| 					showOnScreenMsg(instance, NpcStringId.POWERFUL_ACIDIC_ENERGY_IS_ERUPTING_FROM_ISTINA_S_BODY, ExShowScreenMessage.TOP_CENTER, 6000);
 | |
| 					getTimers().addTimer("ERUPTION_TIMER", 50000 + getRandom(15000), npc, null);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "BALLISTA_START_TIMER":
 | |
| 				{
 | |
| 					final int helpCountDown = npcVars.getInt("HELP_COUNT_DOWN", 5);
 | |
| 					if (helpCountDown == 0)
 | |
| 					{
 | |
| 						getTimers().addTimer("BALLISTA_CHECK_TIMER", 1000, npc, null);
 | |
| 						npc.setTargetable(true);
 | |
| 						npc.setIsInvul(false);
 | |
| 						npcVars.set("COUNTING_ENABLED", true);
 | |
| 						showOnScreenMsg(instance, NpcStringId.START_CHARGING_MANA_BALLISTA, ExShowScreenMessage.MIDDLE_CENTER, 4000);
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						showOnScreenMsg(instance, NpcStringId.AFTER_S1_SECONDS_THE_CHARGING_MAGIC_BALLISTAS_STARTS, ExShowScreenMessage.MIDDLE_CENTER, 4000, Integer.toString(helpCountDown));
 | |
| 						npcVars.set("HELP_COUNT_DOWN", helpCountDown - 1);
 | |
| 						getTimers().addTimer("BALLISTA_START_TIMER", 1000, npc, null);
 | |
| 					}
 | |
| 					break;
 | |
| 				}
 | |
| 				case "BALLISTA_CHECK_TIMER":
 | |
| 				{
 | |
| 					if (npcVars.getBoolean("COUNTING_ENABLED", false))
 | |
| 					{
 | |
| 						final int countDown = npcVars.getInt("COUNT_DOWN", 30);
 | |
| 						final int charged = getChargedPercent(npcVars.getInt("SCORE_VAL", 0), isExtremeMode(instance));
 | |
| 						
 | |
| 						if (countDown == 0)
 | |
| 						{
 | |
| 							npcVars.set("COUNTING_ENABLED", false);
 | |
| 							npc.setTargetable(false);
 | |
| 							npc.setIsInvul(true);
 | |
| 							getTimers().addTimer("BALLISTA_END_TIMER", 1000, npc, null);
 | |
| 							instance.getPlayers().forEach(temp -> temp.sendPacket(new ExSendUIEvent(temp, 2, countDown, charged, 0, 2042, 0, NpcStringId.REPLENISH_BALLISTA_MAGIC_POWER.getId())));
 | |
| 						}
 | |
| 						
 | |
| 						npcVars.set("HELP_COUNT_DOWN", npcVars.getInt("HELP_COUNT_DOWN", 0) + 1);
 | |
| 						if (npcVars.getInt("HELP_COUNT_DOWN", 0) == 2)
 | |
| 						{
 | |
| 							npcVars.set("COUNT_DOWN", countDown - 1);
 | |
| 							npcVars.set("HELP_COUNT_DOWN", 0);
 | |
| 							instance.getPlayers().forEach(temp -> temp.sendPacket(new ExSendUIEvent(temp, 2, countDown, charged, 0, 2042, 0, NpcStringId.REPLENISH_BALLISTA_MAGIC_POWER.getId())));
 | |
| 						}
 | |
| 						getTimers().addTimer("BALLISTA_CHECK_TIMER", 500, npc, null);
 | |
| 					}
 | |
| 					
 | |
| 					break;
 | |
| 				}
 | |
| 				case "BALLISTA_END_TIMER":
 | |
| 				{
 | |
| 					if (getChargedPercent(npcVars.getInt("SCORE_VAL", 0), isExtremeMode(instance)) >= getRandom(100))
 | |
| 					{
 | |
| 						playMovie(instance, Movie.SC_ISTINA_ENDING_A);
 | |
| 						instance.setStatus(3);
 | |
| 						getTimers().addTimer("INSTANCE_FINISH_TIMER", 23000, npc, null);
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						playMovie(instance, Movie.SC_ISTINA_ENDING_B);
 | |
| 						instance.setStatus(4);
 | |
| 						getTimers().addTimer("INSTANCE_FINISH_TIMER", 22000, npc, null);
 | |
| 					}
 | |
| 					instance.getAliveNpcs(ISTINA).forEach(istina ->
 | |
| 					{
 | |
| 						istina.teleToLocation(instance.getEnterLocation());
 | |
| 						istina.setInvisible(true);
 | |
| 					});
 | |
| 					break;
 | |
| 				}
 | |
| 				case "INSTANCE_FINISH_TIMER":
 | |
| 				{
 | |
| 					getTimers().addTimer("NPC_DELETE", 3000, evnt -> npc.deleteMe());
 | |
| 					instance.finishInstance();
 | |
| 					instance.getAliveNpcs(L2Attackable.class, ISTINA).forEach(istina ->
 | |
| 					{
 | |
| 						istina.teleToLocation(DEFEAT_ISTINA_LOC);
 | |
| 						istina.setInvisible(false);
 | |
| 						istina.setUndying(false);
 | |
| 						istina.reduceCurrentHp(istina.getVariables().getInt("REWARD_DAMAGE", 1000000), istina.getVariables().getObject("REWARD_PLAYER", L2PcInstance.class), null);
 | |
| 					});
 | |
| 					break;
 | |
| 				}
 | |
| 				case "AUTHORITY_TIMER":
 | |
| 				{
 | |
| 					final int random = getRandom(1, 3);
 | |
| 					final SkillHolder authoritySkill = npcParams.getSkillHolder("Istina_Authority_Skill0" + random);
 | |
| 					if (authoritySkill != null)
 | |
| 					{
 | |
| 						addSkillCastDesire(npc, npc, authoritySkill, 23);
 | |
| 						instance.broadcastPacket(new PlaySound(1, "Npcdialog1.istina_voice_01", 0, 0, 0, 0, 0));
 | |
| 						
 | |
| 						switch (random)
 | |
| 						{
 | |
| 							case 1:
 | |
| 								showOnScreenMsg(instance, NpcStringId.ISTINA_S_SOUL_STONE_STARTS_POWERFULLY_ILLUMINATING_IN_RED, ExShowScreenMessage.TOP_CENTER, 6000);
 | |
| 								break;
 | |
| 							case 2:
 | |
| 								showOnScreenMsg(instance, NpcStringId.ISTINA_S_SOUL_STONE_STARTS_POWERFULLY_ILLUMINATING_IN_BLUE, ExShowScreenMessage.TOP_CENTER, 6000);
 | |
| 								break;
 | |
| 							case 3:
 | |
| 								showOnScreenMsg(instance, NpcStringId.ISTINA_S_SOUL_STONE_STARTS_POWERFULLY_ILLUMINATING_IN_GREEN, ExShowScreenMessage.TOP_CENTER, 6000);
 | |
| 								break;
 | |
| 						}
 | |
| 					}
 | |
| 					getTimers().addTimer("AUTHORITY_TIMER", 70000 + getRandom(25000), npc, null);
 | |
| 					break;
 | |
| 				}
 | |
| 				case "AUTHORITY_END_TIMER":
 | |
| 				{
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData1, @OFF, myself->InstantZone_GetId());
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData2, @OFF, myself->InstantZone_GetId());
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData3, @OFF, myself->InstantZone_GetId());
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	
 | |
| 	@Override
 | |
| 	public String onSpellFinished(L2Npc npc, L2PcInstance player, Skill skill)
 | |
| 	{
 | |
| 		final Instance instance = npc.getInstanceWorld();
 | |
| 		if ((skill != null) && isIstinaInstance(instance))
 | |
| 		{
 | |
| 			final int skillId = skill.getId();
 | |
| 			
 | |
| 			if (npc.getId() == INVISIBLE_NPC)
 | |
| 			{
 | |
| 				if (skillId == ERUPTION_1.getSkillId())
 | |
| 				{
 | |
| 					npc.setTarget(npc);
 | |
| 					npc.doCast(ERUPTION_2.getSkill());
 | |
| 				}
 | |
| 				else if (skillId == ERUPTION_2.getSkillId())
 | |
| 				{
 | |
| 					getTimers().addTimer("NPC_DELETE", 2000, event -> npc.deleteMe());
 | |
| 					
 | |
| 					if (isExtremeMode(instance) && (getRandom(100) < 30))
 | |
| 					{
 | |
| 						addAttackPlayerDesire(addSpawn(EXTREME_MINION, npc, false, 0, false, instance.getId()), npc.getVariables().getObject("ERUPTION_TARGET", L2PcInstance.class), 23);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				final StatsSet npcParams = npc.getParameters();
 | |
| 				
 | |
| 				if (skillId == npcParams.getSkillHolder("Istina_Death_Skill01").getSkillId())
 | |
| 				{
 | |
| 					showOnScreenMsg(player, NpcStringId.ISTINA_S_MARK_SHINES_ABOVE_THE_HEAD, ExShowScreenMessage.TOP_CENTER, 4000);
 | |
| 					getTimers().addTimer("DEATH_CHECK_TIMER", 10000, npc, null);
 | |
| 				}
 | |
| 				else if (skillId == npcParams.getSkillHolder("Istina_Refraction_Skill").getSkillId())
 | |
| 				{
 | |
| 					npc.setDisplayEffect(1);
 | |
| 					getTimers().addTimer("REFLECT_CHECK_TIMER", 1000, npc, null);
 | |
| 				}
 | |
| 				else if (skillId == ISTINA_ERUPTION_SKILL.getSkillId())
 | |
| 				{
 | |
| 					((L2Attackable) npc).getAggroList().values().stream().sorted(Comparator.comparingInt(AggroInfo::getHate)).map(AggroInfo::getAttacker).limit(5).forEach(character ->
 | |
| 					{
 | |
| 						final L2Npc eruption = addSpawn(INVISIBLE_NPC, Util.getRandomPosition(character, 150, 150), false, 0, false, instance.getId());
 | |
| 						eruption.getVariables().set("ERUPTION_TARGET", character);
 | |
| 					});
 | |
| 				}
 | |
| 				else if (skillId == npcParams.getSkillHolder("Istina_Authority_Skill01").getSkillId())
 | |
| 				{
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData2, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData3, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
 | |
| 					getTimers().addTimer("AUTHORITY_END_TIMER", 15000, npc, null);
 | |
| 				}
 | |
| 				else if (skillId == npcParams.getSkillHolder("Istina_Authority_Skill02").getSkillId())
 | |
| 				{
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData1, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData3, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
 | |
| 					getTimers().addTimer("AUTHORITY_END_TIMER", 15000, npc, null);
 | |
| 				}
 | |
| 				else if (skillId == npcParams.getSkillHolder("Istina_Authority_Skill03").getSkillId())
 | |
| 				{
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData1, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
 | |
| 					// gg->Area_SetOnOffEx(Istina_Authority_AreaData2, @ON, myself->InstantZone_GetId()); // TODO: Need be finished after zone rework
 | |
| 					getTimers().addTimer("AUTHORITY_END_TIMER", 15000, npc, null);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		return super.onSpellFinished(npc, player, skill);
 | |
| 	}
 | |
| 	
 | |
| 	@Override
 | |
| 	public String onAttack(L2Npc npc, L2PcInstance attacker, int damage, boolean isSummon, Skill skill)
 | |
| 	{
 | |
| 		final Instance instance = npc.getInstanceWorld();
 | |
| 		if (isIstinaInstance(instance))
 | |
| 		{
 | |
| 			final StatsSet npcVars = npc.getVariables();
 | |
| 			final int stage = npcVars.getInt("ISTINA_STAGE", -1);
 | |
| 			
 | |
| 			if (npc.getId() == BALLISTA)
 | |
| 			{
 | |
| 				if (npcVars.getBoolean("COUNTING_ENABLED", false))
 | |
| 				{
 | |
| 					final int score = npcVars.getInt("SCORE_VAL", 0);
 | |
| 					
 | |
| 					if (getChargedPercent(score, isExtremeMode(instance)) < 100)
 | |
| 					{
 | |
| 						int addScore = damage;
 | |
| 						
 | |
| 						if (skill != null)
 | |
| 						{
 | |
| 							if (skill.getEffectPoint() < 0)
 | |
| 							{
 | |
| 								addScore *= 1.5;
 | |
| 							}
 | |
| 							addScore *= 1.5;
 | |
| 						}
 | |
| 						
 | |
| 						if (attacker.isInCategory(CategoryType.FIGHTER_GROUP))
 | |
| 						{
 | |
| 							addScore *= 2;
 | |
| 						}
 | |
| 						npcVars.set("SCORE_VAL", score + addScore);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				switch (stage)
 | |
| 				{
 | |
| 					case -1:
 | |
| 					{
 | |
| 						instance.setStatus(1);
 | |
| 						npcVars.set("ISTINA_STAGE", 1);
 | |
| 						instance.getDoors().forEach(L2DoorInstance::closeMe);
 | |
| 						npc.setUndying(true);
 | |
| 						((L2Attackable) npc).setCanReturnToSpawnPoint(false);
 | |
| 						getTimers().addTimer("DEATH_TIMER", 3500, npc, null);
 | |
| 						getTimers().addTimer("REFLECT_TIMER", 3500, npc, null);
 | |
| 						getTimers().addTimer("LOW_ERUPTION_TIMER", 15000, npc, null);
 | |
| 						break;
 | |
| 					}
 | |
| 					case 1:
 | |
| 					{
 | |
| 						if (npc.getCurrentHpPercent() < 85)
 | |
| 						{
 | |
| 							npcVars.set("ISTINA_STAGE", 2);
 | |
| 							getTimers().addTimer("AUTHORITY_TIMER", 3000, npc, null);
 | |
| 						}
 | |
| 						break;
 | |
| 					}
 | |
| 					case 2:
 | |
| 					{
 | |
| 						if (npc.getCurrentHpPercent() < 70)
 | |
| 						{
 | |
| 							npcVars.set("ISTINA_STAGE", 3);
 | |
| 							if (isExtremeMode(instance))
 | |
| 							{
 | |
| 								// myself->AddTimerEx(Seal_Timer, (3 * 1000));
 | |
| 							}
 | |
| 							// myself->AddTimerEx(Overcrowding_Timer, (10 * 1000));
 | |
| 						}
 | |
| 						break;
 | |
| 					}
 | |
| 					case 3:
 | |
| 					{
 | |
| 						if (npc.getCurrentHpPercent() < 55)
 | |
| 						{
 | |
| 							npcVars.set("ISTINA_STAGE", 4);
 | |
| 							getTimers().addTimer("ERUPTION_TIMER", 50000, npc, null);
 | |
| 							// myself->AddTimerEx(Creation_Timer, (Creation_Timer_Interval * 1000));
 | |
| 						}
 | |
| 						break;
 | |
| 					}
 | |
| 					case 4:
 | |
| 					{
 | |
| 						if (npc.getCurrentHpPercent() < 40)
 | |
| 						{
 | |
| 							npcVars.set("ISTINA_STAGE", 5);
 | |
| 							if (isExtremeMode(instance))
 | |
| 							{
 | |
| 								// myself->AddTimerEx(Order_Timer, (Order_Timer_Interval * 100));
 | |
| 							}
 | |
| 						}
 | |
| 						break;
 | |
| 					}
 | |
| 					case 5:
 | |
| 					{
 | |
| 						if (npc.getCurrentHpPercent() < 0.01)
 | |
| 						{
 | |
| 							setPlayerRewardInfo(npc);
 | |
| 							npcVars.set("ISTINA_STAGE", 6);
 | |
| 							getTimers().cancelTimer("DEATH_TIMER", npc, null);
 | |
| 							getTimers().cancelTimer("DEATH_CHECK_TIMER", npc, null);
 | |
| 							getTimers().cancelTimer("REFLECT_TIMER", npc, null);
 | |
| 							getTimers().cancelTimer("REFLECT_CHECK_TIMER", npc, null);
 | |
| 							getTimers().cancelTimer("AUTHORITY_TIMER", npc, null);
 | |
| 							getTimers().cancelTimer("ERUPTION_TIMER", npc, null);
 | |
| 							getTimers().cancelTimer("LOW_ERUPTION_TIMER", npc, null);
 | |
| 							// myself->BlockTimer(Overcrowding_Timer);
 | |
| 							if (isExtremeMode(instance))
 | |
| 							{
 | |
| 								// myself->BlockTimer(Seal_Timer);
 | |
| 								// myself->BlockTimer(Order_Timer);
 | |
| 							}
 | |
| 							instance.getAliveNpcs(EXTREME_MINION, INVISIBLE_NPC).forEach(L2Npc::deleteMe);
 | |
| 							instance.spawnGroup("BALLISTA");
 | |
| 							instance.setStatus(2);
 | |
| 							instance.getAliveNpcs(RUMIESE_INSTANCE).forEach(rumiese -> rumiese.teleToLocation(RUMIESE_LOC));
 | |
| 							instance.getDoors().forEach(L2DoorInstance::openMe);
 | |
| 							// myself->AddTimerEx(Broadcast_Timer, (2 * 1000));
 | |
| 							onTimerEvent("AUTHORITY_END_TIMER", null, npc, null);
 | |
| 							// myself->AddTimerEx(Location_Check_Timer, (4 * 1000));
 | |
| 							npc.disableCoreAI(true);
 | |
| 							npc.teleToLocation(DEFEAT_ISTINA_LOC);
 | |
| 							npc.setDisplayEffect(3);
 | |
| 							npc.setTargetable(false);
 | |
| 							playMovie(instance, Movie.SC_ISTINA_BRIDGE);
 | |
| 							instance.finishInstance(15);
 | |
| 						}
 | |
| 						break;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		return super.onAttack(npc, attacker, damage, isSummon, skill);
 | |
| 	}
 | |
| 	
 | |
| 	@Override
 | |
| 	public String onSpawn(L2Npc npc)
 | |
| 	{
 | |
| 		final Instance instance = npc.getInstanceWorld();
 | |
| 		if (isIstinaInstance(instance))
 | |
| 		{
 | |
| 			if (npc.getId() == INVISIBLE_NPC)
 | |
| 			{
 | |
| 				npc.setTarget(npc);
 | |
| 				npc.doCast(ERUPTION_1.getSkill());
 | |
| 			}
 | |
| 			else if (npc.getId() == BALLISTA)
 | |
| 			{
 | |
| 				npc.disableCoreAI(true);
 | |
| 				npc.setUndying(true);
 | |
| 				npc.setIsInvul(true);
 | |
| 				npc.setTargetable(false);
 | |
| 				getTimers().addTimer("BALLISTA_START_TIMER", 10000, npc, null);
 | |
| 			}
 | |
| 		}
 | |
| 		return super.onSpawn(npc);
 | |
| 	}
 | |
| 	
 | |
| 	@Override
 | |
| 	public String onFirstTalk(L2Npc npc, L2PcInstance player)
 | |
| 	{
 | |
| 		String htmltext = null;
 | |
| 		final Instance instance = npc.getInstanceWorld();
 | |
| 		if (isIstinaInstance(instance))
 | |
| 		{
 | |
| 			switch (instance.getStatus())
 | |
| 			{
 | |
| 				case 0:
 | |
| 					htmltext = "33293-01.html";
 | |
| 					break;
 | |
| 				case 1:
 | |
| 					htmltext = "33293-02.html";
 | |
| 					break;
 | |
| 				case 2:
 | |
| 					htmltext = "33293-03.html";
 | |
| 					break;
 | |
| 				case 3:
 | |
| 					htmltext = "33293-04.html";
 | |
| 					break;
 | |
| 				case 4:
 | |
| 					htmltext = "33293-05.html";
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 		return htmltext;
 | |
| 	}
 | |
| 	
 | |
| 	private boolean isExtremeMode(Instance instance)
 | |
| 	{
 | |
| 		return instance.getTemplateId() == TEMPLATE_ID_EXTREME;
 | |
| 	}
 | |
| 	
 | |
| 	private boolean isIstinaInstance(Instance instance)
 | |
| 	{
 | |
| 		return (instance != null) && ((instance.getTemplateId() == TEMPLATE_ID_COMMON) || (instance.getTemplateId() == TEMPLATE_ID_EXTREME));
 | |
| 	}
 | |
| 	
 | |
| 	private int getChargedPercent(int score, boolean isExtreme)
 | |
| 	{
 | |
| 		final int charged;
 | |
| 		if (score >= (isExtreme ? PERFECT_SCORE_2 : PERFECT_SCORE_1))
 | |
| 		{
 | |
| 			charged = 100;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			charged = (score * 100) / (isExtreme ? PERFECT_SCORE_2 : PERFECT_SCORE_1);
 | |
| 		}
 | |
| 		return charged;
 | |
| 	}
 | |
| 	
 | |
| 	private L2PcInstance setPlayerRewardInfo(L2Npc npc)
 | |
| 	{
 | |
| 		final Map<L2PcInstance, DamageDoneInfo> rewards = new ConcurrentHashMap<>();
 | |
| 		final StatsSet npcVars = npc.getVariables();
 | |
| 		L2PcInstance maxDealer = null;
 | |
| 		int maxDamage = 0;
 | |
| 		int totalDamage = 0;
 | |
| 		
 | |
| 		for (AggroInfo info : ((L2Attackable) npc).getAggroList().values())
 | |
| 		{
 | |
| 			if (info == null)
 | |
| 			{
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			final L2PcInstance attacker = info.getAttacker().getActingPlayer();
 | |
| 			if (attacker != null)
 | |
| 			{
 | |
| 				final int damage = info.getDamage();
 | |
| 				if (damage > 1)
 | |
| 				{
 | |
| 					if (!Util.checkIfInRange(Config.ALT_PARTY_RANGE, npc, attacker, true))
 | |
| 					{
 | |
| 						continue;
 | |
| 					}
 | |
| 					
 | |
| 					final DamageDoneInfo reward = rewards.computeIfAbsent(attacker, DamageDoneInfo::new);
 | |
| 					reward.addDamage(damage);
 | |
| 					
 | |
| 					if (reward.getDamage() > maxDamage)
 | |
| 					{
 | |
| 						maxDealer = attacker;
 | |
| 						maxDamage = reward.getDamage();
 | |
| 					}
 | |
| 					totalDamage += damage;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		
 | |
| 		npcVars.set("REWARD_PLAYER", maxDealer);
 | |
| 		npcVars.set("REWARD_DAMAGE", totalDamage);
 | |
| 		return maxDealer;
 | |
| 	}
 | |
| 	
 | |
| 	public static void main(String[] args)
 | |
| 	{
 | |
| 		new IstinaCavern();
 | |
| 	}
 | |
| } | 
