/*
* Copyright (C) 2004-2015 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 events.ZakenCurse;
/**
* Zaken's Curse : Event
* Written by Paf Euclide updated and fixed by Rayan
* Fixed again for L2J - Fulminus, Kerberos_20, BigBro
* http://svn.assembla.com/L2Emu/browser/trunk/L2EmuProject-Datapack/optional/events/708_ZakenCurse/data/scripts/custom/708_ZakenCurse/
* rev 1020
*
* Rewrite java: JOJO
*
* http://www.l2jserver.com/forum/viewtopic.php?f=73&t=19261
* http://www.lineage2.com/archive/2007/07/zakens_curse.html
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Set;
import java.util.logging.Level;
import com.l2jserver.commons.database.pool.impl.ConnectionFactory;
import com.l2jserver.gameserver.util.Broadcast;
import com.l2jserver.gameserver.data.xml.impl.NpcData;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.quest.State;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.util.Rnd;
class ZakenCurse extends Quest
{
private static final String qn = "ZakenCurse";
//event properties
private static final int[] EVENT_DATE = {18 , 10}; //{DD, MM}
private static final int EVENT_NPC = 31857; //イベント管理人
private static final int EVENT_DAY_TO_STAY = 3; //how many days after event date Event_Npc will be respawn (for giving reward)
//items
private static final int CUPID_BOW = 9141; //キューピッドの弓:イベント
private static final int GOLDEN_APIGA = 9143; //ゴールド アニマル コイン
private static final int PIRATE_HAT = 8922; //パイレーツ ハット
//cupid's bow's skills
// 3260 ハート ショット - 突然変異した動物に愛を込めてハートを飛ばします。
// 3262 ダブル ハート ショット - 突然変異した動物に愛を込めてハートを二回連続で飛ばします。
private static final int[] SKILLS = {3260, 3262};
private static final int[] CHANCE = {45, 5, 2}; //{HugePigs, SuperHugePig, GoldenPig}
private static final int[] REWARD = {1, 7, 10}; //{HugePigs, SuperHugePig, GoldenPig}
private static final int[] Pigs = {13031, 13032, 13033, 13034, 13035};
//private static final int[] HugePigs = {13031, 13032, 13033};
private boolean haveWinner = false;
//Event Manager Spawnlist
private static final int[][] EM = {
{10693, 17345, -4590, 45486},
{115095, -178309, -917, 10631},
{47566, 51138, -3001, 33264},
{-45272, -112396, -245, 652},
{-84542, 244682, -3735, 53988},
{147855, 26629, -2210, 19523},
{16249, 142870, -2711, 12022},
{17832, 170509, -3531, 48408},
{83057, 149281, -3474, 31176},
{-80858, 149456, -3070, 16948},
{-12147, 122760, -3102, 34490},
{110954, 218935, -3548, 0},
{117158, 75807, -2735, 25189},
{82494, 53151, -1501, 946},
{43556, -47626, -802, 42552},
{147388, -55436, -2738, 62376},
{87775, -143216, -1298, 27295}
};
//Event Mob Spawnlist
private static final int[][] MOB = {
{12739, 172819, -3415, 53544},
{13386, 172680, -3452, 63628},
{13304, 173135, -3449, 53988},
{13229, 173748, -3463, 19658},
{14639, 174127, -3486, 65020},
{14924, 174953, -3602, 7150},
{15625, 175086, -3662, 59709},
{16243, 174928, -3644, 60588},
{16217, 174024, -3691, 47810},
{16989, 173868, -3626, 64213},
{16919, 173152, -3598, 43726},
{16477, 172906, -3565, 35563},
{15708, 173583, -3576, 25291},
{17796, 173812, -3645, 63328},
{18306, 174341, -3680, 8494},
{18731, 174004, -3639, 55432},
{19147, 174213, -3598, 64786},
{19715, 173364, -3578, 55248},
{20446, 173433, -3577, 5533},
{20738, 173844, -3577, 59844},
{20235, 172255, -3582, 45099},
{21085, 172082, -3577, 63738},
{21857, 172346, -3567, 2650},
{21763, 173214, -3577, 16169},
{21583, 171240, -3547, 59056},
{20920, 170514, -3556, 41043},
{20314, 169681, -3532, 49447},
{19792, 169950, -3560, 26862},
{19419, 168903, -3480, 48761},
{18970, 169172, -3483, 29138},
{18014, 168372, -3524, 38624},
{18275, 167273, -3486, 50371},
{17227, 167052, -3519, 34197},
{16007, 167490, -3546, 24702},
{14782, 167310, -3643, 36856},
{14296, 167874, -3636, 16980},
{14201, 169242, -3616, 19444},
{14354, 170546, -3558, 13843},
{15016, 170893, -3485, 3419},
{15978, 171333, -3555, 11655},
{21891, 170635, -3516, 49199},
{21252, 169570, -3443, 50277},
{18828, 168262, -3463, 34177},
{17409, 167654, -3460, 33168},
{15513, 168057, -3512, 21964},
{12083, 172092, -3514, 29851},
{12720, 173616, -3463, 10111},
{14383, 173431, -3459, 53120},
{14621, 173096, -3485, 57956},
{14555, 172248, -3479, 48166},
{15692, 171932, -3564, 62491},
{17146, 172578, -3546, 4609},
{17973, 173254, -3580, 4655},
{19411, 173905, -3604, 2154},
{20159, 174128, -3577, 54788},
{23193, 172600, -3472, 554},
{23850, 172349, -3396, 57840},
{24495, 171338, -3381, 54967},
{25261, 170669, -3385, 60908},
{26423, 170887, -3413, 943},
{26357, 170026, -3348, 26605},
{25473, 169179, -3330, 40551},
{26009, 168673, -3295, 64740},
{26556, 168599, -3253, 2226},
{27314, 168350, -3220, 47035},
{27086, 166750, -3365, 46402},
{27221, 165848, -3447, 59247},
{26110, 165447, -3437, 34146},
{26548, 164573, -3496, 54428},
{23190, 166013, -3339, 23885},
{21682, 167176, -3370, 24088},
{20640, 167878, -3390, 27964},
{20771, 168524, -3395, 13984},
{19174, 170072, -3558, 21523},
{18615, 170401, -3507, 54788},
{21504, 173649, -3577, 2177},
{21986, 171263, -3567, 55609},
{23064, 170718, -3419, 19893},
{23737, 171751, -3408, 9846},
{24991, 172189, -3388, 7754},
{25393, 173308, -3428, 15644},
{27313, 172418, -3388, 56835},
{28511, 172474, -3476, 14904},
{28403, 170634, -3390, 44315},
{27401, 169594, -3271, 43576},
{26214, 169225, -3256, 38961},
{29224, 166327, -3548, 56697},
{28861, 164369, -3632, 38263},
{15806, 164244, -3644, 48476},
{15933, 165069, -3556, 15252},
{15342, 165490, -3557, 26398},
{14679, 166316, -3611, 16307},
{15156, 166694, -3551, 14326},
{13016, 166792, -3713, 3823},
{11674, 166816, -3719, 39015},
{11058, 167733, -3696, 19620},
{9968, 167180, -3604, 43620},
{9112, 167076, -3641, 29917},
{9528, 168170, -3545, 12466},
{9690, 169159, -3535, 60733},
{9969, 170049, -3538, 8305},
{11123, 171612, -3605, 9787},
{10489, 173775, -3660, 23256},
{9770, 175077, -3662, 19973},
{10552, 175728, -3623, 8360},
{11806, 176327, -3583, 6701},
{13250, 172087, -3477, 36585},
{14915, 171874, -3504, 3516},
{16333, 170029, -3558, 64040},
{17037, 168803, -3544, 54926},
{16409, 166252, -3494, 45158},
{14410, 163938, -3702, 41423},
{13200, 165174, -3696, 19611},
{12473, 166578, -3675, 21933},
{13818, 168499, -3660, 14813},
{18012, 174804, -3673, 1808},
{23437, 169290, -3436, 64996},
{25486, 167606, -3227, 23874},
{22918, 165340, -3340, 37225},
{20191, 166388, -3405, 31650},
{19683, 167733, -3395, 15523}
};
private boolean isEventPassed(int val)
{
Calendar now = Calendar.getInstance();
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_MONTH, (EVENT_DATE[0]+val));
c.set(Calendar.MONTH, (EVENT_DATE[1]-1));
long time = now.getTimeInMillis() - c.getTimeInMillis();
//System.out.println(time);
//if gameserver lag during loading of the quest or if test when minute change ( 1min59s != 2min00s)
return time > 65000 || time < -65000;
}
private boolean isBestCollector(L2PcInstance player) {
boolean val = false;
int player_id = player.getObjectId();
try (Connection con = ConnectionFactory.getInstance().getConnection();
PreparedStatement offline = con.prepareStatement("SELECT owner_id FROM items WHERE item_id = ? AND `count` = ( SELECT max( `count` ) FROM items WHERE item_id = ? ) LIMIT 0 , 1") )
{
offline.setInt(1, GOLDEN_APIGA);
offline.setInt(2, GOLDEN_APIGA);
ResultSet rs = offline.executeQuery();
while (rs.next()) {
if (rs.getInt("owner_id") == player_id)
val = true;
}
}
catch (SQLException e)
{
_log.log(Level.WARNING, "", e);
}
return val;
}
private void unspawnNpc(int npcId) {
System.out.println("Zaken's Curse: Deleting npc(" + npcId + ") From Table Spawnlist.");
Set<L2Spawn> t = SpawnTable.getInstance().getSpawns(npcId);
if (t != null) {
for (L2Spawn spawn : t) {
System.out.println("Zaken's Curse: @ [" + spawn.getX() + "," + spawn.getY() + "," + spawn.getZ() + "," + spawn.getHeading() + "]");
SpawnTable.getInstance().deleteSpawn(spawn, false);
L2Npc npc = spawn.getLastSpawn();
npc.deleteMe();
}
}
}
private void spawnNpc(String npcName, int npcId, int[][] list) {
System.out.println("Zaken's Curse: Spawning " + npcName + "...");
L2NpcTemplate template = NpcData.getInstance().getTemplate(npcId);
for (int[] data : list) {
System.out.println("Zaken's Curse: @ [" + data[0] + "," + data[1] + "," + data[2] + "," + data[3] + "]");
L2Spawn spawn;
try
{
spawn = new L2Spawn(template);
spawn.setX(data[0]);
spawn.setY(data[1]);
spawn.setZ(data[2]);
spawn.setAmount(1);
spawn.setHeading(data[3]);
spawn.setRespawnDelay(60);
SpawnTable.getInstance().addNewSpawn(spawn, false); //don't save spawn in DB
spawn.init();
}
catch (Exception e)
{
_log.warning("Could not spawn Npc " + npcId);
e.printStackTrace();
}
}
System.out.println("Zaken's Curse: Done...");
}
public ZakenCurse(int questId, String name, String descr) {
super(questId, name, descr);
System.out.println("Zaken's Curse: Event Zaken's Curse Init.");
addStartNpc(EVENT_NPC);
addTalkId(EVENT_NPC);
unspawnNpc(EVENT_NPC); //prevent multiple spawn if server reboot
unspawnNpc(Pigs[0]);
if (!isEventPassed(0)) {
System.out.println("Zaken's Curse: Event Zaken's Curse Is Running.");
System.out.println("Zaken's Curse: Event Manager Need To Be Spawn...");
spawnNpc("Event Manager", EVENT_NPC, EM);
System.out.println("Zaken's Curse: Event Mobs Need To Be Spawn...");
spawnNpc("Event Mobs", Pigs[0], MOB);
Broadcast.toAllOnlinePlayers("Event Zaken's Curse: Go talk to an Event Manager!");
for (int i : Pigs) {
addSkillSeeId(i);
//- addSpellFinishedId(i);
// self.addSkillUseId(i);
}
} else {
System.out.println("Zaken's Curse: Event Zaken's Curse Has Passed.");
if (!isEventPassed(EVENT_DAY_TO_STAY)) {
System.out.println("Zaken's Curse: Event Manager Need To Be Spawn...");
spawnNpc("Event Manager", EVENT_NPC, EM);
}
}
}
@Override
public String onEvent(String event, QuestState st) {
String htmltext = event;
L2PcInstance player = st.getPlayer();
if (event.equals("accept")) {
st.set("cond","1");
st.setState(State.STARTED);
st.playSound("ItemSound.quest_accept");
st.giveItems(CUPID_BOW, 1);
htmltext = "31857-02.htm";
} else if (event.equals("stop")) {
st.takeItems(CUPID_BOW, 1);
st.playSound("ItemSound.quest_giveup");
st.exitQuest(true);
} else if (event.equals("isBest")) {
if (!haveWinner && isBestCollector(player)) {
haveWinner = true;
htmltext = "31857-04.htm";
st.giveItems(PIRATE_HAT, 1);
} else {
htmltext = "31857-05.htm";
}
st.takeItems(GOLDEN_APIGA, st.getQuestItemsCount(GOLDEN_APIGA));
st.playSound("ItemSound.quest_finish");
st.exitQuest(true);
}
return htmltext;
}
@Override
public String onTalk(L2Npc npc, L2PcInstance player) {
QuestState st = player.getQuestState(qn);
String htmltext = Quest.getNoQuestMsg(player);
// String htmltext = "<html><body>You are either not on a quest that involves this NPC, or you don't meet this NPC's minimum quest requirements.</body></html>";
if (st == null) return htmltext;
int npcId = npc.getId();
if (npcId == EVENT_NPC) {
if (!isEventPassed(0)) {
byte id = st.getState();
if (id == State.CREATED)
htmltext = "31857-01.htm";
else if (id == State.STARTED)
htmltext = "31857-02.htm";
} else {
int cond = st.getInt("cond");
if (cond == 1) {
st.set("cond","2");
htmltext = "31857-03.htm";
st.takeItems(CUPID_BOW, 1);
}
}
}
return htmltext;
}
//- @Override
//- public String onSpellFinished(L2Npc npc, L2PcInstance player, L2Skill skill) {
//- return onSkillUse(npc, player, skill);
//- }
@Override
public String onSkillSee(L2Npc npc, L2PcInstance player, Skill skill, L2Object[] targets, boolean isPet) {
return onSkillUse(npc, player, skill);
}
private String onSkillUse(L2Npc npc, L2PcInstance player, Skill skill) {
// gather some values on local variables
QuestState st = player.getQuestState(qn);
int npcId = npc.getId();
int skillId = skill.getId();
// check if the npc and skills used are valid for this script. Exit if invalid.
if (!com.l2jserver.gameserver.util.Util.contains(Pigs, npcId)) return null;
if (!com.l2jserver.gameserver.util.Util.contains(SKILLS, skillId)) return null;
//if someone hit a pig after the end of event, unspawn all pigs
if (isEventPassed(0)) {
for (int pigId : Pigs)
unspawnNpc(pigId);
Broadcast.toAllOnlinePlayers("Event Zaken's Curse has ended, get your reward to an Event Manager!");
return null;
}
npc.onDecay();
if (skillId == 3260/*ハート ショット*/) {
int chance = Rnd.get(1, 100);
//Heart Shot : can only spawn another Huge Pig
if (npcId < 13033/*ジャイアント ピッグ*/) {
if (chance <= CHANCE[0])
// 13031 -> 13032 -> 13033
addSpawn(npcId + 1, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), true, 60000);
else
st.giveItems(GOLDEN_APIGA, REWARD[0]);
return null;
} else if (npcId == 13034/*スーパー ジャイアント ピッグ*/) {
st.giveItems(GOLDEN_APIGA, REWARD[1]);
} else if (npcId == 13035/*ゴールデン ピッグ*/) {
st.giveItems(GOLDEN_APIGA, REWARD[2]);
}
return null;
}
if (skillId == 3262/*ダブル ハート ショット*/) {
int chance = Rnd.get(1, 100);
//Double Heart Shot : can spawn Huge Pig, Super Huge Pig and Golden Pig
if (npcId < 13033/*ジャイアント ピッグ*/) {
if (chance <= CHANCE[2])
addSpawn(13035/*ゴールデン ピッグ*/, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), true, 60000);
else if (chance <= CHANCE[1])
addSpawn(13034/*スーパー ジャイアント ピッグ*/, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), true, 60000);
else if (chance <= CHANCE[0])
{
if (npcId < 13033/*ジャイアント ピッグ*/)
// 13031 -> 13032 -> 13033
addSpawn(npcId + 1, npc.getX(), npc.getY(), npc.getZ(), npc.getHeading(), true, 60000);
}
else
st.giveItems(GOLDEN_APIGA, REWARD[0]);
} else {
if (npcId == 13034/*スーパー ジャイアント ピッグ*/)
st.giveItems(GOLDEN_APIGA, REWARD[1]);
else if (npcId == 13035/*ゴールデン ピッグ*/)
st.giveItems(GOLDEN_APIGA, REWARD[2]);
return null;
}
}
return null;
}
public static void main(String[] args)
{
new ZakenCurse(-1, qn, "events");
}
}