Jump to content

Question

Posted (edited)

Hey guys i have a problem with seven signs

My problem is that i can tp without participate

At pre-period (when i wipe my db) i must participate to join but when the period start players without reg can tp at catas too

i have this html on Priest

 

noYvAz7.png

 

i have try to take the java from other pack where it works but nothing ....

 

any help?

 

my config is this

 

 

 

#============================================================#
#                       Seven Signs                          #
#============================================================#
#           Pack: l2jfrozen Site: www.l2jfrozen.com          #
#============================================================#


# -----------------------
#  Rule 7 Seals -
# -----------------------
# To join the warrior Dawn would require that the player is in the castle allied clan.
AltRequireCastleForDawn = False


# Definition for the ownership of the castle clan or alliance.
AltRequireClanCastle = False


# Need to be winner to enter in Catacombs/Necropolis in validation period
# Default: True
AltRequireWin7s = True


# --------------------------------------------
#  The Rules Of The Festival -
# --------------------------------------------
# Minimum number of players to participate in the festival of the seven seals.
AltFestivalMinPlayer = 5


# The maximum contribution to the player during the festival
# This value does not affect the level of loot.
AltMaxPlayerContrib = 1000000


# The start time of the festival.
# Default: 2 minutes
AltFestivalManagerStart = 120000


# Duration of the festival.
# Default: 18 minutes
AltFestivalLength = 1080000


# The length of the cycle of the Festival.
# Default: 38 minutes (20 minutes of waiting time + festival)
AltFestivalCycleLength = 2280000


# Initial spawn festival.
# Default: 2 minutes
AltFestivalFirstSpawn = 120000


# The initial training of the Festival.
# Default: 5 minutes
AltFestivalFirstSwarm = 300000


# Following should spawn Festival.
# Default: 9 minutes
AltFestivalSecondSpawn = 540000


# The following preparation of the Festival.
# Default: 12 minutes
AltFestivalSecondSwarm = 720000


# Spawn Chests.
# Default: 15 minutes
AltFestivalChestspawn = 900000

 
 
 
 
TaskSevenSignsUpdate.java :
 
 

/* L2jFrozen Project - www.l2jfrozen.com 
 * 
 * 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 2, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.l2jfrozen.gameserver.taskmanager.tasks;


import java.util.logging.Logger;


import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.model.entity.sevensigns.SevenSigns;
import com.l2jfrozen.gameserver.model.entity.sevensigns.SevenSignsFestival;
import com.l2jfrozen.gameserver.taskmanager.Task;
import com.l2jfrozen.gameserver.taskmanager.TaskManager;
import com.l2jfrozen.gameserver.taskmanager.TaskManager.ExecutedTask;
import com.l2jfrozen.gameserver.taskmanager.TaskTypes;




/**
 * Updates all data for the Seven Signs and Festival of Darkness engines, when time is elapsed.
 * @author Tempy
 */
public class TaskSevenSignsUpdate extends Task
{
private static final Logger _log = Logger.getLogger(TaskSevenSignsUpdate.class.getName());
public static final String NAME = "sevensignsupdate";


@Override
public String getName()
{
return NAME;
}


@Override
public void onTimeElapsed(final ExecutedTask task)
{
try
{
SevenSigns.getInstance().saveSevenSignsData(null, true);


if (!SevenSigns.getInstance().isSealValidationPeriod())
SevenSignsFestival.getInstance().saveFestivalData(false);


_log.info("[GlobalTask] SevenSigns save launched.");
}
catch (final Exception e)
{
if (Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.warning("SevenSigns: Failed to save Seven Signs configuration: " + e);
}
}


@Override
public void initializate()
{
super.initializate();
TaskManager.addUniqueTask(NAME, TaskTypes.TYPE_FIXED_SHEDULED, "1800000", "1800000", "");
}
}

 
 
Edited by EloBoost

5 answers to this question

Recommended Posts

  • 0
Posted (edited)
SevenSigns.java

 




/* 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 2, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.l2jfrozen.gameserver.model.entity.sevensigns;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Map;
import java.util.logging.Logger;


import javolution.util.FastMap;


import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.datatables.csv.MapRegionTable;
import com.l2jfrozen.gameserver.handler.AutoChatHandler;
import com.l2jfrozen.gameserver.managers.CastleManager;
import com.l2jfrozen.gameserver.model.L2World;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.spawn.AutoSpawn;
import com.l2jfrozen.gameserver.model.spawn.AutoSpawn.AutoSpawnInstance;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.SignsSky;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.templates.StatsSet;
import com.l2jfrozen.gameserver.thread.ThreadPoolManager;
import com.l2jfrozen.util.CloseUtil;
import com.l2jfrozen.util.database.L2DatabaseFactory;


/**
 * Seven Signs Engine TODO: - Implementation of the Seal of Strife for sieges.
 * 
 * @author programmos
 */
public class SevenSigns
{


/** The Constant _log. */
protected static final Logger _log = Logger.getLogger(SevenSigns.class.getName());


/** The _instance. */
private static SevenSigns _instance;


// Basic Seven Signs Constants \\
/** The Constant SEVEN_SIGNS_DATA_FILE. */
public static final String SEVEN_SIGNS_DATA_FILE = "config/signs.properties";


/** The Constant SEVEN_SIGNS_HTML_PATH. */
public static final String SEVEN_SIGNS_HTML_PATH = "data/html/seven_signs/";


/** The Constant CABAL_NULL. */
public static final int CABAL_NULL = 0;


/** The Constant CABAL_DUSK. */
public static final int CABAL_DUSK = 1;


/** The Constant CABAL_DAWN. */
public static final int CABAL_DAWN = 2;


/** The Constant SEAL_NULL. */
public static final int SEAL_NULL = 0;


/** The Constant SEAL_AVARICE. */
public static final int SEAL_AVARICE = 1;


/** The Constant SEAL_GNOSIS. */
public static final int SEAL_GNOSIS = 2;


/** The Constant SEAL_STRIFE. */
public static final int SEAL_STRIFE = 3;


/** The Constant PERIOD_COMP_RECRUITING. */
public static final int PERIOD_COMP_RECRUITING = 0;


/** The Constant PERIOD_COMPETITION. */
public static final int PERIOD_COMPETITION = 1;


/** The Constant PERIOD_COMP_RESULTS. */
public static final int PERIOD_COMP_RESULTS = 2;


/** The Constant PERIOD_SEAL_VALIDATION. */
public static final int PERIOD_SEAL_VALIDATION = 3;


/** The Constant PERIOD_START_HOUR. */
public static final int PERIOD_START_HOUR = 18;


/** The Constant PERIOD_START_MINS. */
public static final int PERIOD_START_MINS = 00;


/** The Constant PERIOD_START_DAY. */
public static final int PERIOD_START_DAY = Calendar.MONDAY;


// The quest event and seal validation periods last for approximately one week
// with a 15 minutes "interval" period sandwiched between them.
/** The Constant PERIOD_MINOR_LENGTH. */
public static final int PERIOD_MINOR_LENGTH = 900000;


/** The Constant PERIOD_MAJOR_LENGTH. */
public static final int PERIOD_MAJOR_LENGTH = 604800000 - PERIOD_MINOR_LENGTH;


/** The Constant ANCIENT_ADENA_ID. */
public static final int ANCIENT_ADENA_ID = 5575;


/** The Constant RECORD_SEVEN_SIGNS_ID. */
public static final int RECORD_SEVEN_SIGNS_ID = 5707;


/** The Constant CERTIFICATE_OF_APPROVAL_ID. */
public static final int CERTIFICATE_OF_APPROVAL_ID = 6388;


/** The Constant RECORD_SEVEN_SIGNS_COST. */
public static final int RECORD_SEVEN_SIGNS_COST = 500;


/** The Constant ADENA_JOIN_DAWN_COST. */
public static final int ADENA_JOIN_DAWN_COST = 50000;


// NPC Related Constants \\
/** The Constant ORATOR_NPC_ID. */
public static final int ORATOR_NPC_ID = 31094;


/** The Constant PREACHER_NPC_ID. */
public static final int PREACHER_NPC_ID = 31093;


/** The Constant MAMMON_MERCHANT_ID. */
public static final int MAMMON_MERCHANT_ID = 31113;


/** The Constant MAMMON_BLACKSMITH_ID. */
public static final int MAMMON_BLACKSMITH_ID = 31126;


/** The Constant MAMMON_MARKETEER_ID. */
public static final int MAMMON_MARKETEER_ID = 31092;


/** The Constant SPIRIT_IN_ID. */
public static final int SPIRIT_IN_ID = 31111;


/** The Constant SPIRIT_OUT_ID. */
public static final int SPIRIT_OUT_ID = 31112;


/** The Constant LILITH_NPC_ID. */
public static final int LILITH_NPC_ID = 25283;


/** The Constant ANAKIM_NPC_ID. */
public static final int ANAKIM_NPC_ID = 25286;


/** The Constant CREST_OF_DAWN_ID. */
public static final int CREST_OF_DAWN_ID = 31170;


/** The Constant CREST_OF_DUSK_ID. */
public static final int CREST_OF_DUSK_ID = 31171;
// Seal Stone Related Constants \\
/** The Constant SEAL_STONE_BLUE_ID. */
public static final int SEAL_STONE_BLUE_ID = 6360;


/** The Constant SEAL_STONE_GREEN_ID. */
public static final int SEAL_STONE_GREEN_ID = 6361;


/** The Constant SEAL_STONE_RED_ID. */
public static final int SEAL_STONE_RED_ID = 6362;


/** The Constant SEAL_STONE_BLUE_VALUE. */
public static final int SEAL_STONE_BLUE_VALUE = 3;


/** The Constant SEAL_STONE_GREEN_VALUE. */
public static final int SEAL_STONE_GREEN_VALUE = 5;


/** The Constant SEAL_STONE_RED_VALUE. */
public static final int SEAL_STONE_RED_VALUE = 10;


/** The Constant BLUE_CONTRIB_POINTS. */
public static final int BLUE_CONTRIB_POINTS = 3;


/** The Constant GREEN_CONTRIB_POINTS. */
public static final int GREEN_CONTRIB_POINTS = 5;


/** The Constant RED_CONTRIB_POINTS. */
public static final int RED_CONTRIB_POINTS = 10;


/** The _calendar. */
private final Calendar _calendar = Calendar.getInstance();


/** The _active period. */
protected int _activePeriod;


/** The _current cycle. */
protected int _currentCycle;


/** The _dawn stone score. */
protected double _dawnStoneScore;


/** The _dusk stone score. */
protected double _duskStoneScore;


/** The _dawn festival score. */
protected int _dawnFestivalScore;


/** The _dusk festival score. */
protected int _duskFestivalScore;


/** The _comp winner. */
protected int _compWinner;


/** The _previous winner. */
protected int _previousWinner;


/** The _signs player data. */
private Map<Integer, StatsSet> _signsPlayerData;


/** The _signs seal owners. */
private Map<Integer, Integer> _signsSealOwners;


/** The _signs dusk seal totals. */
private Map<Integer, Integer> _signsDuskSealTotals;


/** The _signs dawn seal totals. */
private Map<Integer, Integer> _signsDawnSealTotals;


/** The _merchant spawn. */
private static AutoSpawnInstance _merchantSpawn;


/** The _blacksmith spawn. */
private static AutoSpawnInstance _blacksmithSpawn;


/** The _spirit in spawn. */
private static AutoSpawnInstance _spiritInSpawn;


/** The _spirit out spawn. */
private static AutoSpawnInstance _spiritOutSpawn;


/** The _lilith spawn. */
private static AutoSpawnInstance _lilithSpawn;


/** The _anakim spawn. */
private static AutoSpawnInstance _anakimSpawn;


/** The _crestofdawnspawn. */
private static AutoSpawnInstance _crestofdawnspawn;


/** The _crestofduskspawn. */
private static AutoSpawnInstance _crestofduskspawn;


/** The _orator spawns. */
private static Map<Integer, AutoSpawnInstance> _oratorSpawns;


/** The _preacher spawns. */
private static Map<Integer, AutoSpawnInstance> _preacherSpawns;


/** The _marketeer spawns. */
private static Map<Integer, AutoSpawnInstance> _marketeerSpawns;


/**
* Instantiates a new seven signs.
*/
@SuppressWarnings("unused")
public SevenSigns()
{
_signsPlayerData = new FastMap<Integer, StatsSet>();
_signsSealOwners = new FastMap<Integer, Integer>();
_signsDuskSealTotals = new FastMap<Integer, Integer>();
_signsDawnSealTotals = new FastMap<Integer, Integer>();


try
{
restoreSevenSignsData();
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.severe("SevenSigns: Failed to load configuration: " + e);
}


_log.info("SevenSigns: Currently in the " + getCurrentPeriodName() + " period!");
initializeSeals();


if(isSealValidationPeriod())
if(getCabalHighestScore() == CABAL_NULL)
{
_log.info("SevenSigns: The competition ended with a tie last week.");
}
else
{
_log.info("SevenSigns: The " + getCabalName(getCabalHighestScore()) + " were victorious last week.");
}
else if(getCabalHighestScore() == CABAL_NULL)
{
_log.info("SevenSigns: The competition, if the current trend continues, will end in a tie this week.");
}
else
{
_log.info("SevenSigns: The " + getCabalName(getCabalHighestScore()) + " are in the lead this week.");
}


synchronized (this)
{
setCalendarForNextPeriodChange();
long milliToChange = getMilliToPeriodChange();


SevenSignsPeriodChange sspc = new SevenSignsPeriodChange();
ThreadPoolManager.getInstance().scheduleGeneral(sspc, milliToChange);
sspc = null;


// Thanks to http://rainbow.arch.scriptmania.com/scripts/timezone_countdown.html for help with this.
double numSecs = milliToChange / 1000 % 60;
double countDown = (milliToChange / 1000 - numSecs) / 60;
int numMins = (int) Math.floor(countDown % 60);
countDown = (countDown - numMins) / 60;
int numHours = (int) Math.floor(countDown % 24);
int numDays = (int) Math.floor((countDown - numHours) / 24);


_log.info("SevenSigns: Next period begins in " + numDays + " days, " + numHours + " hours and " + numMins + " mins.");
}


spawnSevenSignsNPC();
}


/**
* Registers all random spawns and auto-chats for Seven Signs NPCs, along with spawns for the Preachers of Doom and
* Orators of Revelations at the beginning of the Seal Validation period.
*/
public void spawnSevenSignsNPC()
{
_merchantSpawn = AutoSpawn.getInstance().getAutoSpawnInstance(MAMMON_MERCHANT_ID, false);
_blacksmithSpawn = AutoSpawn.getInstance().getAutoSpawnInstance(MAMMON_BLACKSMITH_ID, false);
_marketeerSpawns = AutoSpawn.getInstance().getAutoSpawnInstances(MAMMON_MARKETEER_ID);
_spiritInSpawn = AutoSpawn.getInstance().getAutoSpawnInstance(SPIRIT_IN_ID, false);
_spiritOutSpawn = AutoSpawn.getInstance().getAutoSpawnInstance(SPIRIT_OUT_ID, false);
_lilithSpawn = AutoSpawn.getInstance().getAutoSpawnInstance(LILITH_NPC_ID, false);
_anakimSpawn = AutoSpawn.getInstance().getAutoSpawnInstance(ANAKIM_NPC_ID, false);
_crestofdawnspawn = AutoSpawn.getInstance().getAutoSpawnInstance(CREST_OF_DAWN_ID, false);
_crestofduskspawn = AutoSpawn.getInstance().getAutoSpawnInstance(CREST_OF_DUSK_ID, false);
_oratorSpawns = AutoSpawn.getInstance().getAutoSpawnInstances(ORATOR_NPC_ID);
_preacherSpawns = AutoSpawn.getInstance().getAutoSpawnInstances(PREACHER_NPC_ID);


if(isSealValidationPeriod() || isCompResultsPeriod())
{
for(AutoSpawnInstance spawnInst : _marketeerSpawns.values())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, true);
}


if(getSealOwner(SEAL_GNOSIS) == getCabalHighestScore() && getSealOwner(SEAL_GNOSIS) != CABAL_NULL)
{
if(!Config.ANNOUNCE_MAMMON_SPAWN)
{
_blacksmithSpawn.setBroadcast(false);
}


if(!AutoSpawn.getInstance().getAutoSpawnInstance(_blacksmithSpawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_blacksmithSpawn, true);
}


for(AutoSpawnInstance spawnInst : _oratorSpawns.values())
if(!AutoSpawn.getInstance().getAutoSpawnInstance(spawnInst.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, true);
}


for(AutoSpawnInstance spawnInst : _preacherSpawns.values())
if(!AutoSpawn.getInstance().getAutoSpawnInstance(spawnInst.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, true);
}


if(!AutoChatHandler.getInstance().getAutoChatInstance(PREACHER_NPC_ID, false).isActive() && !AutoChatHandler.getInstance().getAutoChatInstance(ORATOR_NPC_ID, false).isActive())
{
AutoChatHandler.getInstance().setAutoChatActive(true);
}
}
else
{
AutoSpawn.getInstance().setSpawnActive(_blacksmithSpawn, false);


for(AutoSpawnInstance spawnInst : _oratorSpawns.values())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, false);
}


for(AutoSpawnInstance spawnInst : _preacherSpawns.values())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, false);
}


AutoChatHandler.getInstance().setAutoChatActive(false);
}


if(getSealOwner(SEAL_AVARICE) == getCabalHighestScore() && getSealOwner(SEAL_AVARICE) != CABAL_NULL)
{
if(!Config.ANNOUNCE_MAMMON_SPAWN)
{
_merchantSpawn.setBroadcast(false);
}


if(!AutoSpawn.getInstance().getAutoSpawnInstance(_merchantSpawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_merchantSpawn, true);
}


if(!AutoSpawn.getInstance().getAutoSpawnInstance(_spiritInSpawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_spiritInSpawn, true);
}


if(!AutoSpawn.getInstance().getAutoSpawnInstance(_spiritOutSpawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_spiritOutSpawn, true);
}


switch(getCabalHighestScore())
{
case CABAL_DAWN:
if(!AutoSpawn.getInstance().getAutoSpawnInstance(_lilithSpawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_lilithSpawn, true);
}


AutoSpawn.getInstance().setSpawnActive(_anakimSpawn, false);
if(!AutoSpawn.getInstance().getAutoSpawnInstance(_crestofdawnspawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_crestofdawnspawn, true);
}


AutoSpawn.getInstance().setSpawnActive(_crestofduskspawn, false);
break;


case CABAL_DUSK:
if(!AutoSpawn.getInstance().getAutoSpawnInstance(_anakimSpawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_anakimSpawn, true);
}


AutoSpawn.getInstance().setSpawnActive(_lilithSpawn, false);
if(!AutoSpawn.getInstance().getAutoSpawnInstance(_crestofduskspawn.getObjectId(), true).isSpawnActive())
{
AutoSpawn.getInstance().setSpawnActive(_crestofduskspawn, true);
}


AutoSpawn.getInstance().setSpawnActive(_crestofdawnspawn, false);
break;
}
}
else
{
AutoSpawn.getInstance().setSpawnActive(_merchantSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_lilithSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_anakimSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_crestofdawnspawn, false);
AutoSpawn.getInstance().setSpawnActive(_crestofduskspawn, false);
AutoSpawn.getInstance().setSpawnActive(_spiritInSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_spiritOutSpawn, false);
}
}
else
{
AutoSpawn.getInstance().setSpawnActive(_merchantSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_blacksmithSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_lilithSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_anakimSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_crestofdawnspawn, false);
AutoSpawn.getInstance().setSpawnActive(_crestofduskspawn, false);
AutoSpawn.getInstance().setSpawnActive(_spiritInSpawn, false);
AutoSpawn.getInstance().setSpawnActive(_spiritOutSpawn, false);


for(AutoSpawnInstance spawnInst : _oratorSpawns.values())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, false);
}


for(AutoSpawnInstance spawnInst : _preacherSpawns.values())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, false);
}


for(AutoSpawnInstance spawnInst : _marketeerSpawns.values())
{
AutoSpawn.getInstance().setSpawnActive(spawnInst, false);
}


AutoChatHandler.getInstance().setAutoChatActive(false);
}
}


/**
* Gets the single instance of SevenSigns.
*
* @return single instance of SevenSigns
*/
public static SevenSigns getInstance()
{
if(_instance == null)
{
_instance = new SevenSigns();
}


return _instance;
}


/**
* Calc contribution score.
*
* @param blueCount the blue count
* @param greenCount the green count
* @param redCount the red count
* @return the int
*/
public static int calcContributionScore(int blueCount, int greenCount, int redCount)
{
int contrib = blueCount * BLUE_CONTRIB_POINTS;
contrib += greenCount * GREEN_CONTRIB_POINTS;
contrib += redCount * RED_CONTRIB_POINTS;


return contrib;
}


/**
* Calc ancient adena reward.
*
* @param blueCount the blue count
* @param greenCount the green count
* @param redCount the red count
* @return the int
*/
public static int calcAncientAdenaReward(int blueCount, int greenCount, int redCount)
{
int reward = blueCount * SEAL_STONE_BLUE_VALUE;
reward += greenCount * SEAL_STONE_GREEN_VALUE;
reward += redCount * SEAL_STONE_RED_VALUE;


return reward;
}


/**
* Gets the cabal short name.
*
* @param cabal the cabal
* @return the cabal short name
*/
public static final String getCabalShortName(int cabal)
{
switch(cabal)
{
case CABAL_DAWN:
return "dawn";
case CABAL_DUSK:
return "dusk";
}


return "No Cabal";
}


/**
* Gets the cabal name.
*
* @param cabal the cabal
* @return the cabal name
*/
public static final String getCabalName(int cabal)
{
switch(cabal)
{
case CABAL_DAWN:
return "Lords of Dawn";
case CABAL_DUSK:
return "Revolutionaries of Dusk";
}


return "No Cabal";
}


/**
* Gets the seal name.
*
* @param seal the seal
* @param shortName the short name
* @return the seal name
*/
public static final String getSealName(int seal, boolean shortName)
{
String sealName = !shortName ? "Seal of " : "";


switch(seal)
{
case SEAL_AVARICE:
sealName += "Avarice";
break;
case SEAL_GNOSIS:
sealName += "Gnosis";
break;
case SEAL_STRIFE:
sealName += "Strife";
break;
}


return sealName;
}


/**
* Gets the current cycle.
*
* @return the current cycle
*/
public final int getCurrentCycle()
{
return _currentCycle;
}


/**
* Gets the current period.
*
* @return the current period
*/
public final int getCurrentPeriod()
{
return _activePeriod;
}


/**
* Gets the days to period change.
*
* @return the days to period change
*/
private final int getDaysToPeriodChange()
{
int numDays = _calendar.get(Calendar.DAY_OF_WEEK) - PERIOD_START_DAY;


if(numDays < 0)
return 0 - numDays;


return 7 - numDays;
}


/**
* Gets the milli to period change.
*
* @return the milli to period change
*/
public final long getMilliToPeriodChange()
{
long currTimeMillis = System.currentTimeMillis();
long changeTimeMillis = _calendar.getTimeInMillis();


return changeTimeMillis - currTimeMillis;
}


/**
* Sets the calendar for next period change.
*/
protected void setCalendarForNextPeriodChange()
{
// Calculate the number of days until the next period
// A period starts at 18:00 pm (local time), like on official servers.
switch(getCurrentPeriod())
{
case PERIOD_SEAL_VALIDATION:
case PERIOD_COMPETITION:
int daysToChange = getDaysToPeriodChange();


if(daysToChange == 7)
if(_calendar.get(Calendar.HOUR_OF_DAY) < PERIOD_START_HOUR)
{
daysToChange = 0;
}
else if(_calendar.get(Calendar.HOUR_OF_DAY) == PERIOD_START_HOUR && _calendar.get(Calendar.MINUTE) < PERIOD_START_MINS)
{
daysToChange = 0;
}


// Otherwise...
if(daysToChange > 0)
{
_calendar.add(Calendar.DATE, daysToChange);
}


_calendar.set(Calendar.HOUR_OF_DAY, PERIOD_START_HOUR);
_calendar.set(Calendar.MINUTE, PERIOD_START_MINS);
break;
case PERIOD_COMP_RECRUITING:
case PERIOD_COMP_RESULTS:
_calendar.add(Calendar.MILLISECOND, PERIOD_MINOR_LENGTH);
break;
}
}


/**
* Gets the current period name.
*
* @return the current period name
*/
public final String getCurrentPeriodName()
{
String periodName = null;


switch(_activePeriod)
{
case PERIOD_COMP_RECRUITING:
periodName = "Quest Event Initialization";
break;
case PERIOD_COMPETITION:
periodName = "Competition (Quest Event)";
break;
case PERIOD_COMP_RESULTS:
periodName = "Quest Event Results";
break;
case PERIOD_SEAL_VALIDATION:
periodName = "Seal Validation";
break;
}


return periodName;
}


/**
* Checks if is seal validation period.
*
* @return true, if is seal validation period
*/
public final boolean isSealValidationPeriod()
{
return _activePeriod == PERIOD_SEAL_VALIDATION;
}


/**
* Checks if is comp results period.
*
* @return true, if is comp results period
*/
public final boolean isCompResultsPeriod()
{
return _activePeriod == PERIOD_COMP_RESULTS;
}


/**
* Gets the current score.
*
* @param cabal the cabal
* @return the current score
*/
public final int getCurrentScore(int cabal)
{
double totalStoneScore = _dawnStoneScore + _duskStoneScore;


switch(cabal)
{
case CABAL_NULL:
return 0;
case CABAL_DAWN:
return Math.round((float) (_dawnStoneScore / ((float) totalStoneScore == 0 ? 1 : totalStoneScore)) * 500) + _dawnFestivalScore;
case CABAL_DUSK:
return Math.round((float) (_duskStoneScore / ((float) totalStoneScore == 0 ? 1 : totalStoneScore)) * 500) + _duskFestivalScore;
}


return 0;
}


/**
* Gets the current stone score.
*
* @param cabal the cabal
* @return the current stone score
*/
public final double getCurrentStoneScore(int cabal)
{
switch(cabal)
{
case CABAL_NULL:
return 0;
case CABAL_DAWN:
return _dawnStoneScore;
case CABAL_DUSK:
return _duskStoneScore;
}


return 0;
}


/**
* Gets the current festival score.
*
* @param cabal the cabal
* @return the current festival score
*/
public final int getCurrentFestivalScore(int cabal)
{
switch(cabal)
{
case CABAL_NULL:
return 0;
case CABAL_DAWN:
return _dawnFestivalScore;
case CABAL_DUSK:
return _duskFestivalScore;
}


return 0;
}


/**
* Gets the cabal highest score.
*
* @return the cabal highest score
*/
public final int getCabalHighestScore()
{
if(getCurrentScore(CABAL_DUSK) == getCurrentScore(CABAL_DAWN))
return CABAL_NULL;
else if(getCurrentScore(CABAL_DUSK) > getCurrentScore(CABAL_DAWN))
return CABAL_DUSK;
else
return CABAL_DAWN;
}


/**
* Gets the seal owner.
*
* @param seal the seal
* @return the seal owner
*/
public final int getSealOwner(int seal)
{
return _signsSealOwners.get(seal);
}


/**
* Gets the seal proportion.
*
* @param seal the seal
* @param cabal the cabal
* @return the seal proportion
*/
public final int getSealProportion(int seal, int cabal)
{
if(cabal == CABAL_NULL)
return 0;
else if(cabal == CABAL_DUSK)
return _signsDuskSealTotals.get(seal);
else
return _signsDawnSealTotals.get(seal);
}


/**
* Gets the total members.
*
* @param cabal the cabal
* @return the total members
*/
public final int getTotalMembers(int cabal)
{
int cabalMembers = 0;
String cabalName = getCabalShortName(cabal);


for(StatsSet sevenDat : _signsPlayerData.values())
if(sevenDat.getString("cabal").equals(cabalName))
{
cabalMembers++;
}


cabalName = null;


return cabalMembers;
}


/**
* Gets the player data.
*
* @param player the player
* @return the player data
*/
public final StatsSet getPlayerData(L2PcInstance player)
{
if(!hasRegisteredBefore(player))
return null;


return _signsPlayerData.get(player.getObjectId());
}


/**
* Gets the player stone contrib.
*
* @param player the player
* @return the player stone contrib
*/
public int getPlayerStoneContrib(L2PcInstance player)
{
if(!hasRegisteredBefore(player))
return 0;


int stoneCount = 0;


StatsSet currPlayer = getPlayerData(player);


stoneCount += currPlayer.getInteger("red_stones");
stoneCount += currPlayer.getInteger("green_stones");
stoneCount += currPlayer.getInteger("blue_stones");


currPlayer = null;


return stoneCount;
}


/**
* Gets the player contrib score.
*
* @param player the player
* @return the player contrib score
*/
public int getPlayerContribScore(L2PcInstance player)
{
if(!hasRegisteredBefore(player))
return 0;


StatsSet currPlayer = getPlayerData(player);


return currPlayer.getInteger("contribution_score");
}


/**
* Gets the player adena collect.
*
* @param player the player
* @return the player adena collect
*/
public int getPlayerAdenaCollect(L2PcInstance player)
{
if(!hasRegisteredBefore(player))
return 0;


return _signsPlayerData.get(player.getObjectId()).getInteger("ancient_adena_amount");
}


/**
* Gets the player seal.
*
* @param player the player
* @return the player seal
*/
public int getPlayerSeal(L2PcInstance player)
{
if(!hasRegisteredBefore(player))
return SEAL_NULL;


return getPlayerData(player).getInteger("seal");
}


/**
* Gets the player cabal.
*
* @param player the player
* @return the player cabal
*/
public int getPlayerCabal(L2PcInstance player)
{
if(!hasRegisteredBefore(player))
return CABAL_NULL;


String playerCabal = getPlayerData(player).getString("cabal");


if(playerCabal.equalsIgnoreCase("dawn"))
return CABAL_DAWN;
else if(playerCabal.equalsIgnoreCase("dusk"))
{
playerCabal = null;
return CABAL_DUSK;
}
else
return CABAL_NULL;
}


/**
* Restores all Seven Signs data and settings, usually called at server startup.
*
*/
protected void restoreSevenSignsData()
{
Connection con = null;


try
{
con = L2DatabaseFactory.getInstance().getConnection(false);
PreparedStatement statement = con.prepareStatement("SELECT char_obj_id, cabal, seal, red_stones, green_stones, blue_stones, " + "ancient_adena_amount, contribution_score FROM seven_signs");
ResultSet rset = statement.executeQuery();


while(rset.next())
{
int charObjId = rset.getInt("char_obj_id");


StatsSet sevenDat = new StatsSet();
sevenDat.set("char_obj_id", charObjId);
sevenDat.set("cabal", rset.getString("cabal"));
sevenDat.set("seal", rset.getInt("seal"));
sevenDat.set("red_stones", rset.getInt("red_stones"));
sevenDat.set("green_stones", rset.getInt("green_stones"));
sevenDat.set("blue_stones", rset.getInt("blue_stones"));
sevenDat.set("ancient_adena_amount", rset.getDouble("ancient_adena_amount"));
sevenDat.set("contribution_score", rset.getDouble("contribution_score"));


if(Config.DEBUG)
{
_log.info("SevenSigns: Loaded data from DB for char ID " + charObjId + " (" + sevenDat.getString("cabal") + ")");
}


_signsPlayerData.put(charObjId, sevenDat);
}


rset.close();
statement.close();


statement = con.prepareStatement("SELECT * FROM seven_signs_status WHERE id=0");
rset = statement.executeQuery();


while(rset.next())
{
_currentCycle = rset.getInt("current_cycle");
_activePeriod = rset.getInt("active_period");
_previousWinner = rset.getInt("previous_winner");


_dawnStoneScore = rset.getDouble("dawn_stone_score");
_dawnFestivalScore = rset.getInt("dawn_festival_score");
_duskStoneScore = rset.getDouble("dusk_stone_score");
_duskFestivalScore = rset.getInt("dusk_festival_score");


_signsSealOwners.put(SEAL_AVARICE, rset.getInt("avarice_owner"));
_signsSealOwners.put(SEAL_GNOSIS, rset.getInt("gnosis_owner"));
_signsSealOwners.put(SEAL_STRIFE, rset.getInt("strife_owner"));


_signsDawnSealTotals.put(SEAL_AVARICE, rset.getInt("avarice_dawn_score"));
_signsDawnSealTotals.put(SEAL_GNOSIS, rset.getInt("gnosis_dawn_score"));
_signsDawnSealTotals.put(SEAL_STRIFE, rset.getInt("strife_dawn_score"));
_signsDuskSealTotals.put(SEAL_AVARICE, rset.getInt("avarice_dusk_score"));
_signsDuskSealTotals.put(SEAL_GNOSIS, rset.getInt("gnosis_dusk_score"));
_signsDuskSealTotals.put(SEAL_STRIFE, rset.getInt("strife_dusk_score"));
}


rset.close();
statement.close();


statement = con.prepareStatement("UPDATE seven_signs_status SET date=? WHERE id=0");
statement.setInt(1, Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
statement.execute();


statement.close();




}
catch(SQLException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.severe("SevenSigns: Unable to load Seven Signs data from database: " + e);
}
finally
{
CloseUtil.close(con);
con = null;
}


// Festival data is loaded now after the Seven Signs engine data.
}


/**
* Saves all Seven Signs data, both to the database and properties file (if updateSettings = True). Often called to
* preserve data integrity and synchronization with DB, in case of errors. <BR>
* If player != null, just that player's data is updated in the database, otherwise all player's data is
* sequentially updated.
*
* @param player the player
* @param updateSettings the update settings
*/
public void saveSevenSignsData(L2PcInstance player, boolean updateSettings)
{
Connection con = null;


if(Config.DEBUG)
{
_log.info("SevenSigns: Saving data to disk.");
}


try
{
con = L2DatabaseFactory.getInstance().getConnection(false);
PreparedStatement statement = null;


for(StatsSet sevenDat : _signsPlayerData.values())
{
if(player != null)
if(sevenDat.getInteger("char_obj_id") != player.getObjectId())
{
continue;
}


statement = con.prepareStatement("UPDATE seven_signs SET cabal=?, seal=?, red_stones=?, " + "green_stones=?, blue_stones=?, " + "ancient_adena_amount=?, contribution_score=? " + "WHERE char_obj_id=?");
statement.setString(1, sevenDat.getString("cabal"));
statement.setInt(2, sevenDat.getInteger("seal"));
statement.setInt(3, sevenDat.getInteger("red_stones"));
statement.setInt(4, sevenDat.getInteger("green_stones"));
statement.setInt(5, sevenDat.getInteger("blue_stones"));
statement.setDouble(6, sevenDat.getDouble("ancient_adena_amount"));
statement.setDouble(7, sevenDat.getDouble("contribution_score"));
statement.setInt(8, sevenDat.getInteger("char_obj_id"));
statement.execute();


statement.close();


if(Config.DEBUG)
{
_log.info("SevenSigns: Updated data in database for char ID " + sevenDat.getInteger("char_obj_id") + " (" + sevenDat.getString("cabal") + ")");
}
}


if(updateSettings)
{
String sqlQuery = "UPDATE seven_signs_status SET current_cycle=?, active_period=?, previous_winner=?, " + "dawn_stone_score=?, dawn_festival_score=?, dusk_stone_score=?, dusk_festival_score=?, " + "avarice_owner=?, gnosis_owner=?, strife_owner=?, avarice_dawn_score=?, gnosis_dawn_score=?, " + "strife_dawn_score=?, avarice_dusk_score=?, gnosis_dusk_score=?, strife_dusk_score=?, " + "festival_cycle=?, ";


for(int i = 0; i < SevenSignsFestival.FESTIVAL_COUNT; i++)
{
sqlQuery += "accumulated_bonus" + String.valueOf(i) + "=?, ";
}


sqlQuery += "date=? WHERE id=0";


statement = con.prepareStatement(sqlQuery);
statement.setInt(1, _currentCycle);
statement.setInt(2, _activePeriod);
statement.setInt(3, _previousWinner);
statement.setDouble(4, _dawnStoneScore);
statement.setInt(5, _dawnFestivalScore);
statement.setDouble(6, _duskStoneScore);
statement.setInt(7, _duskFestivalScore);
statement.setInt(8, _signsSealOwners.get(SEAL_AVARICE));
statement.setInt(9, _signsSealOwners.get(SEAL_GNOSIS));
statement.setInt(10, _signsSealOwners.get(SEAL_STRIFE));
statement.setInt(11, _signsDawnSealTotals.get(SEAL_AVARICE));
statement.setInt(12, _signsDawnSealTotals.get(SEAL_GNOSIS));
statement.setInt(13, _signsDawnSealTotals.get(SEAL_STRIFE));
statement.setInt(14, _signsDuskSealTotals.get(SEAL_AVARICE));
statement.setInt(15, _signsDuskSealTotals.get(SEAL_GNOSIS));
statement.setInt(16, _signsDuskSealTotals.get(SEAL_STRIFE));
statement.setInt(17, SevenSignsFestival.getInstance().getCurrentFestivalCycle());


for(int i = 0; i < SevenSignsFestival.FESTIVAL_COUNT; i++)
{
statement.setInt(18 + i, SevenSignsFestival.getInstance().getAccumulatedBonus(i));
}


statement.setInt(18 + SevenSignsFestival.FESTIVAL_COUNT, Calendar.getInstance().get(Calendar.DAY_OF_WEEK));
statement.execute();


statement.close();


if(Config.DEBUG)
{
_log.info("SevenSigns: Updated data in database.");
}


sqlQuery = null;


}
}
catch(SQLException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.severe("SevenSigns: Unable to save data to database: " + e);
}
finally
{
CloseUtil.close(con);
con = null;
}
}


/**
* Used to reset the cabal details of all players, and update the database.<BR>
* Primarily used when beginning a new cycle, and should otherwise never be called.
*/
protected void resetPlayerData()
{
if(Config.DEBUG)
{
_log.info("SevenSigns: Resetting player data for new event period.");
}


// Reset each player's contribution data as well as seal and cabal.
for(StatsSet sevenDat : _signsPlayerData.values())
{
int charObjId = sevenDat.getInteger("char_obj_id");


// Reset the player's cabal and seal information
sevenDat.set("cabal", "");
sevenDat.set("seal", SEAL_NULL);
sevenDat.set("contribution_score", 0);


_signsPlayerData.put(charObjId, sevenDat);
}
}


/**
* Tests whether the specified player has joined a cabal in the past.
*
* @param player the player
* @return boolean hasRegistered
*/
private boolean hasRegisteredBefore(L2PcInstance player)
{
return _signsPlayerData.containsKey(player.getObjectId());
}


/**
* Used to specify cabal-related details for the specified player. This method checks to see if the player has
* registered before and will update the database if necessary. <BR>
* Returns the cabal ID the player has joined.
*
* @param player the player
* @param chosenCabal the chosen cabal
* @param chosenSeal the chosen seal
* @return int cabal
*/
public int setPlayerInfo(L2PcInstance player, int chosenCabal, int chosenSeal)
{
int charObjId = player.getObjectId();
Connection con = null;
PreparedStatement statement = null;
StatsSet currPlayerData = getPlayerData(player);


if(currPlayerData != null)
{
// If the seal validation period has passed,
// cabal information was removed and so "re-register" player
currPlayerData.set("cabal", getCabalShortName(chosenCabal));
currPlayerData.set("seal", chosenSeal);


_signsPlayerData.put(charObjId, currPlayerData);
}
else
{
currPlayerData = new StatsSet();
currPlayerData.set("char_obj_id", charObjId);
currPlayerData.set("cabal", getCabalShortName(chosenCabal));
currPlayerData.set("seal", chosenSeal);
currPlayerData.set("red_stones", 0);
currPlayerData.set("green_stones", 0);
currPlayerData.set("blue_stones", 0);
currPlayerData.set("ancient_adena_amount", 0);
currPlayerData.set("contribution_score", 0);


_signsPlayerData.put(charObjId, currPlayerData);


// Update data in database, as we have a new player signing up.
try
{
con = L2DatabaseFactory.getInstance().getConnection(false);
statement = con.prepareStatement("INSERT INTO seven_signs (char_obj_id, cabal, seal) VALUES (?,?,?)");
statement.setInt(1, charObjId);
statement.setString(2, getCabalShortName(chosenCabal));
statement.setInt(3, chosenSeal);
statement.execute();


statement.close();




if(Config.DEBUG)
{
_log.info("SevenSigns: Inserted data in DB for char ID " + currPlayerData.getInteger("char_obj_id") + " (" + currPlayerData.getString("cabal") + ")");
}
}
catch(SQLException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.severe("SevenSigns: Failed to save data: " + e);
}
finally
{
CloseUtil.close(con);
con = null;
}
}


// Increasing Seal total score for the player chosen Seal.
if(currPlayerData.getString("cabal") == "dawn")
{
_signsDawnSealTotals.put(chosenSeal, _signsDawnSealTotals.get(chosenSeal) + 1);
}
else
{
_signsDuskSealTotals.put(chosenSeal, _signsDuskSealTotals.get(chosenSeal) + 1);
}


currPlayerData = null;


saveSevenSignsData(player, true);


if(Config.DEBUG)
{
_log.info("SevenSigns: " + player.getName() + " has joined the " + getCabalName(chosenCabal) + " for the " + getSealName(chosenSeal, false) + "!");
}


return chosenCabal;
}


/**
* Returns the amount of ancient adena the specified player can claim, if any.<BR>
* If removeReward = True, all the ancient adena owed to them is removed, then DB is updated.
*
* @param player the player
* @param removeReward the remove reward
* @return int rewardAmount
*/
public int getAncientAdenaReward(L2PcInstance player, boolean removeReward)
{
StatsSet currPlayer = getPlayerData(player);
int rewardAmount = currPlayer.getInteger("ancient_adena_amount");


currPlayer.set("red_stones", 0);
currPlayer.set("green_stones", 0);
currPlayer.set("blue_stones", 0);
currPlayer.set("ancient_adena_amount", 0);


if(removeReward)
{
_signsPlayerData.put(player.getObjectId(), currPlayer);
saveSevenSignsData(player, true);
}


currPlayer = null;


return rewardAmount;
}


/**
* Used to add the specified player's seal stone contribution points to the current total for their cabal. Returns
* the point score the contribution was worth. Each stone count <B>must be</B> broken down and specified by the
* stone's color.
*
* @param player the player
* @param blueCount the blue count
* @param greenCount the green count
* @param redCount the red count
* @return int contribScore
*/
public int addPlayerStoneContrib(L2PcInstance player, int blueCount, int greenCount, int redCount)
{
StatsSet currPlayer = getPlayerData(player);


int contribScore = calcContributionScore(blueCount, greenCount, redCount);
int totalAncientAdena = currPlayer.getInteger("ancient_adena_amount") + calcAncientAdenaReward(blueCount, greenCount, redCount);
int totalContribScore = currPlayer.getInteger("contribution_score") + contribScore;


if(totalContribScore > Config.ALT_MAXIMUM_PLAYER_CONTRIB)
return -1;


currPlayer.set("red_stones", currPlayer.getInteger("red_stones") + redCount);
currPlayer.set("green_stones", currPlayer.getInteger("green_stones") + greenCount);
currPlayer.set("blue_stones", currPlayer.getInteger("blue_stones") + blueCount);
currPlayer.set("ancient_adena_amount", totalAncientAdena);
currPlayer.set("contribution_score", totalContribScore);
_signsPlayerData.put(player.getObjectId(), currPlayer);


currPlayer = null;


switch(getPlayerCabal(player))
{
case CABAL_DAWN:
_dawnStoneScore += contribScore;
break;
case CABAL_DUSK:
_duskStoneScore += contribScore;
break;
}


saveSevenSignsData(player, true);


if(Config.DEBUG)
{
_log.info("SevenSigns: " + player.getName() + " contributed " + contribScore + " seal stone points to their cabal.");
}


return contribScore;
}


/**
* Adds the specified number of festival points to the specified cabal. Remember, the same number of points are
* <B>deducted from the rival cabal</B> to maintain proportionality.
*
* @param cabal the cabal
* @param amount the amount
*/
public void addFestivalScore(int cabal, int amount)
{
if(cabal == CABAL_DUSK)
{
_duskFestivalScore += amount;


// To prevent negative scores!
if(_dawnFestivalScore >= amount)
{
_dawnFestivalScore -= amount;
}
}
else
{
_dawnFestivalScore += amount;


if(_duskFestivalScore >= amount)
{
_duskFestivalScore -= amount;
}
}
}


/**
* Send info on the current Seven Signs period to the specified player.
*
* @param player the player
*/
public void sendCurrentPeriodMsg(L2PcInstance player)
{
SystemMessage sm = null;


switch(getCurrentPeriod())
{
case PERIOD_COMP_RECRUITING:
sm = new SystemMessage(SystemMessageId.PREPARATIONS_PERIOD_BEGUN);
break;
case PERIOD_COMPETITION:
sm = new SystemMessage(SystemMessageId.COMPETITION_PERIOD_BEGUN);
break;
case PERIOD_COMP_RESULTS:
sm = new SystemMessage(SystemMessageId.RESULTS_PERIOD_BEGUN);
break;
case PERIOD_SEAL_VALIDATION:
sm = new SystemMessage(SystemMessageId.VALIDATION_PERIOD_BEGUN);
break;
}


player.sendPacket(sm);
sm = null;
}


/**
* Sends the built-in system message specified by sysMsgId to all online players.
*
* @param sysMsgId the sys msg id
*/
public void sendMessageToAll(SystemMessageId sysMsgId)
{
SystemMessage sm = new SystemMessage(sysMsgId);


for(L2PcInstance player : L2World.getInstance().getAllPlayers())
{
player.sendPacket(sm);
}
sm = null;
}


/**
* Used to initialize the seals for each cabal. (Used at startup or at beginning of a new cycle). This method should
* be called after <B>resetSeals()</B> and <B>calcNewSealOwners()</B> on a new cycle.
*/
protected void initializeSeals()
{
for(Integer currSeal : _signsSealOwners.keySet())
{
int sealOwner = _signsSealOwners.get(currSeal);


if(sealOwner != CABAL_NULL)
if(isSealValidationPeriod())
{
_log.info("SevenSigns: The " + getCabalName(sealOwner) + " have won the " + getSealName(currSeal, false) + ".");
}
else
{
_log.info("SevenSigns: The " + getSealName(currSeal, false) + " is currently owned by " + getCabalName(sealOwner) + ".");
}
else
{
_log.info("SevenSigns: The " + getSealName(currSeal, false) + " remains unclaimed.");
}
}
}


/**
* Only really used at the beginning of a new cycle, this method resets all seal-related data.
*/
protected void resetSeals()
{
_signsDawnSealTotals.put(SEAL_AVARICE, 0);
_signsDawnSealTotals.put(SEAL_GNOSIS, 0);
_signsDawnSealTotals.put(SEAL_STRIFE, 0);
_signsDuskSealTotals.put(SEAL_AVARICE, 0);
_signsDuskSealTotals.put(SEAL_GNOSIS, 0);
_signsDuskSealTotals.put(SEAL_STRIFE, 0);
}


/**
* Calculates the ownership of the three Seals of the Seven Signs, based on various criterion. <BR>
* <BR>
* Should only ever called at the beginning of a new cycle.
*/
protected void calcNewSealOwners()
{
if(Config.DEBUG)
{
_log.info("SevenSigns: (Avarice) Dawn = " + _signsDawnSealTotals.get(SEAL_AVARICE) + ", Dusk = " + _signsDuskSealTotals.get(SEAL_AVARICE));
_log.info("SevenSigns: (Gnosis) Dawn = " + _signsDawnSealTotals.get(SEAL_GNOSIS) + ", Dusk = " + _signsDuskSealTotals.get(SEAL_GNOSIS));
_log.info("SevenSigns: (Strife) Dawn = " + _signsDawnSealTotals.get(SEAL_STRIFE) + ", Dusk = " + _signsDuskSealTotals.get(SEAL_STRIFE));
}


for(Integer currSeal : _signsDawnSealTotals.keySet())
{
int prevSealOwner = _signsSealOwners.get(currSeal);
int newSealOwner = CABAL_NULL;
int dawnProportion = getSealProportion(currSeal, CABAL_DAWN);
int totalDawnMembers = getTotalMembers(CABAL_DAWN) == 0 ? 1 : getTotalMembers(CABAL_DAWN);
int dawnPercent = Math.round((float) dawnProportion / (float) totalDawnMembers * 100);
int duskProportion = getSealProportion(currSeal, CABAL_DUSK);
int totalDuskMembers = getTotalMembers(CABAL_DUSK) == 0 ? 1 : getTotalMembers(CABAL_DUSK);
int duskPercent = Math.round((float) duskProportion / (float) totalDuskMembers * 100);


/*
* - If a Seal was already closed or owned by the opponent and the new winner wants
*   to assume ownership of the Seal, 35% or more of the members of the Cabal must
*   have chosen the Seal. If they chose less than 35%, they cannot own the Seal.
*
* - If the Seal was owned by the winner in the previous Seven Signs, they can retain
*   that seal if 10% or more members have chosen it. If they want to possess a new Seal,
*   at least 35% of the members of the Cabal must have chosen the new Seal.
*/
switch(prevSealOwner)
{
case CABAL_NULL:
switch(getCabalHighestScore())
{
case CABAL_NULL:
newSealOwner = CABAL_NULL;
break;
case CABAL_DAWN:
if(dawnPercent >= 35)
{
newSealOwner = CABAL_DAWN;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
case CABAL_DUSK:
if(duskPercent >= 35)
{
newSealOwner = CABAL_DUSK;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
}
break;
case CABAL_DAWN:
switch(getCabalHighestScore())
{
case CABAL_NULL:
if(dawnPercent >= 10)
{
newSealOwner = CABAL_DAWN;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
case CABAL_DAWN:
if(dawnPercent >= 10)
{
newSealOwner = CABAL_DAWN;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
case CABAL_DUSK:
if(duskPercent >= 35)
{
newSealOwner = CABAL_DUSK;
}
else if(dawnPercent >= 10)
{
newSealOwner = CABAL_DAWN;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
}
break;
case CABAL_DUSK:
switch(getCabalHighestScore())
{
case CABAL_NULL:
if(duskPercent >= 10)
{
newSealOwner = CABAL_DUSK;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
case CABAL_DAWN:
if(dawnPercent >= 35)
{
newSealOwner = CABAL_DAWN;
}
else if(duskPercent >= 10)
{
newSealOwner = CABAL_DUSK;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
case CABAL_DUSK:
if(duskPercent >= 10)
{
newSealOwner = CABAL_DUSK;
}
else
{
newSealOwner = CABAL_NULL;
}
break;
}
break;
}


_signsSealOwners.put(currSeal, newSealOwner);


// Alert all online players to new seal status.
switch(currSeal)
{
case SEAL_AVARICE:
if(newSealOwner == CABAL_DAWN)
{
sendMessageToAll(SystemMessageId.DAWN_OBTAINED_AVARICE);
}
else if(newSealOwner == CABAL_DUSK)
{
sendMessageToAll(SystemMessageId.DUSK_OBTAINED_AVARICE);
}
break;
case SEAL_GNOSIS:
if(newSealOwner == CABAL_DAWN)
{
sendMessageToAll(SystemMessageId.DAWN_OBTAINED_GNOSIS);
}
else if(newSealOwner == CABAL_DUSK)
{
sendMessageToAll(SystemMessageId.DUSK_OBTAINED_GNOSIS);
}
break;
case SEAL_STRIFE:
if(newSealOwner == CABAL_DAWN)
{
sendMessageToAll(SystemMessageId.DAWN_OBTAINED_STRIFE);
}
else if(newSealOwner == CABAL_DUSK)
{
sendMessageToAll(SystemMessageId.DUSK_OBTAINED_STRIFE);
}


CastleManager.getInstance().validateTaxes(newSealOwner);
break;
}
}
}


/**
* This method is called to remove all players from catacombs and necropolises, who belong to the losing cabal. <BR>
* <BR>
* Should only ever called at the beginning of Seal Validation.
*
* @param compWinner the comp winner
*/
protected void teleLosingCabalFromDungeons(String compWinner)
{
for(L2PcInstance onlinePlayer : L2World.getInstance().getAllPlayers())
{
StatsSet currPlayer = getPlayerData(onlinePlayer);


if(isSealValidationPeriod() || isCompResultsPeriod())
{
if(!onlinePlayer.isGM() && onlinePlayer.isIn7sDungeon() && !currPlayer.getString("cabal").equals(compWinner))
{
onlinePlayer.teleToLocation(MapRegionTable.TeleportWhereType.Town);
onlinePlayer.setIsIn7sDungeon(false);
onlinePlayer.sendMessage("You have been teleported to the nearest town due to the beginning of the Seal Validation period.");
}
}
else
{
if(!onlinePlayer.isGM() && onlinePlayer.isIn7sDungeon() && !currPlayer.getString("cabal").equals(""))
{
onlinePlayer.teleToLocation(MapRegionTable.TeleportWhereType.Town);
onlinePlayer.setIsIn7sDungeon(false);
onlinePlayer.sendMessage("You have been teleported to the nearest town because you have not signed for any cabal.");
}
}
currPlayer = null;
}
}


/**
* The primary controller of period change of the Seven Signs system. This runs all related tasks depending on the
* period that is about to begin.

* @author Tempy
*/
protected class SevenSignsPeriodChange implements Runnable
{


/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{
/*
* Remember the period check here refers to the period just ENDED!
*/
final int periodEnded = getCurrentPeriod();
_activePeriod++;


switch(periodEnded)
{
case PERIOD_COMP_RECRUITING: // Initialization


// Start the Festival of Darkness cycle.
SevenSignsFestival.getInstance().startFestivalManager();


// Send message that Competition has begun.
sendMessageToAll(SystemMessageId.QUEST_EVENT_PERIOD_BEGUN);
break;
case PERIOD_COMPETITION: // Results Calculation


// Send message that Competition has ended.
sendMessageToAll(SystemMessageId.QUEST_EVENT_PERIOD_ENDED);


int compWinner = getCabalHighestScore();


// Schedule a stop of the festival engine.
SevenSignsFestival.getInstance().getFestivalManagerSchedule().cancel(false);


calcNewSealOwners();


switch(compWinner)
{
case CABAL_DAWN:
sendMessageToAll(SystemMessageId.DAWN_WON);
break;
case CABAL_DUSK:
sendMessageToAll(SystemMessageId.DUSK_WON);
break;
}


_previousWinner = compWinner;
break;
case PERIOD_COMP_RESULTS: // Seal Validation


// Perform initial Seal Validation set up.
initializeSeals();


// Send message that Seal Validation has begun.
sendMessageToAll(SystemMessageId.SEAL_VALIDATION_PERIOD_BEGUN);


_log.info("SevenSigns: The " + getCabalName(_previousWinner) + " have won the competition with " + getCurrentScore(_previousWinner) + " points!");
break;
case PERIOD_SEAL_VALIDATION: // Reset for New Cycle


SevenSignsFestival.getInstance().rewardHighRanked();


// Ensure a cycle restart when this period ends.
_activePeriod = PERIOD_COMP_RECRUITING;


// Send message that Seal Validation has ended.
sendMessageToAll(SystemMessageId.SEAL_VALIDATION_PERIOD_ENDED);


// Reset all data
resetPlayerData();
resetSeals();


// Reset all Festival-related data and remove any unused blood offerings.
// NOTE: A full update of Festival data in the database is also performed.
SevenSignsFestival.getInstance().resetFestivalData(false);


_dawnStoneScore = 0;
_duskStoneScore = 0;


_dawnFestivalScore = 0;
_duskFestivalScore = 0;


_currentCycle++;


break;
}


// Make sure all Seven Signs data is saved for future use.
saveSevenSignsData(null, true);


teleLosingCabalFromDungeons(getCabalShortName(getCabalHighestScore()));


SignsSky ss = new SignsSky();


for(L2PcInstance player : L2World.getInstance().getAllPlayers())
{
player.sendPacket(ss);
}


ss = null;


spawnSevenSignsNPC();


_log.info("SevenSigns: The " + getCurrentPeriodName() + " period has begun!");


setCalendarForNextPeriodChange();


SevenSignsPeriodChange sspc = new SevenSignsPeriodChange();
ThreadPoolManager.getInstance().scheduleGeneral(sspc, getMilliToPeriodChange());
sspc = null;
}
}
}



Edited by EloBoost
  • 0
Posted (edited)

SevenSignsPriestInstance

 




/*
 * 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 2, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * http://www.gnu.org/copyleft/gpl.html
 */
package com.l2jfrozen.gameserver.model.actor.instance;


import java.util.StringTokenizer;


import javolution.text.TextBuilder;


import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.cache.HtmCache;
import com.l2jfrozen.gameserver.datatables.sql.ClanTable;
import com.l2jfrozen.gameserver.model.L2Clan;
import com.l2jfrozen.gameserver.model.entity.sevensigns.SevenSigns;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.InventoryUpdate;
import com.l2jfrozen.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jfrozen.gameserver.network.serverpackets.StatusUpdate;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.templates.L2NpcTemplate;


/**
 * Dawn/Dusk Seven Signs Priest Instance
 * 
 * @author Tempy
 */
public class L2SignsPriestInstance extends L2FolkInstance
{
//private static Logger _log = Logger.getLogger(L2SignsPriestInstance.class.getName());


public L2SignsPriestInstance(int objectId, L2NpcTemplate template)
{
super(objectId, template);
}


@Override
public void onBypassFeedback(L2PcInstance player, String command)
{
if(command.startsWith("SevenSignsDesc"))
{
int val = Integer.parseInt(command.substring(15));
showChatWindow(player, val, null, true);
}
else if(command.startsWith("SevenSigns"))
{
SystemMessage sm;
InventoryUpdate iu;
StatusUpdate su;
String path;
int cabal = SevenSigns.CABAL_NULL;
int stoneType = 0;
L2ItemInstance ancientAdena = player.getInventory().getItemByItemId(SevenSigns.ANCIENT_ADENA_ID);
int ancientAdenaAmount = ancientAdena == null ? 0 : ancientAdena.getCount();
int val = Integer.parseInt(command.substring(11, 12).trim());


if(command.length() > 12)
{
val = Integer.parseInt(command.substring(11, 13).trim());
}


if(command.length() > 13)
{
try
{
cabal = Integer.parseInt(command.substring(14, 15).trim());
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


try
{
cabal = Integer.parseInt(command.substring(13, 14).trim());
}
catch(Exception e2)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e2.printStackTrace();


try
{
StringTokenizer st = new StringTokenizer(command.trim());
st.nextToken();
cabal = Integer.parseInt(st.nextToken());
st = null;
}
catch(Exception e3)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e3.printStackTrace();


_log.warning("Failed to retrieve cabal from bypass command. NpcId: " + getNpcId() + "; Command: " + command);
}
}
}
}


switch(val)
{
case 2: // Purchase Record of the Seven Signs
if(!player.getInventory().validateCapacity(1))
{
player.sendPacket(new SystemMessage(SystemMessageId.INVENTORY_VOLUME));
break;
}


//L2ItemInstance adenaItem = player.getInventory().getAdenaInstance();
if(!player.reduceAdena("SevenSigns", SevenSigns.RECORD_SEVEN_SIGNS_COST, this, false))
{
String filename = "data/html/seven_signs/noadena.htm";                  
NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setFile(filename);
html.replace("%objectId%", String.valueOf(getObjectId()));
player.sendPacket(html);
break;
}


player.addItem("SevenSigns", SevenSigns.RECORD_SEVEN_SIGNS_ID, 1, player, true);


// Update current load as well
su = new StatusUpdate(player.getObjectId());
su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
sendPacket(su);


//adenaItem = null;
break;
case 3: // Join Cabal Intro 1
case 8: // Festival of Darkness Intro - SevenSigns x [0]1
case 10: // Teleport Locations List
showChatWindow(player, val, SevenSigns.getCabalShortName(cabal), false);
break;
case 4: // Join a Cabal - SevenSigns 4 [0]1 x
int newSeal = Integer.parseInt(command.substring(15));
int oldCabal = SevenSigns.getInstance().getPlayerCabal(player);


if(oldCabal != SevenSigns.CABAL_NULL)
{
player.sendMessage("You are already a member of the " + SevenSigns.getCabalName(cabal) + ".");
return;
}


if(player.getClassId().level() == 0)
{
player.sendMessage("You must have already completed your first class transfer.");
break;
}
else if(player.getClassId().level() >= 2)
{
if(Config.ALT_GAME_REQUIRE_CASTLE_DAWN)
{
if(getPlayerAllyHasCastle(player))
{
if(cabal == SevenSigns.CABAL_DUSK)
{
player.sendMessage("You must not be a member of a castle-owning clan to join the Revolutionaries of Dusk.");
return;
}
}
//TODO
if(!getPlayerAllyHasCastle(player))
{
if(cabal == SevenSigns.CABAL_DAWN)
{
player.sendMessage("You must be a member of a castle-owning clan to join the Lords Of Dawn.");
return;
}
}


else
{
/*
* If the player is trying to join the Lords of Dawn, check if they are
* carrying a Lord's certificate.
*
* If not then try to take the required amount of adena instead.
*/
if(cabal == SevenSigns.CABAL_DAWN)
{
boolean allowJoinDawn = false;


if(player.destroyItemByItemId("SevenSigns", SevenSigns.CERTIFICATE_OF_APPROVAL_ID, 1, this, false))
{
sm = new SystemMessage(SystemMessageId.DISSAPEARED_ITEM);
sm.addNumber(1);
sm.addItemName(SevenSigns.CERTIFICATE_OF_APPROVAL_ID);
player.sendPacket(sm);
allowJoinDawn = true;
}
else if(player.reduceAdena("SevenSigns", SevenSigns.ADENA_JOIN_DAWN_COST, this, false))
{
sm = new SystemMessage(SystemMessageId.DISSAPEARED_ADENA);
sm.addNumber(SevenSigns.ADENA_JOIN_DAWN_COST);
player.sendPacket(sm);
allowJoinDawn = true;
}


if(!allowJoinDawn)
{
player.sendMessage("You must be a member of a castle-owning clan, have a Certificate of Lord's Approval, or pay 50000 adena to join the Lords of Dawn.");
return;
}
}
}
}
}


SevenSigns.getInstance().setPlayerInfo(player, cabal, newSeal);


// Joined Dawn
if(cabal == SevenSigns.CABAL_DAWN)
{
player.sendPacket(new SystemMessage(SystemMessageId.SEVENSIGNS_PARTECIPATION_DAWN));
}
else
{
player.sendPacket(new SystemMessage(SystemMessageId.SEVENSIGNS_PARTECIPATION_DUSK)); // Joined Dusk
}


// Show a confirmation message to the user, indicating which seal they chose.
switch(newSeal)
{
case SevenSigns.SEAL_AVARICE:
player.sendPacket(new SystemMessage(SystemMessageId.FIGHT_FOR_AVARICE));
break;
case SevenSigns.SEAL_GNOSIS:
player.sendPacket(new SystemMessage(SystemMessageId.FIGHT_FOR_GNOSIS));
break;
case SevenSigns.SEAL_STRIFE:
player.sendPacket(new SystemMessage(SystemMessageId.FIGHT_FOR_STRIFE));
break;
}


showChatWindow(player, 4, SevenSigns.getCabalShortName(cabal), false);
break;
case 6: // Contribute Seal Stones - SevenSigns 6 x
stoneType = Integer.parseInt(command.substring(13));
L2ItemInstance redStones = player.getInventory().getItemByItemId(SevenSigns.SEAL_STONE_RED_ID);
int redStoneCount = redStones == null ? 0 : redStones.getCount();
L2ItemInstance greenStones = player.getInventory().getItemByItemId(SevenSigns.SEAL_STONE_GREEN_ID);
int greenStoneCount = greenStones == null ? 0 : greenStones.getCount();
L2ItemInstance blueStones = player.getInventory().getItemByItemId(SevenSigns.SEAL_STONE_BLUE_ID);
int blueStoneCount = blueStones == null ? 0 : blueStones.getCount();
int contribScore = SevenSigns.getInstance().getPlayerContribScore(player);
boolean stonesFound = false;


if(contribScore == Config.ALT_MAXIMUM_PLAYER_CONTRIB)
{
player.sendPacket(new SystemMessage(SystemMessageId.CONTRIB_SCORE_EXCEEDED));
break;
}


int redContribCount = 0;
int greenContribCount = 0;
int blueContribCount = 0;


switch(stoneType)
{
case 1:
blueContribCount = (Config.ALT_MAXIMUM_PLAYER_CONTRIB - contribScore) / SevenSigns.BLUE_CONTRIB_POINTS;
if(blueContribCount > blueStoneCount)
{
blueContribCount = blueStoneCount;
}
break;
case 2:
greenContribCount = (Config.ALT_MAXIMUM_PLAYER_CONTRIB - contribScore) / SevenSigns.GREEN_CONTRIB_POINTS;
if(greenContribCount > greenStoneCount)
{
greenContribCount = greenStoneCount;
}
break;
case 3:
redContribCount = (Config.ALT_MAXIMUM_PLAYER_CONTRIB - contribScore) / SevenSigns.RED_CONTRIB_POINTS;
if(redContribCount > redStoneCount)
{
redContribCount = redStoneCount;
}
break;
case 4:
int tempContribScore = contribScore;
redContribCount = (Config.ALT_MAXIMUM_PLAYER_CONTRIB - tempContribScore) / SevenSigns.RED_CONTRIB_POINTS;
if(redContribCount > redStoneCount)
{
redContribCount = redStoneCount;
}
tempContribScore += redContribCount * SevenSigns.RED_CONTRIB_POINTS;
greenContribCount = (Config.ALT_MAXIMUM_PLAYER_CONTRIB - tempContribScore) / SevenSigns.GREEN_CONTRIB_POINTS;
if(greenContribCount > greenStoneCount)
{
greenContribCount = greenStoneCount;
}
tempContribScore += greenContribCount * SevenSigns.GREEN_CONTRIB_POINTS;
blueContribCount = (Config.ALT_MAXIMUM_PLAYER_CONTRIB - tempContribScore) / SevenSigns.BLUE_CONTRIB_POINTS;
if(blueContribCount > blueStoneCount)
{
blueContribCount = blueStoneCount;
}
break;
}
if(redContribCount > 0)
{
if(player.destroyItemByItemId("SevenSigns", SevenSigns.SEAL_STONE_RED_ID, redContribCount, this, false))
{
stonesFound = true;
}
}
if(greenContribCount > 0)
{
if(player.destroyItemByItemId("SevenSigns", SevenSigns.SEAL_STONE_GREEN_ID, greenContribCount, this, false))
{
stonesFound = true;
}
}
if(blueContribCount > 0)
{
if(player.destroyItemByItemId("SevenSigns", SevenSigns.SEAL_STONE_BLUE_ID, blueContribCount, this, false))
{
stonesFound = true;
}
}


if(!stonesFound)
{
player.sendMessage("You do not have any seal stones of that type.");
break;
}


contribScore = SevenSigns.getInstance().addPlayerStoneContrib(player, blueContribCount, greenContribCount, redContribCount);


sm = new SystemMessage(SystemMessageId.CONTRIB_SCORE_INCREASED);
sm.addNumber(contribScore);
player.sendPacket(sm);


showChatWindow(player, 6, null, false);
redStones = null;
greenStones = null;
blueStones = null;
break;
case 7: // Exchange Ancient Adena for Adena - SevenSigns 7 xxxxxxx
int ancientAdenaConvert = 0;


try
{
ancientAdenaConvert = Integer.parseInt(command.substring(13).trim());
}
catch(NumberFormatException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


showChatWindow(player, SevenSigns.SEVEN_SIGNS_HTML_PATH + "blkmrkt_3.htm");
break;
}
catch(StringIndexOutOfBoundsException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


showChatWindow(player, SevenSigns.SEVEN_SIGNS_HTML_PATH + "blkmrkt_3.htm");
break;
}


if(ancientAdenaConvert < 1)
{
showChatWindow(player, SevenSigns.SEVEN_SIGNS_HTML_PATH + "blkmrkt_3.htm");
break;
}


if(ancientAdenaAmount < ancientAdenaConvert)
{
showChatWindow(player, SevenSigns.SEVEN_SIGNS_HTML_PATH + "blkmrkt_4.htm");
break;
}


player.reduceAncientAdena("SevenSigns", ancientAdenaConvert, this, true);
player.addAdena("SevenSigns", ancientAdenaConvert, this, true);


iu = new InventoryUpdate();
iu.addModifiedItem(player.getInventory().getAncientAdenaInstance());
iu.addModifiedItem(player.getInventory().getAdenaInstance());
player.sendPacket(iu);
break;
case 9: // Receive Contribution Rewards
int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);
int winningCabal = SevenSigns.getInstance().getCabalHighestScore();


if(SevenSigns.getInstance().isSealValidationPeriod() && playerCabal == winningCabal)
{
int ancientAdenaReward = SevenSigns.getInstance().getAncientAdenaReward(player, true);


if(ancientAdenaReward < 3)
{
showChatWindow(player, 9, "b", false);
break;
}


player.addAncientAdena("SevenSigns", ancientAdenaReward, this, true);


// Send inventory update packet
iu = new InventoryUpdate();
iu.addModifiedItem(player.getInventory().getAncientAdenaInstance());
sendPacket(iu);


// Update current load as well
su = new StatusUpdate(player.getObjectId());
su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
sendPacket(su);


showChatWindow(player, 9, "a", false);
}
break;
case 11: // Teleport to Hunting Grounds
try
{
String portInfo = command.substring(14).trim();


StringTokenizer st = new StringTokenizer(portInfo);
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int z = Integer.parseInt(st.nextToken());
int ancientAdenaCost = Integer.parseInt(st.nextToken());


if(ancientAdenaCost > 0)
{
if(!player.reduceAncientAdena("SevenSigns", ancientAdenaCost, this, true))
{
break;
}
}


portInfo = null;
st = null;
player.teleToLocation(x, y, z, true);
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.warning("SevenSigns: Error occurred while teleporting player: " + e);
}
break;
case 17: // Exchange Seal Stones for Ancient Adena (Type Choice) - SevenSigns 17 x
stoneType = Integer.parseInt(command.substring(14));
int stoneId = 0;
int stoneCount = 0;
int stoneValue = 0;
String stoneColor = null;
String content;


switch(stoneType)
{
case 1:
stoneColor = "blue";
stoneId = SevenSigns.SEAL_STONE_BLUE_ID;
stoneValue = SevenSigns.SEAL_STONE_BLUE_VALUE;
break;
case 2:
stoneColor = "green";
stoneId = SevenSigns.SEAL_STONE_GREEN_ID;
stoneValue = SevenSigns.SEAL_STONE_GREEN_VALUE;
break;
case 3:
stoneColor = "red";
stoneId = SevenSigns.SEAL_STONE_RED_ID;
stoneValue = SevenSigns.SEAL_STONE_RED_VALUE;
break;
}


L2ItemInstance stoneInstance = player.getInventory().getItemByItemId(stoneId);


if(stoneInstance != null)
{
stoneCount = stoneInstance.getCount();
}


path = SevenSigns.SEVEN_SIGNS_HTML_PATH + "signs_17.htm";
content = HtmCache.getInstance().getHtm(path);


if(content != null)
{
content = content.replaceAll("%stoneColor%", stoneColor);
content = content.replaceAll("%stoneValue%", String.valueOf(stoneValue));
content = content.replaceAll("%stoneCount%", String.valueOf(stoneCount));
content = content.replaceAll("%stoneItemId%", String.valueOf(stoneId));
content = content.replaceAll("%objectId%", String.valueOf(getObjectId()));


NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setHtml(content);
player.sendPacket(html);
html = null;
}
else
{
_log.warning("Problem with HTML text " + SevenSigns.SEVEN_SIGNS_HTML_PATH + "signs_17.htm: " + path);
}


stoneInstance = null;
stoneColor = null;
content = null;
break;
case 18: // Exchange Seal Stones for Ancient Adena - SevenSigns 18 xxxx xxxxxx
int convertStoneId = Integer.parseInt(command.substring(14, 18));
int convertCount = 0;


try
{
convertCount = Integer.parseInt(command.substring(19).trim());
}
catch(Exception NumberFormatException)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
NumberFormatException.printStackTrace();


player.sendMessage("You must enter an integer amount.");
break;
}


L2ItemInstance convertItem = player.getInventory().getItemByItemId(convertStoneId);


if(convertItem == null)
{
player.sendMessage("You do not have any seal stones of that type.");
break;
}


int totalCount = convertItem.getCount();
int ancientAdenaReward = 0;


if(convertCount <= totalCount && convertCount > 0)
{
switch(convertStoneId)
{
case SevenSigns.SEAL_STONE_BLUE_ID:
ancientAdenaReward = SevenSigns.calcAncientAdenaReward(convertCount, 0, 0);
break;
case SevenSigns.SEAL_STONE_GREEN_ID:
ancientAdenaReward = SevenSigns.calcAncientAdenaReward(0, convertCount, 0);
break;
case SevenSigns.SEAL_STONE_RED_ID:
ancientAdenaReward = SevenSigns.calcAncientAdenaReward(0, 0, convertCount);
break;
}


if(player.destroyItemByItemId("SevenSigns", convertStoneId, convertCount, this, true))
{
player.addAncientAdena("SevenSigns", ancientAdenaReward, this, true);


// Send inventory update packet
iu = new InventoryUpdate();
iu.addModifiedItem(player.getInventory().getAncientAdenaInstance());
iu.addModifiedItem(convertItem);
sendPacket(iu);


// Update current load as well
su = new StatusUpdate(player.getObjectId());
su.addAttribute(StatusUpdate.CUR_LOAD, player.getCurrentLoad());
sendPacket(su);
}
}
else
{
player.sendMessage("You do not have that many seal stones.");
}
convertItem = null;
break;
case 19: // Seal Information (for when joining a cabal)
int chosenSeal = Integer.parseInt(command.substring(16));
String fileSuffix = SevenSigns.getSealName(chosenSeal, true) + "_" + SevenSigns.getCabalShortName(cabal);


showChatWindow(player, val, fileSuffix, false);
fileSuffix = null;
break;
case 20: // Seal Status (for when joining a cabal)
TextBuilder contentBuffer = new TextBuilder("<html><body><font color=\"LEVEL\">[ Seal Status ]</font><br>");


for(int i = 1; i < 4; i++)
{
int sealOwner = SevenSigns.getInstance().getSealOwner(i);


if(sealOwner != SevenSigns.CABAL_NULL)
{
contentBuffer.append("[" + SevenSigns.getSealName(i, false) + ": " + SevenSigns.getCabalName(sealOwner) + "]<br>");
}
else
{
contentBuffer.append("[" + SevenSigns.getSealName(i, false) + ": Nothingness]<br>");
}
}


contentBuffer.append("<a action=\"bypass -h npc_" + getObjectId() + "_SevenSigns 3 " + cabal + "\">Go back.</a></body></html>");


NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
html.setHtml(contentBuffer.toString());
player.sendPacket(html);
contentBuffer = null;
html = null;
break;
default:
// 1 = Purchase Record Intro
// 5 = Contrib Seal Stones Intro
// 16 = Choose Type of Seal Stones to Convert


showChatWindow(player, val, null, false);
break;


}
sm = null;
iu = null;
su = null;
path = null;
ancientAdena = null;
}
else
{
super.onBypassFeedback(player, command);
}
}


private final boolean getPlayerAllyHasCastle(L2PcInstance player)
{
L2Clan playerClan = player.getClan();


// The player is not in a clan, so return false.
if(playerClan == null)
return false;


// If castle ownage check is clan-based rather than ally-based,
// check if the player's clan has a castle and return the result.
if(!Config.ALT_GAME_REQUIRE_CLAN_CASTLE)
{
int allyId = playerClan.getAllyId();


// The player's clan is not in an alliance, so return false.
if(allyId != 0)
{
// Check if another clan in the same alliance owns a castle,
// by traversing the list of clans and act accordingly.
L2Clan[] clanList = ClanTable.getInstance().getClans();


for(L2Clan clan : clanList)
if(clan.getAllyId() == allyId && clan.getHasCastle() > 0)
return true;


clanList = null;
}
}


return playerClan.getHasCastle() > 0;
}


private void showChatWindow(L2PcInstance player, int val, String suffix, boolean isDescription)
{
String filename = SevenSigns.SEVEN_SIGNS_HTML_PATH;


filename += isDescription ? "desc_" + val : "signs_" + val;
filename += suffix != null ? "_" + suffix + ".htm" : ".htm";


showChatWindow(player, filename);
filename = null;
}
}



 

Edited by EloBoost
  • 0
Posted
 

SevenSignFestival.java

 




package com.l2jfrozen.gameserver.model.entity.sevensigns;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Logger;


import javolution.util.FastList;
import javolution.util.FastMap;


import com.l2jfrozen.Config;
import com.l2jfrozen.gameserver.ai.CtrlIntention;
import com.l2jfrozen.gameserver.datatables.csv.MapRegionTable;
import com.l2jfrozen.gameserver.datatables.sql.ClanTable;
import com.l2jfrozen.gameserver.datatables.sql.NpcTable;
import com.l2jfrozen.gameserver.datatables.sql.SpawnTable;
import com.l2jfrozen.gameserver.datatables.xml.ExperienceData;
import com.l2jfrozen.gameserver.model.L2Clan;
import com.l2jfrozen.gameserver.model.L2Party;
import com.l2jfrozen.gameserver.model.L2World;
import com.l2jfrozen.gameserver.model.actor.instance.L2FestivalMonsterInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2ItemInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2NpcInstance;
import com.l2jfrozen.gameserver.model.actor.instance.L2PcInstance;
import com.l2jfrozen.gameserver.model.actor.position.L2CharPosition;
import com.l2jfrozen.gameserver.model.spawn.L2Spawn;
import com.l2jfrozen.gameserver.model.spawn.SpawnListener;
import com.l2jfrozen.gameserver.network.SystemMessageId;
import com.l2jfrozen.gameserver.network.serverpackets.CreatureSay;
import com.l2jfrozen.gameserver.network.serverpackets.MagicSkillUser;
import com.l2jfrozen.gameserver.network.serverpackets.PledgeShowInfoUpdate;
import com.l2jfrozen.gameserver.network.serverpackets.SystemMessage;
import com.l2jfrozen.gameserver.templates.L2NpcTemplate;
import com.l2jfrozen.gameserver.templates.StatsSet;
import com.l2jfrozen.gameserver.thread.ThreadPoolManager;
import com.l2jfrozen.gameserver.util.Util;
import com.l2jfrozen.util.CloseUtil;
import com.l2jfrozen.util.database.L2DatabaseFactory;
import com.l2jfrozen.util.random.Rnd;


public class SevenSignsFestival implements SpawnListener
{


/** The Constant _log. */
protected static final Logger _log = Logger.getLogger(SevenSignsFestival.class.getName());


/** The _instance. */
private static SevenSignsFestival _instance;


/** The Constant GET_CLAN_NAME. */
private static final String GET_CLAN_NAME = "SELECT clan_name FROM clan_data WHERE clan_id = (SELECT clanid FROM characters WHERE char_name = ?)";


public static final long FESTIVAL_SIGNUP_TIME = Config.ALT_FESTIVAL_CYCLE_LENGTH - Config.ALT_FESTIVAL_LENGTH - 60000;


// Key Constants \\
/** The Constant FESTIVAL_MAX_OFFSET_X. */
private static final int FESTIVAL_MAX_OFFSET_X = 230;


/** The Constant FESTIVAL_MAX_OFFSET_Y. */
private static final int FESTIVAL_MAX_OFFSET_Y = 230;


/** The Constant FESTIVAL_DEFAULT_RESPAWN. */
private static final int FESTIVAL_DEFAULT_RESPAWN = 60; // Specify in seconds!


/** The Constant FESTIVAL_COUNT. */
public static final int FESTIVAL_COUNT = 5;


/** The Constant FESTIVAL_LEVEL_MAX_FOR_31. */
public static final int FESTIVAL_LEVEL_MAX_FOR_31 = 0;


/** The Constant FESTIVAL_LEVEL_MAX_FOR_42. */
public static final int FESTIVAL_LEVEL_MAX_FOR_42 = 1;


/** The Constant FESTIVAL_LEVEL_MAX_FOR_53. */
public static final int FESTIVAL_LEVEL_MAX_FOR_53 = 2;


/** The Constant FESTIVAL_LEVEL_MAX_FOR_64. */
public static final int FESTIVAL_LEVEL_MAX_FOR_64 = 3;


/** The Constant FESTIVAL_LEVEL_MAX_FOR_NONE. */
public static final int FESTIVAL_LEVEL_MAX_FOR_NONE = 4;


/** The Constant FESTIVAL_LEVEL_SCORES. */
public static final int[] FESTIVAL_LEVEL_SCORES =
{
60, 70, 100, 120, 150
}; // 500 maximum possible score


/** The Constant FESTIVAL_OFFERING_ID. */
public static final int FESTIVAL_OFFERING_ID = 5901;


/** The Constant FESTIVAL_OFFERING_VALUE. */
public static final int FESTIVAL_OFFERING_VALUE = 5;


public static final int[][] FESTIVAL_DAWN_PLAYER_SPAWNS =
{
{
-79187, 113186, -4895, 0
}, // 31 and below
{
-75918, 110137, -4895, 0
}, // 42 and below
{
-73835, 111969, -4895, 0
}, // 53 and below
{
-76170, 113804, -4895, 0
}, // 64 and below
{
-78927, 109528, -4895, 0
}
// No level limit
};


/** The Constant FESTIVAL_DUSK_PLAYER_SPAWNS. */
public static final int[][] FESTIVAL_DUSK_PLAYER_SPAWNS =
{
{
-77200, 88966, -5151, 0
}, // 31 and below
{
-76941, 85307, -5151, 0
}, // 42 and below
{
-74855, 87135, -5151, 0
}, // 53 and below
{
-80208, 88222, -5151, 0
}, // 64 and below
{
-79954, 84697, -5151, 0
}
// No level limit
};


/** The Constant FESTIVAL_DAWN_WITCH_SPAWNS. */
protected static final int[][] FESTIVAL_DAWN_WITCH_SPAWNS =
{
{
-79183, 113052, -4891, 0, 31132
}, // 31 and below
{
-75916, 110270, -4891, 0, 31133
}, // 42 and below
{
-73979, 111970, -4891, 0, 31134
}, // 53 and below
{
-76174, 113663, -4891, 0, 31135
}, // 64 and below
{
-78930, 109664, -4891, 0, 31136
}
// No level limit
};


/** The Constant FESTIVAL_DUSK_WITCH_SPAWNS. */
protected static final int[][] FESTIVAL_DUSK_WITCH_SPAWNS =
{
{
-77199, 88830, -5147, 0, 31142
}, // 31 and below
{
-76942, 85438, -5147, 0, 31143
}, // 42 and below
{
-74990, 87135, -5147, 0, 31144
}, // 53 and below
{
-80207, 88222, -5147, 0, 31145
}, // 64 and below
{
-79952, 84833, -5147, 0, 31146
}
// No level limit
};


/** The Constant FESTIVAL_DAWN_PRIMARY_SPAWNS. */
protected static final int[][][] FESTIVAL_DAWN_PRIMARY_SPAWNS =
{
{
/* Level 31 and Below - Offering of the Branded */
{
-78537, 113839, -4895, -1, 18009
},
{
-78466, 113852, -4895, -1, 18010
},
{
-78509, 113899, -4895, -1, 18010
},


{
-78481, 112557, -4895, -1, 18009
},
{
-78559, 112504, -4895, -1, 18010
},
{
-78489, 112494, -4895, -1, 18010
},


{
-79803, 112543, -4895, -1, 18012
},
{
-79854, 112492, -4895, -1, 18013
},
{
-79886, 112557, -4895, -1, 18014
},


{
-79821, 113811, -4895, -1, 18015
},
{
-79857, 113896, -4895, -1, 18017
},
{
-79878, 113816, -4895, -1, 18018
},


// Archers and Marksmen \\
{
-79190, 113660, -4895, -1, 18011
},
{
-78710, 113188, -4895, -1, 18011
},
{
-79190, 112730, -4895, -1, 18016
},
{
-79656, 113188, -4895, -1, 18016
}
},
{
/* Level 42 and Below - Apostate Offering */
{
-76558, 110784, -4895, -1, 18019
},
{
-76607, 110815, -4895, -1, 18020
}, // South West
{
-76559, 110820, -4895, -1, 18020
},


{
-75277, 110792, -4895, -1, 18019
},
{
-75225, 110801, -4895, -1, 18020
}, // South East
{
-75262, 110832, -4895, -1, 18020
},


{
-75249, 109441, -4895, -1, 18022
},
{
-75278, 109495, -4895, -1, 18023
}, // North East
{
-75223, 109489, -4895, -1, 18024
},


{
-76556, 109490, -4895, -1, 18025
},
{
-76607, 109469, -4895, -1, 18027
}, // North West
{
-76561, 109450, -4895, -1, 18028
},


// Archers and Marksmen \\
{
-76399, 110144, -4895, -1, 18021
},
{
-75912, 110606, -4895, -1, 18021
},
{
-75444, 110144, -4895, -1, 18026
},
{
-75930, 109665, -4895, -1, 18026
}
},
{
/* Level 53 and Below - Witch's Offering */
{
-73184, 111319, -4895, -1, 18029
},
{
-73135, 111294, -4895, -1, 18030
}, // South West
{
-73185, 111281, -4895, -1, 18030
},


{
-74477, 111321, -4895, -1, 18029
},
{
-74523, 111293, -4895, -1, 18030
}, // South East
{
-74481, 111280, -4895, -1, 18030
},


{
-74489, 112604, -4895, -1, 18032
},
{
-74491, 112660, -4895, -1, 18033
}, // North East
{
-74527, 112629, -4895, -1, 18034
},


{
-73197, 112621, -4895, -1, 18035
},
{
-73142, 112631, -4895, -1, 18037
}, // North West
{
-73182, 112656, -4895, -1, 18038
},


// Archers and Marksmen \\
{
-73834, 112430, -4895, -1, 18031
},
{
-74299, 111959, -4895, -1, 18031
},
{
-73841, 111491, -4895, -1, 18036
},
{
-73363, 111959, -4895, -1, 18036
}
},
{
/* Level 64 and Below - Dark Omen Offering */
{
-75543, 114461, -4895, -1, 18039
},
{
-75514, 114493, -4895, -1, 18040
}, // South West
{
-75488, 114456, -4895, -1, 18040
},


{
-75521, 113158, -4895, -1, 18039
},
{
-75504, 113110, -4895, -1, 18040
}, // South East
{
-75489, 113142, -4895, -1, 18040
},


{
-76809, 113143, -4895, -1, 18042
},
{
-76860, 113138, -4895, -1, 18043
}, // North East
{
-76831, 113112, -4895, -1, 18044
},


{
-76831, 114441, -4895, -1, 18045
},
{
-76840, 114490, -4895, -1, 18047
}, // North West
{
-76864, 114455, -4895, -1, 18048
},


// Archers and Marksmen \\
{
-75703, 113797, -4895, -1, 18041
},
{
-76180, 114263, -4895, -1, 18041
},
{
-76639, 113797, -4895, -1, 18046
},
{
-76180, 113337, -4895, -1, 18046
}
},
{
/* No Level Limit - Offering of Forbidden Path */
{
-79576, 108881, -4895, -1, 18049
},
{
-79592, 108835, -4895, -1, 18050
}, // South West
{
-79614, 108871, -4895, -1, 18050
},


{
-79586, 110171, -4895, -1, 18049
},
{
-79589, 110216, -4895, -1, 18050
}, // South East
{
-79620, 110177, -4895, -1, 18050
},


{
-78825, 110182, -4895, -1, 18052
},
{
-78238, 110182, -4895, -1, 18053
}, // North East
{
-78266, 110218, -4895, -1, 18054
},


{
-78275, 108883, -4895, -1, 18055
},
{
-78267, 108839, -4895, -1, 18057
}, // North West
{
-78241, 108871, -4895, -1, 18058
},


// Archers and Marksmen \\
{
-79394, 109538, -4895, -1, 18051
},
{
-78929, 109992, -4895, -1, 18051
},
{
-78454, 109538, -4895, -1, 18056
},
{
-78929, 109053, -4895, -1, 18056
}
}
};


/** The Constant FESTIVAL_DUSK_PRIMARY_SPAWNS. */
protected static final int[][][] FESTIVAL_DUSK_PRIMARY_SPAWNS =
{
{
/* Level 31 and Below - Offering of the Branded */
{
-76542, 89653, -5151, -1, 18009
},
{
-76509, 89637, -5151, -1, 18010
},
{
-76548, 89614, -5151, -1, 18010
},


{
-76539, 88326, -5151, -1, 18009
},
{
-76512, 88289, -5151, -1, 18010
},
{
-76546, 88287, -5151, -1, 18010
},


{
-77879, 88308, -5151, -1, 18012
},
{
-77886, 88310, -5151, -1, 18013
},
{
-77879, 88278, -5151, -1, 18014
},


{
-77857, 89605, -5151, -1, 18015
},
{
-77858, 89658, -5151, -1, 18017
},
{
-77891, 89633, -5151, -1, 18018
},


// Archers and Marksmen \\
{
-76728, 88962, -5151, -1, 18011
},
{
-77194, 88494, -5151, -1, 18011
},
{
-77660, 88896, -5151, -1, 18016
},
{
-77195, 89438, -5151, -1, 18016
}
},
{
/* Level 42 and Below - Apostate's Offering */
{
-77585, 84650, -5151, -1, 18019
},
{
-77628, 84643, -5151, -1, 18020
},
{
-77607, 84613, -5151, -1, 18020
},


{
-76603, 85946, -5151, -1, 18019
},
{
-77606, 85994, -5151, -1, 18020
},
{
-77638, 85959, -5151, -1, 18020
},


{
-76301, 85960, -5151, -1, 18022
},
{
-76257, 85972, -5151, -1, 18023
},
{
-76286, 85992, -5151, -1, 18024
},


{
-76281, 84667, -5151, -1, 18025
},
{
-76291, 84611, -5151, -1, 18027
},
{
-76257, 84616, -5151, -1, 18028
},


// Archers and Marksmen \\
{
-77419, 85307, -5151, -1, 18021
},
{
-76952, 85768, -5151, -1, 18021
},
{
-76477, 85312, -5151, -1, 18026
},
{
-76942, 84832, -5151, -1, 18026
}
},
{
/* Level 53 and Below - Witch's Offering */
{
-74211, 86494, -5151, -1, 18029
},
{
-74200, 86449, -5151, -1, 18030
},
{
-74167, 86464, -5151, -1, 18030
},


{
-75495, 86482, -5151, -1, 18029
},
{
-75540, 86473, -5151, -1, 18030
},
{
-75509, 86445, -5151, -1, 18030
},


{
-75509, 87775, -5151, -1, 18032
},
{
-75518, 87826, -5151, -1, 18033
},
{
-75542, 87780, -5151, -1, 18034
},


{
-74214, 87789, -5151, -1, 18035
},
{
-74169, 87801, -5151, -1, 18037
},
{
-74198, 87827, -5151, -1, 18038
},


// Archers and Marksmen \\
{
-75324, 87135, -5151, -1, 18031
},
{
-74852, 87606, -5151, -1, 18031
},
{
-74388, 87146, -5151, -1, 18036
},
{
-74856, 86663, -5151, -1, 18036
}
},
{
/* Level 64 and Below - Dark Omen Offering */
{
-79560, 89007, -5151, -1, 18039
},
{
-79521, 89016, -5151, -1, 18040
},
{
-79544, 89047, -5151, -1, 18040
},


{
-79552, 87717, -5151, -1, 18039
},
{
-79552, 87673, -5151, -1, 18040
},
{
-79510, 87702, -5151, -1, 18040
},


{
-80866, 87719, -5151, -1, 18042
},
{
-80897, 87689, -5151, -1, 18043
},
{
-80850, 87685, -5151, -1, 18044
},


{
-80848, 89013, -5151, -1, 18045
},
{
-80887, 89051, -5151, -1, 18047
},
{
-80891, 89004, -5151, -1, 18048
},


// Archers and Marksmen \\
{
-80205, 87895, -5151, -1, 18041
},
{
-80674, 88350, -5151, -1, 18041
},
{
-80209, 88833, -5151, -1, 18046
},
{
-79743, 88364, -5151, -1, 18046
}
},
{
/* No Level Limit - Offering of Forbidden Path */
{
-80624, 84060, -5151, -1, 18049
},
{
-80621, 84007, -5151, -1, 18050
},
{
-80590, 84039, -5151, -1, 18050
},


{
-80605, 85349, -5151, -1, 18049
},
{
-80639, 85363, -5151, -1, 18050
},
{
-80611, 85385, -5151, -1, 18050
},


{
-79311, 85353, -5151, -1, 18052
},
{
-79277, 85384, -5151, -1, 18053
},
{
-79273, 85539, -5151, -1, 18054
},


{
-79297, 84054, -5151, -1, 18055
},
{
-79285, 84006, -5151, -1, 18057
},
{
-79260, 84040, -5151, -1, 18058
},


// Archers and Marksmen \\
{
-79945, 85171, -5151, -1, 18051
},
{
-79489, 84707, -5151, -1, 18051
},
{
-79952, 84222, -5151, -1, 18056
},
{
-80423, 84703, -5151, -1, 18056
}
}
};


/** The Constant FESTIVAL_DAWN_SECONDARY_SPAWNS. */
protected static final int[][][] FESTIVAL_DAWN_SECONDARY_SPAWNS =
{
{
/* 31 and Below */
{
-78757, 112834, -4895, -1, 18016
},
{
-78581, 112834, -4895, -1, 18016
},


{
-78822, 112526, -4895, -1, 18011
},
{
-78822, 113702, -4895, -1, 18011
},
{
-78822, 113874, -4895, -1, 18011
},


{
-79524, 113546, -4895, -1, 18011
},
{
-79693, 113546, -4895, -1, 18011
},
{
-79858, 113546, -4895, -1, 18011
},


{
-79545, 112757, -4895, -1, 18016
},
{
-79545, 112586, -4895, -1, 18016
},
},
{
/* 42 and Below */
{
-75565, 110580, -4895, -1, 18026
},
{
-75565, 110740, -4895, -1, 18026
},


{
-75577, 109776, -4895, -1, 18021
},
{
-75413, 109776, -4895, -1, 18021
},
{
-75237, 109776, -4895, -1, 18021
},


{
-76274, 109468, -4895, -1, 18021
},
{
-76274, 109635, -4895, -1, 18021
},
{
-76274, 109795, -4895, -1, 18021
},


{
-76351, 110500, -4895, -1, 18056
},
{
-76528, 110500, -4895, -1, 18056
},
},
{
/* 53 and Below */
{
-74191, 111527, -4895, -1, 18036
},
{
-74191, 111362, -4895, -1, 18036
},


{
-73495, 111611, -4895, -1, 18031
},
{
-73327, 111611, -4895, -1, 18031
},
{
-73154, 111611, -4895, -1, 18031
},


{
-73473, 112301, -4895, -1, 18031
},
{
-73473, 112475, -4895, -1, 18031
},
{
-73473, 112649, -4895, -1, 18031
},


{
-74270, 112326, -4895, -1, 18036
},
{
-74443, 112326, -4895, -1, 18036
},
},
{
/* 64 and Below */
{
-75738, 113439, -4895, -1, 18046
},
{
-75571, 113439, -4895, -1, 18046
},


{
-75824, 114141, -4895, -1, 18041
},
{
-75824, 114309, -4895, -1, 18041
},
{
-75824, 114477, -4895, -1, 18041
},


{
-76513, 114158, -4895, -1, 18041
},
{
-76683, 114158, -4895, -1, 18041
},
{
-76857, 114158, -4895, -1, 18041
},


{
-76535, 113357, -4895, -1, 18056
},
{
-76535, 113190, -4895, -1, 18056
},
},
{
/* No Level Limit */
{
-79350, 109894, -4895, -1, 18056
},
{
-79534, 109894, -4895, -1, 18056
},


{
-79285, 109187, -4895, -1, 18051
},
{
-79285, 109019, -4895, -1, 18051
},
{
-79285, 108860, -4895, -1, 18051
},


{
-78587, 109172, -4895, -1, 18051
},
{
-78415, 109172, -4895, -1, 18051
},
{
-78249, 109172, -4895, -1, 18051
},


{
-78575, 109961, -4895, -1, 18056
},
{
-78575, 110130, -4895, -1, 18056
},
}
};


/** The Constant FESTIVAL_DUSK_SECONDARY_SPAWNS. */
protected static final int[][][] FESTIVAL_DUSK_SECONDARY_SPAWNS =
{
{
/* 31 and Below */
{
-76844, 89304, -5151, -1, 18011
},
{
-76844, 89479, -5151, -1, 18011
},
{
-76844, 89649, -5151, -1, 18011
},


{
-77544, 89326, -5151, -1, 18011
},
{
-77716, 89326, -5151, -1, 18011
},
{
-77881, 89326, -5151, -1, 18011
},


{
-77561, 88530, -5151, -1, 18016
},
{
-77561, 88364, -5151, -1, 18016
},


{
-76762, 88615, -5151, -1, 18016
},
{
-76594, 88615, -5151, -1, 18016
},
},
{
/* 42 and Below */
{
-77307, 84969, -5151, -1, 18021
},
{
-77307, 84795, -5151, -1, 18021
},
{
-77307, 84623, -5151, -1, 18021
},


{
-76614, 84944, -5151, -1, 18021
},
{
-76433, 84944, -5151, -1, 18021
},
{
-7626 - 1, 84944, -5151, -1, 18021
},


{
-76594, 85745, -5151, -1, 18026
},
{
-76594, 85910, -5151, -1, 18026
},


{
-77384, 85660, -5151, -1, 18026
},
{
-77555, 85660, -5151, -1, 18026
},
},
{
/* 53 and Below */
{
-74517, 86782, -5151, -1, 18031
},
{
-74344, 86782, -5151, -1, 18031
},
{
-74185, 86782, -5151, -1, 18031
},


{
-74496, 87464, -5151, -1, 18031
},
{
-74496, 87636, -5151, -1, 18031
},
{
-74496, 87815, -5151, -1, 18031
},


{
-75298, 87497, -5151, -1, 18036
},
{
-75460, 87497, -5151, -1, 18036
},


{
-75219, 86712, -5151, -1, 18036
},
{
-75219, 86531, -5151, -1, 18036
},
},
{
/* 64 and Below */
{
-79851, 88703, -5151, -1, 18041
},
{
-79851, 88868, -5151, -1, 18041
},
{
-79851, 89040, -5151, -1, 18041
},


{
-80548, 88722, -5151, -1, 18041
},
{
-80711, 88722, -5151, -1, 18041
},
{
-80883, 88722, -5151, -1, 18041
},


{
-80565, 87916, -5151, -1, 18046
},
{
-80565, 87752, -5151, -1, 18046
},


{
-79779, 87996, -5151, -1, 18046
},
{
-79613, 87996, -5151, -1, 18046
},
},
{
/* No Level Limit */
{
-79271, 84330, -5151, -1, 18051
},
{
-79448, 84330, -5151, -1, 18051
},
{
-79601, 84330, -5151, -1, 18051
},


{
-80311, 84367, -5151, -1, 18051
},
{
-80311, 84196, -5151, -1, 18051
},
{
-80311, 84015, -5151, -1, 18051
},


{
-80556, 85049, -5151, -1, 18056
},
{
-80384, 85049, -5151, -1, 18056
},


{
-79598, 85127, -5151, -1, 18056
},
{
-79598, 85303, -5151, -1, 18056
},
}
};


/** The Constant FESTIVAL_DAWN_CHEST_SPAWNS. */
protected static final int[][][] FESTIVAL_DAWN_CHEST_SPAWNS =
{
{
/* Level 31 and Below */
{
-78999, 112957, -4927, -1, 18109
},
{
-79153, 112873, -4927, -1, 18109
},
{
-79256, 112873, -4927, -1, 18109
},
{
-79368, 112957, -4927, -1, 18109
},


{
-79481, 113124, -4927, -1, 18109
},
{
-79481, 113275, -4927, -1, 18109
},


{
-79364, 113398, -4927, -1, 18109
},
{
-79213, 113500, -4927, -1, 18109
},
{
-79099, 113500, -4927, -1, 18109
},
{
-78960, 113398, -4927, -1, 18109
},


{
-78882, 113235, -4927, -1, 18109
},
{
-78882, 113099, -4927, -1, 18109
},
},
{
/* Level 42 and Below */
{
-76119, 110383, -4927, -1, 18110
},
{
-75980, 110442, -4927, -1, 18110
},
{
-75848, 110442, -4927, -1, 18110
},
{
-75720, 110383, -4927, -1, 18110
},


{
-75625, 110195, -4927, -1, 18110
},
{
-75625, 110063, -4927, -1, 18110
},


{
-75722, 109908, -4927, -1, 18110
},
{
-75863, 109832, -4927, -1, 18110
},
{
-75989, 109832, -4927, -1, 18110
},
{
-76130, 109908, -4927, -1, 18110
},


{
-76230, 110079, -4927, -1, 18110
},
{
-76230, 110215, -4927, -1, 18110
},
},
{
/* Level 53 and Below */
{
-74055, 111781, -4927, -1, 18111
},
{
-74144, 111938, -4927, -1, 18111
},
{
-74144, 112075, -4927, -1, 18111
},
{
-74055, 112173, -4927, -1, 18111
},


{
-73885, 112289, -4927, -1, 18111
},
{
-73756, 112289, -4927, -1, 18111
},


{
-73574, 112141, -4927, -1, 18111
},
{
-73511, 112040, -4927, -1, 18111
},
{
-73511, 111912, -4927, -1, 18111
},
{
-73574, 111772, -4927, -1, 18111
},


{
-73767, 111669, -4927, -1, 18111
},
{
-73899, 111669, -4927, -1, 18111
},
},
{
/* Level 64 and Below */
{
-76008, 113566, -4927, -1, 18112
},
{
-76159, 113485, -4927, -1, 18112
},
{
-76267, 113485, -4927, -1, 18112
},
{
-76386, 113566, -4927, -1, 18112
},


{
-76482, 113748, -4927, -1, 18112
},
{
-76482, 113885, -4927, -1, 18112
},


{
-76371, 114029, -4927, -1, 18112
},
{
-76220, 114118, -4927, -1, 18112
},
{
-76092, 114118, -4927, -1, 18112
},
{
-75975, 114029, -4927, -1, 18112
},


{
-75861, 11385 - 1, -4927, -1, 18112
},
{
-75861, 113713, -4927, -1, 18112
},
},
{
/* No Level Limit */
{
-79100, 109782, -4927, -1, 18113
},
{
-78962, 109853, -4927, -1, 18113
},
{
-78851, 109853, -4927, -1, 18113
},
{
-78721, 109782, -4927, -1, 18113
},


{
-78615, 109596, -4927, -1, 18113
},
{
-78615, 109453, -4927, -1, 18113
},


{
-78746, 109300, -4927, -1, 18113
},
{
-78881, 109203, -4927, -1, 18113
},
{
-79027, 109203, -4927, -1, 18113
},
{
-79159, 109300, -4927, -1, 18113
},


{
-79240, 109480, -4927, -1, 18113
},
{
-79240, 109615, -4927, -1, 18113
},
}
};


/** The Constant FESTIVAL_DUSK_CHEST_SPAWNS. */
protected static final int[][][] FESTIVAL_DUSK_CHEST_SPAWNS =
{
{
/* Level 31 and Below */
{
-77016, 88726, -5183, -1, 18114
},
{
-77136, 88646, -5183, -1, 18114
},
{
-77247, 88646, -5183, -1, 18114
},
{
-77380, 88726, -5183, -1, 18114
},


{
-77512, 88883, -5183, -1, 18114
},
{
-77512, 89053, -5183, -1, 18114
},


{
-77378, 89287, -5183, -1, 18114
},
{
-77254, 89238, -5183, -1, 18114
},
{
-77095, 89238, -5183, -1, 18114
},
{
-76996, 89287, -5183, -1, 18114
},


{
-76901, 89025, -5183, -1, 18114
},
{
-76901, 88891, -5183, -1, 18114
},
},
{
/* Level 42 and Below */
{
-77128, 85553, -5183, -1, 18115
},
{
-77036, 85594, -5183, -1, 18115
},
{
-76919, 85594, -5183, -1, 18115
},
{
-76755, 85553, -5183, -1, 18115
},


{
-76635, 85392, -5183, -1, 18115
},
{
-76635, 85216, -5183, -1, 18115
},


{
-76761, 85025, -5183, -1, 18115
},
{
-76908, 85004, -5183, -1, 18115
},
{
-77041, 85004, -5183, -1, 18115
},
{
-77138, 85025, -5183, -1, 18115
},


{
-77268, 85219, -5183, -1, 18115
},
{
-77268, 85410, -5183, -1, 18115
},
},
{
/* Level 53 and Below */
{
-75150, 87303, -5183, -1, 18116
},
{
-75150, 87175, -5183, -1, 18116
},
{
-75150, 87175, -5183, -1, 18116
},
{
-75150, 87303, -5183, -1, 18116
},


{
-74943, 87433, -5183, -1, 18116
},
{
-74767, 87433, -5183, -1, 18116
},


{
-74556, 87306, -5183, -1, 18116
},
{
-74556, 87184, -5183, -1, 18116
},
{
-74556, 87184, -5183, -1, 18116
},
{
-74556, 87306, -5183, -1, 18116
},


{
-74757, 86830, -5183, -1, 18116
},
{
-74927, 86830, -5183, -1, 18116
},
},
{
/* Level 64 and Below */
{
-80010, 88128, -5183, -1, 18117
},
{
-80113, 88066, -5183, -1, 18117
},
{
-80220, 88066, -5183, -1, 18117
},
{
-80359, 88128, -5183, -1, 18117
},


{
-80467, 88267, -5183, -1, 18117
},
{
-80467, 88436, -5183, -1, 18117
},


{
-80381, 88639, -5183, -1, 18117
},
{
-80278, 88577, -5183, -1, 18117
},
{
-80142, 88577, -5183, -1, 18117
},
{
-80028, 88639, -5183, -1, 18117
},


{
-79915, 88466, -5183, -1, 18117
},
{
-79915, 88322, -5183, -1, 18117
},
},
{
/* No Level Limit */
{
-80153, 84947, -5183, -1, 18118
},
{
-80003, 84962, -5183, -1, 18118
},
{
-79848, 84962, -5183, -1, 18118
},
{
-79742, 84947, -5183, -1, 18118
},


{
-79668, 84772, -5183, -1, 18118
},
{
-79668, 84619, -5183, -1, 18118
},


{
-79772, 84471, -5183, -1, 18118
},
{
-79888, 84414, -5183, -1, 18118
},
{
-80023, 84414, -5183, -1, 18118
},
{
-80166, 84471, -5183, -1, 18118
},


{
-80253, 84600, -5183, -1, 18118
},
{
-80253, 84780, -5183, -1, 18118
},
}
};


//////////////////////// \\\\\\\\\\\\\\\\\\\\\\\\\\


/** The _manager instance. */
protected FestivalManager _managerInstance;


/** The _manager scheduled task. */
protected ScheduledFuture<?> _managerScheduledTask;


/** The _signs cycle. */
protected int _signsCycle = SevenSigns.getInstance().getCurrentCycle();


/** The _festival cycle. */
protected int _festivalCycle;


/** The _next festival cycle start. */
protected long _nextFestivalCycleStart;


/** The _next festival start. */
protected long _nextFestivalStart;


/** The _festival initialized. */
protected boolean _festivalInitialized;


/** The _festival in progress. */
protected boolean _festivalInProgress;


/** The _accumulated bonuses. */
protected List<Integer> _accumulatedBonuses; // The total bonus available (in Ancient Adena)


/** The _dawn chat guide. */
private L2NpcInstance _dawnChatGuide;


/** The _dusk chat guide. */
private L2NpcInstance _duskChatGuide;


/** The _dawn festival participants. */
protected Map<Integer, List<L2PcInstance>> _dawnFestivalParticipants;


/** The _dusk festival participants. */
protected Map<Integer, List<L2PcInstance>> _duskFestivalParticipants;


/** The _dawn previous participants. */
protected Map<Integer, List<L2PcInstance>> _dawnPreviousParticipants;


/** The _dusk previous participants. */
protected Map<Integer, List<L2PcInstance>> _duskPreviousParticipants;


/** The _dawn festival scores. */
private Map<Integer, Integer> _dawnFestivalScores;


/** The _dusk festival scores. */
private Map<Integer, Integer> _duskFestivalScores;


/**
* _festivalData is essentially an instance of the seven_signs_festival table and should be treated as such. Data is
* initially accessed by the related Seven Signs cycle, with _signsCycle representing data for the current round of
* Festivals. The actual table data is stored as a series of StatsSet constructs. These are accessed by the use of
* an offset based on the number of festivals, thus: offset = FESTIVAL_COUNT + festivalId (Data for Dawn is always
* accessed by offset > FESTIVAL_COUNT)
*/
private Map<Integer, Map<Integer, StatsSet>> _festivalData;


/**
* Instantiates a new seven signs festival.
*/
@SuppressWarnings("unused")
public SevenSignsFestival()
{
_accumulatedBonuses = new FastList<Integer>();


_dawnFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
_dawnPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
_dawnFestivalScores = new FastMap<Integer, Integer>();


_duskFestivalParticipants = new FastMap<Integer, List<L2PcInstance>>();
_duskPreviousParticipants = new FastMap<Integer, List<L2PcInstance>>();
_duskFestivalScores = new FastMap<Integer, Integer>();


_festivalData = new FastMap<Integer, Map<Integer, StatsSet>>();


restoreFestivalData();
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new RestoreStatus(), 7200000, 10800000);


if(SevenSigns.getInstance().isSealValidationPeriod())
{
_log.info("SevenSignsFestival: Initialization bypassed due to Seal Validation in effect.");
return;
}


L2Spawn.addSpawnListener(this);
startFestivalManager();
}


/**
* Gets the single instance of SevenSignsFestival.
*
* @return single instance of SevenSignsFestival
*/
public static SevenSignsFestival getInstance()
{
if(_instance == null)
{
_instance = new SevenSignsFestival();
}


return _instance;
}


/**
* Returns the associated name (level range) to a given festival ID.
*
* @param festivalID the festival id
* @return String festivalName
*/
public static final String getFestivalName(int festivalID)
{
String festivalName;


switch(festivalID)
{
case FESTIVAL_LEVEL_MAX_FOR_31:
festivalName = "Level 31 or lower";
break;
case FESTIVAL_LEVEL_MAX_FOR_42:
festivalName = "Level 42 or lower";
break;
case FESTIVAL_LEVEL_MAX_FOR_53:
festivalName = "Level 53 or lower";
break;
case FESTIVAL_LEVEL_MAX_FOR_64:
festivalName = "Level 64 or lower";
break;
default:
festivalName = "No Level Limit";
break;
}


return festivalName;
}


/**
* Returns the maximum allowed player level for the given festival type.
*
* @param festivalId the festival id
* @return int maxLevel
*/
public static final int getMaxLevelForFestival(int festivalId)
{
int maxLevel = ExperienceData.getInstance().getMaxLevel() - 1;


switch(festivalId)
{
case SevenSignsFestival.FESTIVAL_LEVEL_MAX_FOR_31:
maxLevel = 31;
break;
case SevenSignsFestival.FESTIVAL_LEVEL_MAX_FOR_42:
maxLevel = 42;
break;
case SevenSignsFestival.FESTIVAL_LEVEL_MAX_FOR_53:
maxLevel = 53;
break;
case SevenSignsFestival.FESTIVAL_LEVEL_MAX_FOR_64:
maxLevel = 64;
break;
}


return maxLevel;
}


/**
* Returns true if the monster ID given is of an archer/marksman type.
*
* @param npcId the npc id
* @return boolean isArcher
*/
protected static final boolean isFestivalArcher(int npcId)
{
if(npcId < 18009 || npcId > 18108)
return false;


int identifier = npcId % 10;
return identifier == 4 || identifier == 9;
}


/**
* Returns true if the monster ID given is a festival chest.
*
* @param npcId the npc id
* @return boolean isChest
*/
protected static final boolean isFestivalChest(int npcId)
{
return npcId < 18109 || npcId > 18118;
}


/**
* Primarily used to terminate the Festival Manager, when the Seven Signs period changes.

* @return ScheduledFuture festManagerScheduler
*/
protected final ScheduledFuture<?> getFestivalManagerSchedule()
{
if(_managerScheduledTask == null)
{
startFestivalManager();
}


return _managerScheduledTask;
}


/**
* Used to start the Festival Manager, if the current period is not Seal Validation.
*/
protected void startFestivalManager()
{
// Start the Festival Manager for the first time after the server has started
// at the specified time, then invoke it automatically after every cycle.
FestivalManager fm = new FestivalManager();
setNextFestivalStart(Config.ALT_FESTIVAL_MANAGER_START + FESTIVAL_SIGNUP_TIME);
_managerScheduledTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(fm, Config.ALT_FESTIVAL_MANAGER_START, Config.ALT_FESTIVAL_CYCLE_LENGTH);


fm = null;
_log.info("SevenSignsFestival: The first Festival of Darkness cycle begins in " + Config.ALT_FESTIVAL_MANAGER_START / 60000 + " minute(s).");
}


/**
* Restores saved festival data, basic settings from the properties file and past high score data from the database.
*
*/
@SuppressWarnings("unused")
protected void restoreFestivalData()
{
Connection con = null;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Restoring festival data. Current SS Cycle: " + _signsCycle);
}


try
{
con = L2DatabaseFactory.getInstance().getConnection(false);
PreparedStatement statement = con.prepareStatement("SELECT festivalId, cabal, cycle, date, score, members FROM seven_signs_festival");
ResultSet rset = statement.executeQuery();


while(rset.next())
{
int festivalCycle = rset.getInt("cycle");
int festivalId = rset.getInt("festivalId");
String cabal = rset.getString("cabal");


StatsSet festivalDat = new StatsSet();
festivalDat.set("festivalId", festivalId);
festivalDat.set("cabal", cabal);
festivalDat.set("cycle", festivalCycle);
festivalDat.set("date", rset.getString("date"));
festivalDat.set("score", rset.getInt("score"));
festivalDat.set("members", rset.getString("members"));


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Loaded data from DB for (Cycle = " + festivalCycle + ", Oracle = " + cabal + ", Festival = " + getFestivalName(festivalId));
}


if(cabal.equals("dawn"))
{
festivalId += FESTIVAL_COUNT;
}


cabal = null;


Map<Integer, StatsSet> tempData = _festivalData.get(festivalCycle);


if(tempData == null)
{
tempData = new FastMap<Integer, StatsSet>();
}


tempData.put(festivalId, festivalDat);
_festivalData.put(festivalCycle, tempData);
tempData = null;
}


rset.close();
statement.close();


rset = null;
statement = null;


String query = "SELECT festival_cycle, ";


for(int i = 0; i < FESTIVAL_COUNT - 1; i++)
{
query += "accumulated_bonus" + String.valueOf(i) + ", ";
}
query += "accumulated_bonus" + String.valueOf(FESTIVAL_COUNT - 1) + " ";
query += "FROM seven_signs_status WHERE id=0";


statement = con.prepareStatement(query);
rset = statement.executeQuery();


while(rset.next())
{
_festivalCycle = rset.getInt("festival_cycle");


for(int i = 0; i < FESTIVAL_COUNT; i++)
{
_accumulatedBonuses.add(i, rset.getInt("accumulated_bonus" + String.valueOf(i)));
}
}


query = null;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Loaded data from database.");
}


rset.close();
statement.close();
rset = null;
statement = null;
}
catch(SQLException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.severe("SevenSignsFestival: Failed to load configuration: " + e);
}
finally
{
CloseUtil.close(con);
con = null;
}
}


/**
* Stores current festival data, basic settings to the properties file and past high score data to the database. If
* updateSettings = true, then all Seven Signs data is updated in the database.
*
* @param updateSettings the update settings
*/
public void saveFestivalData(boolean updateSettings)
{
Connection con = null;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Saving festival data to disk.");
}


try
{
con = L2DatabaseFactory.getInstance().getConnection(false);
PreparedStatement statement = null;


for(Map<Integer, StatsSet> currCycleData : _festivalData.values())
{
for(StatsSet festivalDat : currCycleData.values())
{
int festivalCycle = festivalDat.getInteger("cycle");
int festivalId = festivalDat.getInteger("festivalId");
String cabal = festivalDat.getString("cabal");


// Try to update an existing record.
statement = con.prepareStatement("UPDATE seven_signs_festival SET date=?, score=?, members=? WHERE cycle=? AND cabal=? AND festivalId=?");
statement.setLong(1, Long.valueOf(festivalDat.getString("date")));
statement.setInt(2, festivalDat.getInteger("score"));
statement.setString(3, festivalDat.getString("members"));
statement.setInt(4, festivalCycle);
statement.setString(5, cabal);
statement.setInt(6, festivalId);


// If there was no record to update, assume it doesn't exist and add a new one,
// otherwise continue with the next record to store.
if(statement.executeUpdate() > 0)
{
if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Updated data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal + ", FestID = " + festivalId + ")");
}


statement.close();
continue;
}


statement.close();


statement = con.prepareStatement("INSERT INTO seven_signs_festival (festivalId, cabal, cycle, date, score, members) VALUES (?,?,?,?,?,?)");
statement.setInt(1, festivalId);
statement.setString(2, cabal);
statement.setInt(3, festivalCycle);
statement.setLong(4, Long.valueOf(festivalDat.getString("date")));
statement.setInt(5, festivalDat.getInteger("score"));
statement.setString(6, festivalDat.getString("members"));
statement.execute();
statement.close();
statement = null;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Inserted data in DB (Cycle = " + festivalCycle + ", Cabal = " + cabal + ", FestID = " + festivalId + ")");
}
cabal = null;
}
}


// Updates Seven Signs DB data also, so call only if really necessary.
if(updateSettings)
{
SevenSigns.getInstance().saveSevenSignsData(null, true);
}
}
catch(SQLException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.severe("SevenSignsFestival: Failed to save configuration: " + e);
}
finally
{
CloseUtil.close(con);
con = null;
}
}


/**
* If a clan member is a member of the highest-ranked party in the Festival of Darkness, 100 points are added per
* member.
*/
protected void rewardHighRanked()
{
String[] partyMembers;
StatsSet overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_FOR_31);
if(overallData != null)
{
partyMembers = overallData.getString("members").split(",");
for(String partyMemberName : partyMembers)
{
addReputationPointsForPartyMemberClan(partyMemberName);
}
partyMembers = null;
}


overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_FOR_42);
if(overallData != null)
{
partyMembers = overallData.getString("members").split(",");
for(String partyMemberName : partyMembers)
{
addReputationPointsForPartyMemberClan(partyMemberName);
}
partyMembers = null;
}


overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_FOR_53);
if(overallData != null)
{
partyMembers = overallData.getString("members").split(",");
for(String partyMemberName : partyMembers)
{
addReputationPointsForPartyMemberClan(partyMemberName);
}
partyMembers = null;
}


overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_FOR_64);
if(overallData != null)
{
partyMembers = overallData.getString("members").split(",");
for(String partyMemberName : partyMembers)
{
addReputationPointsForPartyMemberClan(partyMemberName);
}
partyMembers = null;
}


overallData = getOverallHighestScoreData(FESTIVAL_LEVEL_MAX_FOR_NONE);
if(overallData != null)
{
partyMembers = overallData.getString("members").split(",");
for(String partyMemberName : partyMembers)
{
addReputationPointsForPartyMemberClan(partyMemberName);
}
partyMembers = null;
}
overallData = null;
partyMembers = null;
}


/**
* Adds the reputation points for party member clan.
*
* @param partyMemberName the party member name
*/
private void addReputationPointsForPartyMemberClan(String partyMemberName)
{
L2PcInstance player = L2World.getInstance().getPlayer(partyMemberName);
if(player != null)
{
if(player.getClan() != null)
{
player.getClan().setReputationScore(player.getClan().getReputationScore() + 100, true);
player.getClan().broadcastToOnlineMembers(new PledgeShowInfoUpdate(player.getClan()));
SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_S1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
sm.addString(partyMemberName);
sm.addNumber(100);
player.getClan().broadcastToOnlineMembers(sm);
sm = null;
}
}
else
{
Connection con = null;


try
{
con = L2DatabaseFactory.getInstance().getConnection(false);
PreparedStatement statement = con.prepareStatement(GET_CLAN_NAME);
statement.setString(1, partyMemberName);
ResultSet rset = statement.executeQuery();
if(rset.next())
{
String clanName = rset.getString("clan_name");
if(clanName != null)
{
L2Clan clan = ClanTable.getInstance().getClanByName(clanName);
if(clan != null)
{
clan.setReputationScore(clan.getReputationScore() + 100, true);
clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
SystemMessage sm = new SystemMessage(SystemMessageId.CLAN_MEMBER_S1_WAS_IN_HIGHEST_RANKED_PARTY_IN_FESTIVAL_OF_DARKNESS_AND_GAINED_S2_REPUTATION);
sm.addString(partyMemberName);
sm.addNumber(100);
clan.broadcastToOnlineMembers(sm);
sm = null;
}
clan = null;
}
clanName = null;
}


rset.close();
statement.close();


rset = null;
statement = null;
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.warning("could not get clan name of " + partyMemberName + ": " + e);
}
finally
{
CloseUtil.close(con);
con = null;
}
}
}


/**
* Used to reset all festival data at the beginning of a new quest event period.
*
* @param updateSettings the update settings
*/
protected void resetFestivalData(boolean updateSettings)
{
_festivalCycle = 0;
_signsCycle = SevenSigns.getInstance().getCurrentCycle();


// Set all accumulated bonuses back to 0.
for(int i = 0; i < FESTIVAL_COUNT; i++)
{
_accumulatedBonuses.set(i, 0);
}


_dawnFestivalParticipants.clear();
_dawnPreviousParticipants.clear();
_dawnFestivalScores.clear();


_duskFestivalParticipants.clear();
_duskPreviousParticipants.clear();
_duskFestivalScores.clear();


// Set up a new data set for the current cycle of festivals
Map<Integer, StatsSet> newData = new FastMap<Integer, StatsSet>();


for(int i = 0; i < FESTIVAL_COUNT * 2; i++)
{
int festivalId = i;


if(i >= FESTIVAL_COUNT)
{
festivalId -= FESTIVAL_COUNT;
}


// Create a new StatsSet with "default" data for Dusk
StatsSet tempStats = new StatsSet();
tempStats.set("festivalId", festivalId);
tempStats.set("cycle", _signsCycle);
tempStats.set("date", "0");
tempStats.set("score", 0);
tempStats.set("members", "");


if(i >= FESTIVAL_COUNT)
{
tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DAWN));
}
else
{
tempStats.set("cabal", SevenSigns.getCabalShortName(SevenSigns.CABAL_DUSK));
}


newData.put(i, tempStats);
}


// Add the newly created cycle data to the existing festival data, and
// subsequently save it to the database.
_festivalData.put(_signsCycle, newData);


newData = null;


saveFestivalData(updateSettings);


// Remove any unused blood offerings from online players.
for(L2PcInstance onlinePlayer : L2World.getInstance().getAllPlayers())
{
try
{
L2ItemInstance bloodOfferings = onlinePlayer.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);


if(bloodOfferings != null)
{
onlinePlayer.destroyItem("SevenSigns", bloodOfferings, null, false);
}
bloodOfferings = null;
}
catch(NullPointerException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}
}


_log.info("SevenSignsFestival: Reinitialized engine for next competition period.");
}


/**
* Gets the current festival cycle.
*
* @return the current festival cycle
*/
public final int getCurrentFestivalCycle()
{
return _festivalCycle;
}


/**
* Checks if is festival initialized.
*
* @return true, if is festival initialized
*/
public final boolean isFestivalInitialized()
{
return _festivalInitialized;
}


/**
* Checks if is festival in progress.
*
* @return true, if is festival in progress
*/
public final boolean isFestivalInProgress()
{
return _festivalInProgress;
}


/**
* Sets the next cycle start.
*/
public void setNextCycleStart()
{
_nextFestivalCycleStart = System.currentTimeMillis() + Config.ALT_FESTIVAL_CYCLE_LENGTH;
}


/**
* Sets the next festival start.
*
* @param milliFromNow the new next festival start
*/
public void setNextFestivalStart(long milliFromNow)
{
_nextFestivalStart = System.currentTimeMillis() + milliFromNow;
}


/**
* Gets the mins to next cycle.
*
* @return the mins to next cycle
*/
public final int getMinsToNextCycle()
{
if(SevenSigns.getInstance().isSealValidationPeriod())
return -1;


return Math.round((_nextFestivalCycleStart - System.currentTimeMillis()) / 60000);
}


/**
* Gets the mins to next festival.
*
* @return the mins to next festival
*/
public final int getMinsToNextFestival()
{
if(SevenSigns.getInstance().isSealValidationPeriod())
return -1;


return Math.round((_nextFestivalStart - System.currentTimeMillis()) / 60000) + 1;
}


/**
* Gets the time to next festival start.
*
* @return the time to next festival start
*/
public final String getTimeToNextFestivalStart()
{
if(SevenSigns.getInstance().isSealValidationPeriod())
return "<font color=\"FF0000\">This is the Seal Validation period. Festivals will resume next week.</font>";


return "<font color=\"FF0000\">The next festival will begin in " + getMinsToNextFestival() + " minute(s).</font>";
}


/**
* Returns the current festival ID and oracle ID that the specified player is in, but will return the default of
* {-1, -1} if the player is not found as a participant.
*
* @param player the player
* @return int[] playerFestivalInfo
*/
public final int[] getFestivalForPlayer(L2PcInstance player)
{
int[] playerFestivalInfo =
{
-1, -1
};
int festivalId = 0;


while(festivalId < FESTIVAL_COUNT)
{
List<L2PcInstance> participants = _dawnFestivalParticipants.get(festivalId);


// If there are no participants in this festival, move on to the next.
if(participants != null && participants.contains(player))
{
playerFestivalInfo[0] = SevenSigns.CABAL_DAWN;
playerFestivalInfo[1] = festivalId;


return playerFestivalInfo;
}


festivalId++;


participants = _duskFestivalParticipants.get(festivalId);


if(participants != null && participants.contains(player))
{
playerFestivalInfo[0] = SevenSigns.CABAL_DUSK;
playerFestivalInfo[1] = festivalId;


return playerFestivalInfo;
}
participants = null;


festivalId++;
}


// Return default data if the player is not found as a participant.
return playerFestivalInfo;
}


/**
* Checks if is player participant.
*
* @param player the player
* @return true, if is player participant
*/
public final boolean isPlayerParticipant(L2PcInstance player)
{
if(SevenSigns.getInstance().isSealValidationPeriod())
return false;


if(_managerInstance == null)
return false;


for(List<L2PcInstance> participants : _dawnFestivalParticipants.values())
if(participants.contains(player))
return true;


for(List<L2PcInstance> participants : _duskFestivalParticipants.values())
if(participants.contains(player))
return true;


return false;
}


/**
* Gets the participants.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return the participants
*/
public final List<L2PcInstance> getParticipants(int oracle, int festivalId)
{
if(oracle == SevenSigns.CABAL_DAWN)
return _dawnFestivalParticipants.get(festivalId);


return _duskFestivalParticipants.get(festivalId);
}


/**
* Gets the previous participants.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return the previous participants
*/
public final List<L2PcInstance> getPreviousParticipants(int oracle, int festivalId)
{
if(oracle == SevenSigns.CABAL_DAWN)
return _dawnPreviousParticipants.get(festivalId);


return _duskPreviousParticipants.get(festivalId);
}


/**
* Sets the participants.
*
* @param oracle the oracle
* @param festivalId the festival id
* @param festivalParty the festival party
*/
public void setParticipants(int oracle, int festivalId, L2Party festivalParty)
{
List<L2PcInstance> participants = new FastList<L2PcInstance>();


if(festivalParty != null)
{
participants = festivalParty.getPartyMembers();


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: " + festivalParty.getPartyMembers().toString() + " have signed up to the " + SevenSigns.getCabalShortName(oracle) + " " + getFestivalName(festivalId) + " festival.");
}
}


if(oracle == SevenSigns.CABAL_DAWN)
{
_dawnFestivalParticipants.put(festivalId, participants);
}
else
{
_duskFestivalParticipants.put(festivalId, participants);
}


participants = null;
}


/**
* Update participants.
*
* @param player the player
* @param festivalParty the festival party
*/
public void updateParticipants(L2PcInstance player, L2Party festivalParty)
{
if(!isPlayerParticipant(player))
return;


final int[] playerFestInfo = getFestivalForPlayer(player);
final int oracle = playerFestInfo[0];
final int festivalId = playerFestInfo[1];


if(festivalId > -1)
{
if(_festivalInitialized)
{
L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);


if(festivalParty == null)
{
for(L2PcInstance partyMember : getParticipants(oracle, festivalId))
{
festivalInst.relocatePlayer(partyMember, true);
}
}
else
{
festivalInst.relocatePlayer(player, true);
}


festivalInst = null;
}


setParticipants(oracle, festivalId, festivalParty);
}
}


/**
* Gets the final score.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return the final score
*/
public final int getFinalScore(int oracle, int festivalId)
{
if(oracle == SevenSigns.CABAL_DAWN)
return _dawnFestivalScores.get(festivalId);


return _duskFestivalScores.get(festivalId);
}


/**
* Gets the highest score.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return the highest score
*/
public final int getHighestScore(int oracle, int festivalId)
{
return getHighestScoreData(oracle, festivalId).getInteger("score");
}


/**
* Returns a stats set containing the highest score <b>this cycle</b> for the the specified cabal and associated
* festival ID.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return StatsSet festivalDat
*/
public final StatsSet getHighestScoreData(int oracle, int festivalId)
{
int offsetId = festivalId;


if(oracle == SevenSigns.CABAL_DAWN)
{
offsetId += 5;
}


// Attempt to retrieve existing score data (if found), otherwise create a
// new blank data set and display a console warning.
StatsSet currData = null;


if(_festivalData!=null && _festivalData.get(_signsCycle)!=null){
currData = _festivalData.get(_signsCycle).get(offsetId);
}else{
currData = new StatsSet();
currData.set("score", 0);
currData.set("members", "");


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Data missing for " + SevenSigns.getCabalName(oracle) + ", FestivalID = " + festivalId + " (Current Cycle " + _signsCycle + ")");
}
}


return currData;
}


/**
* Returns a stats set containing the highest ever recorded score data for the specified festival.
*
* @param festivalId the festival id
* @return StatsSet result
*/
public final StatsSet getOverallHighestScoreData(int festivalId)
{
StatsSet result = null;
int highestScore = 0;


for(Map<Integer, StatsSet> currCycleData : _festivalData.values())
{
for(StatsSet currFestData : currCycleData.values())
{
int currFestID = currFestData.getInteger("festivalId");
int festivalScore = currFestData.getInteger("score");


if(currFestID != festivalId)
{
continue;
}


if(festivalScore > highestScore)
{
highestScore = festivalScore;
result = currFestData;
}
}
}


return result;
}


/**
* Set the final score details for the last participants of the specified festival data. Returns <b>true</b> if the
* score is higher than that previously recorded <b>this cycle</b>.
*
* @param player the player
* @param oracle the oracle
* @param festivalId the festival id
* @param offeringScore the offering score
* @return boolean isHighestScore
*/
public boolean setFinalScore(L2PcInstance player, int oracle, int festivalId, int offeringScore)
{
List<String> partyMembers;


int currDawnHighScore = getHighestScore(SevenSigns.CABAL_DAWN, festivalId);
int currDuskHighScore = getHighestScore(SevenSigns.CABAL_DUSK, festivalId);


int thisCabalHighScore = 0;
int otherCabalHighScore = 0;


if(oracle == SevenSigns.CABAL_DAWN)
{
thisCabalHighScore = currDawnHighScore;
otherCabalHighScore = currDuskHighScore;


_dawnFestivalScores.put(festivalId, offeringScore);
}
else
{
thisCabalHighScore = currDuskHighScore;
otherCabalHighScore = currDawnHighScore;


_duskFestivalScores.put(festivalId, offeringScore);
}


StatsSet currFestData = getHighestScoreData(oracle, festivalId);


// Check if this is the highest score for this level range so far for the player's cabal.
if(offeringScore > thisCabalHighScore)
{
// If the current score is greater than that for the other cabal,
// then they already have the points from this festival.
if(thisCabalHighScore > otherCabalHighScore)
return false;


partyMembers = new FastList<String>();
List<L2PcInstance> prevParticipants = getPreviousParticipants(oracle, festivalId);


// Record a string list of the party members involved.
for(L2PcInstance partyMember : prevParticipants)
{
try
{
partyMembers.add(partyMember.getName());
}
catch(NullPointerException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}
}
prevParticipants = null;


// Update the highest scores and party list.
currFestData.set("date", String.valueOf(System.currentTimeMillis()));
currFestData.set("score", offeringScore);
currFestData.set("members", Util.implodeString(partyMembers, ","));
partyMembers = null;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: " + player.getName() + "'s party has the highest score (" + offeringScore + ") so far for " + SevenSigns.getCabalName(oracle) + " in " + getFestivalName(festivalId));
}


// Only add the score to the cabal's overall if it's higher than the other cabal's score.
if(offeringScore > otherCabalHighScore)
{
int contribPoints = FESTIVAL_LEVEL_SCORES[festivalId];


// Give this cabal the festival points, while deducting them from the other.
SevenSigns.getInstance().addFestivalScore(oracle, contribPoints);


//if (Config.DEBUG)
_log.info("SevenSignsFestival: This is the highest score overall so far for the " + getFestivalName(festivalId) + " festival!");
}


saveFestivalData(true);


return true;
}


return false;
}


/**
* Gets the accumulated bonus.
*
* @param festivalId the festival id
* @return the accumulated bonus
*/
public final int getAccumulatedBonus(int festivalId)
{
return _accumulatedBonuses.get(festivalId);
}


/**
* Gets the total accumulated bonus.
*
* @return the total accumulated bonus
*/
public final int getTotalAccumulatedBonus()
{
int totalAccumBonus = 0;


for(int accumBonus : _accumulatedBonuses)
{
totalAccumBonus += accumBonus;
}


return totalAccumBonus;
}


/**
* Adds the accumulated bonus.
*
* @param festivalId the festival id
* @param stoneType the stone type
* @param stoneAmount the stone amount
*/
public void addAccumulatedBonus(int festivalId, int stoneType, int stoneAmount)
{
int eachStoneBonus = 0;


switch(stoneType)
{
case SevenSigns.SEAL_STONE_BLUE_ID:
eachStoneBonus = SevenSigns.SEAL_STONE_BLUE_VALUE;
break;
case SevenSigns.SEAL_STONE_GREEN_ID:
eachStoneBonus = SevenSigns.SEAL_STONE_GREEN_VALUE;
break;
case SevenSigns.SEAL_STONE_RED_ID:
eachStoneBonus = SevenSigns.SEAL_STONE_RED_VALUE;
break;
}


int newTotalBonus = _accumulatedBonuses.get(festivalId) + stoneAmount * eachStoneBonus;
_accumulatedBonuses.set(festivalId, newTotalBonus);
}


/**
* Calculate and return the proportion of the accumulated bonus for the festival where the player was in the winning
* party, if the winning party's cabal won the event. The accumulated bonus is then updated, with the player's share
* deducted.
*
* @param player the player
* @return playerBonus (the share of the bonus for the party)
*/
public final int distribAccumulatedBonus(L2PcInstance player)
{
int playerBonus = 0;
String playerName = player.getName();
int playerCabal = SevenSigns.getInstance().getPlayerCabal(player);


if(playerCabal != SevenSigns.getInstance().getCabalHighestScore())
return 0;


if(_festivalData.get(_signsCycle) != null)
{
for(StatsSet festivalData : _festivalData.get(_signsCycle).values())
{
if(festivalData.getString("members").indexOf(playerName) > -1)
{
int festivalId = festivalData.getInteger("festivalId");
int numPartyMembers = festivalData.getString("members").split(",").length;
int totalAccumBonus = _accumulatedBonuses.get(festivalId);


playerBonus = totalAccumBonus / numPartyMembers;
_accumulatedBonuses.set(festivalId, totalAccumBonus - playerBonus);
playerName = null;
break;
}
}
}
return playerBonus;
}


/**
* Used to send a "shout" message to all players currently present in an Oracle. Primarily used for Festival Guide
* and Witch related speech.
*
* @param senderName the sender name
* @param message the message
*/
public void sendMessageToAll(String senderName, String message)
{
if(_dawnChatGuide == null || _duskChatGuide == null)
return;


CreatureSay cs = new CreatureSay(_dawnChatGuide.getObjectId(), 1, senderName, message);
_dawnChatGuide.broadcastPacket(cs);
cs = null;


cs = new CreatureSay(_duskChatGuide.getObjectId(), 1, senderName, message);
_duskChatGuide.broadcastPacket(cs);
cs = null;
}


/**
* Basically a wrapper-call to signal to increase the challenge of the specified festival.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return boolean isChalIncreased
*/
public final boolean increaseChallenge(int oracle, int festivalId)
{
L2DarknessFestival festivalInst = _managerInstance.getFestivalInstance(oracle, festivalId);


return festivalInst.increaseChallenge();
}


/**
* The Class RestoreStatus.
*/
protected class RestoreStatus implements Runnable
{


/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run()
{


}
}


/**
* Used with the SpawnListener, to update the required "chat guide" instances, for use with announcements in the
* oracles.
*
* @param npc the npc
*/
@Override
public void npcSpawned(L2NpcInstance npc)
{
if(npc == null)
return;


int npcId = npc.getNpcId();


// If the spawned NPC ID matches the ones we need, assign their instances.
if(npcId == 31127)
{
if(Config.DEBUG)
{
_log.config("SevenSignsFestival: Instance found for NPC ID 31127 (" + npc.getObjectId() + ").");
}


_dawnChatGuide = npc;
}


if(npcId == 31137)
{
if(Config.DEBUG)
{
_log.config("SevenSignsFestival: Instance found for NPC ID 31137 (" + npc.getObjectId() + ").");
}


_duskChatGuide = npc;
}
}


/**
* The FestivalManager class is the main runner of all the festivals. It is used for easier integration and
* management of all running festivals.

* @author Tempy
*/
private class FestivalManager implements Runnable
{


/** The _festival instances. */
protected Map<Integer, L2DarknessFestival> _festivalInstances;


/**
* Instantiates a new festival manager.
*/
public FestivalManager()
{
_festivalInstances = new FastMap<Integer, L2DarknessFestival>();
_managerInstance = this;


// Increment the cycle counter.
_festivalCycle++;


// Set the next start timers.
setNextCycleStart();
setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH - FESTIVAL_SIGNUP_TIME);
}


/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public synchronized void run()
{
// The manager shouldn't be running if Seal Validation is in effect.
if(SevenSigns.getInstance().isSealValidationPeriod())
return;


// If the next period is due to start before the end of this
// festival cycle, then don't run it.
if(SevenSigns.getInstance().getMilliToPeriodChange() < Config.ALT_FESTIVAL_CYCLE_LENGTH)
return;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Festival manager initialized. Those wishing to participate have " + getMinsToNextFestival() + " minute(s) to sign up.");
}


sendMessageToAll("Festival Guide", "The main event will start in " + getMinsToNextFestival() + " minutes. Please register now.");


// Stand by until the allowed signup period has elapsed.
try
{
wait(FESTIVAL_SIGNUP_TIME);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


// Clear past participants, they can no longer register their score if not done so already.
_dawnPreviousParticipants.clear();
_duskPreviousParticipants.clear();


// Get rid of random monsters that avoided deletion after last festival
for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.unspawnMobs();
}


/* INITIATION */
// Set the festival timer to 0, as it is just beginning.
long elapsedTime = 0;


// Create the instances for the festivals in both Oracles,
// but only if they have participants signed up for them.
for(int i = 0; i < FESTIVAL_COUNT; i++)
{
if(_duskFestivalParticipants.get(i) != null)
{
_festivalInstances.put(10 + i, new L2DarknessFestival(SevenSigns.CABAL_DUSK, i));
}


if(_dawnFestivalParticipants.get(i) != null)
{
_festivalInstances.put(20 + i, new L2DarknessFestival(SevenSigns.CABAL_DAWN, i));
}
}


// Prevent future signups while festival is in progress.
_festivalInitialized = true;


setNextFestivalStart(Config.ALT_FESTIVAL_CYCLE_LENGTH);
sendMessageToAll("Festival Guide", "The main event is now starting.");


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: The current set of festivals will begin in " + Config.ALT_FESTIVAL_FIRST_SPAWN / 60000 + " minute(s).");
}


// Stand by for a short length of time before starting the festival.
try
{
wait(Config.ALT_FESTIVAL_FIRST_SPAWN);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


elapsedTime = Config.ALT_FESTIVAL_FIRST_SPAWN;


// Participants can now opt to increase the challenge, if desired.
_festivalInProgress = true;


/* PROPOGATION */
// Sequentially set all festivals to begin, spawn the Festival Witch and notify participants.
for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.festivalStart();
festivalInst.sendMessageToParticipants("The festival is about to begin!");
}


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Each of the festivals will end in " + Config.ALT_FESTIVAL_LENGTH / 60000 + " minutes. New participants can signup then.");
}


// After a short time period, move all idle spawns to the center of the arena.
try
{
wait(Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


elapsedTime += Config.ALT_FESTIVAL_FIRST_SWARM - Config.ALT_FESTIVAL_FIRST_SPAWN;


for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.moveMonstersToCenter();
}


// Stand by until the time comes for the second spawn.
try
{
wait(Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


// Spawn an extra set of monsters (archers) on the free platforms with
// a faster respawn when killed.
for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN / 2, 2);
festivalInst.sendMessageToParticipants("The festival will end in " + (Config.ALT_FESTIVAL_LENGTH - Config.ALT_FESTIVAL_SECOND_SPAWN) / 60000 + " minute(s).");
}


elapsedTime += Config.ALT_FESTIVAL_SECOND_SPAWN - Config.ALT_FESTIVAL_FIRST_SWARM;


// After another short time period, again move all idle spawns to the center of the arena.
try
{
wait(Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.moveMonstersToCenter();
}


elapsedTime += Config.ALT_FESTIVAL_SECOND_SWARM - Config.ALT_FESTIVAL_SECOND_SPAWN;


// Stand by until the time comes for the chests to be spawned.
try
{
wait(Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


// Spawn the festival chests, which enable the team to gain greater rewards
// for each chest they kill.
for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 3);
festivalInst.sendMessageToParticipants("The chests have spawned! Be quick, the festival will end soon.");
}


elapsedTime += Config.ALT_FESTIVAL_CHEST_SPAWN - Config.ALT_FESTIVAL_SECOND_SWARM;


// Stand by and wait until it's time to end the festival.
try
{
wait(Config.ALT_FESTIVAL_LENGTH - elapsedTime);
}
catch(InterruptedException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}


// Participants can no longer opt to increase the challenge, as the festival will soon close.
_festivalInProgress = false;


/* TERMINATION */
// Sequentially begin the ending sequence for all running festivals.
for(L2DarknessFestival festivalInst : _festivalInstances.values())
{
festivalInst.festivalEnd();
}


// Clear the participants list for the next round of signups.
_dawnFestivalParticipants.clear();
_duskFestivalParticipants.clear();


// Allow signups for the next festival cycle.
_festivalInitialized = false;


sendMessageToAll("Festival Witch", "That will do! I'll move you to the outside soon.");


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: The next set of festivals begin in " + getMinsToNextFestival() + " minute(s).");
}
}


/**
* Returns the running instance of a festival for the given Oracle and festivalID. <BR>
* A <B>null</B> value is returned if there are no participants in that festival.
*
* @param oracle the oracle
* @param festivalId the festival id
* @return L2DarknessFestival festivalInst
*/
public final L2DarknessFestival getFestivalInstance(int oracle, int festivalId)
{
if(!isFestivalInitialized())
return null;


/* Compute the offset if a Dusk instance is required.
*
* ID:      0   1   2   3   4
* Dusk 1:  10  11  12  13  14
* Dawn 2:  20  21  22  23  24
*/


festivalId += oracle == SevenSigns.CABAL_DUSK ? 10 : 20;
return _festivalInstances.get(festivalId);
}


/**
* Returns the number of currently running festivals <b>WITH</b> participants.

* @return int Count
*/
/*public final int getInstanceCount()
{
   return _festivalInstances.size();
}*/
}


/**
* Each running festival is represented by an L2DarknessFestival class. It contains all the spawn information and
* data for the running festival. All festivals are managed by the FestivalManager class, which must be initialized
* first.

* @author Tempy
*/
private class L2DarknessFestival
{


/** The _cabal. */
protected final int _cabal;


/** The _level range. */
protected final int _levelRange;


/** The _challenge increased. */
protected boolean _challengeIncreased;


/** The _start location. */
private FestivalSpawn _startLocation;


/** The _witch spawn. */
private FestivalSpawn _witchSpawn;


/** The _witch inst. */
private L2NpcInstance _witchInst;


/** The _npc insts. */
private List<L2FestivalMonsterInstance> _npcInsts;


/** The _participants. */
private List<L2PcInstance> _participants;


/** The _original locations. */
private Map<L2PcInstance, FestivalSpawn> _originalLocations;


/**
* Instantiates a new l2 darkness festival.
*
* @param cabal the cabal
* @param levelRange the level range
*/
protected L2DarknessFestival(int cabal, int levelRange)
{
_cabal = cabal;
_levelRange = levelRange;
_originalLocations = new FastMap<L2PcInstance, FestivalSpawn>();
_npcInsts = new FastList<L2FestivalMonsterInstance>();


if(cabal == SevenSigns.CABAL_DAWN)
{
_participants = _dawnFestivalParticipants.get(levelRange);
_witchSpawn = new FestivalSpawn(FESTIVAL_DAWN_WITCH_SPAWNS[levelRange]);
_startLocation = new FestivalSpawn(FESTIVAL_DAWN_PLAYER_SPAWNS[levelRange]);
}
else
{
_participants = _duskFestivalParticipants.get(levelRange);
_witchSpawn = new FestivalSpawn(FESTIVAL_DUSK_WITCH_SPAWNS[levelRange]);
_startLocation = new FestivalSpawn(FESTIVAL_DUSK_PLAYER_SPAWNS[levelRange]);
}


// FOR TESTING!
if(_participants == null)
{
_participants = new FastList<L2PcInstance>();
}


festivalInit();
}


/**
* Festival init.
*/
protected void festivalInit()
{
boolean isPositive;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Initializing festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
}


// Teleport all players to arena and notify them.
if(_participants.size() > 0)
{
try
{
for(L2PcInstance participant : _participants)
{
_originalLocations.put(participant, new FestivalSpawn(participant.getX(), participant.getY(), participant.getZ(), participant.getHeading()));


// Randomize the spawn point around the specific centerpoint for each player.
int x = _startLocation._x;
int y = _startLocation._y;


isPositive = Rnd.nextInt(2) == 1;


if(isPositive)
{
x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
}
else
{
x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
}


participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
participant.teleToLocation(x, y, _startLocation._z, true);


// Remove all buffs from all participants on entry. Works like the skill Cancel.
participant.stopAllEffects();


// Remove any stray blood offerings in inventory
L2ItemInstance bloodOfferings = participant.getInventory().getItemByItemId(FESTIVAL_OFFERING_ID);
if(bloodOfferings != null)
{
participant.destroyItem("SevenSigns", bloodOfferings, null, true);
}
}
}
catch(NullPointerException e)
{
// deleteMe handling should teleport party out in case of disconnect
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}
}


L2NpcTemplate witchTemplate = NpcTable.getInstance().getTemplate(_witchSpawn._npcId);


// Spawn the festival witch for this arena
try
{
L2Spawn npcSpawn = new L2Spawn(witchTemplate);


npcSpawn.setLocx(_witchSpawn._x);
npcSpawn.setLocy(_witchSpawn._y);
npcSpawn.setLocz(_witchSpawn._z);
npcSpawn.setHeading(_witchSpawn._heading);
npcSpawn.setAmount(1);
npcSpawn.setRespawnDelay(1);


// Needed as doSpawn() is required to be called also for the NpcInstance it returns.
npcSpawn.startRespawn();


SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
_witchInst = npcSpawn.doSpawn();


if(Config.DEBUG)
{
_log.fine("SevenSignsFestival: Spawned the Festival Witch " + npcSpawn.getNpcid() + " at " + _witchSpawn._x + " " + _witchSpawn._y + " " + _witchSpawn._z);
}


npcSpawn = null;
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.warning("SevenSignsFestival: Error while spawning Festival Witch ID " + _witchSpawn._npcId + ": " + e);
}


// Make it appear as though the Witch has apparated there.
MagicSkillUser msu = new MagicSkillUser(_witchInst, _witchInst, 2003, 1, 1, 0);
_witchInst.broadcastPacket(msu);
msu = null;


// And another one... :D
msu = new MagicSkillUser(_witchInst, _witchInst, 2133, 1, 1, 0);
_witchInst.broadcastPacket(msu);
msu = null;


// Send a message to all participants from the witch.
sendMessageToParticipants("The festival will begin in 2 minutes.");
}


/**
* Festival start.
*/
protected void festivalStart()
{
if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Starting festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
}


spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 0);
}


/**
* Move monsters to center.
*/
protected void moveMonstersToCenter()
{
boolean isPositive;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Moving spawns to arena center for festival " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
}


for(L2FestivalMonsterInstance festivalMob : _npcInsts)
{
if(festivalMob.isDead())
{
continue;
}


// Only move monsters that are idle or doing their usual functions.
CtrlIntention currIntention = festivalMob.getAI().getIntention();


if(currIntention != CtrlIntention.AI_INTENTION_IDLE && currIntention != CtrlIntention.AI_INTENTION_ACTIVE)
{
continue;
}


int x = _startLocation._x;
int y = _startLocation._y;


/*
* Random X and Y coords around the player start location, up to half of the
* maximum allowed offset are generated to prevent the mobs from all moving
* to the exact same place.
*/
isPositive = Rnd.nextInt(2) == 1;


if(isPositive)
{
x += Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
y += Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
}
else
{
x -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_X);
y -= Rnd.nextInt(FESTIVAL_MAX_OFFSET_Y);
}


L2CharPosition moveTo = new L2CharPosition(x, y, _startLocation._z, Rnd.nextInt(65536));


festivalMob.setRunning();
festivalMob.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, moveTo);
moveTo = null;
}
}


/*public void setSpawnRate(int respawnDelay)
{
   if (Config.DEBUG)
       _log.info("SevenSignsFestival: Modifying spawn rate of festival mobs to " + respawnDelay + " ms for festival " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");


   for (L2FestivalMonsterInstance monsterInst : _npcInsts)
       monsterInst.getSpawn().setRespawnDelay(respawnDelay);
}*/


/**
* Used to spawn monsters unique to the festival. <BR>
* Valid SpawnTypes:<BR>
* 0 - All Primary Monsters (starting monsters) <BR>
* 1 - Same as 0, but without archers/marksmen. (used for challenge increase) <BR>
* 2 - Secondary Monsters (archers) <BR>
* 3 - Festival Chests
*
* @param respawnDelay the respawn delay
* @param spawnType the spawn type
*/
protected void spawnFestivalMonsters(int respawnDelay, int spawnType)
{
int[][] _npcSpawns = null;


switch(spawnType)
{
case 0:
case 1:
_npcSpawns = _cabal == SevenSigns.CABAL_DAWN ? FESTIVAL_DAWN_PRIMARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_PRIMARY_SPAWNS[_levelRange];
break;
case 2:
_npcSpawns = _cabal == SevenSigns.CABAL_DAWN ? FESTIVAL_DAWN_SECONDARY_SPAWNS[_levelRange] : FESTIVAL_DUSK_SECONDARY_SPAWNS[_levelRange];
break;
case 3:
_npcSpawns = _cabal == SevenSigns.CABAL_DAWN ? FESTIVAL_DAWN_CHEST_SPAWNS[_levelRange] : FESTIVAL_DUSK_CHEST_SPAWNS[_levelRange];
break;
default:
return;
}


for(int[] npcSpawn2 : _npcSpawns)
{
FestivalSpawn currSpawn = new FestivalSpawn(npcSpawn2);


// Only spawn archers/marksmen if specified to do so.
if(spawnType == 1 && isFestivalArcher(currSpawn._npcId))
{
continue;
}


L2NpcTemplate npcTemplate = NpcTable.getInstance().getTemplate(currSpawn._npcId);


try
{
L2Spawn npcSpawn = new L2Spawn(npcTemplate);


npcSpawn.setLocx(currSpawn._x);
npcSpawn.setLocy(currSpawn._y);
npcSpawn.setLocz(currSpawn._z);
npcSpawn.setHeading(Rnd.nextInt(65536));
npcSpawn.setAmount(1);
npcSpawn.setRespawnDelay(respawnDelay);


// Needed as doSpawn() is required to be called also for the NpcInstance it returns.
npcSpawn.startRespawn();


SpawnTable.getInstance().addNewSpawn(npcSpawn, false);
L2FestivalMonsterInstance festivalMob = (L2FestivalMonsterInstance) npcSpawn.doSpawn();


// Set the offering bonus to 2x or 5x the amount per kill,
// if this spawn is part of an increased challenge or is a festival chest.
if(spawnType == 1)
{
festivalMob.setOfferingBonus(2);
}
else if(spawnType == 3)
{
festivalMob.setOfferingBonus(5);
}


_npcInsts.add(festivalMob);


if(Config.DEBUG)
{
_log.fine("SevenSignsFestival: Spawned NPC ID " + currSpawn._npcId + " at " + currSpawn._x + " " + currSpawn._y + " " + currSpawn._z);
}
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


_log.warning("SevenSignsFestival: Error while spawning NPC ID " + currSpawn._npcId + ": " + e);
}
}
}


/**
* Increase challenge.
*
* @return true, if successful
*/
protected boolean increaseChallenge()
{
if(_challengeIncreased)
return false;


// Set this flag to true to make sure that this can only be done once.
_challengeIncreased = true;


if(Config.DEBUG)
{
_log.info("SevenSignsFestival: " + _participants.get(0).getName() + "'s team have opted to increase the festival challenge!");
}


// Spawn more festival monsters, but this time with a twist.
spawnFestivalMonsters(FESTIVAL_DEFAULT_RESPAWN, 1);
return true;
}


/**
* Send message to participants.
*
* @param message the message
*/
public void sendMessageToParticipants(String message)
{
if(_participants.size() > 0)
{
CreatureSay cs = new CreatureSay(_witchInst.getObjectId(), 0, "Festival Witch", message);


for(L2PcInstance participant : _participants)
{
try
{
participant.sendPacket(cs);
cs = null;
}
catch(NullPointerException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}
}
}
}


/**
* Festival end.
*/
protected void festivalEnd()
{
if(Config.DEBUG)
{
_log.info("SevenSignsFestival: Ending festival for " + SevenSigns.getCabalShortName(_cabal) + " (" + getFestivalName(_levelRange) + ")");
}


if(_participants.size() > 0)
{
for(L2PcInstance participant : _participants)
{
try
{
relocatePlayer(participant, false);
participant.sendMessage("The festival has ended. Your party leader must now register your score before the next festival takes place.");
}
catch(NullPointerException e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();
}
}


if(_cabal == SevenSigns.CABAL_DAWN)
{
_dawnPreviousParticipants.put(_levelRange, _participants);
}
else
{
_duskPreviousParticipants.put(_levelRange, _participants);
}
}
_participants = null;


unspawnMobs();
}


/**
* Unspawn mobs.
*/
protected void unspawnMobs()
{
// Delete all the NPCs in the current festival arena.
if(_witchInst != null)
{
_witchInst.deleteMe();
}


if(_npcInsts != null)
{
for(L2FestivalMonsterInstance monsterInst : _npcInsts)
if(monsterInst != null)
{
monsterInst.deleteMe();
}
}
}


/**
* Relocate player.
*
* @param participant the participant
* @param isRemoving the is removing
*/
public void relocatePlayer(L2PcInstance participant, boolean isRemoving)
{
try
{
FestivalSpawn origPosition = _originalLocations.get(participant);


if(isRemoving)
{
_originalLocations.remove(participant);
}


participant.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
participant.teleToLocation(origPosition._x, origPosition._y, origPosition._z, true);
origPosition = null;
participant.sendMessage("You have been removed from the festival arena.");
}
catch(Exception e)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e.printStackTrace();


// If an exception occurs, just move the player to the nearest town.
try
{
participant.teleToLocation(MapRegionTable.TeleportWhereType.Town);
participant.sendMessage("You have been removed from the festival arena.");
}
catch(NullPointerException e2)
{
if(Config.ENABLE_ALL_EXCEPTIONS)
e2.printStackTrace();
}
}
}
}


/**
* The Class FestivalSpawn.
*/
private class FestivalSpawn
{


/** The _x. */
protected final int _x;


/** The _y. */
protected final int _y;


/** The _z. */
protected final int _z;


/** The _heading. */
protected final int _heading;


/** The _npc id. */
protected final int _npcId;


/**
* Instantiates a new festival spawn.
*
* @param x the x
* @param y the y
* @param z the z
* @param heading the heading
*/
protected FestivalSpawn(int x, int y, int z, int heading)
{
_x = x;
_y = y;
_z = z;


// Generate a random heading if no positive one given.
_heading = heading < 0 ? Rnd.nextInt(65536) : heading;


_npcId = -1;
}


/**
* Instantiates a new festival spawn.
*
* @param spawnData the spawn data
*/
protected FestivalSpawn(int[] spawnData)
{
_x = spawnData[0];
_y = spawnData[1];
_z = spawnData[2];


_heading = spawnData[3] < 0 ? Rnd.nextInt(65536) : spawnData[3];


if(spawnData.length > 4)
{
_npcId = spawnData[4];
}
else
{
_npcId = -1;
}
}
}
}



Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

AdBlock Extension Detected!

Our website is made possible by displaying online advertisements to our members.

Please disable AdBlock browser extension first, to be able to use our community.

I've Disabled AdBlock