Package l2p.gameserver.model.entity.SevenSignsFestival

Source Code of l2p.gameserver.model.entity.SevenSignsFestival.SevenSignsFestival

package l2p.gameserver.model.entity.SevenSignsFestival;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.logging.Logger;

import javolution.util.FastMap;
import l2p.database.DatabaseUtils;
import l2p.database.FiltredPreparedStatement;
import l2p.database.L2DatabaseFactory;
import l2p.database.ThreadConnection;
import l2p.extensions.scripts.Functions;
import l2p.gameserver.model.L2Clan;
import l2p.gameserver.model.L2ObjectsStorage;
import l2p.gameserver.model.L2Party;
import l2p.gameserver.model.L2Player;
import l2p.gameserver.model.base.Experience;
import l2p.gameserver.model.entity.SevenSigns;
import l2p.gameserver.serverpackets.PledgeShowInfoUpdate;
import l2p.gameserver.serverpackets.SystemMessage;
import l2p.gameserver.tables.ClanTable;
import l2p.gameserver.templates.StatsSet;
import l2p.util.GArray;

public class SevenSignsFestival
{
  private static Logger _log = Logger.getLogger(SevenSignsFestival.class.getName());
  private static SevenSignsFestival _instance;
  private static final SevenSigns _signsInstance = SevenSigns.getInstance();
  public static final int FESTIVAL_MANAGER_START = 120000; // 2 mins
  public static final int FESTIVAL_LENGTH = 1080000; // 18 mins
  public static final int FESTIVAL_CYCLE_LENGTH = 2280000; // 38 mins
  public static final int FESTIVAL_SIGNUP_TIME = FESTIVAL_CYCLE_LENGTH - FESTIVAL_LENGTH;
  public static final int FESTIVAL_FIRST_SPAWN = 120000; // 2 mins
  public static final int FESTIVAL_FIRST_SWARM = 300000; // 5 mins
  public static final int FESTIVAL_SECOND_SPAWN = 540000; // 9 mins
  public static final int FESTIVAL_SECOND_SWARM = 720000; // 12 mins
  public static final int FESTIVAL_CHEST_SPAWN = 900000; // 15 mins
  public static final int FESTIVAL_COUNT = 5;
  public static final int FESTIVAL_LEVEL_MAX_31 = 0;
  public static final int FESTIVAL_LEVEL_MAX_42 = 1;
  public static final int FESTIVAL_LEVEL_MAX_53 = 2;
  public static final int FESTIVAL_LEVEL_MAX_64 = 3;
  public static final int FESTIVAL_LEVEL_MAX_NONE = 4;
  public static final int[] FESTIVAL_LEVEL_SCORES = {60, 70, 100, 120, 150}; // 500 maximum possible score
  public static final short FESTIVAL_BLOOD_OFFERING = 5901;
  public static final short FESTIVAL_OFFERING_VALUE = 1;
  private static boolean _festivalInitialized;
  private static long[] _accumulatedBonuses; // The total bonus available (in Ancient Adena)
  private static Map<Integer, Long> _dawnFestivalScores, _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;

  public SevenSignsFestival()
  {
    _accumulatedBonuses = new long[FESTIVAL_COUNT];
    _dawnFestivalScores = new FastMap<Integer, Long>().setShared(true);
    _duskFestivalScores = new FastMap<Integer, Long>().setShared(true);
    _festivalData = new FastMap<Integer, Map<Integer, StatsSet>>().setShared(true);
    restoreFestivalData();
  }

  public static SevenSignsFestival getInstance()
  {
    if(_instance == null)
    {
      _instance = new SevenSignsFestival();
    }
    return _instance;
  }

  /**
   * Returns the associated name (level range) to a given festival ID.
   *
   * @param int festivalID
   * @return String festivalName
   */
  public static String getFestivalName(int festivalID)
  {
    switch(festivalID)
    {
      case FESTIVAL_LEVEL_MAX_31:
        return "31";
      case FESTIVAL_LEVEL_MAX_42:
        return "42";
      case FESTIVAL_LEVEL_MAX_53:
        return "53";
      case FESTIVAL_LEVEL_MAX_64:
        return "64";
      default:
        return "No Level Limit";
    }
  }

  /**
   * Returns the maximum allowed player level for the given festival type.
   *
   * @param festivalId
   * @return int maxLevel
   */
  public static int getMaxLevelForFestival(int festivalId)
  {
    switch(festivalId)
    {
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_31:
        return 31;
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_42:
        return 42;
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_53:
        return 53;
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_64:
        return 64;
      default:
        return Experience.getMaxLevel();
    }
  }

  public static int getStoneCount(int festivalId, int stoneId)
  {
    switch(festivalId)
    {
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_31:
        if(stoneId == 6360)
        {
          return 900;
        }
        else if(stoneId == 6361)
        {
          return 520;
        }
        else
        {
          return 270;
        }
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_42:
        if(stoneId == 6360)
        {
          return 1500;
        }
        else if(stoneId == 6361)
        {
          return 900;
        }
        else
        {
          return 450;
        }
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_53:
        if(stoneId == 6360)
        {
          return 3000;
        }
        else if(stoneId == 6361)
        {
          return 1500;
        }
        else
        {
          return 900;
        }
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_64:
        if(stoneId == 6360)
        {
          return 1500;
        }
        else if(stoneId == 6361)
        {
          return 2700;
        }
        else
        {
          return 1350;
        }
      case SevenSignsFestival.FESTIVAL_LEVEL_MAX_NONE:
        if(stoneId == 6360)
        {
          return 6000;
        }
        else if(stoneId == 6361)
        {
          return 3600;
        }
        else
        {
          return 1800;
        }
      default:
        System.out.println("WTF???");
        return 0;
    }
  }

  public static String implodeString(GArray<?> strArray)
  {
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < strArray.size();)
    {
      Object o = strArray.get(i);
      if(o instanceof L2Player)
      {
        sb.append(((L2Player) o).getName());
      }
      else
      {
        sb.append(o);
      }
      if(++i < strArray.size())
      {
        sb.append(",");
      }
    }
    return sb.toString();
  }

  /**
   * Restores saved festival data, basic settings from the properties file
   * and past high score data from the database.
   */
  private void restoreFestivalData()
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement = null;
    ResultSet rset = null;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      statement = con.prepareStatement("SELECT festivalId, cabal, cycle, date, score, members, names FROM seven_signs_festival");
      rset = statement.executeQuery();
      while(rset.next())
      {
        int cycle = _signsInstance.getCurrentCycle();
        int festivalId = rset.getInt("festivalId");
        int cabal = SevenSigns.getCabalNumber(rset.getString("cabal"));
        StatsSet festivalDat = new StatsSet();
        festivalDat.set("festivalId", festivalId);
        festivalDat.set("cabal", cabal);
        festivalDat.set("cycle", cycle);
        festivalDat.set("date", rset.getString("date"));
        festivalDat.set("score", rset.getInt("score"));
        festivalDat.set("members", rset.getString("members"));
        festivalDat.set("names", rset.getString("names"));
        if(cabal == SevenSigns.CABAL_DAWN)
        {
          festivalId += FESTIVAL_COUNT;
        }
        Map<Integer, StatsSet> tempData = _festivalData.get(cycle);
        if(tempData == null)
        {
          tempData = new FastMap<Integer, StatsSet>();
        }
        tempData.put(festivalId, festivalDat);
        _festivalData.put(cycle, tempData);
      }
      DatabaseUtils.closeDatabaseSR(statement, rset);
      StringBuffer query = new StringBuffer("SELECT festival_cycle, ");
      for(int i = 0; i < FESTIVAL_COUNT - 1; i++)
      {
        query.append("accumulated_bonus" + String.valueOf(i) + ", ");
      }
      query.append("accumulated_bonus" + String.valueOf(FESTIVAL_COUNT - 1) + " ");
      query.append("FROM seven_signs_status");
      statement = con.prepareStatement(query.toString());
      rset = statement.executeQuery();
      while(rset.next())
      {
        for(int i = 0; i < FESTIVAL_COUNT; i++)
        {
          _accumulatedBonuses[i] = rset.getInt("accumulated_bonus" + String.valueOf(i));
        }
      }
    }
    catch(SQLException e)
    {
      _log.severe("SevenSignsFestival: Failed to load configuration: " + e);
    }
    finally
    {
      DatabaseUtils.closeDatabaseCSR(con, statement, rset);
    }
  }

  /**
   * Stores current festival data, basic settings to the properties file
   * and past high score data to the database.
   *
   * @param updateSettings
   * @throws Exception
   */
  public synchronized void saveFestivalData(boolean updateSettings)
  {
    ThreadConnection con = null;
    FiltredPreparedStatement statement;
    try
    {
      con = L2DatabaseFactory.getInstance().getConnection();
      for(Map<Integer, StatsSet> currCycleData : _festivalData.values())
      {
        for(StatsSet festivalDat : currCycleData.values())
        {
          int festivalCycle = festivalDat.getInteger("cycle");
          int festivalId = festivalDat.getInteger("festivalId");
          String cabal = SevenSigns.getCabalShortName(festivalDat.getInteger("cabal"));
          // Try to update an existing record.
          statement = con.prepareStatement("UPDATE seven_signs_festival SET date=?, score=?, members=?, names=? 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.setString(4, festivalDat.getString("names", ""));
          statement.setInt(5, festivalCycle);
          statement.setString(6, cabal);
          statement.setInt(7, 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)
          {
            statement.close();
            continue;
          }
          DatabaseUtils.closeStatement(statement);
          FiltredPreparedStatement statement2 = con.prepareStatement("INSERT INTO seven_signs_festival (festivalId, cabal, cycle, date, score, members, names) VALUES (?,?,?,?,?,?,?)");
          statement2.setInt(1, festivalId);
          statement2.setString(2, cabal);
          statement2.setInt(3, festivalCycle);
          statement2.setLong(4, Long.valueOf(festivalDat.getString("date")));
          statement2.setInt(5, festivalDat.getInteger("score"));
          statement2.setString(6, festivalDat.getString("members"));
          statement2.setString(7, festivalDat.getString("names", ""));
          statement2.execute();
          DatabaseUtils.closeStatement(statement2);
        }
      }
    }
    catch(SQLException e)
    {
      _log.severe("SevenSignsFestival: Failed to save configuration: " + e);
      e.printStackTrace();
    }
    finally
    {
      DatabaseUtils.closeConnection(con);
    }
    // Updates Seven Signs DB data also, so call only if really necessary.
    if(updateSettings)
    {
      _signsInstance.saveSevenSignsData(0, true);
    }
  }

  /**
   * If a clan member is a member of the highest-ranked party in the Festival of Darkness, 100 points are added per member
   */
  public void rewardHighestRanked()
  {
    String[] partyMembers;
    for(int i = 0; i < FESTIVAL_COUNT; i++)
    {
      StatsSet overallData = getOverallHighestScoreData(i);
      if(overallData != null)
      {
        partyMembers = overallData.getString("members").split(",");
        for(String partyMemberId : partyMembers)
        {
          addReputationPointsForPartyMemberClan(partyMemberId);
        }
      }
    }
  }

  private void addReputationPointsForPartyMemberClan(String playerId)
  {
    L2Player player = L2ObjectsStorage.getPlayer(Integer.parseInt(playerId));
    if(player != null)
    {
      if(player.getClan() != null)
      {
        player.getClan().incReputation(100, true, "SevenSignsFestival");
        SystemMessage sm = new SystemMessage(SystemMessage.CLAN_MEMBER_S1_WAS_AN_ACTIVE_MEMBER_OF_THE_HIGHEST_RANKED_PARTY_IN_THE_FESTIVAL_OF_DARKNESS_S2_POINTS_HAVE_BEEN_ADDED_TO_YOUR_CLAN_REPUTATION_SCORE);
        sm.addName(player);
        sm.addNumber(100);
        player.getClan().broadcastToOnlineMembers(sm);
      }
    }
    else
    {
      ThreadConnection con = null;
      FiltredPreparedStatement statement;
      try
      {
        con = L2DatabaseFactory.getInstance().getConnection();
        statement = con.prepareStatement("SELECT char_name, clanid FROM characters WHERE obj_Id = ?");
        statement.setString(1, playerId);
        ResultSet rset = statement.executeQuery();
        if(rset.next())
        {
          int clanId = rset.getInt("clanid");
          if(clanId > 0)
          {
            L2Clan clan = ClanTable.getInstance().getClan(clanId);
            if(clan != null)
            {
              clan.incReputation(100, true, "SevenSignsFestival");
              clan.broadcastToOnlineMembers(new PledgeShowInfoUpdate(clan));
              SystemMessage sm = new SystemMessage(SystemMessage.CLAN_MEMBER_S1_WAS_AN_ACTIVE_MEMBER_OF_THE_HIGHEST_RANKED_PARTY_IN_THE_FESTIVAL_OF_DARKNESS_S2_POINTS_HAVE_BEEN_ADDED_TO_YOUR_CLAN_REPUTATION_SCORE);
              sm.addString(rset.getString("char_name"));
              sm.addNumber(100);
              clan.broadcastToOnlineMembers(sm);
            }
          }
        }
        DatabaseUtils.closeResultSet(rset);
        DatabaseUtils.closeStatement(statement);
      }
      catch(Exception e)
      {
        _log.warning("could not get clan name of " + playerId + ": " + e);
        e.printStackTrace();
      }
      finally
      {
        DatabaseUtils.closeConnection(con);
      }
    }
  }

  /**
   * Раздает призы за текущий период и очищает всю информацию для нового.
   */
  public void resetFestivalData(boolean updateSettings)
  {
    // Set all accumulated bonuses back to 0.
    for(int i = 0; i < FESTIVAL_COUNT; i++)
    {
      _accumulatedBonuses[i] = 0;
    }
    _dawnFestivalScores.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", _signsInstance.getCurrentCycle());
      tempStats.set("date", "0");
      tempStats.set("score", 0);
      tempStats.set("members", "");
      if(i >= FESTIVAL_COUNT)
      {
        tempStats.set("cabal", SevenSigns.CABAL_DAWN);
      }
      else
      {
        tempStats.set("cabal", 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(_signsInstance.getCurrentCycle(), newData);
    saveFestivalData(updateSettings);
    // Remove any unused blood offerings from online players.
    for(L2Player onlinePlayer : L2ObjectsStorage.getAllPlayers())
    {
      Functions.removeItem(onlinePlayer, FESTIVAL_BLOOD_OFFERING, Functions.getItemCount(onlinePlayer, FESTIVAL_BLOOD_OFFERING));
    }
    _log.info("SevenSignsFestival: Reinitialized engine for next competition period.");
  }

  public boolean isFestivalInitialized()
  {
    return _festivalInitialized;
  }

  public static void setFestivalInitialized(boolean isInitialized)
  {
    _festivalInitialized = isInitialized;
  }

  public String getTimeToNextFestivalStr()
  {
    if(_signsInstance.isSealValidationPeriod())
    {
      return "<font color=\"FF0000\">This is the Seal Validation period. Festivals will resume next week.</font>";
    }
    return "<font color=\"FF0000\">The next festival is ready to start.</font>";
  }

  public long getHighestScore(int oracle, int festivalId)
  {
    return getHighestScoreData(oracle, festivalId).getLong("score");
  }

  /**
   * Returns a stats set containing the highest score <b>this cycle</b> for the
   * the specified cabal and associated festival ID.
   *
   * @param oracle
   * @param festivalId
   * @return StatsSet festivalDat
   */
  public 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;
    try
    {
      currData = _festivalData.get(_signsInstance.getCurrentCycle()).get(offsetId);
    }
    catch(Exception e)
    {
      _log.warning("SSF: Error while getting scores");
      _log.warning("oracle=" + oracle + " festivalId=" + festivalId + " offsetId" + offsetId + " _signsCycle" + _signsInstance.getCurrentCycle());
      _log.warning("_festivalData=" + _festivalData.toString());
      e.printStackTrace();
    }
    if(currData == null)
    {
      currData = new StatsSet();
      currData.set("score", 0);
      currData.set("members", "");
      _log.warning("SevenSignsFestival: Data missing for " + SevenSigns.getCabalName(oracle) + ", FestivalID = " + festivalId + " (Current Cycle " + _signsInstance.getCurrentCycle() + ")");
    }
    return currData;
  }

  /**
   * Returns a stats set containing the highest ever recorded
   * score data for the specified festival.
   *
   * @param festivalId
   * @return StatsSet result
   */
  public 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
   * @param oracle
   * @param festivalId
   * @param offeringScore
   * @return boolean isHighestScore
   */
  public boolean setFinalScore(L2Party party, int oracle, int festivalId, long offeringScore)
  {
    GArray<Integer> partyMemberIds = party.getPartyMembersObjIds();
    GArray<L2Player> partyMembers = party.getPartyMembers();
    long currDawnHighScore = getHighestScore(SevenSigns.CABAL_DAWN, festivalId);
    long currDuskHighScore = getHighestScore(SevenSigns.CABAL_DUSK, festivalId);
    long thisCabalHighScore;
    long otherCabalHighScore;
    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;
      // Update the highest scores and party list.
      currFestData.set("date", String.valueOf(System.currentTimeMillis()));
      currFestData.set("score", offeringScore);
      currFestData.set("members", implodeString(partyMemberIds));
      currFestData.set("names", implodeString(partyMembers));
      // Only add the score to the cabal's overall if it's higher than the other cabal's score.
      if(offeringScore > otherCabalHighScore)
      {
        _signsInstance.updateFestivalScore();
      }
      saveFestivalData(true);
      return true;
    }
    return false;
  }

  public long getAccumulatedBonus(int festivalId)
  {
    return _accumulatedBonuses[festivalId];
  }

  public void addAccumulatedBonus(int festivalId, int stoneType, long 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;
    }
    _accumulatedBonuses[festivalId] += stoneAmount * eachStoneBonus;
  }

  /**
   * 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
   * @return playerBonus (the share of the bonus for the party)
   */
  public void distribAccumulatedBonus()
  {
    long[][] result = new long[FESTIVAL_COUNT][];
    long draw_count = 0;
    long draw_score = 0;
    // предварительный подсчет, определение ничьих
    for(int i = 0; i < FESTIVAL_COUNT; i++)
    {
      long dawnHigh = getHighestScore(SevenSigns.CABAL_DAWN, i);
      long duskHigh = getHighestScore(SevenSigns.CABAL_DUSK, i);
      if(dawnHigh > duskHigh)
      {
        result[i] = new long[] {SevenSigns.CABAL_DAWN, dawnHigh};
      }
      else if(duskHigh > dawnHigh)
      {
        result[i] = new long[] {SevenSigns.CABAL_DUSK, duskHigh};
      }
      else
      {
        result[i] = new long[] {SevenSigns.CABAL_NULL, dawnHigh};
        draw_count++;
        draw_score += _accumulatedBonuses[i];
      }
    }
    for(int i = 0; i < FESTIVAL_COUNT; i++)
    {
      if(result[i][0] != SevenSigns.CABAL_NULL)
      {
        StatsSet high = getHighestScoreData((int) result[i][0], i);
        String membersString = high.getString("members");
        long add = draw_count > 0 ? draw_score / draw_count : 0;
        String[] members = membersString.split(",");
        long count = (_accumulatedBonuses[i] + add) / members.length;
        for(String pIdStr : members)
        {
          SevenSigns.getInstance().addPlayerStoneContrib(Integer.parseInt(pIdStr), 0, 0, count / 10);
        }
      }
    }
  }
}
TOP

Related Classes of l2p.gameserver.model.entity.SevenSignsFestival.SevenSignsFestival

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.