From 20138715d839f0f25860a2c09284936fa8c65a1e Mon Sep 17 00:00:00 2001
From: St3eT <St3eT@users.noreply.github.com>
Date: Tue, 4 Feb 2014 12:03:53 +0000
Subject: [PATCH] BETA: Reworked '''IOPRace''' and '''!PrisonGuards''' AI. *
 Reviewed by: Adry_85, Zoey76

---
 L2J_DataPack_BETA/dist/game/data/scripts.cfg  |   2 +-
 .../ai/group_template/PrisonGuards.java       | 247 ++++++------------
 .../data/scripts/ai/npc/Rignos/32349-01.html  |   4 +
 .../npc/Rignos/32349-02.html}                 |   4 +-
 .../ai/npc/Rignos/32349-03.html}              |   2 +-
 .../ai/npc/Rignos/32349.html}                 |   6 +-
 .../data/scripts/ai/npc/Rignos/Rignos.java    | 112 ++++++++
 .../scripts/custom/IOPRace/32349-return.htm   |   5 -
 .../data/scripts/custom/IOPRace/IOPRace.java  | 143 ----------
 L2J_DataPack_BETA/dist/sql/game/spawnlist.sql |  13 +
 10 files changed, 215 insertions(+), 323 deletions(-)
 create mode 100644 L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-01.html
 rename L2J_DataPack_BETA/dist/game/data/scripts/{custom/IOPRace/32349-notavailable.htm => ai/npc/Rignos/32349-02.html} (57%)
 rename L2J_DataPack_BETA/dist/game/data/{html/default/32349-1.htm => scripts/ai/npc/Rignos/32349-03.html} (83%)
 rename L2J_DataPack_BETA/dist/game/data/{html/default/32349.htm => scripts/ai/npc/Rignos/32349.html} (71%)
 create mode 100644 L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/Rignos.java
 delete mode 100644 L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-return.htm
 delete mode 100644 L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/IOPRace.java

diff --git a/L2J_DataPack_BETA/dist/game/data/scripts.cfg b/L2J_DataPack_BETA/dist/game/data/scripts.cfg
index 11cdcdbbbe..68f857bd95 100644
--- a/L2J_DataPack_BETA/dist/game/data/scripts.cfg
+++ b/L2J_DataPack_BETA/dist/game/data/scripts.cfg
@@ -40,6 +40,7 @@ ai/npc/Nottingale/Nottingale.java
 ai/npc/NpcBuffers/NpcBuffers.java
 ai/npc/NpcBuffers/impl/CabaleBuffer.java
 ai/npc/PriestOfBlessing/PriestOfBlessing.java
+ai/npc/Rignos/Rignos.java
 ai/npc/Rafforty/Rafforty.java
 ai/npc/Seyo/Seyo.java
 ai/npc/SubclassCertification/SubclassCertification.java
@@ -687,7 +688,6 @@ custom/ShadowWeapons/ShadowWeapons.java
 custom/NewbieCoupons/NewbieCoupons.java
 custom/RaidbossInfo/RaidbossInfo.java
 custom/NpcLocationInfo/NpcLocationInfo.java
-custom/IOPRace/IOPRace.java
 custom/Validators/SkillTransferValidator.java
 custom/Validators/SubClassSkills.java
 
diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/PrisonGuards.java b/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/PrisonGuards.java
index 9107fa91c7..e9d5c47fd4 100644
--- a/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/PrisonGuards.java
+++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/group_template/PrisonGuards.java
@@ -18,242 +18,153 @@
  */
 package ai.group_template;
 
-import java.util.Map;
-
-import javolution.util.FastMap;
 import ai.npc.AbstractNpcAI;
 
-import com.l2jserver.gameserver.ai.CtrlIntention;
-import com.l2jserver.gameserver.datatables.SkillTable;
+import com.l2jserver.gameserver.datatables.SpawnTable;
 import com.l2jserver.gameserver.model.L2Object;
+import com.l2jserver.gameserver.model.L2Spawn;
 import com.l2jserver.gameserver.model.actor.L2Attackable;
-import com.l2jserver.gameserver.model.actor.L2Character;
 import com.l2jserver.gameserver.model.actor.L2Npc;
+import com.l2jserver.gameserver.model.actor.L2Playable;
 import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.quest.QuestState;
+import com.l2jserver.gameserver.model.holders.SkillHolder;
 import com.l2jserver.gameserver.model.skills.L2Skill;
 import com.l2jserver.gameserver.network.NpcStringId;
 import com.l2jserver.gameserver.network.clientpackets.Say2;
-import com.l2jserver.gameserver.network.serverpackets.NpcSay;
-
-import custom.IOPRace.IOPRace;
 
 /**
  * Prison Guards AI.
- * @author Gigiikun
+ * @author St3eT
  */
-public class PrisonGuards extends AbstractNpcAI
+public final class PrisonGuards extends AbstractNpcAI
 {
-	final private static int GUARD1 = 18367;
-	final private static int GUARD2 = 18368;
-	final private static int STAMP = 10013;
-	
-	final private static String[] GUARDVARS =
-	{
-		"1st",
-		"2nd",
-		"3rd",
-		"4th"
-	};
-	
-	private final static int SKILL_SILENCE = 4098;
-	private final static int SKILL_PERTIFICATION = 4578;
-	private final static int SKILL_EVENT_TIMER = 5239;
-	
-	private boolean _firstAttacked = false;
-	
-	private final Map<L2Npc, Integer> _guards = new FastMap<>();
+	// NPCs
+	private static final int GUARD_HEAD = 18367; // Prison Guard
+	private static final int GUARD = 18368; // Prison Guard
+	// Item
+	private static final int STAMP = 10013; // Race Stamp
+	// Skills
+	private static final int TIMER = 5239; // Event Timer
+	private static final SkillHolder STONE = new SkillHolder(4578, 1); // Petrification
+	private static final SkillHolder SILENCE = new SkillHolder(4098, 9); // Silence
 	
 	private PrisonGuards()
 	{
 		super(PrisonGuards.class.getSimpleName(), "ai/group_template");
-		registerMobs(GUARD1, GUARD2);
+		addAttackId(GUARD_HEAD, GUARD);
+		addSpawnId(GUARD_HEAD, GUARD);
+		addNpcHateId(GUARD);
+		addSkillSeeId(GUARD);
+		addSpellFinishedId(GUARD_HEAD, GUARD);
 		
-		// place 1
-		_guards.put(addSpawn(GUARD2, 160704, 184704, -3704, 49152, false, 0), 0);
-		_guards.put(addSpawn(GUARD2, 160384, 184704, -3704, 49152, false, 0), 0);
-		_guards.put(addSpawn(GUARD1, 160528, 185216, -3704, 49152, false, 0), 0);
-		// place 2
-		_guards.put(addSpawn(GUARD2, 135120, 171856, -3704, 49152, false, 0), 1);
-		_guards.put(addSpawn(GUARD2, 134768, 171856, -3704, 49152, false, 0), 1);
-		_guards.put(addSpawn(GUARD1, 134928, 172432, -3704, 49152, false, 0), 1);
-		// place 3
-		_guards.put(addSpawn(GUARD2, 146880, 151504, -2872, 49152, false, 0), 2);
-		_guards.put(addSpawn(GUARD2, 146366, 151506, -2872, 49152, false, 0), 2);
-		_guards.put(addSpawn(GUARD1, 146592, 151888, -2872, 49152, false, 0), 2);
-		// place 4
-		_guards.put(addSpawn(GUARD2, 155840, 160448, -3352, 0, false, 0), 3);
-		_guards.put(addSpawn(GUARD2, 155840, 159936, -3352, 0, false, 0), 3);
-		_guards.put(addSpawn(GUARD1, 155578, 160177, -3352, 0, false, 0), 3);
+		for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(GUARD_HEAD))
+		{
+			onSpawn(spawn.getLastSpawn());
+		}
 		
-		for (L2Npc npc : _guards.keySet())
+		for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(GUARD))
 		{
-			npc.setIsNoRndWalk(true);
-			npc.setIsImmobilized(true);
-			if (npc.getId() == GUARD1)
-			{
-				npc.setIsInvul(true);
-				npc.disableCoreAI(true);
-			}
+			onSpawn(spawn.getLastSpawn());
 		}
 	}
 	
 	@Override
 	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
 	{
-		if (event.equals("Respawn"))
+		if (event.equals("CLEAR_STATUS"))
 		{
-			L2Npc newGuard = addSpawn(npc.getId(), npc.getSpawn().getX(), npc.getSpawn().getY(), npc.getSpawn().getZ(), npc.getSpawn().getHeading(), false, 0);
-			newGuard.setIsNoRndWalk(true);
-			newGuard.setIsImmobilized(true);
-			if (npc.getId() == GUARD1)
-			{
-				newGuard.setIsInvul(true);
-				newGuard.disableCoreAI(true);
-			}
-			
-			int place = _guards.get(npc);
-			_guards.remove(npc);
-			_guards.put(newGuard, place);
+			npc.setScriptValue(0);
 		}
-		else if (event.equals("attackEnd") && (npc.getId() == GUARD2))
+		else if (event.equals("CHECK_HOME"))
 		{
-			if ((npc.getX() != npc.getSpawn().getX()) || (npc.getY() != npc.getSpawn().getY()))
+			if ((npc.calculateDistance(npc.getSpawn().getLocation(), false, false) > 10) && !npc.isInCombat() && !npc.isDead())
 			{
 				npc.teleToLocation(npc.getSpawn().getLocation());
-				npc.setIsImmobilized(true);
 			}
-			((L2Attackable) npc).getAggroList().clear();
-			npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
+			startQuestTimer("CHECK_HOME", 30000, npc, null);
 		}
-		
 		return super.onAdvEvent(event, npc, player);
 	}
 	
 	@Override
-	public String onSkillSee(L2Npc npc, L2PcInstance player, L2Skill skill, L2Object[] targets, boolean isSummon)
+	public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
 	{
-		L2Character caster = isSummon ? player.getSummon() : player;
-		
-		if (npc.getId() == GUARD2)
+		if (npc.getId() == GUARD_HEAD)
 		{
-			if (_firstAttacked && !caster.isAffectedBySkill(SKILL_EVENT_TIMER))
+			if (player.isAffectedBySkill(TIMER))
 			{
-				if (!caster.isAffectedBySkill(SKILL_SILENCE))
+				if ((getRandom(100) < 10) && (npc.calculateDistance(player, true, false) < 100))
 				{
-					castDebuff(npc, caster, SKILL_SILENCE, isSummon, false, true);
+					if ((getQuestItemsCount(player, STAMP) <= 3) && npc.isScriptValue(0))
+					{
+						giveItems(player, STAMP, 1);
+						npc.setScriptValue(1);
+						startQuestTimer("CLEAR_STATUS", 600000, npc, null);
+					}
 				}
 			}
-		}
-		
-		return super.onSkillSee(npc, player, skill, targets, isSummon);
-	}
-	
-	@Override
-	public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
-	{
-		L2Character target = isSummon ? player.getSummon() : player;
-		
-		if (npc.getId() == GUARD2)
-		{
-			if (target.isAffectedBySkill(SKILL_EVENT_TIMER))
+			else
 			{
-				cancelQuestTimer("attackEnd", null, null);
-				startQuestTimer("attackEnd", 180000, npc, null);
-				
-				npc.setIsImmobilized(false);
-				npc.setTarget(target);
-				npc.setRunning();
-				((L2Attackable) npc).addDamageHate(target, 0, 999);
-				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target);
+				npc.setTarget(player);
+				npc.doCast(STONE.getSkill());
+				broadcastNpcSay(npc, Say2.ALL, NpcStringId.ITS_NOT_EASY_TO_OBTAIN);
 			}
-			else
+		}
+		else
+		{
+			if (!player.isAffectedBySkill(TIMER) && (npc.calculateDistance(npc.getSpawn().getLocation(), false, false) < 2000))
 			{
-				if ((npc.getX() != npc.getSpawn().getX()) || (npc.getY() != npc.getSpawn().getY()))
-				{
-					npc.teleToLocation(npc.getSpawn().getLocation());
-					npc.setIsImmobilized(true);
-				}
-				((L2Attackable) npc).getAggroList().remove(target);
-				npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-				return null;
+				npc.setTarget(player);
+				npc.doCast(STONE.getSkill());
+				broadcastNpcSay(npc, Say2.ALL, NpcStringId.YOURE_OUT_OF_YOUR_MIND_COMING_HERE);
 			}
 		}
-		
-		return super.onAggroRangeEnter(npc, player, isSummon);
+		return super.onAttack(npc, player, damage, isSummon);
 	}
 	
 	@Override
-	public String onAttack(L2Npc npc, L2PcInstance player, int damage, boolean isSummon)
+	public String onSkillSee(L2Npc npc, L2PcInstance caster, L2Skill skill, L2Object[] targets, boolean isSummon)
 	{
-		L2Character attacker = isSummon ? player.getSummon() : player;
-		
-		_firstAttacked = true;
-		
-		if (!attacker.isAffectedBySkill(SKILL_EVENT_TIMER))
-		{
-			if (!attacker.isAffectedBySkill(SKILL_PERTIFICATION))
-			{
-				castDebuff(npc, attacker, SKILL_PERTIFICATION, isSummon, true, false);
-			}
-			
-			npc.setTarget(null);
-			((L2Attackable) npc).getAggroList().remove(attacker);
-			((L2Attackable) npc).stopHating(attacker);
-			((L2Attackable) npc).abortAttack();
-			npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
-			return null;
-		}
-		
-		if (npc.getId() == GUARD2)
-		{
-			cancelQuestTimer("attackEnd", null, null);
-			startQuestTimer("attackEnd", 180000, npc, null);
-			
-			npc.setIsImmobilized(false);
-			npc.setTarget(attacker);
-			npc.setRunning();
-			((L2Attackable) npc).addDamageHate(attacker, 0, 999);
-			npc.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, attacker);
-		}
-		else if ((npc.getId() == GUARD1) && (getRandom(100) < 5))
+		if (!caster.isAffectedBySkill(TIMER))
 		{
-			final QuestState qs = player.getQuestState(IOPRace.class.getSimpleName());
-			if ((qs != null) && (qs.getInt(GUARDVARS[_guards.get(npc)]) != 1))
-			{
-				qs.set(GUARDVARS[_guards.get(npc)], "1");
-				qs.giveItems(STAMP, 1);
-			}
+			npc.setTarget(caster);
+			npc.doCast(SILENCE.getSkill());
 		}
-		
-		return super.onAttack(npc, player, damage, isSummon);
+		return super.onSkillSee(npc, caster, skill, targets, isSummon);
 	}
 	
 	@Override
-	public String onKill(L2Npc npc, L2PcInstance player, boolean isSummon)
+	public String onSpellFinished(L2Npc npc, L2PcInstance player, L2Skill skill)
 	{
-		if (_guards.containsKey(npc))
+		if ((skill == SILENCE.getSkill()) || (skill == STONE.getSkill()))
 		{
-			startQuestTimer("Respawn", 20000, npc, null);
+			((L2Attackable) npc).clearAggroList();
+			npc.setTarget(npc);
 		}
-		
-		return super.onKill(npc, player, isSummon);
+		return super.onSpellFinished(npc, player, skill);
+	}
+	
+	@Override
+	public boolean onNpcHate(L2Attackable mob, L2Playable playable)
+	{
+		return playable.isAffectedBySkill(TIMER);
 	}
 	
-	private void castDebuff(L2Npc npc, L2Character player, int effectId, boolean isSummon, boolean fromAttack, boolean isSpell)
+	@Override
+	public String onSpawn(L2Npc npc)
 	{
-		if (fromAttack)
+		if (npc.getId() == GUARD_HEAD)
 		{
-			NpcStringId npcString = (npc.getId() == GUARD1 ? NpcStringId.ITS_NOT_EASY_TO_OBTAIN : NpcStringId.YOURE_OUT_OF_YOUR_MIND_COMING_HERE);
-			npc.broadcastPacket(new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), npcString));
+			npc.setIsImmobilized(true);
+			npc.setIsInvul(true);
 		}
-		
-		L2Skill skill = SkillTable.getInstance().getInfo(effectId, isSpell ? 9 : 1);
-		if (skill != null)
+		else
 		{
-			npc.setTarget(isSummon ? player.getSummon() : player);
-			npc.doCast(skill);
+			npc.setIsNoRndWalk(true);
+			cancelQuestTimer("CHECK_HOME", npc, null);
+			startQuestTimer("CHECK_HOME", 30000, npc, null);
 		}
+		return super.onSpawn(npc);
 	}
 	
 	public static void main(String[] args)
diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-01.html b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-01.html
new file mode 100644
index 0000000000..3fe6cc09a0
--- /dev/null
+++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-01.html
@@ -0,0 +1,4 @@
+<html><body>Rignos:<br>
+Marvellous! So, have you collected all 4 Race Stamps? You haven't taken any shortcuts or copied any of them, have you? Excellent! Then take this key -- it will prove useful when rescuing Parme!<br>
+<a action="bypass -h Quest Rignos exchange">Exchange Race Stamps for the Secret Garden Key.</a>
+</body></html>
diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-notavailable.htm b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-02.html
similarity index 57%
rename from L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-notavailable.htm
rename to L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-02.html
index 794a4d2fe5..6c12c8e05f 100644
--- a/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-notavailable.htm
+++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-02.html
@@ -1,5 +1,5 @@
 <html><body>Rignos:<br>
-Welcome, welcome! I am Rignos. Parme and I are old friends, so I've come here to help. It's been a long time since I've traveled this far, but beautiful Isle of Prayer always makes me feel like I'm on vacation. Now then, how can I help? A race! You know I always say, "Joy and energy, all the time and in every way!" I call it the <font color="LEVEL">Grand Isle of Prayer Race</font>!<br>
+Welcome, welcome! I am Rignos. Parme and I are old friends, so I've come here to help. It's been a long time since I've traveled this far, but beautiful Isle of Prayer always makes me feel like I'm on vacation. Now then, how can I help? A race! You know what I always say, "Joy and energy, all the time and in every way!" I call it the <font color="LEVEL">Grand Isle of Prayer Race</font>!<br>
 You're a little late, though -- the race is already underway!<br>
 Come back another time.
-</body></html>
\ No newline at end of file
+</body></html>
diff --git a/L2J_DataPack_BETA/dist/game/data/html/default/32349-1.htm b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-03.html
similarity index 83%
rename from L2J_DataPack_BETA/dist/game/data/html/default/32349-1.htm
rename to L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-03.html
index d61be2f30f..032538708e 100644
--- a/L2J_DataPack_BETA/dist/game/data/html/default/32349-1.htm
+++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349-03.html
@@ -1,5 +1,5 @@
 <html><body>Rignos:<br>
 You have 30 minutes to find three other structures just like the one behind me. They are scattered around the island. Once you find them, go inside and battle the opponents you find there. One of these combatants will drop a Race Stamp. Bring 4 Race Stamps to me within the allotted time, and I will give you a reward that will aid you in your endeavor to rescue Parme.<br>
 Don't forget to include the building behind me!<br>
-<a action="bypass -h npc_%objectId%_Quest IOPRace">I'm ready! Let's start the race.</a>
+<a action="bypass -h Quest Rignos startRace">I'm ready! Let's start the race.</a>
 </body></html>
\ No newline at end of file
diff --git a/L2J_DataPack_BETA/dist/game/data/html/default/32349.htm b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349.html
similarity index 71%
rename from L2J_DataPack_BETA/dist/game/data/html/default/32349.htm
rename to L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349.html
index 8d9ce461dd..315101ca07 100644
--- a/L2J_DataPack_BETA/dist/game/data/html/default/32349.htm
+++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/32349.html
@@ -1,6 +1,6 @@
 <html><body>Rignos:<br>
 Welcome, welcome! I am Rignos. Parme and I are old friends, so I've come here to help. It's been a long time since I've traveled this far, but the beautiful Isle of Prayer always makes me feel like I'm on vacation. Now then, how can I help? A race! You know what I always say, "Joy and energy, all the time and in every way!" I call it the <font color="LEVEL">Grand Isle of Prayer Race</font>!<br>
 You do know what this means, don't you?<br>
-<a action="bypass -h npc_%objectId%_Chat 1">Ask about the Grand Isle of Prayer Race.</a><br>
-<a action="bypass -h npc_%objectId%_Quest IOPRace">Start the Race.</a>
-</body></html>
\ No newline at end of file
+<a action="bypass -h Quest Rignos 32349-03.html">Ask about the Grand Isle of Prayer Race.</a><br>
+<a action="bypass -h Quest Rignos startRace">Start the Race.</a>
+</body></html>
diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/Rignos.java b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/Rignos.java
new file mode 100644
index 0000000000..2f8b1b961e
--- /dev/null
+++ b/L2J_DataPack_BETA/dist/game/data/scripts/ai/npc/Rignos/Rignos.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2014 L2J DataPack
+ * 
+ * This file is part of L2J DataPack.
+ * 
+ * L2J DataPack 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.
+ * 
+ * L2J DataPack 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 ai.npc.Rignos;
+
+import ai.npc.AbstractNpcAI;
+
+import com.l2jserver.gameserver.model.actor.L2Npc;
+import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jserver.gameserver.model.holders.SkillHolder;
+
+/**
+ * Rignos AI.
+ * @author St3eT
+ */
+public class Rignos extends AbstractNpcAI
+{
+	// NPC
+	private static final int RIGNOS = 32349; // Rignos
+	// Item
+	private static final int STAMP = 10013; // Race Stamp
+	private static final int KEY = 9694; // Secret Key
+	// Skill
+	private static final SkillHolder TIMER = new SkillHolder(5239, 5); // Event Timer
+	// Misc
+	private static final int MIN_LV = 78;
+	
+	private Rignos()
+	{
+		super(Rignos.class.getSimpleName(), "ai/npc");
+		addStartNpc(RIGNOS);
+		addTalkId(RIGNOS);
+		addFirstTalkId(RIGNOS);
+	}
+	
+	@Override
+	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
+	{
+		switch (event)
+		{
+			case "32349-03.html":
+			{
+				return event;
+			}
+			case "startRace":
+			{
+				if (npc.isScriptValue(0))
+				{
+					npc.setScriptValue(1);
+					startQuestTimer("TIME_OUT", 1800000, npc, null);
+					TIMER.getSkill().applyEffects(player, player);
+					if (player.hasSummon())
+					{
+						TIMER.getSkill().applyEffects(player.getSummon(), player.getSummon());
+					}
+					
+					if (hasQuestItems(player, STAMP))
+					{
+						takeItems(player, STAMP, -1);
+					}
+				}
+				break;
+			}
+			case "exchange":
+			{
+				if (getQuestItemsCount(player, STAMP) >= 4)
+				{
+					giveItems(player, KEY, 3);
+					takeItems(player, STAMP, -1);
+				}
+				break;
+			}
+			case "TIME_OUT":
+			{
+				npc.setScriptValue(0);
+				break;
+			}
+		}
+		return super.onAdvEvent(event, npc, player);
+	}
+	
+	@Override
+	public String onFirstTalk(L2Npc npc, L2PcInstance player)
+	{
+		String htmltext = (npc.isScriptValue(0) && (player.getLevel() >= MIN_LV)) ? "32349.html" : "32349-02.html";
+		if (getQuestItemsCount(player, STAMP) >= 4)
+		{
+			htmltext = "32349-01.html";
+		}
+		return htmltext;
+	}
+	
+	public static void main(String[] args)
+	{
+		new Rignos();
+	}
+}
\ No newline at end of file
diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-return.htm b/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-return.htm
deleted file mode 100644
index ca769dbb47..0000000000
--- a/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/32349-return.htm
+++ /dev/null
@@ -1,5 +0,0 @@
-<html><body>Rignos:<br>
-Great! You collected 4 ride medals? You does not cheat and not copy them, yes?<br>
-Then take this key -- you will need it for saving Parme!<br>
-<a action="bypass -h Quest IOPRace finish">Exchange ride medals to the Secret Garden Key.</a>
-</body></html>
\ No newline at end of file
diff --git a/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/IOPRace.java b/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/IOPRace.java
deleted file mode 100644
index 5487209a91..0000000000
--- a/L2J_DataPack_BETA/dist/game/data/scripts/custom/IOPRace/IOPRace.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2004-2014 L2J DataPack
- * 
- * This file is part of L2J DataPack.
- * 
- * L2J DataPack 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.
- * 
- * L2J DataPack 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 custom.IOPRace;
-
-import com.l2jserver.gameserver.datatables.SkillTable;
-import com.l2jserver.gameserver.model.actor.L2Npc;
-import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
-import com.l2jserver.gameserver.model.quest.Quest;
-import com.l2jserver.gameserver.model.quest.QuestState;
-import com.l2jserver.gameserver.model.skills.L2Skill;
-
-/**
- * IOP Race AI.
- * @author Gigiikun, Charus
- */
-public final class IOPRace extends Quest
-{
-	final private static int RIGNOS = 32349;
-	final private static int STAMP = 10013;
-	final private static int KEY = 9694;
-	
-	private int _player = -1;
-	
-	private IOPRace()
-	{
-		super(-1, IOPRace.class.getSimpleName(), "custom");
-		addStartNpc(RIGNOS);
-		addTalkId(RIGNOS);
-		addFirstTalkId(RIGNOS);
-	}
-	
-	@Override
-	public String onFirstTalk(L2Npc npc, L2PcInstance player)
-	{
-		QuestState st = player.getQuestState(getName());
-		if (st == null)
-		{
-			st = newQuestState(player);
-		}
-		
-		if (player.getLevel() < 78)
-		{
-			return "32349-notavailable.htm";
-		}
-		else if ((_player != -1) && (_player == player.getObjectId()) && (st.getQuestItemsCount(STAMP) == 4))
-		{
-			return "32349-return.htm";
-		}
-		else if (_player != -1)
-		{
-			return "32349-notavailable.htm";
-		}
-		
-		npc.showChatWindow(player);
-		return null;
-	}
-	
-	@Override
-	public String onTalk(L2Npc npc, L2PcInstance player)
-	{
-		QuestState st = player.getQuestState(getName());
-		if (st == null)
-		{
-			st = newQuestState(player);
-		}
-		
-		if (_player == -1)
-		{
-			// clean old data
-			player.stopSkillEffects(true, 5239);
-			if (player.hasSummon())
-			{
-				player.getSummon().stopSkillEffects(true, 5239);
-			}
-			
-			st.takeItems(STAMP, -1);
-			st.set("1st", "0");
-			st.set("2nd", "0");
-			st.set("3rd", "0");
-			st.set("4th", "0");
-			
-			L2Skill skill = SkillTable.getInstance().getInfo(5239, 5);
-			if (skill != null)
-			{
-				skill.applyEffects(npc, player);
-				if (player.hasSummon())
-				{
-					skill.applyEffects(npc, player.getSummon());
-				}
-			}
-			
-			startQuestTimer("timer", 1800000, null, null); // 30 min
-			_player = player.getObjectId();
-		}
-		
-		return null;
-	}
-	
-	@Override
-	public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
-	{
-		String htmltext = "";
-		
-		if (event.equalsIgnoreCase("timer"))
-		{
-			_player = -1;
-			return null;
-		}
-		else if (event.equalsIgnoreCase("finish"))
-		{
-			if (_player == player.getObjectId())
-			{
-				QuestState st = player.getQuestState(getName());
-				st.giveItems(KEY, 3);
-				st.takeItems(STAMP, -1);
-				st.exitQuest(true);
-			}
-		}
-		
-		return htmltext;
-	}
-	
-	public static void main(String[] args)
-	{
-		new IOPRace();
-	}
-}
\ No newline at end of file
diff --git a/L2J_DataPack_BETA/dist/sql/game/spawnlist.sql b/L2J_DataPack_BETA/dist/sql/game/spawnlist.sql
index f4bcf11bd1..a436bd12bd 100644
--- a/L2J_DataPack_BETA/dist/sql/game/spawnlist.sql
+++ b/L2J_DataPack_BETA/dist/sql/game/spawnlist.sql
@@ -41245,6 +41245,19 @@ INSERT INTO `spawnlist` VALUES
 ("Isle_of_Prayer", 1, 32342, 147844, 175992, -4848, 0, 0, 0, 60, 0, 0, 0),
 -- Rignos
 ("Isle_of_Prayer", 1, 32349, 159312, 183904, -3680, 0, 0, 34248, 60, 0, 0, 0),
+-- Prison Guard
+("Isle_of_Prayer", 1, 18367, 155312, 160160, -3344, 0, 0, 0, 60, 0, 0, 0),
+("Isle_of_Prayer", 1, 18367, 146592, 151888, -2864, 0, 0, 49152, 60, 0, 0, 0),
+("Isle_of_Prayer", 1, 18367, 134928, 172432, -3696, 0, 0, 49152, 60, 0, 0, 0),
+("Isle_of_Prayer", 1, 18367, 160528, 185216, -3696, 0, 0, 49152, 60, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 155840, 159936, -3344, 0, 0, 0, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 155840, 160448, -3344, 0, 0, 0, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 146366, 151506, -2864, 0, 0, 49152, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 146880, 151504, -2864, 0, 0, 49152, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 135120, 171856, -3696, 0, 0, 49152, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 134768, 171856, -3696, 0, 0, 49152, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 160384, 184704, -3696, 0, 0, 49152, 15, 0, 0, 0),
+("Isle_of_Prayer", 1, 18368, 160704, 184704, -3696, 0, 0, 49152, 15, 0, 0, 0),
 
 -- [25_11]
 
-- 
GitLab