mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-31 00:15:54 -04:00
5713 lines
168 KiB
Plaintext
5713 lines
168 KiB
Plaintext
/********************************************************************************************************************************************
|
|
* Copyright (c)2000-2002 Sony Online Entertainment Inc.
|
|
* All Rights Reserved
|
|
*
|
|
* Title: force_rank.scriptlib
|
|
* Description: Support functions for the Force Ranking System
|
|
* @author $Author:$
|
|
* @version $Revision:$
|
|
**********************************************************************/
|
|
|
|
|
|
/***** INCLUDES ********************************************************/
|
|
include library.skill;
|
|
include library.xp;
|
|
include library.utils;
|
|
include library.prose;
|
|
include library.pvp;
|
|
include library.trace;
|
|
include library.player_structure;
|
|
include java.lang.Math;
|
|
|
|
/***** CONSTANTS *******************************************************/
|
|
// System constants
|
|
|
|
const string FRS_DATATABLE = "datatables/pvp/force_rank.iff";
|
|
const string FRS_DARK_DATATABLE = "datatables/pvp/force_rank_dark.iff";
|
|
const string JEDI_TERMINAL_DATATABLE = "datatables/pvp/jedi_enclave_terminals.iff";
|
|
const string ENCLAVE_REWARDS_DATATABLE = "datatables/pvp/enclave_rewards.iff";
|
|
const string FRS_XP = "force_rank_xp";
|
|
const string STF_FILE = "force_rank";
|
|
const string CLUSTER_DATA_NAME = "jedi_frs";
|
|
|
|
const int PVP_BOARD_SIZE = 25;
|
|
const int UPDATE_INTERVAL = 900;
|
|
const int BACK_UP_INTERVAL = 172800;
|
|
const int MAX_RANK_SLOTS = 20;
|
|
const int PETITION_INTERVAL = 86400; // 86400
|
|
const int VOTING_INTERVAL = 86400; // 86400
|
|
const int ACCEPTANCE_INTERVAL = 86400; // 86400
|
|
const int MAX_PETITIONERS = 11;
|
|
const int MISSED_VOTE_PENALTY = 100;
|
|
const int REQUEST_DEMOTION_DURATION = 604800; // 604800;
|
|
const int REQUEST_DEMOTION_COST = 2500;
|
|
const int MAINTENANCE_PULSE = 1200; // 1200
|
|
const int BASE_XP_MAINTENANCE = 100;
|
|
const int XP_MAINTENANCE_INTERVAL = 86400; // 86400;
|
|
const int VOTE_CHALLENGE_COST = 2000;
|
|
const int VOTE_CHALLENGE_DURATION = 604800;
|
|
const int MAX_CHAL_LIST_SIZE = 20;
|
|
const int DEBUFF_DURATION = 120;
|
|
|
|
const string EMPTY_SLOT = "Open Seat";
|
|
const string SCRIPT_DATA_HANDLER = "systems.gcw.enclave_data_handler";
|
|
const string SCRIPT_FRS_PLAYER = "systems.gcw.player_force_rank";
|
|
const string SCRIPT_ENCLAVE_CONTROLLER = "systems.gcw.enclave_controller";
|
|
const string JEDI_ROOM_PERMISSIONS_TABLE = "datatables/pvp/jedi_enclave_room_permissions.iff";
|
|
const string DATA_COLUMN_COMMUNITY_CELLS = "_community_cells";
|
|
const boolean DEBUGGING = false;
|
|
|
|
// Councils
|
|
const int TEST_COUNCIL = 0;
|
|
const int DARK_COUNCIL = 1;
|
|
const int LIGHT_COUNCIL = 2;
|
|
const string[] COUNCIL_NAMES = {"Test Enclave", "Dark Enclave", "Light Enclave"};
|
|
|
|
// Player ObjVars
|
|
const string VAR_RATING = "force_rank.rating";
|
|
const string VAR_RANK = "force_rank.rank";
|
|
const string VAR_COUNCIL = "force_rank.council";
|
|
const string VAR_REQUEST_DEMOTE = "force_rank.request_demote";
|
|
const string VAR_VOTE_CHALLENGE = "force_rank.vote_challenge";
|
|
|
|
const string SCRIPT_VAR_DATA_REQUEST = "force_rank.data_request";
|
|
const string SCRIPT_VAR_PARAMS_REQUEST = "force_rank.rank_request";
|
|
const string SCRIPT_VAR_HANDLER_REQUEST = "force_rank.handler_request";
|
|
const string SCRIPT_VAR_SKILL_RESYNC = "force_rank.script_resync";
|
|
const string SCRIPT_VAR_REVALIDATE = "force_rank.revalidate";
|
|
|
|
// Voting Terminals
|
|
const string BATCH_VAR_VOTERS = "force_rank.voters_rank";
|
|
|
|
// Enclave ObjVars
|
|
const string VAR_RANK11 = "force_rank.roster.rank11";
|
|
const string VAR_RANK10 = "force_rank.roster.rank10";
|
|
const string VAR_RANK9 = "force_rank.roster.rank9";
|
|
const string VAR_RANK8 = "force_rank.roster.rank8";
|
|
const string VAR_RANK7 = "force_rank.roster.rank7";
|
|
const string VAR_RANK6 = "force_rank.roster.rank6";
|
|
const string VAR_RANK5 = "force_rank.roster.rank5";
|
|
const string VAR_RANK4 = "force_rank.roster.rank4";
|
|
const string VAR_RANK3 = "force_rank.roster.rank3";
|
|
const string VAR_RANK2 = "force_rank.roster.rank2";
|
|
const string VAR_RANK1 = "force_rank.roster.rank1";
|
|
const string VAR_RANK_BASE = "force_rank.roster.rank";
|
|
const string VAR_VOTING_BASE = "force_rank.voting.rank";
|
|
const string VAR_CHAL_VOTING_BASE = "force_rank.chal_voting";
|
|
|
|
const string VAR_MEMBER_DATA = "force_rank.data.";
|
|
const string VAR_BACKUP_TIME = "force_rank.backup_time";
|
|
const string STRING_CLUSTER_ENCLAVE_NAME = "enclave_";
|
|
const string BATCH_VAR_PVPBOARD_NAME = "force_rank.stats.pvpboard_name";
|
|
const string BATCH_VAR_PVPBOARD_RATING = "force_rank.stats.pvpboard_rating";
|
|
const string VAR_ENCLAVE = "force_rank.enclave"; // Cluster data only
|
|
const string VAR_XP_MAINTENANCE = "force_rank.xp_maintenance";
|
|
const int COUNCIL_RANK_NUMBER = 10;
|
|
const string SCRIPT_VAR_VOTE_TERMINAL = "force_rank.vote_terminal";
|
|
const string SCRIPT_VAR_CHAL_VOTE_TERMINAL = "force_rank.chal_vote_terminal";
|
|
|
|
const string ACTION_VENDETTA = "force_rank.vendettas";
|
|
const int ACTION_VENDETTA_DURATION = 604800;
|
|
|
|
const string ACTION_BANISHMENT = "force_rank.banishments";
|
|
const int ACTION_BANISHMENT_DURATION = 604800;
|
|
|
|
const string ACTION_PURGE_COUNCIL = "force_rank.councilPurges";
|
|
const int ACTION_PURGE_COUNCIL_DURATION = 604800;
|
|
|
|
const string ACTION_CANDIDATE_SUDDEN_DEATH = "force_rank.candidateSuddenDeath";
|
|
const int ACTION_CANDIATE_SUDDEN_DEATH_DURATION = 604800;
|
|
|
|
const string VAR_INITIATORS = ".initiators";
|
|
const string VAR_VICTIMS = ".victims";
|
|
const string VAR_START_TIMESTAMPS = ".timestamps";
|
|
|
|
const string VAR_NOTIFY_ENCLAVE_OF_DEATH = "force_rank.notifyEnclaveOfDeath"; // found on the player if the enclave needs to be notified when they die
|
|
const string VAR_MY_ENCLAVE_ID = "force_rank.myEnclaveId";
|
|
|
|
const float MIN_KILL_CONTRIB_FOR_ACTION_DEATH = .51f; // the minimum percent contribution that a dark jedi must have against another dark jedi death in order for the PVP ACTION to be considered "fulfilled".
|
|
|
|
/***** TRIGGERS ********************************************************/
|
|
|
|
|
|
/***** MESSAGEHANDLERS *************************************************/
|
|
|
|
|
|
/***** COMMANDHANDLERS *************************************************/
|
|
|
|
|
|
/***** FUNCTIONS *******************************************************/
|
|
|
|
/***********************************************************************
|
|
* @brief Initiates the player into the FRS
|
|
*
|
|
* @param obj_id player
|
|
* @param int faction_id
|
|
*
|
|
* @return boolean returns true if successful
|
|
***********************************************************************/
|
|
boolean addToForceRankSystem(obj_id player, int council)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.addToForceRankSystem -- player is invalid.");
|
|
return false;
|
|
}
|
|
if (council != LIGHT_COUNCIL && council != DARK_COUNCIL)
|
|
{
|
|
LOG("force_rank", "force_rank.addToForceRankSystem -- " + player + " has an invalid council value of " + council);
|
|
return false;
|
|
}
|
|
|
|
string rank_skill = getForceRankSkill(0, council);
|
|
if (rank_skill == null)
|
|
{
|
|
LOG("force_rank", "force_rank.addToForceRankSystem -- rank_skill is null for rank 0.");
|
|
return false;
|
|
}
|
|
setObjVar(player, VAR_RANK, 0);
|
|
setObjVar(player, VAR_COUNCIL, council);
|
|
|
|
// FRS Jedi are always overt.
|
|
if (council == LIGHT_COUNCIL)
|
|
{
|
|
setJediState(player, JEDI_STATE_FORCE_RANKED_LIGHT);
|
|
pvpSetAlignedFaction(player, getFactionId("Rebel"));
|
|
}
|
|
else
|
|
{
|
|
setJediState(player, JEDI_STATE_FORCE_RANKED_DARK);
|
|
pvpSetAlignedFaction(player, getFactionId("Imperial"));
|
|
}
|
|
|
|
pvpMakeDeclared(player);
|
|
|
|
grantSkill(player, rank_skill);
|
|
|
|
prose_package pp = prose.getPackage(new string_id(STF_FILE, "council_joined"), getCouncilName(council), 0);
|
|
sendSystemMessageProse(player, pp);
|
|
|
|
if (!hasScript(player, SCRIPT_FRS_PLAYER))
|
|
attachScript(player, SCRIPT_FRS_PLAYER);
|
|
|
|
// Set up the enclave obj_id
|
|
getEnclaveObjId(player, council, "enclaveIdResponse");
|
|
|
|
// Check for new items to grant
|
|
force_rank.grantRankItems(player);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* @brief Removes the player from the FRS. The player must
|
|
* already be at FRS 0. Use fullDemotePlayer to do this.
|
|
*
|
|
* @param obj_id player
|
|
* @param boolean surrendered whether or not the player initiated
|
|
* the removal by surrendering the novice skill
|
|
*
|
|
* @return boolean returns true if successful
|
|
***********************************************************************/
|
|
boolean removeFromForceRankSystem(obj_id player, boolean surrendered)
|
|
{
|
|
LOG("force_rank", "force_rank.removeFromForceRankSystem");
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.removeFromForceRankSystem -- player is invalid.");
|
|
return false;
|
|
}
|
|
|
|
int council = getCouncilAffiliation(player);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.removeFromForceRankSystem -- " + player + " has an invalid council affiliation.");
|
|
return false;
|
|
}
|
|
if (getForceRank(player) > 0)
|
|
{
|
|
LOG("force_rank", "force_rank.removeFromForceRankSystem -- " + player + " has a force rank > 0.");
|
|
return false;
|
|
}
|
|
|
|
// Remove the skills
|
|
//string skill = force_rank.getForceRankSkill(0, council);
|
|
//if (skill != null)
|
|
//{
|
|
//
|
|
// revokeSkill(player, skill);
|
|
//}
|
|
|
|
if (!surrendered)
|
|
force_rank.removeForceRankSkills(player, -1);
|
|
|
|
//LOG("force_rank", "force_rank.removeFromForceRankSystem --- 1111");
|
|
|
|
// Remove the data.
|
|
removeObjVar(player, "force_rank");
|
|
if (hasScript(player, SCRIPT_FRS_PLAYER))
|
|
detachScript(player, SCRIPT_FRS_PLAYER);
|
|
|
|
//LOG("force_rank", "force_rank.removeFromForceRankSystem --- 2222");
|
|
|
|
prose_package pp = prose.getPackage(new string_id(STF_FILE, "council_left"), getCouncilName(council), 0);
|
|
sendSystemMessageProse(player, pp);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Grants or removes FRS experience
|
|
*
|
|
* @param obj_id player
|
|
* @param int amount
|
|
*
|
|
* @return int returns the new xp total, -1 on error
|
|
***********************************************************************/
|
|
int adjustForceRankXP(obj_id player, int amt)
|
|
{
|
|
LOG("force_rank", "force_rank.adjustForceRankXP -- player ->" + player + " amt ->" + amt);
|
|
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.grantForceRankXP -- player is invalid.");
|
|
return -1;
|
|
}
|
|
|
|
if (amt == 0)
|
|
return getExperiencePoints(player, FRS_XP);
|
|
else if (amt > 0)
|
|
{
|
|
grantExperiencePoints(player, FRS_XP, amt);
|
|
prose_package pp = prose.getPackage(new string_id(STF_FILE, "experience_granted"), amt);
|
|
sendSystemMessageProse(player, pp);
|
|
}
|
|
else
|
|
{
|
|
int current_xp = getExperiencePoints(player, FRS_XP);
|
|
// Cannot go to negative xp.
|
|
if (amt * -1 > current_xp)
|
|
amt = current_xp * -1;
|
|
|
|
LOG("force_rank", "force_rank.adjustForceRankXP -- current_xp ->" + current_xp + " final amt ->" + amt);
|
|
grantExperiencePoints(player, FRS_XP, amt);
|
|
prose_package pp = prose.getPackage(new string_id(STF_FILE, "experience_lost"), amt * -1);
|
|
sendSystemMessageProse(player, pp);
|
|
|
|
// Check to see if this loss of xp drops the player down a rank. We only drop
|
|
// one rank max at a time.
|
|
current_xp += amt;
|
|
int rank = getForceRank(player);
|
|
int min_xp = getForceRankMinXp(rank);
|
|
|
|
LOG("force_rank", "rank ->" + rank + " min_xp ->" + min_xp + " current_xp ->" + current_xp);
|
|
|
|
if (min_xp > current_xp)
|
|
demoteForceRank(player, rank - 1);
|
|
}
|
|
|
|
return getExperiencePoints(player, FRS_XP);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief adds to the experience debt of a player. This should
|
|
* only be used to impose experience penalties when the player
|
|
* is off-line. Otherwise, use adjustForceRankXP.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param string player_name
|
|
* @param int xp_debt
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean addExperienceDebt(obj_id enclave, string player_name, int xp_debt)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.addExperienceDebt -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (player_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.addExperienceDebt -- player_name is null.");
|
|
return false;
|
|
}
|
|
if (xp_debt < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.addExperienceDebt -- illegal value for xp_debt: " + xp_debt);
|
|
return false;
|
|
}
|
|
|
|
// Check to see if the player is in the force ranks.
|
|
boolean in_rank = false;
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
resizeable string[] rank_list = getPlayersInForceRankResizeable(enclave, i);
|
|
if (rank_list != null)
|
|
{
|
|
if (rank_list.indexOf(player_name) != -1)
|
|
{
|
|
in_rank = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (in_rank)
|
|
{
|
|
string obj_var_name = VAR_MEMBER_DATA + player_name + ".xp_debt";
|
|
int current_debt = 0;
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
current_debt = getIntObjVar(enclave, obj_var_name);
|
|
|
|
current_debt += xp_debt;
|
|
setObjVar(enclave, obj_var_name, current_debt);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
LOG("force_rank", "force_rank.addExperienceDebt -- " + player_name + " is not in the force rank list.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Spends FRS experience. Does not let the experience total
|
|
* go below the minimum for the rank.
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return int returns the new xp total, -1 on error
|
|
***********************************************************************/
|
|
int spendForceRankXP(obj_id player, int amt)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.spendForceRankXP -- player is invalid.");
|
|
return -1;
|
|
}
|
|
if (amt < 0)
|
|
{
|
|
LOG("force_rank", "force_rank.spendForceRankXP -- illegal amount value: " + amt);
|
|
return -1;
|
|
}
|
|
|
|
int current_xp = getExperiencePoints(player, FRS_XP);
|
|
int min_xp = getForceRankMinXp(getForceRank(player));
|
|
LOG("force_rank", "current_xp ->" + current_xp + " min_xp ->" + min_xp);
|
|
|
|
if (current_xp - amt < min_xp)
|
|
return -1;
|
|
else
|
|
{
|
|
adjustForceRankXP(player, amt * -1);
|
|
return getExperiencePoints(player, FRS_XP);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Promotes the target within the FRS. Requires the player
|
|
* to be authoritative.
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return boolean result handler is in msgForceRankPromoted
|
|
***********************************************************************/
|
|
boolean promoteForceRank(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.promoteForceRank -- player is invalid.");
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(player);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.promoteForceRank -- " + player + " has an invalid council value.");
|
|
return false;
|
|
}
|
|
int current_rank = getForceRank(player);
|
|
if (current_rank < 0 || current_rank > 10)
|
|
{
|
|
LOG("force_rank", "force_rank.promoteForceRank -- attempting to promote " + player + " when his rank is at " + current_rank);
|
|
return false;
|
|
}
|
|
string rank_skill = getForceRankSkill(current_rank + 1, council);
|
|
if (rank_skill == null)
|
|
{
|
|
LOG("force_rank", "force_rank.promoteForceRank -- rank_skill is null for rank " + (current_rank + 1));
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(player, council, 3, Integer.toString(current_rank), "msgForceRankPromotePlayer", true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Demotes the player within the FRS. Requires the player to
|
|
* be authoritative.
|
|
*
|
|
* @param obj_id player
|
|
* @param int rank rank to which to demote.
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean demoteForceRank(obj_id player, int rank)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- player is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 0 || rank > 10)
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- illegal rank value: " + rank);
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(player);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- " + player + " has an invalid council value.");
|
|
return false;
|
|
}
|
|
int current_rank = getForceRank(player);
|
|
if (current_rank < 1 || current_rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- attempting to demote " + player + " when his rank is at " + current_rank);
|
|
return false;
|
|
}
|
|
//LOG("force_rank", "current ->" + current_rank + " rank ->" + rank);
|
|
if (rank >= current_rank)
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- attempting to demote " + player + " to a rank that is greater than or equal to his current rank.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(player, council, 4, Integer.toString(rank), "msgForceRankDemotePlayer", true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Demotes the player within the FRS. Requires the enclave
|
|
* to be authoritative
|
|
*
|
|
* @param obj_id enclave
|
|
* @param string player_name
|
|
* @param int rank rank to which to demote
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean demoteForceRank(obj_id enclave, string player_name, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (player_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- player_name is null.");
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(enclave);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.demoteForceRank -- " + enclave + " has an invalid council value.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(enclave, council, 5, player_name + " " + rank, "msgForceRankDemotePlayer", true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Removes all cluster data for the enclave and replaces
|
|
* it from the current enclave data.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean resetClusterData(obj_id enclave)
|
|
{
|
|
LOG("force_rank", "force_rank.resetClusterData");
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.resetClusterData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(enclave);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.resetClusterData -- " + enclave + " has an invalid council value.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(enclave, council, 8, "", "msgFRSUpdateClusterData", true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Changes the name entry specified to the player's current
|
|
* name. This should be called after a successful player
|
|
* rename.
|
|
*
|
|
* @param obj_id player
|
|
* @param string old_name The player's old name.
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean renameRankMember(obj_id player, string old_name)
|
|
{
|
|
if (old_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.renameRankMember -- old_name is null.");
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(player);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.renameRankMember -- " + player + " has an invalid council value.");
|
|
return false;
|
|
}
|
|
int current_rank = getForceRank(player);
|
|
if (current_rank < 1 || current_rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.renameRankMember -- attempting to demote " + player + " when his rank is at " + current_rank);
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(player, council, 9, old_name, "msgForceRankRenamePlayer", true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Removes a player's skills down to the specified rank.
|
|
*
|
|
* @param obj_id player
|
|
* @param int rank -1 for all skills
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean removeForceRankSkills(obj_id player, int rank)
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills");
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills -- player is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < -1 || rank > 10)
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills -- invalid value for rank: " + rank);
|
|
return false;
|
|
}
|
|
|
|
int current_rank = getForceRank(player);
|
|
if (current_rank < 0)
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills -- can't remove skills from a player with a rank of " + current_rank);
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(player);
|
|
if (council < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills -- " + player + " has an invalid council affiliation.");
|
|
return false;
|
|
}
|
|
|
|
// set script var to prevent firing the skill revoke trigger for voluntary skill surrendering.
|
|
utils.setScriptVar(player, SCRIPT_VAR_SKILL_RESYNC, 1);
|
|
|
|
for (int i = current_rank; i > rank; i--)
|
|
{
|
|
string rank_skill = getForceRankSkill(i, council);
|
|
LOG("force_rank", "rank_skill[" + i + "]->" + rank_skill);
|
|
if (hasSkill(player, rank_skill))
|
|
revokeSkill(player, rank_skill);
|
|
}
|
|
|
|
utils.removeScriptVar(player, SCRIPT_VAR_SKILL_RESYNC);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Resyncs a player's FRS skills based on his existing rank.
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return boolean
|
|
***********************************************************************/
|
|
boolean resyncForceRankSkills(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills -- player is invalid.");
|
|
return false;
|
|
}
|
|
|
|
int rank = getForceRank(player);
|
|
if (rank < 0 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.removeForceRankSkills -- invalid value for rank: " + rank);
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(player);
|
|
if (council < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.resyncForceRankSkills -- " + player + " has an invalid council affiliation.");
|
|
return false;
|
|
}
|
|
|
|
// Set this scriptvar so that the lost skill trigger won't assume any skill revocations are a demotion.
|
|
utils.setScriptVar(player, SCRIPT_VAR_SKILL_RESYNC, 1);
|
|
|
|
// Check for skills the player should have. Start at 0 and go to 12, so that prereqs are always met.
|
|
for (int i = 0; i < 12; i++)
|
|
{
|
|
string skill = getForceRankSkill(i, council);
|
|
if (skill != null)
|
|
{
|
|
if (i <= rank)
|
|
{
|
|
// Player should have this skill
|
|
if (!hasSkill(player, skill))
|
|
{
|
|
grantSkill(player, skill);
|
|
CustomerServiceLog("force_rank", "Adding skill " + skill + " to %TU since it should be granted for rank " + rank, player, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check for skills the player shouldn't have. Start and 12 and go to 0, so that prereqs are always met.
|
|
for (int i = 11; i >= 0; i--)
|
|
{
|
|
string skill = getForceRankSkill(i, council);
|
|
if (skill != null)
|
|
{
|
|
if (i > rank)
|
|
{
|
|
// Player shouldn't have this skill
|
|
if (hasSkill(player, skill))
|
|
{
|
|
revokeSkill(player, skill);
|
|
CustomerServiceLog("force_rank", "Removing skill " + skill + " from %TU since it not valid for rank " + rank, player, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
utils.removeScriptVar(player, SCRIPT_VAR_SKILL_RESYNC);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief handles the periodic enclave functions such as updating
|
|
* clusterwide data and checking for voting results.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return int -1 if error or the player is not ranked
|
|
*********************************************************************/
|
|
boolean performEnclaveMaintenance(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.performEnclaveMaintenance -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
// Check to see if it's time for experience maintenance.
|
|
if (hasObjVar(enclave, VAR_XP_MAINTENANCE))
|
|
{
|
|
int last_maintenance = getIntObjVar(enclave, VAR_XP_MAINTENANCE);
|
|
if (getGameTime() > last_maintenance)
|
|
{
|
|
deductXpMaintenance(enclave);
|
|
setObjVar(enclave, VAR_XP_MAINTENANCE, getGameTime() + getXpInterval());
|
|
}
|
|
}
|
|
else
|
|
setObjVar(enclave, VAR_XP_MAINTENANCE, getGameTime() + getXpInterval());
|
|
|
|
arena.checkArenaMaintenance(enclave);
|
|
checkExperienceDebt(enclave);
|
|
checkVotingResults(enclave);
|
|
int council = force_rank.getCouncilAffiliation(enclave);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "enclave_controller.performEnclaveMaintenance -- " + enclave + " does not have a valid council value.");
|
|
return false;
|
|
}
|
|
|
|
// Create terminals if needed.
|
|
createEnclaveTerminals(enclave);
|
|
|
|
// update the enclave's data.
|
|
int request_id = getClusterWideData(force_rank.CLUSTER_DATA_NAME, force_rank.STRING_CLUSTER_ENCLAVE_NAME + council, false, enclave);
|
|
utils.setScriptVar(enclave, force_rank.SCRIPT_VAR_DATA_REQUEST + request_id, 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief examines voting data to determine results.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return true
|
|
*********************************************************************/
|
|
boolean checkVotingResults(obj_id enclave)
|
|
{
|
|
LOG("force_rank", "force_rank.checkVotingResults");
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.checkVotingResults -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
// Loop through the voting data for each rank and check the results.
|
|
for (int rank = 1; rank < 12; rank++)
|
|
{
|
|
// Look at the status of voting for the rank.
|
|
int status = getVoteStatus(enclave, rank);
|
|
int time = getVoteEndTime(enclave, rank);
|
|
if (status == -1 || time == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.checkVotingResults -- invalid value for status/time :" + status + "/" + time + " for rank " + rank);
|
|
continue;
|
|
}
|
|
string obj_var_base = VAR_VOTING_BASE + rank;
|
|
if (!hasObjVar(enclave, obj_var_base) && status != 4)
|
|
{
|
|
setObjVar(enclave, obj_var_base + ".status", 4);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime());
|
|
continue;
|
|
}
|
|
|
|
boolean time_expired = time < getGameTime();
|
|
|
|
switch (status)
|
|
{
|
|
case 1:
|
|
{
|
|
// Petitioning open
|
|
if (time_expired)
|
|
{
|
|
string[] petitioners = getRankPetitioners(enclave, rank);
|
|
if (petitioners == null)
|
|
{
|
|
// If no one petitioned, we open it up for another round.
|
|
int avail_slots = getAvailableRankSlots(enclave, rank);
|
|
if (avail_slots > 0)
|
|
{
|
|
setObjVar(enclave, obj_var_base + ".status", 1);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime() + getPetitionInterval());
|
|
}
|
|
else
|
|
resetVotingTerminal(enclave, rank);
|
|
}
|
|
else
|
|
{
|
|
// If there's more open slots than petitioners, everyone wins.
|
|
// If there's only on petitioner, he wins.
|
|
int avail_slots = getAvailableRankSlots(enclave, rank);
|
|
if (petitioners.length <= avail_slots || petitioners.length == 1)
|
|
{
|
|
removeObjVar(enclave, obj_var_base + ".petition");
|
|
removeObjVar(enclave, obj_var_base + ".time");
|
|
removeObjVar(enclave, obj_var_base + ".votes");
|
|
//string[] winner_list = {petitioners[0]};
|
|
setObjVar(enclave, obj_var_base + ".winner", petitioners);
|
|
setObjVar(enclave, obj_var_base + ".status", 3);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime() + getAcceptanceInterval());
|
|
|
|
// Send a message to the winners
|
|
string_id sub = new string_id(force_rank.STF_FILE, "vote_win_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "vote_win_body");
|
|
for (int i = 0; i < petitioners.length; i++)
|
|
utils.sendMail(sub, body, petitioners[i], "Enclave Records");
|
|
}
|
|
else
|
|
{
|
|
// Open up voting for the given petitioners.
|
|
setObjVar(enclave, obj_var_base + ".status", 2);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime() + getVoteInterval());
|
|
int[] votes = new int[petitioners.length];
|
|
Arrays.fill(votes, 0);
|
|
setObjVar(enclave, obj_var_base + ".votes", votes);
|
|
|
|
// make the petitioners enemies of each other
|
|
/*
|
|
if(getCouncilAffiliation(enclave) == DARK_COUNCIL)
|
|
{
|
|
startPvPAction(enclave, playerNamesToIds(petitioners), ACTION_CANDIDATE_SUDDEN_DEATH, enclave);
|
|
}
|
|
*/
|
|
|
|
// e-mail all eligible voters about the vote
|
|
string_id sub = new string_id(force_rank.STF_FILE, "vote_cycle_begun_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "vote_cycle_begun_body");
|
|
string rank_str = localize(new string_id(force_rank.STF_FILE, "rank" + rank));
|
|
int vote_interval = getVoteInterval();
|
|
string time_str = player_structure.assembleTimeRemaining(player_structure.convertSecondsTime(vote_interval));
|
|
prose_package pp = prose.getPackage(body, time_str, rank_str);
|
|
sendVoterMail(enclave, rank, sub, pp);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
// Voting open
|
|
if (time_expired)
|
|
{
|
|
// Check the votes.
|
|
int avail_slots = getAvailableRankSlots(enclave, rank);
|
|
string[] petitioners = getRankPetitioners(enclave, rank);
|
|
int[] votes = getRankPetitionerVotes(enclave, rank);
|
|
|
|
/*
|
|
// stop the pvp sudden death PvP Action
|
|
if(getCouncilAffiliation(enclave) == DARK_COUNCIL)
|
|
{
|
|
resizeable obj_id[] players_o = new obj_id[0];
|
|
string[] lists = {VAR_VICTIMS, VAR_INITIATORS}; // clear actions for which @player is either a victim or an initiator
|
|
|
|
for(int x = 0; x < petitioners.length; x++)
|
|
{
|
|
utils.addElement(players_o, getPlayerIdFromFirstName(petitioners[x]));
|
|
_clearPvPActionDataForPlayer(players_o[x], lists, ACTION_CANDIDATE_SUDDEN_DEATH, enclave);
|
|
}
|
|
|
|
notifyPlayerOfPvPActionEnd(null, ACTION_CANDIDATE_SUDDEN_DEATH, players_o, players_o, true);
|
|
}
|
|
*/
|
|
|
|
// Pick the top vote getters to fill the vacant slots.
|
|
if (avail_slots > 0)
|
|
{
|
|
int[] top_votes = getTopVotes(votes, avail_slots);
|
|
votes = getRankPetitionerVotes(enclave, rank);
|
|
if (top_votes != null)
|
|
{
|
|
//resizeable int[] res_votes = getRankPetitionerVotesResizeable(enclave, rank);
|
|
resizeable string[] winners = new string[0];
|
|
for (int i = 0; i < top_votes.length; i++)
|
|
{
|
|
int vote_idx = utils.getElementPositionInArray(votes, top_votes[i]);
|
|
winners.add(petitioners[vote_idx]);
|
|
votes[vote_idx] = -1;
|
|
|
|
// Send a message to the winners
|
|
string_id sub = new string_id(force_rank.STF_FILE, "vote_win_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "vote_win_body");
|
|
utils.sendMail(sub, body, petitioners[vote_idx], "Enclave Records");
|
|
|
|
CustomerServiceLog("force_rank", petitioners[vote_idx] + " won an open seat in rank " + rank + " with " + top_votes[i] + " votes.");
|
|
}
|
|
|
|
if (winners.size() > 0)
|
|
{
|
|
// At this point, the winners may accept their positions.
|
|
removeObjVar(enclave, obj_var_base + ".petition");
|
|
removeObjVar(enclave, obj_var_base + ".votes");
|
|
setObjVar(enclave, obj_var_base + ".winner", winners);
|
|
setObjVar(enclave, obj_var_base + ".status", 3);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime() + getAcceptanceInterval());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOG("force_rank", "force_rank.checkVotingResults -- voting failed for rank " + rank + " due to a null top_votes.");
|
|
resetVotingTerminal(enclave, rank);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No spots are open now. The top vote getting automatically wins the vote on the next available slot.
|
|
int[] top_votes = getTopVotes(votes, 1);
|
|
if (top_votes != null)
|
|
{
|
|
int vote_idx = utils.getElementPositionInArray(votes, top_votes[0]);
|
|
removeObjVar(enclave, obj_var_base + ".petition");
|
|
removeObjVar(enclave, obj_var_base + ".time");
|
|
removeObjVar(enclave, obj_var_base + ".votes");
|
|
string[] winner_list = {petitioners[vote_idx]};
|
|
setObjVar(enclave, obj_var_base + ".winner", winner_list);
|
|
setObjVar(enclave, obj_var_base + ".status", 4);
|
|
|
|
// Send a message to the winners
|
|
string_id sub = new string_id(force_rank.STF_FILE, "vote_win_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "vote_win_no_slot_body");
|
|
utils.sendMail(sub, body, petitioners[vote_idx], "Enclave Records");
|
|
}
|
|
else
|
|
{
|
|
LOG("force_rank", "force_rank.checkVotingResults -- voting failed for rank " + rank + " due to a null top_votes.");
|
|
resetVotingTerminal(enclave, rank);
|
|
}
|
|
}
|
|
|
|
// Eligible votes who miss a vote loose experience.
|
|
checkMissedVotes(enclave, rank);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
// Waiting Acceptance
|
|
if (time_expired)
|
|
{
|
|
// The acceptance period is over. Clear the data and remove all winners.
|
|
//LOG("force_rank", "force_rank.checkVotingResults -- reset voting data.");
|
|
string[] winners = getVoteWinners(enclave, rank);
|
|
//LOG("force_rank", "winners ->" + winners);
|
|
if (winners != null)
|
|
{
|
|
string_id sub = new string_id(force_rank.STF_FILE, "acceptance_expired_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "acceptance_expired_body");
|
|
string rank_str = localize(new string_id(force_rank.STF_FILE, "rank" + rank));
|
|
prose_package pp = prose.getPackage(body, rank_str);
|
|
for (int i = 0; i < winners.length; i++)
|
|
{
|
|
utils.sendMail(sub, pp, winners[i], "Enclave Records");
|
|
CustomerServiceLog("force_rank", winners[i] + "'s chance to accept a promotion to rank " + rank + " has expired.");
|
|
}
|
|
}
|
|
resetVotingTerminal(enclave, rank);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
//LOG("force_rank", "!!!!!!!!!!!!!!! voting_closed -->" + rank);
|
|
// Voting is closed.
|
|
// Check for available slots.
|
|
int avail_slots = getAvailableRankSlots(enclave, rank);
|
|
if (avail_slots > 0)
|
|
{
|
|
// Check for a previous vote winners awaiting an open slots. If they exist, reopen
|
|
// the acceptance process.
|
|
string[] winners = getVoteWinners(enclave, rank);
|
|
if (winners != null)
|
|
{
|
|
setObjVar(enclave, obj_var_base + ".status", 3);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime() + getAcceptanceInterval());
|
|
|
|
// Send a message to the winners
|
|
string_id sub = new string_id(force_rank.STF_FILE, "vote_seat_available_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "vote_seat_available_body");
|
|
string rank_str = localize(new string_id(force_rank.STF_FILE, "rank" + rank));
|
|
prose_package pp = prose.getPackage(body, rank_str);
|
|
for (int i = 0; i < winners.length; i++)
|
|
utils.sendMail(sub, pp, winners[i], "Enclave Records");
|
|
}
|
|
else
|
|
{
|
|
setObjVar(enclave, obj_var_base + ".status", 1);
|
|
setObjVar(enclave, obj_var_base + ".time", getGameTime() + getPetitionInterval());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief examines challenge voting data and determines results.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return true
|
|
*********************************************************************/
|
|
boolean checkChallengeVotingResults(obj_id enclave)
|
|
{
|
|
LOG("force_rank", "force_rank.checkChallengeVotingResults");
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.checkChallengeVotingResults -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
obj_id terminal = getChallengeVotingTerminal(enclave);
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.checkChallengeVotingResults -- terminal is invalid.");
|
|
return false;
|
|
}
|
|
obj_var_list vote_list = getObjVarList(terminal, VAR_CHAL_VOTING_BASE);
|
|
if (vote_list == null)
|
|
{
|
|
// There are currently no active challenges.
|
|
return true;
|
|
}
|
|
|
|
for (int i = 0; i < vote_list.getNumItems(); i++)
|
|
{
|
|
// Get the list of challenges.
|
|
obj_var challenge_objvar = vote_list.getObjVar(i);
|
|
if (challenge_objvar == null)
|
|
continue;
|
|
|
|
// The name of the objvar is the challenged player's name.
|
|
string name = challenge_objvar.getName();
|
|
if (name == null)
|
|
continue;
|
|
|
|
string objvar_name = VAR_CHAL_VOTING_BASE + "." + name;
|
|
|
|
// Get all of the data.
|
|
int rank = getForceRank(enclave, name);
|
|
int challenge_rank = getChallengeVoteRank(terminal, name);
|
|
|
|
int status = getChallengeVoteStatus(terminal, name);
|
|
if (status == -1 || status == 3)
|
|
{
|
|
// This challenge is no longer valid. Remove it.
|
|
if (hasObjVar(terminal, objvar_name))
|
|
removeObjVar(terminal, objvar_name);
|
|
if (hasObjVar(terminal, BATCH_VAR_VOTERS + "." + name))
|
|
removeObjVar(terminal, BATCH_VAR_VOTERS + "." + name);
|
|
|
|
continue;
|
|
}
|
|
int time = getChallengeVoteEndTime(terminal, name);
|
|
boolean time_expired = time < getGameTime();
|
|
switch (status)
|
|
{
|
|
case 1:
|
|
{
|
|
// Voting Open
|
|
if (challenge_rank != rank)
|
|
{
|
|
// The player is no longer at the rank where the challenge was issued. Cancel it.
|
|
removeObjVar(terminal, objvar_name);
|
|
if (hasObjVar(terminal, BATCH_VAR_VOTERS + "." + name))
|
|
removeObjVar(terminal, BATCH_VAR_VOTERS + "." + name);
|
|
|
|
// Tell all of the voters about it.
|
|
string_id sub = new string_id(force_rank.STF_FILE, "challenge_vote_cancelled_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "challenge_vote_cancelled_body");
|
|
prose_package pp = prose.getPackage(body, name);
|
|
sendChallengeVoterMail(enclave, challenge_rank, sub, pp);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (time_expired)
|
|
{
|
|
int[] votes = getChallengeVotes(terminal, name);
|
|
boolean success = false;
|
|
if (votes != null)
|
|
{
|
|
// Requires at least 2/3 vote for challenge to succeed.
|
|
if (votes[0] >= votes[1] * 2)
|
|
success = true;
|
|
}
|
|
|
|
if (success)
|
|
{
|
|
// demote the player challenged.
|
|
demoteForceRank(enclave, name, challenge_rank - 1);
|
|
|
|
// Tell the voting ranks about it.
|
|
string_id sub = new string_id(force_rank.STF_FILE, "challenge_vote_success_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "challenge_vote_success_body");
|
|
prose_package pp = prose.getPackage(body, name, Integer.toString(votes[0]), votes[1]);
|
|
sendChallengeVoterMail(enclave, challenge_rank, sub, pp);
|
|
}
|
|
else
|
|
{
|
|
// The challenge failed. Tell the voting ranks about it.
|
|
string_id sub = new string_id(force_rank.STF_FILE, "challenge_vote_fail_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "challenge_vote_fail_body");
|
|
prose_package pp = prose.getPackage(body, name, Integer.toString(votes[0]), votes[1]);
|
|
sendChallengeVoterMail(enclave, challenge_rank, sub, pp);
|
|
}
|
|
|
|
setObjVar(terminal, objvar_name + ".status", 2);
|
|
setObjVar(terminal, objvar_name + ".time", getGameTime() + 3600);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
// Voting Closed
|
|
if (time_expired)
|
|
{
|
|
if (hasObjVar(terminal, objvar_name))
|
|
removeObjVar(terminal, objvar_name);
|
|
if (hasObjVar(terminal, BATCH_VAR_VOTERS + "." + name))
|
|
removeObjVar(terminal, BATCH_VAR_VOTERS + "." + name);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief determines who missed a vote and imposes experience
|
|
* debt for doing so.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return true
|
|
*********************************************************************/
|
|
boolean checkMissedVotes(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.checkMissedVotes -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.checkMissedVotes -- illegal rank value of " + rank);
|
|
return false;
|
|
}
|
|
|
|
obj_id terminal = getVotingTerminal(enclave);
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.checkMissedVotes -- can't find the voting terminal for enclave " + enclave);
|
|
return false;
|
|
}
|
|
resizeable string[] voters = utils.getResizeableStringBatchObjVar(terminal, BATCH_VAR_VOTERS + rank);
|
|
for (int vote_rank = 1; vote_rank < 12; vote_rank++)
|
|
{
|
|
// If the vote weight for a given rank is > 0, then that rank was eligible to vote.
|
|
if (getVoteWeight(vote_rank, rank) > 0)
|
|
{
|
|
string[] rank_list = getPlayersInForceRank(enclave, vote_rank);
|
|
if (rank_list != null)
|
|
{
|
|
int xp_debt = (int)(MISSED_VOTE_PENALTY * Math.pow(vote_rank, 2));
|
|
for (int i = 0; i < rank_list.length; i++)
|
|
{
|
|
if (voters != null)
|
|
{
|
|
// Players not in the voters list are hit with an experience penalty.
|
|
if (voters.indexOf(rank_list[i]) != -1)
|
|
continue;
|
|
}
|
|
|
|
CustomerServiceLog("force_rank", "Adding experience debt of " + xp_debt + " to " + rank_list[i] + " for missing a vote on rank " + vote_rank);
|
|
addExperienceDebt(enclave, rank_list[i], xp_debt);
|
|
|
|
// Give the player a message about it.
|
|
string_id sub = new string_id(force_rank.STF_FILE, "vote_missed_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "vote_missed_body");
|
|
string rank_str = localize(new string_id(force_rank.STF_FILE, "rank" + rank));
|
|
prose_package pp = prose.getPackage(body, rank_str, xp_debt);
|
|
utils.sendMail(sub, pp, rank_list[i], "Enclave Records");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the status of a given rank
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
int getVoteStatus(obj_id enclave, int rank)
|
|
{
|
|
// Status Key
|
|
// 1: Petitioning Open
|
|
// 2: Voting Open
|
|
// 3: Waiting Acceptance
|
|
// 4: Voting Closed
|
|
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getRankVoteStatus -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankVoteStatus -- illegal rank value of " + rank);
|
|
return -1;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".status";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getIntObjVar(enclave, obj_var_name);
|
|
else
|
|
return 4;
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the end time of the current voting status for a
|
|
* given rank
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return int -1 on error or no end time set.
|
|
*********************************************************************/
|
|
int getVoteEndTime(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getVoteEndTime -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getVoteEndTime -- illegal rank value of " + rank);
|
|
return -1;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".time";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getIntObjVar(enclave, obj_var_name);
|
|
else
|
|
return 0;
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns whether or not the vote time for a given
|
|
* rank has expired
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return boolean false on error
|
|
*********************************************************************/
|
|
boolean isVoteTimeExpired(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.hasVoteTimeExpired -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.hasVoteTimeExpired -- illegal rank value of " + rank);
|
|
return false;
|
|
}
|
|
|
|
int time = getVoteEndTime(enclave, rank);
|
|
if (time < getGameTime())
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the challenge vote status of a given player
|
|
*
|
|
* @param obj_id terminal
|
|
* @param string challenged Player being challenged
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
int getChallengeVoteStatus(obj_id terminal, string challenged)
|
|
{
|
|
// Status key
|
|
// 1 Voting Open
|
|
// 2 Voting Closed
|
|
// 3 Inactive
|
|
|
|
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVoteStatus -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (challenged == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVoteStatus -- challenged is null.");
|
|
return -1;
|
|
}
|
|
|
|
string obj_var_name = VAR_CHAL_VOTING_BASE + "." + challenged + ".status";
|
|
if (hasObjVar(terminal, obj_var_name))
|
|
return getIntObjVar(terminal, obj_var_name);
|
|
else
|
|
return 3;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the voting end time for a given challenge
|
|
*
|
|
* @param obj_id terminal
|
|
* @param string challenged
|
|
*
|
|
* @return return int -1 on error or no end time set.
|
|
*********************************************************************/
|
|
int getChallengeVoteEndTime(obj_id terminal, string challenged)
|
|
{
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.getVoteEndTime -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (challenged == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVoteEndTime -- challenged is null.");
|
|
return -1;
|
|
}
|
|
|
|
string obj_var_name = VAR_CHAL_VOTING_BASE + "." + challenged + ".time";
|
|
if (hasObjVar(terminal, obj_var_name))
|
|
return getIntObjVar(terminal, obj_var_name);
|
|
else
|
|
return 0;
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns whether or not the vote time for a given
|
|
* challenge has expired
|
|
*
|
|
* @param obj_id terminal
|
|
* @param string challenged
|
|
*
|
|
* @return return boolean false on error
|
|
*********************************************************************/
|
|
boolean isChallengeVoteTimeExpired(obj_id terminal, string challenged)
|
|
{
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.isChallengeVoteTimeExpired -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (challenged == null)
|
|
{
|
|
LOG("force_rank", "force_rank.isChallengeVoteTimeExpired -- challenged is null.");
|
|
return false;
|
|
}
|
|
|
|
int time = getChallengeVoteEndTime(terminal, challenged);
|
|
if (time < getGameTime())
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the rank for which this challenge was issued.
|
|
*
|
|
* @param obj_id terminal
|
|
* @param string challenged
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
int getChallengeVoteRank(obj_id terminal, string challenged)
|
|
{
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVoteRank -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (challenged == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVoteRank -- challenged is null.");
|
|
return -1;
|
|
}
|
|
|
|
string obj_var_name = VAR_CHAL_VOTING_BASE + "." + challenged + ".rank";
|
|
if (hasObjVar(terminal, obj_var_name))
|
|
return getIntObjVar(terminal, obj_var_name);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the votes for a given petitioner
|
|
*
|
|
* @param obj_id terminal
|
|
* @param string challenged
|
|
*
|
|
* @return return int[] Number of yes/no votes
|
|
*********************************************************************/
|
|
int[] getChallengeVotes(obj_id terminal, string challenged)
|
|
{
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVotes -- terminal is invalid.");
|
|
return null;
|
|
}
|
|
|
|
string obj_var_name = VAR_CHAL_VOTING_BASE + "." + challenged + ".votes";
|
|
if (hasObjVar(terminal, obj_var_name))
|
|
{
|
|
int[] votes = getIntArrayObjVar(terminal, obj_var_name);
|
|
if (votes.length != 2)
|
|
return null;
|
|
else
|
|
return votes;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Returns a list of players being challenged.
|
|
*
|
|
* @param obj_id terminal
|
|
*
|
|
* @return return string[] List of players being challenged
|
|
* Null on error or no challenges.
|
|
*********************************************************************/
|
|
string[] getChallengeVoteList(obj_id terminal)
|
|
{
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVoteList -- terminal is invalid.");
|
|
return null;
|
|
}
|
|
|
|
resizeable string[] names = new string[0];
|
|
obj_var_list vote_list = getObjVarList(terminal, VAR_CHAL_VOTING_BASE);
|
|
if (vote_list == null)
|
|
{
|
|
// There are currently no active challenges.
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < vote_list.getNumItems(); i++)
|
|
{
|
|
obj_var challenge_objvar = vote_list.getObjVar(i);
|
|
if (challenge_objvar != null)
|
|
{
|
|
string name = challenge_objvar.getName();
|
|
if (name != null)
|
|
names.add(name);
|
|
}
|
|
}
|
|
|
|
if (names.length > 0)
|
|
return names;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Returns the number of active challenges
|
|
*
|
|
* @param obj_id terminal
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
int getNumChallengeVoteList(obj_id terminal)
|
|
{
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.getNumChallengeVoteList -- terminal is invalid.");
|
|
return -1;
|
|
}
|
|
|
|
obj_var_list vote_list = getObjVarList(terminal, VAR_CHAL_VOTING_BASE);
|
|
if (vote_list != null)
|
|
return vote_list.getNumItems();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the petitioners of a given rank
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return string[]
|
|
*********************************************************************/
|
|
string[] getRankPetitioners(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitioners -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitioners -- illegal rank value of " + rank);
|
|
return null;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".petition";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getStringArrayObjVar(enclave, obj_var_name);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the petitioners of a given rank
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return string[]
|
|
*********************************************************************/
|
|
resizeable string[] getRankPetitionersResizeable(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitionersResizeable -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitionersResizeable -- illegal rank value of " + rank);
|
|
return null;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".petition";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getResizeableStringArrayObjVar(enclave, obj_var_name);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the votes for a given petitioner
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return int[]
|
|
*********************************************************************/
|
|
int[] getRankPetitionerVotes(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitioners -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitioners -- illegal rank value of " + rank);
|
|
return null;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".votes";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getIntArrayObjVar(enclave, obj_var_name);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the votes for a given petitioner
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return resizeable int[]
|
|
*********************************************************************/
|
|
resizeable int[] getRankPetitionerVotesResizeable(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitionerVotesResizeable -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankPetitionerVotesResizeable -- illegal rank value of " + rank);
|
|
return null;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".votes";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getResizeableIntArrayObjVar(enclave, obj_var_name);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* @brief returns the specified number of top votes
|
|
*
|
|
* @param resizeable int[]
|
|
* @param int winners
|
|
*
|
|
* @return return int[]
|
|
*********************************************************************/
|
|
int[] getTopVotes(int[] votes, int winners)
|
|
{
|
|
if (votes == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getTopVotes -- votes is null.");
|
|
return null;
|
|
}
|
|
if (winners < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.getTopVotes -- illegal winners value of " + winners);
|
|
return null;
|
|
}
|
|
|
|
if (winners > votes.length)
|
|
return votes;
|
|
|
|
int[] top_votes = new int[winners];
|
|
Arrays.sort(votes);
|
|
for (int i = 0; i < top_votes.length; i++)
|
|
top_votes[i] = votes[votes.length - (i + 1)];
|
|
|
|
return top_votes;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the players who have won a vote but are
|
|
* waiting an open slot
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return string null on error or no winner
|
|
*********************************************************************/
|
|
string[] getVoteWinners(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getVoteWinner -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getVoteWinner -- illegal rank value of " + rank);
|
|
return null;
|
|
}
|
|
|
|
string obj_var_name = VAR_VOTING_BASE + rank + ".winner";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getStringArrayObjVar(enclave, obj_var_name);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the voting terminal
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return obj_id null on error or no terminal
|
|
*********************************************************************/
|
|
obj_id getVotingTerminal(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getVotingTerminal -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
|
|
if (utils.hasScriptVar(enclave, SCRIPT_VAR_VOTE_TERMINAL))
|
|
{
|
|
obj_id terminal = utils.getObjIdScriptVar(enclave, SCRIPT_VAR_VOTE_TERMINAL);
|
|
if (terminal.isAuthoritative())
|
|
return terminal;
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* @brief returns the arena terminal
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return obj_id null on error or no terminal
|
|
*********************************************************************/
|
|
obj_id getArenaTerminal(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getArenaTerminal -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
|
|
if (utils.hasScriptVar(enclave, arena.VAR_CHALLENGE_TERMINAL))
|
|
{
|
|
obj_id terminal = utils.getObjIdScriptVar(enclave, arena.VAR_CHALLENGE_TERMINAL);
|
|
if (terminal.isAuthoritative())
|
|
return terminal;
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the challenge voting terminal
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return obj_id null on error or no terminal
|
|
*********************************************************************/
|
|
obj_id getChallengeVotingTerminal(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getChallengeVotingTerminal -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
|
|
if (utils.hasScriptVar(enclave, SCRIPT_VAR_CHAL_VOTE_TERMINAL))
|
|
{
|
|
obj_id terminal = utils.getObjIdScriptVar(enclave, SCRIPT_VAR_CHAL_VOTE_TERMINAL);
|
|
if (terminal.isAuthoritative())
|
|
return terminal;
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief clears the voting terminal data for the specified
|
|
* rank.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean resetVotingTerminal(obj_id enclave, int rank)
|
|
{
|
|
LOG("force_rank", "force_rank.resetVotingTerminal -- " + VAR_VOTING_BASE + rank);
|
|
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.resetVotingTerminal -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.resetVotingTerminal -- illegal rank value of " + rank);
|
|
return false;
|
|
}
|
|
|
|
obj_id terminal = getVotingTerminal(enclave);
|
|
if (!isIdValid(terminal))
|
|
{
|
|
LOG("force_rank", "force_rank.resetVotingTerminal -- can't find a voting terminal for " + enclave);
|
|
return false;
|
|
}
|
|
|
|
removeObjVar(terminal, BATCH_VAR_VOTERS + rank);
|
|
removeObjVar(enclave, VAR_VOTING_BASE + rank);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Imparts the daily experience cost for being a rank
|
|
* member.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean deductXpMaintenance(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.deductXpMaintenance -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
// Each rank member must pay experience at a set interval.
|
|
int base_xp_cost = BASE_XP_MAINTENANCE;
|
|
for (int rank = 1; rank < 12; rank++)
|
|
{
|
|
string[] rank_list = getPlayersInForceRank(enclave, rank);
|
|
if (rank_list != null)
|
|
{
|
|
//int xp_cost = base_xp_cost * (int) Math.pow(rank, 1.5);
|
|
int xp_cost = base_xp_cost * rank;
|
|
for (int i = 0; i < rank_list.length; i++)
|
|
{
|
|
addExperienceDebt(enclave, rank_list[i], xp_cost);
|
|
CustomerServiceLog("force_rank", "Adding experience debt of " + xp_cost + " to " + rank_list[i] + " for regular experience maintenance.");
|
|
|
|
string_id sub = new string_id(force_rank.STF_FILE, "xp_maintenace_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "xp_maintenance_body");
|
|
prose_package pp = prose.getPackage(body, xp_cost);
|
|
utils.sendMail(sub, pp, rank_list[i], "Enclave Records");
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief looks over experience debt and demotes players that
|
|
* have attained too much of it.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean checkExperienceDebt(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.checkExperienceDebt -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
string[] rank_list = getPlayersInForceRank(enclave, i);
|
|
if (rank_list != null)
|
|
{
|
|
int xp_to_demote = 5000 * i;
|
|
for (int j = 0; j < rank_list.length; j++)
|
|
{
|
|
string obj_var_name = VAR_MEMBER_DATA + rank_list[j] + ".xp_debt";
|
|
//LOG("force_rank", "obj_var_name ->" + obj_var_name);
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
{
|
|
int xp_debt = getIntObjVar(enclave, obj_var_name);
|
|
//LOG("force_rank", "... xp_debt->" + xp_debt + " xp_to_demote ->" + xp_to_demote);
|
|
if (xp_debt > xp_to_demote)
|
|
{
|
|
// The player has accumulated too much debt. Demote him.
|
|
if (!demoteForceRank(enclave, rank_list[j], i - 1))
|
|
{
|
|
LOG("force_rank", "force_rank.checkExperienceDebt -- failed to demote " + rank_list[j] + " due to too much xp debt.");
|
|
CustomerServiceLog("force_rank", "Failed to demote " + rank_list[j] + " for too much xp debt");
|
|
}
|
|
else
|
|
{
|
|
CustomerServiceLog("force_rank", "Demoting " + rank_list[j] + " for too much xp debt");
|
|
// send the player an e-mail.
|
|
string_id sub = new string_id(force_rank.STF_FILE, "demote_xp_debt_sub");
|
|
string_id body = new string_id(force_rank.STF_FILE, "demote_xp_debt_body");
|
|
utils.sendMail(sub, body, rank_list[j], "Enclave Records");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief checks the player's experience debt against the enclave
|
|
* and deducts xp if necessary.
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean requestExperienceDebt(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.requestExperienceDebt -- player is invalid.");
|
|
return false;
|
|
}
|
|
|
|
obj_id enclave = getEnclave(player);
|
|
if (isIdValid(enclave))
|
|
{
|
|
dictionary d = new dictionary();
|
|
d.put("player", player);
|
|
d.put("player_name", getFirstName(player));
|
|
messageTo(enclave, "msgRequestExperienceDebt", d, 3.0f, false);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief gets a player's experience debt
|
|
*
|
|
* @param obj_id enclave
|
|
* @param string player_name
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
int getExperienceDebt(obj_id enclave, string player_name)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getExperienceDebt -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (player_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getExperienceDebt -- player_name is null.");
|
|
return -1;
|
|
}
|
|
|
|
string obj_var_name = VAR_MEMBER_DATA + player_name + ".xp_debt";
|
|
if (hasObjVar(enclave, obj_var_name))
|
|
return getIntObjVar(enclave, obj_var_name);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief validates the player's data against the enclave
|
|
* data.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param string player_name
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
boolean validateFRSPlayerData(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.validateFRSPlayerData -- player is invalid.");
|
|
return false;
|
|
}
|
|
|
|
// Don't validate until the rename is handled.
|
|
if (hasObjVar(player, "renamePerformed"))
|
|
return false;
|
|
|
|
int council = getCouncilAffiliation(player);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.validateFRSPlayerData -- " + player + " does not have council value.");
|
|
return false;
|
|
}
|
|
obj_id enclave = getEnclave(player);
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.validateFRSPlayerData -- " + player + " does not have an enclave. Resetting it.");
|
|
getEnclaveObjId(player, getCouncilAffiliation(player), "enclaveIdResponse");
|
|
|
|
return false;
|
|
}
|
|
|
|
LOG("force_rank", "force_rank.validateFRSPlayerData -- player name " + getFirstName(player));
|
|
|
|
// Get the enclave's data on the player
|
|
dictionary d = new dictionary();
|
|
d.put("player", player);
|
|
d.put("player_name", getFirstName(player));
|
|
d.put("player_rank", getForceRank(player));
|
|
messageTo(enclave, "msgValidateFRSPlayerData", d, 10.0f, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief gets the rank of the specified player.
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return return int -1 if error or the player is not ranked
|
|
*********************************************************************/
|
|
int getForceRank(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRank -- player is invalid.");
|
|
return -1;
|
|
}
|
|
|
|
if (hasObjVar(player, VAR_RANK))
|
|
return getIntObjVar(player, VAR_RANK);
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief gets the rank of the specified player, using the enclave
|
|
*
|
|
* @param obj_id enclave
|
|
* @param string player_name
|
|
*
|
|
* @return return int -1 if error or the player is not ranked
|
|
*********************************************************************/
|
|
int getForceRank(obj_id enclave, string player_name)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRank -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (player_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRank -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
resizeable string[] rank_list = getPlayersInForceRankResizeable(enclave, i);
|
|
if (rank_list != null)
|
|
{
|
|
int idx = rank_list.indexOf(player_name);
|
|
if (idx != -1)
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the tier of a specified rank
|
|
*
|
|
* @param int rank
|
|
*
|
|
* @return return int -1 on error
|
|
*********************************************************************/
|
|
int getForceTier(int rank)
|
|
{
|
|
if (rank < 0 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceTier -- illegal rank value: " + rank);
|
|
return -1;
|
|
}
|
|
|
|
if (rank == 0)
|
|
return 0;
|
|
|
|
if (rank > 0 && rank < 5)
|
|
return 1;
|
|
|
|
if (rank > 4 && rank < 8)
|
|
return 2;
|
|
|
|
if (rank > 7 && rank <10)
|
|
return 3;
|
|
|
|
if (rank == 10)
|
|
return 4;
|
|
|
|
if (rank == 11)
|
|
return 5;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief gets the enclave to which the specified player is associated
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return return obj_id null on error or player not in FRS
|
|
*********************************************************************/
|
|
obj_id getEnclave(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.getEnclave -- player is invalid.");
|
|
return null;
|
|
}
|
|
if (hasObjVar(player, VAR_MY_ENCLAVE_ID))
|
|
return getObjIdObjVar(player, VAR_MY_ENCLAVE_ID);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief gets the council affiliation of the specified player or enclave
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return return int -1 if error or not ranked
|
|
*********************************************************************/
|
|
int getCouncilAffiliation(obj_id object)
|
|
{
|
|
if (!isIdValid(object))
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRanking -- object is invalid.");
|
|
return -1;
|
|
}
|
|
|
|
if (hasObjVar(object, VAR_COUNCIL))
|
|
{
|
|
int council = getIntObjVar(object, VAR_COUNCIL);
|
|
if (council != DARK_COUNCIL && council != LIGHT_COUNCIL)
|
|
return -1;
|
|
else
|
|
return council;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the name of a given council
|
|
*
|
|
* @param int council
|
|
*
|
|
* @return return string null if error or no council name
|
|
*********************************************************************/
|
|
string getCouncilName(int council)
|
|
{
|
|
if (COUNCIL_NAMES.length < council)
|
|
return null;
|
|
|
|
string name = COUNCIL_NAMES[council];
|
|
if (name != null && name.length() > 0)
|
|
return name;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Returns the available number of slots for a given rank
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return int -1 if error
|
|
*********************************************************************/
|
|
int getAvailableRankSlots(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getAvailableRankSlots -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
|
|
int max_slots = getForceRankNumSlots(rank);
|
|
if (max_slots > 0)
|
|
{
|
|
// Get the available slots using the cluster-wide data stuff.
|
|
int slots_taken = 0;
|
|
string[] rank_list = getPlayersInForceRank(enclave, rank);
|
|
if (rank_list != null)
|
|
slots_taken = rank_list.length;
|
|
|
|
return max_slots - slots_taken;
|
|
}
|
|
else
|
|
{
|
|
LOG("force_rank", "force_rank.getAvailableRankSlots -- invalid rank value of " + rank);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns a faction id from the string
|
|
*
|
|
* @param string player
|
|
*
|
|
* @return return int
|
|
*********************************************************************/
|
|
int getFactionId(string faction)
|
|
{
|
|
if (faction == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getFactionId -- faction is null.");
|
|
return 0;
|
|
}
|
|
int faction_num = factions.getFactionNumber(faction);
|
|
if (faction_num == -1)
|
|
return 0;
|
|
|
|
int faction_id = dataTableGetInt("datatables/faction/faction.iff", faction_num, "pvpFaction");
|
|
|
|
return faction_id;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the skill associated with a given rank
|
|
*
|
|
* @param int rank
|
|
* @param int council
|
|
*
|
|
* @return return string, null if error or rank not found
|
|
*********************************************************************/
|
|
string getForceRankSkill(int rank, int council)
|
|
{
|
|
if (council != LIGHT_COUNCIL && council != DARK_COUNCIL)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRankSkill -- invalid council value of " + council);
|
|
return null;
|
|
}
|
|
string datatable;
|
|
if (council == LIGHT_COUNCIL)
|
|
datatable = FRS_DATATABLE;
|
|
else
|
|
datatable = FRS_DARK_DATATABLE;
|
|
|
|
int index = dataTableSearchColumnForInt(rank, "rank", datatable);
|
|
if (index == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRankSkill -- faction invalid rank value of " + rank);
|
|
return null;
|
|
}
|
|
|
|
string skill = dataTableGetString(datatable, index, "skill");
|
|
//LOG("force_rank", "force_rank.getForceRankSkill --- datatable ->" + datatable + " skill ->" + skill + " council ->" + council);
|
|
|
|
|
|
if (skill.length() < 1)
|
|
return null;
|
|
else
|
|
return skill;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the rank of a given skill
|
|
*
|
|
* @param string skill
|
|
* @param int council
|
|
*
|
|
* @return return int; -1 on error or skill not in FRS
|
|
*********************************************************************/
|
|
int getForceSkillRank(string skill, int council)
|
|
{
|
|
if (skill == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceSkillRank -- skill is null.");
|
|
return -1;
|
|
}
|
|
if (council != LIGHT_COUNCIL && council != DARK_COUNCIL)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceSkillRank -- invalid council value of " + council);
|
|
return -1;
|
|
}
|
|
string datatable;
|
|
if (council == LIGHT_COUNCIL)
|
|
datatable = FRS_DATATABLE;
|
|
else
|
|
datatable = FRS_DARK_DATATABLE;
|
|
|
|
int index = dataTableSearchColumnForString(skill, "skill", datatable);
|
|
|
|
return index;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the number of allowed players at a given rank
|
|
*
|
|
* @param int rank
|
|
*
|
|
* @return return int, -1 if error or rank not found
|
|
*********************************************************************/
|
|
int getForceRankNumSlots(int rank)
|
|
{
|
|
int index = dataTableSearchColumnForInt(rank, "rank", FRS_DATATABLE);
|
|
if (index == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRankNumSlots -- faction invalid rank value of " + rank);
|
|
return -1;
|
|
}
|
|
|
|
int num_slots = dataTableGetInt(FRS_DATATABLE, index, "num_slots");
|
|
|
|
return num_slots;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the minimum experience needed to maintain a rank
|
|
*
|
|
* @param int rank
|
|
*
|
|
* @return return int, -1 if error or rank not found
|
|
*********************************************************************/
|
|
int getForceRankMinXp(int rank)
|
|
{
|
|
int index = dataTableSearchColumnForInt(rank, "rank", FRS_DATATABLE);
|
|
if (index == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.getForceRankMinXp -- faction invalid rank value of " + rank);
|
|
return -1;
|
|
}
|
|
|
|
int min_xp = dataTableGetInt(FRS_DATATABLE, index, "min_xp");
|
|
|
|
return min_xp;
|
|
}
|
|
|
|
//
|
|
// @returns the number of votes that @player has registered on the @enclave
|
|
//
|
|
int getVotesForPlayer(obj_id player, obj_id enclave)
|
|
{
|
|
int playerRank = getForceRank(enclave, utils.getRealPlayerFirstName(player));
|
|
if(playerRank < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
string[] petitioners = getRankPetitioners(enclave, playerRank+1);
|
|
int[] votes = getRankPetitionerVotes(enclave, playerRank+1);
|
|
|
|
if(votes.length != petitioners.length)
|
|
{
|
|
LOG("force_rank", "force_rank::getVotesForPlayer: -> Votes.length != petitioners.length. Returning zero votes for player " + utils.getRealPlayerFirstName(player));
|
|
return 0;
|
|
}
|
|
|
|
string playerName = utils.getRealPlayerFirstName(player);
|
|
int idx = utils.getElementPositionInArray(petitioners, playerName);
|
|
if(idx < 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return votes[idx];
|
|
}
|
|
|
|
//
|
|
// sets the votes for @player at @numVotes on the @enclave
|
|
//
|
|
void setVotesForPlayer(obj_id player, int numVotes, obj_id enclave)
|
|
{
|
|
if(!isIdValid(player) || player == null)
|
|
{
|
|
trace.log("force_rank", "force_rank::getVotesForPlayer: -> Can't set votes for null player.", player, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
int playerRank = getForceRank(enclave, utils.getRealPlayerFirstName(player));
|
|
if(playerRank < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
resizeable string[] petitioners = getRankPetitionersResizeable(enclave, playerRank+1);
|
|
resizeable int[] votes = getRankPetitionerVotesResizeable(enclave, playerRank+1);
|
|
|
|
if(votes.length != petitioners.length)
|
|
{
|
|
trace.log("force_rank", "force_rank::getVotesForPlayer: -> Votes.length != petitioners.length. Returning zero votes for player " + utils.getRealPlayerFirstName(player), player, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
string playerName = utils.getRealPlayerFirstName(player);
|
|
int idx = utils.getElementPositionInArray(petitioners, playerName);
|
|
if(idx > -1)
|
|
{
|
|
if(numVotes < 1)
|
|
{
|
|
utils.removeElementAt(petitioners, idx);
|
|
utils.removeElementAt(votes, idx);
|
|
}
|
|
else
|
|
{
|
|
votes[idx] = numVotes;
|
|
}
|
|
}
|
|
else if(numVotes > 0) // player has no votes set currently... need to set votes.
|
|
{
|
|
utils.addElement(petitioners, playerName);
|
|
utils.addElement(votes, numVotes);
|
|
}
|
|
|
|
setObjVar(enclave, VAR_VOTING_BASE + (playerRank+1) + ".petition", petitioners);
|
|
setObjVar(enclave, VAR_VOTING_BASE + (playerRank+1) + ".votes", votes);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// @ returns all names for everyone listed on the @enclave
|
|
//
|
|
Vector getAllPlayerNamesInForceRank(obj_id enclave)
|
|
{
|
|
Vector allNames = new Vector();
|
|
for(int h = 1; h < 12; h++)
|
|
{
|
|
string[] players = getPlayersInForceRank(enclave, h);
|
|
if(players == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
allNames = utils.concatArrays(allNames, players);
|
|
}
|
|
|
|
return allNames;
|
|
}
|
|
|
|
//
|
|
// gets all players in the force rank @rank by obj_id. if the rank is given as -1, all members will be returned
|
|
//
|
|
obj_id[] getAllPlayersInForceRank(obj_id enclave, int rank)
|
|
{
|
|
resizeable obj_id[] playerIds = new obj_id[0];
|
|
obj_id player = null;
|
|
|
|
if(rank >= 0)
|
|
{
|
|
string[] players = getPlayersInForceRank(enclave, rank);
|
|
if(players == null)
|
|
{
|
|
return playerIds;
|
|
}
|
|
|
|
for(int i = 0; i < players.length; i++)
|
|
{
|
|
player = getPlayerIdFromFirstName(players[i]);
|
|
if(player != null && isIdValid(player))
|
|
{
|
|
utils.addElement(playerIds, player);
|
|
}
|
|
}
|
|
}
|
|
|
|
// -1 gets all players in the ranks
|
|
else
|
|
{
|
|
for(int h = 1; h < 12; h++)
|
|
{
|
|
string[] players = getPlayersInForceRank(enclave, h);
|
|
if(players == null)
|
|
{
|
|
continue;
|
|
}
|
|
for(int s = 0; s < players.length; s++)
|
|
{
|
|
player = getPlayerIdFromFirstName(players[s]);
|
|
if(player != null && isIdValid(player))
|
|
{
|
|
utils.addElement(playerIds, player);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return playerIds;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the vote weight for a given rank voting for
|
|
* promotion into the specified rank.
|
|
*
|
|
* @param int voter_rank
|
|
* @param int promotion_rank
|
|
*
|
|
* @return return int -1 if the rank is not eligible.
|
|
*********************************************************************/
|
|
int getVoteWeight(int voter_rank, int promotion_rank)
|
|
{
|
|
if (voter_rank < 1)
|
|
return -1;
|
|
|
|
if (promotion_rank < 1 || promotion_rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.isRankVoteEligible -- invalid promotion_rank value of " + promotion_rank);
|
|
return -1;
|
|
}
|
|
|
|
// If of the same rank, votes count double.
|
|
if (voter_rank == promotion_rank)
|
|
return 2;
|
|
|
|
// All first tiers can vote for first tier promotions.
|
|
if (promotion_rank > 0 && promotion_rank < 5)
|
|
{
|
|
if (voter_rank > 0 && voter_rank < 5)
|
|
return 1;
|
|
}
|
|
// All second tiers can vote for second tier promotions.
|
|
if (promotion_rank > 4 && promotion_rank < 8)
|
|
{
|
|
if (voter_rank > 4 && voter_rank < 8)
|
|
return 1;
|
|
}
|
|
// All third tiers can vote for third tier promotions.
|
|
if (promotion_rank == 8 || promotion_rank == 9)
|
|
{
|
|
if (voter_rank == 8 || voter_rank == 9)
|
|
return 1;
|
|
}
|
|
// Council members vote for council promotions
|
|
if (promotion_rank == 10)
|
|
{
|
|
if (voter_rank == 11)
|
|
return 1;
|
|
}
|
|
// Council members vote for council leader.
|
|
if (promotion_rank == 11)
|
|
{
|
|
if (voter_rank == 10)
|
|
return 1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the vote weight for a given rank voting for
|
|
* no-confidence against the specified rank.
|
|
*
|
|
* @param int voter_rank
|
|
* @param int challenge_rank
|
|
*
|
|
* @return return int -1 if the rank is not eligible.
|
|
*********************************************************************/
|
|
int getChallengeVoteWeight(int voter_rank, int challenge_rank)
|
|
{
|
|
if (voter_rank < 1)
|
|
return -1;
|
|
|
|
if (challenge_rank < 1 || challenge_rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.isRankVoteEligible -- invalid challenge_rank value of " + challenge_rank);
|
|
return -1;
|
|
}
|
|
|
|
// Ranks of equal or less that the challenged tier may vote.
|
|
int voter_tier = getForceTier(voter_rank);
|
|
int challenge_tier = getForceTier(challenge_rank);
|
|
|
|
if (voter_tier <= challenge_tier)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the list of players in a given rank for a given
|
|
* enclave. Removes the empty slots.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return string[] list of player first names, null on error
|
|
* or no members
|
|
*********************************************************************/
|
|
string[] getPlayersInForceRank(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
|
|
string objvar_name = VAR_RANK_BASE + rank;
|
|
if (hasObjVar(enclave, objvar_name))
|
|
{
|
|
string[] rank_list = getStringArrayObjVar(enclave, objvar_name);
|
|
// Pull out empty slots
|
|
resizeable string[] final_list = new string[0];
|
|
for (int i = 0; i < rank_list.length; i++)
|
|
{
|
|
if (rank_list[i] != null && rank_list[i].length() > 0 && !rank_list[i].equals(EMPTY_SLOT))
|
|
final_list = utils.addElement(final_list, rank_list[i]);
|
|
}
|
|
|
|
if (final_list.length > 0)
|
|
return final_list;
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the list of players in a given rank for a given
|
|
* enclave. Removes the empty slots.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
*
|
|
* @return return resizeable string[] list of player first names, null on error
|
|
* or no members
|
|
*********************************************************************/
|
|
resizeable string[] getPlayersInForceRankResizeable(obj_id enclave, int rank)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
string objvar_name = VAR_RANK_BASE + rank;
|
|
if (hasObjVar(enclave, objvar_name))
|
|
{
|
|
resizeable string[] rank_list = getResizeableStringArrayObjVar(enclave, objvar_name);
|
|
if (rank_list != null)
|
|
{
|
|
int idx = rank_list.indexOf(EMPTY_SLOT);
|
|
while (idx > -1)
|
|
{
|
|
rank_list.removeElementAt(idx);
|
|
idx = rank_list.indexOf(EMPTY_SLOT);
|
|
}
|
|
}
|
|
|
|
if (rank_list.size() > 0)
|
|
return rank_list;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the list of players in a given rank for a given
|
|
* council. The information is returned via the clusterwide
|
|
* data system. Removes the empty slots
|
|
*
|
|
* @param source The object requesting the data.
|
|
* @param int rank 0 means all ranks
|
|
* @param int council
|
|
* @param string handler messageHandler to return the data.
|
|
*
|
|
* @return return boolean data is returned in the specified handler
|
|
* under the key "rank_list" or "rank_list#"
|
|
* if all requested. "rank_requested" contains
|
|
* the value of rank.
|
|
*********************************************************************/
|
|
boolean getPlayersInForceRank(obj_id source, int rank, int council, string handler)
|
|
{
|
|
if (!isIdValid(source))
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- source is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 0 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- rank value of " + rank + " is invalid.");
|
|
return false;
|
|
}
|
|
if (handler == null || handler.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- handler value of " + handler + " is invalid.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(source, council, 1, Integer.toString(rank), handler, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief validates whether or not a player is eligible to advance
|
|
* to the specified rank.
|
|
*
|
|
* @param obj_id player
|
|
* @param int rank
|
|
*
|
|
* @return return boolean, false on error or no eligible
|
|
*********************************************************************/
|
|
boolean isPlayerEligibleForPromotion(obj_id player, int rank)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.isPlayerEligibleForPromotion -- player is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 0 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.isPlayerEligibleForPromotion -- rank value of " + rank + " is invalid.");
|
|
return false;
|
|
}
|
|
|
|
int experience = getExperiencePoints(player, FRS_XP);
|
|
string skill_name = getForceRankSkill(rank, getCouncilAffiliation(player));
|
|
if (skill_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.isPlayerEligibleForPromotion -- no skill found for rank " + rank);
|
|
return false;
|
|
}
|
|
LOG("force_rank", "force_rank.isPlayerEligibleForPromotion -- " + skill_name);
|
|
if (!skill.hasRequiredSkillsForSkillPurchase(player, skill_name))
|
|
return false;
|
|
else
|
|
return skill.hasRequiredXpForSkillPurchase(player, skill_name);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the obj_id of the specified enclave.
|
|
*
|
|
* @param source The object requesting the data.
|
|
* @param int council
|
|
* @param string handler messageHandler to return the data.
|
|
*
|
|
* @return return boolean data is returned in the specified handler
|
|
* under the key "enclave"
|
|
*********************************************************************/
|
|
boolean getEnclaveObjId(obj_id source, int council, string handler)
|
|
{
|
|
if(!isIdValid(source))
|
|
{
|
|
LOG("force_rank", "force_rank.getEnclaveObjId -- source is invalid.");
|
|
return false;
|
|
}
|
|
if (handler == null || handler.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.getEnclaveObjId -- handler value of " + handler + " is invalid.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(source, council, 6, "None", handler, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns a list of members for a specified rank given the
|
|
* clusterwide dictionary. Removes the empty slots
|
|
*
|
|
* @param dictionary enclave_data clusterwide dictionary
|
|
* @param int rank
|
|
*
|
|
* @return return string[] Returns null on error, empty list on
|
|
* all empty slots.
|
|
*********************************************************************/
|
|
resizeable string[] getRankMembersFromDictionary(dictionary enclave_data, int rank)
|
|
{
|
|
if (enclave_data == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankMembersFromDictionary -- enclave data is null.");
|
|
return null;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.getRankMembersFromDictionary -- rank value of " + rank + " is invalid.");
|
|
return null;
|
|
}
|
|
|
|
string key_name = VAR_RANK_BASE + rank + "-";
|
|
int slots = MAX_RANK_SLOTS;
|
|
|
|
resizeable string[] rank_list = new string[0];
|
|
for (int i = 0; i < slots; i++)
|
|
{
|
|
if (enclave_data.containsKey(key_name + i))
|
|
{
|
|
string name = enclave_data.getString(key_name + i);
|
|
if (name != null && name.length() > 0)
|
|
rank_list = utils.addElement(rank_list, name);
|
|
}
|
|
}
|
|
|
|
return rank_list;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the list of top players in the pvp rankings
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean list of player first names, null on error
|
|
*********************************************************************/
|
|
string[] getPvpBoardNames(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getPvpBoardNames -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
|
|
if (hasObjVar(enclave, BATCH_VAR_PVPBOARD_NAME))
|
|
{
|
|
string[] names = utils.getStringBatchObjVar(enclave, BATCH_VAR_PVPBOARD_NAME);
|
|
if (names == null)
|
|
return null;
|
|
|
|
// Pull out empty slots
|
|
resizeable string[] final_list = new string[0];
|
|
for (int i = 0; i < names.length; i++)
|
|
{
|
|
if (names[i] != null && names[i].length() > 0 && !names[i].equals(EMPTY_SLOT))
|
|
final_list = utils.addElement(final_list, names[i]);
|
|
|
|
}
|
|
if (final_list.length > 0)
|
|
return final_list;
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the list of top players in the pvp rankings
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return string[] list of player first names, null on error
|
|
* or no players
|
|
*********************************************************************/
|
|
int[] getPvpBoardRatings(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getPvpBoardRatings -- enclave is invalid.");
|
|
return null;
|
|
}
|
|
|
|
if (hasObjVar(enclave, BATCH_VAR_PVPBOARD_RATING))
|
|
{
|
|
int[] ratings = utils.getIntBatchObjVar(enclave, BATCH_VAR_PVPBOARD_RATING);
|
|
if (ratings == null)
|
|
return null;
|
|
|
|
// Pull out empty slots
|
|
resizeable int[] final_list = new string[0];
|
|
for (int i = 0; i < ratings.length; i++)
|
|
{
|
|
if (ratings[i] > 0)
|
|
final_list = utils.addElement(final_list, ratings[i]);
|
|
|
|
}
|
|
if (final_list.length > 0)
|
|
return final_list;
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the list of top players in the pvp rankings
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return int -1 on error or no ranking
|
|
*********************************************************************/
|
|
int getPvpRankingForPlayer(obj_id enclave, string player_name)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.getPvpRatingForPlayer -- enclave is invalid.");
|
|
return -1;
|
|
}
|
|
if (player_name == null)
|
|
{
|
|
LOG("force_rank", "force_rank.getPvpRatingForPlayer -- player_name is null.");
|
|
return -1;
|
|
}
|
|
|
|
resizeable string[] pvp_board_names = utils.getResizeableStringBatchObjVar(enclave, BATCH_VAR_PVPBOARD_NAME);
|
|
|
|
return pvp_board_names.indexOf(player_name);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief returns the pvp board data for a given council.
|
|
* The information is returned via the clusterwide data system.
|
|
*
|
|
* @param obj_id source Object requesting the data
|
|
* @param int council
|
|
* @param string handler Handler to which to return the data.
|
|
*
|
|
* @return return boolean data is returned in the specified handler
|
|
* as "board_names" and "board_ratings"
|
|
*********************************************************************/
|
|
boolean getPvpBoardRatings(obj_id source, int council, string handler)
|
|
{
|
|
if (!isIdValid(source))
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- source is invalid.");
|
|
return false;
|
|
}
|
|
if (handler == null || handler.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.getPlayersInForceRank -- handler value of " + handler + " is invalid.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(source, council, 2, Integer.toString(0), handler, false);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief updates the pvp boards with the new data that is specified.
|
|
*
|
|
* @param obj_id player Player to updated
|
|
* @param int rating Player's new rating
|
|
* @param int council
|
|
* @param string handler Handler to which to return success/fail.
|
|
*
|
|
* @return return boolean The player's new pvp rank is returned
|
|
* in the specified handler as "pvp_rank"
|
|
*********************************************************************/
|
|
boolean updatePvpBoardData(obj_id player, int rating, int council, string handler)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.updatePvpBoardData -- player is invalid.");
|
|
return false;
|
|
}
|
|
if (handler == null || handler.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.updatePvpBoardData -- handler value of " + handler + " is invalid.");
|
|
return false;
|
|
}
|
|
|
|
_updateForceRankData(player, council, 7, Integer.toString(rating), handler, true);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Adjusts the pvp board data based on the new player data
|
|
* given.
|
|
*
|
|
* @param obj_id player Player to update
|
|
* @param int rating Player's rating
|
|
* @param dictionary enclave_data from the clusterwide data system.
|
|
*
|
|
* @return return dictionary The clusterwide data with the updated boards
|
|
* null on no change
|
|
*********************************************************************/
|
|
dictionary adjustPvpBoardRankings(obj_id player, int player_rating, dictionary enclave_data)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.adjustPvpBoardRankings -- player is invalid.");
|
|
return null;
|
|
}
|
|
if (enclave_data == null)
|
|
{
|
|
LOG("force_rank", "force_rank.adjustPvpBoardRankings -- enclave_data is null.");
|
|
return null;
|
|
}
|
|
|
|
resizeable string[] board_names = new string[0];
|
|
resizeable int[] board_ratings = new int[0];
|
|
|
|
for (int i = 0; i < PVP_BOARD_SIZE; i++)
|
|
{
|
|
string key_name = BATCH_VAR_PVPBOARD_NAME + i;
|
|
string key_rating = BATCH_VAR_PVPBOARD_RATING + i;
|
|
if (enclave_data.containsKey(key_name) && enclave_data.containsKey(key_rating))
|
|
{
|
|
string name = enclave_data.getString(key_name);
|
|
int rating = enclave_data.getInt(key_rating);
|
|
if (name != null && name.length() > 0 && !name.equals(EMPTY_SLOT) && rating > 0)
|
|
{
|
|
board_names = utils.addElement(board_names, name);
|
|
board_ratings = utils.addElement(board_ratings, rating);
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean empty_slots = board_names.length < PVP_BOARD_SIZE;
|
|
boolean on_board = false;
|
|
int current_board_idx = board_names.indexOf(utils.getRealPlayerFirstName(player));
|
|
if (current_board_idx != -1)
|
|
on_board = true;
|
|
|
|
// The rankings stay sorted with the highest at 0 and lowest as last element
|
|
if (!empty_slots && !on_board)
|
|
{
|
|
// If the player isn't on the board and has a rating less than the last spot, stop right here.
|
|
if (player_rating < board_ratings[board_ratings.length])
|
|
return null;
|
|
}
|
|
|
|
// Find the player's new position on the board.
|
|
int new_board_idx = -1;
|
|
for (int i = 0; i < board_ratings.length; i++)
|
|
{
|
|
if (board_ratings[i] < player_rating)
|
|
{
|
|
new_board_idx = i;
|
|
break;
|
|
}
|
|
}
|
|
if (new_board_idx == -1)
|
|
{
|
|
if (!on_board && empty_slots)
|
|
{
|
|
board_names.add(utils.getRealPlayerFirstName(player));
|
|
board_ratings.add(utils.getRealPlayerFirstName(player));
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
if (on_board)
|
|
{
|
|
if (current_board_idx == new_board_idx)
|
|
return null;
|
|
|
|
// Remove the player from his old position.
|
|
board_names.remove(current_board_idx);
|
|
board_ratings.remove(current_board_idx);
|
|
}
|
|
|
|
// Add the player to his new position.
|
|
board_names.add(new_board_idx, utils.getRealPlayerFirstName(player));
|
|
board_ratings.add(new_board_idx, new Integer(player_rating));
|
|
}
|
|
|
|
// Trim the board down to its maximum size.
|
|
if (board_names.length > PVP_BOARD_SIZE)
|
|
{
|
|
board_names.setSize(PVP_BOARD_SIZE);
|
|
board_ratings.setSize(PVP_BOARD_SIZE);
|
|
}
|
|
|
|
// Update the dictionary.
|
|
for (int i = 0; i < board_names.length; i++)
|
|
{
|
|
string key_name = BATCH_VAR_PVPBOARD_NAME + i;
|
|
string key_rating = BATCH_VAR_PVPBOARD_RATING + i;
|
|
|
|
enclave_data.put(key_name, board_names[i]);
|
|
enclave_data.put(key_rating, board_ratings[i]);
|
|
}
|
|
|
|
return enclave_data;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief sends a mail message to everyone in the specified rank
|
|
* requires an authoritative enclave.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank
|
|
* @param string_id subject
|
|
* @param prose_package body
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean sendRankMail(obj_id enclave, int rank, string_id subject, prose_package body)
|
|
{
|
|
LOG("force_rank", "force_rank.sendRankMail -- " + rank);
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.sendRankMail -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.sendRankMail -- illegal value for rank: " + rank);
|
|
return false;
|
|
}
|
|
|
|
string[] rank_list = getPlayersInForceRank(enclave, rank);
|
|
if (rank_list != null)
|
|
{
|
|
for (int i = 0; i < rank_list.length; i++)
|
|
{
|
|
LOG("force_rank", "rank_list[" + i + "] ->" + rank_list[i]);
|
|
utils.sendMail(subject, body, rank_list[i], "Enclave Records");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief sends a mail message to everyone qualified to vote in
|
|
* the specified rank.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank rank which voting is for.
|
|
* @param string_id subject
|
|
* @param prose_package body
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean sendVoterMail(obj_id enclave, int rank, string_id subject, prose_package body)
|
|
{
|
|
//LOG("force_rank", "force_rank.sendVoterMail");
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.sendVoterMail -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.sendVoterMail -- illegal value for rank: " + rank);
|
|
return false;
|
|
}
|
|
|
|
// Iterate through all 12 ranks check each to see if it's eligible to vote.
|
|
for (int i = 0; i < 12; i++)
|
|
{
|
|
LOG("force_rank", "vote weight[" + i + "] ->" + getVoteWeight(i, rank));
|
|
if (getVoteWeight(i, rank) > 0)
|
|
{
|
|
sendRankMail(enclave, i, subject, body);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief sends a mail message to everyone qualified to vote in
|
|
* a no-confidence challenge of the specified rank.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int rank rank which voting is for.
|
|
* @param string_id subject
|
|
* @param prose_package body
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean sendChallengeVoterMail(obj_id enclave, int rank, string_id subject, prose_package body)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.sendChallengeVoterMail -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (rank < 1 || rank > 11)
|
|
{
|
|
LOG("force_rank", "force_rank.sendChallengeVoterMail -- illegal value for rank: " + rank);
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < 12; i++)
|
|
{
|
|
if (getChallengeVoteWeight(i, rank) > 0)
|
|
sendRankMail(enclave, i, subject, body);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief resets the enclave's data, clearing everything
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean resetEnclaveData(obj_id enclave)
|
|
{
|
|
LOG("force_rank", "force_rank.resetEnclaveData");
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.resetEnclaveData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
int slots = force_rank.getForceRankNumSlots(i);
|
|
if (slots > 0)
|
|
{
|
|
string[] rank_list = new string[slots];
|
|
Arrays.fill(rank_list, EMPTY_SLOT);
|
|
|
|
setObjVar(enclave, force_rank.VAR_RANK_BASE + i, rank_list);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief replaces the enclave's clusterwide data.
|
|
*
|
|
* @param obj_id enclave
|
|
* @param int lock_key if the data is to be locked.
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean replaceEnclaveClusterData(obj_id enclave, int lock_key)
|
|
{
|
|
LOG("force_rank", "force_rank.replaceEnclaveClusterData");
|
|
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.replaceEnclaveClusterData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
int council = force_rank.getCouncilAffiliation(enclave);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "enclave_controller.replaceEnclaveData -- " + enclave + " has an invalid council value.");
|
|
return false;
|
|
}
|
|
|
|
if (lock_key < 0)
|
|
lock_key = 0;
|
|
|
|
dictionary enclave_info = new dictionary();
|
|
|
|
|
|
LOG("force_rank", "force_rank.replaceEnclaveClusterData -- 1");
|
|
// Add the enclave's obj_id
|
|
enclave_info.put(VAR_ENCLAVE, enclave);
|
|
|
|
// Get the rank info
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
// We want to keep the "empty" slots when updating the cluster wide data.
|
|
string[] rank_members = getStringArrayObjVar(enclave, VAR_RANK_BASE + i);
|
|
if (rank_members != null)
|
|
{
|
|
for (int j = 0; j < rank_members.length; j++)
|
|
{
|
|
string key = force_rank.VAR_RANK_BASE + i + "-" + j;
|
|
enclave_info.put(key, rank_members[j]);
|
|
//LOG("force_rank", "key ->" + key + " member ->" + rank_members[j]);
|
|
}
|
|
}
|
|
}
|
|
LOG("force_rank", "force_rank.replaceEnclaveClusterData -- 2");
|
|
|
|
/*
|
|
// Get the leaderboard info
|
|
string[] board_names = getPvpBoardNames(enclave);
|
|
int[] board_ratings = getPvpBoardRatings(enclave);
|
|
if (board_names != null && board_names.length > 0 && board_ratings != null && board_ratings.length > 0)
|
|
{
|
|
if (board_names.length > board_ratings.length)
|
|
{
|
|
LOG("force_rank", "enclave_controller.replaceEnclaveData -- PvPBoard array lengths do not match. Resetting board for enclave " + enclave);
|
|
removeObjVar(enclave, BATCH_VAR_PVPBOARD_NAME);
|
|
removeObjVar(enclave, BATCH_VAR_PVPBOARD_RATING);
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < board_names.length; i++)
|
|
{
|
|
enclave_info.put(BATCH_VAR_PVPBOARD_NAME + i, board_names[i]);
|
|
enclave_info.put(BATCH_VAR_PVPBOARD_RATING + i, board_ratings[i]);
|
|
//LOG("force_rank", "name ->" + board_names[i] + " rating ->" + board_ratings[i]);
|
|
}
|
|
}
|
|
}
|
|
LOG("force_rank", "force_rank.replaceEnclaveClusterData -- 3");
|
|
*/
|
|
|
|
replaceClusterWideData(CLUSTER_DATA_NAME, STRING_CLUSTER_ENCLAVE_NAME + council, enclave_info, false, lock_key);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief writes the latest clusterwide data to the enclave
|
|
*
|
|
* @param obj_id enclave
|
|
* @param dictionary enclave_data Data to write out as given by
|
|
* OnClusterWideDataResponse.
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean updateEnclaveClusterData(obj_id enclave, dictionary enclave_data)
|
|
{
|
|
LOG("force_rank", "force_rank.updateEnclaveClusterData");
|
|
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.replaceEnclaveData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
if (enclave_data == null)
|
|
{
|
|
LOG("force_rank", "force_rank.replaceEnclaveData -- enclave_data is null for " + enclave);
|
|
return false;
|
|
}
|
|
|
|
//LOG("force_rank", "data ->" + enclave_data);
|
|
|
|
// Initialize the rank arrays.
|
|
//string[][] ranks = new string[11][MAX_RANK_SLOTS];
|
|
Object[] ranks = new Object[11];
|
|
for (int i = 0; i < ranks.length; i++)
|
|
ranks[i] = new Vector();
|
|
|
|
// Initialize the PvP Board arrays
|
|
string[] pvp_board_name = new string[PVP_BOARD_SIZE];
|
|
Arrays.fill(pvp_board_name, EMPTY_SLOT);
|
|
int[] pvp_board_rating = new int[PVP_BOARD_SIZE];
|
|
|
|
|
|
// Enumerate through the dictionary and write everything out.
|
|
java.util.Enumeration e = enclave_data.keys();
|
|
while (e.hasMoreElements())
|
|
{
|
|
string key_name = (string)(e.nextElement());
|
|
if (key_name.length() > 0)
|
|
{
|
|
//LOG("force_rank", "key_name ->" + key_name);
|
|
if (key_name.startsWith(VAR_RANK_BASE))
|
|
{
|
|
// Rank lists are stored in the format RANK#-slot
|
|
java.util.StringTokenizer st = new java.util.StringTokenizer(key_name, "-");
|
|
if (st.countTokens() != 2)
|
|
continue;
|
|
|
|
string prefix = st.nextToken();
|
|
string slot = st.nextToken();
|
|
int slot_number = utils.stringToInt(slot);
|
|
if (slot_number < 0)
|
|
continue;
|
|
|
|
// Split the prefix to get the rank #
|
|
java.util.StringTokenizer st2 = new java.util.StringTokenizer(prefix, VAR_RANK_BASE);
|
|
if (st2.countTokens() != 1)
|
|
continue;
|
|
|
|
string prefix_rank = st2.nextToken();
|
|
int rank = utils.stringToInt(prefix_rank);
|
|
if (rank < 1)
|
|
continue;
|
|
|
|
//LOG("force_rank", " rank ->" + rank + " slot_number ->" + slot_number);
|
|
Vector edit_list = (Vector)(ranks[rank-1]);
|
|
edit_list.add(enclave_data.getString(key_name));
|
|
}
|
|
|
|
if (key_name.startsWith(BATCH_VAR_PVPBOARD_NAME))
|
|
{
|
|
// The PvP board is stored as Name#
|
|
java.util.StringTokenizer st = new java.util.StringTokenizer(key_name, BATCH_VAR_PVPBOARD_NAME);
|
|
if (st.countTokens() != 1)
|
|
continue;
|
|
string slot = st.nextToken();
|
|
int slot_number = utils.stringToInt(slot);
|
|
if (slot_number < 0)
|
|
continue;
|
|
|
|
pvp_board_name[slot_number] = enclave_data.getString(key_name);
|
|
pvp_board_rating[slot_number] = enclave_data.getInt(BATCH_VAR_PVPBOARD_RATING + slot);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write everything out.
|
|
for (int i = 0; i < ranks.length; i++)
|
|
{
|
|
Object obj_list = ranks[i];
|
|
Vector vec_list = (Vector) obj_list;
|
|
string[] rank_list = new string[vec_list.size()];
|
|
vec_list.toArray(rank_list);
|
|
|
|
setObjVar(enclave, VAR_RANK_BASE + (i + 1), rank_list);
|
|
}
|
|
|
|
//utils.setBatchObjVar(enclave, BATCH_VAR_PVPBOARD_NAME, pvp_board_name);
|
|
//utils.setBatchObjVar(enclave, BATCH_VAR_PVPBOARD_RATING, pvp_board_rating);
|
|
|
|
// Update the permissions list.
|
|
//LOG("force_rank", "force_rank.updateEnclaveClusterData -- updateAllRoomPermissions " + enclave);
|
|
//updateAllRoomPermissions(enclave);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief creates a back-up of the ranking data
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean backupEnclaveData(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.backupEnclaveData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
string[] rank_list = getStringArrayObjVar(enclave, VAR_RANK_BASE + i);
|
|
if (rank_list != null && rank_list.length > 0)
|
|
setObjVar(enclave, "bk_" + VAR_RANK_BASE + i, rank_list);
|
|
}
|
|
|
|
// set the new timestamp
|
|
setObjVar(enclave, VAR_BACKUP_TIME, getGameTime());
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief restores an enclave's data from back-up
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean restoreEnclaveData(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.restoreEnclaveData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
string[] rank_list = getStringArrayObjVar(enclave, "bk_" + VAR_RANK_BASE + i);
|
|
if (rank_list != null && rank_list.length > 0)
|
|
setObjVar(enclave, VAR_RANK_BASE + i, rank_list);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief logs the enclaves current data to the customer service log.
|
|
*
|
|
* @param obj_id enclave
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean logEnclaveData(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
LOG("force_rank", "force_rank.logEnclaveData -- enclave is invalid.");
|
|
return false;
|
|
}
|
|
|
|
int council = getCouncilAffiliation(enclave);
|
|
if (council == -1)
|
|
{
|
|
LOG("force_rank", "force_rank.logEnclaveData -- " + enclave + " does not have a council affiliation.");
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < 12; i++)
|
|
{
|
|
string[] rank_list = getPlayersInForceRank(enclave, i);
|
|
if (rank_list != null)
|
|
{
|
|
for (int j = 0; j < rank_list.length; j++)
|
|
{
|
|
if (rank_list[j] != null)
|
|
{
|
|
obj_id player = getPlayerIdFromFirstName(rank_list[j]);
|
|
CustomerServiceLog("force_rank", COUNCIL_NAMES[council] + " Data: " + rank_list[j] + "(" + player + ") is at rank " + i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief removes the first empty slot in the enclave data dictionary
|
|
* for the given rank. This is used to remove extra slots
|
|
* that were created to make room for demotions.
|
|
*
|
|
* @param dictionary enclave_data from the clusterwide data
|
|
* @param int rank
|
|
*
|
|
* @return return dictionary
|
|
*********************************************************************/
|
|
dictionary removeExtraSlotFromRankList(dictionary enclave_data, int rank)
|
|
{
|
|
//LOG("force_rank", "!!!!!!!!!force_rank.removeExtraSlotFromRankList!!!!!!!!!!!!!");
|
|
if (enclave_data == null)
|
|
{
|
|
LOG("force_rank", "force_rank.removeEntryFromRankList -- enclave is null.");
|
|
return null;
|
|
}
|
|
|
|
int max_slots = getForceRankNumSlots(rank);
|
|
if (max_slots < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.removeEntryFromRankList -- invalid max slot data from " + rank);
|
|
return null;
|
|
}
|
|
|
|
resizeable string[] rank_list = getRankMembersFromDictionary(enclave_data, rank);
|
|
if (rank_list != null)
|
|
{
|
|
int slots_to_remove = rank_list.length - max_slots;
|
|
int rank_length = rank_list.size();
|
|
//LOG("force_rank", "rank_list.length ->" + rank_list.length + " max_slots ->" + max_slots);
|
|
//LOG("force_rank", "rank ->" + rank + " slots_to_remove ->" + slots_to_remove);
|
|
if (slots_to_remove < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.removeEntryFromRankList -- there are not slots to remove.");
|
|
return null;
|
|
}
|
|
string key_name = force_rank.VAR_RANK_BASE + rank + "-";
|
|
int data_idx = 0;
|
|
for (int i = 0; i < rank_list.length; i++)
|
|
{
|
|
//LOG("force_rank", "rank_list[" + i + "] ->" + rank_list[i] + " data_idx ->" + data_idx + " slots ->" + slots_to_remove);
|
|
if (slots_to_remove > 0)
|
|
{
|
|
if (rank_list[i] == null || rank_list[i].length() < 1 || rank_list[i].equals(EMPTY_SLOT))
|
|
{
|
|
//rank_list.remove(i);
|
|
rank_length--;
|
|
slots_to_remove--;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//LOG("force_rank", "key ->" + (key_name + data_idx) + " ranklist[" + i +"] ->" + rank_list[i]);
|
|
enclave_data.put(key_name + data_idx, rank_list[i]);
|
|
data_idx++;
|
|
}
|
|
|
|
// remove the extra keys from the dictionary
|
|
for (int i = rank_length; i <= MAX_RANK_SLOTS; i++)
|
|
{
|
|
string key_remove = force_rank.VAR_RANK_BASE + rank + "-" + i;
|
|
if (enclave_data.containsKey(key_remove))
|
|
enclave_data.remove(key_remove);
|
|
}
|
|
|
|
return enclave_data;
|
|
}
|
|
else
|
|
{
|
|
LOG("force_rank", "force_rank.removeEntryFromRankList -- rank_list is null.");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Grants items to the player for achieving a given rank
|
|
*
|
|
* @param obj_id player
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean grantRankItems(obj_id player, boolean retroactive)
|
|
{
|
|
/*
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.grantRankItems -- player is invalid.");
|
|
return false;
|
|
}
|
|
|
|
int rank = getForceRank(player);
|
|
if (rank < 0)
|
|
{
|
|
LOG("force_rank", "force_rank.grantRankItems -- " + player + " does not have a rank.");
|
|
return false;
|
|
}
|
|
int council = getCouncilAffiliation(player);
|
|
if (council < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.grantRankItems -- " + player + " does not have a council affiliation.");
|
|
return false;
|
|
}
|
|
|
|
int index = 0;
|
|
if (!retroactive)
|
|
{
|
|
index = dataTableSearchColumnForInt(rank, "rank", ENCLAVE_REWARDS_DATATABLE);
|
|
if (index == -1)
|
|
return false;
|
|
}
|
|
|
|
obj_id inv = getObjectInSlot(player, "inventory");
|
|
if (!isIdValid(inv))
|
|
{
|
|
LOG("force_rank", "force_rank.grantRankItems -- " + player + " has an invalid inventory.");
|
|
return false;
|
|
}
|
|
|
|
for (int i = index; i < dataTableGetNumRows(ENCLAVE_REWARDS_DATATABLE); i++)
|
|
{
|
|
dictionary row = dataTableGetRow(ENCLAVE_REWARDS_DATATABLE, i);
|
|
int row_rank = row.getInt("rank");
|
|
|
|
if (retroactive)
|
|
{
|
|
if (row_rank > rank)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (row_rank != rank)
|
|
break;
|
|
}
|
|
|
|
int row_council = row.getInt("council");
|
|
if (council == row_council)
|
|
{
|
|
string item = row.getString("item");
|
|
if (item != null && item.length() > 0)
|
|
{
|
|
int free_space = getVolumeFree(inv);
|
|
if (free_space < 1)
|
|
break;
|
|
|
|
obj_id created_object = createObject(item, inv, "");
|
|
if (isIdValid(created_object))
|
|
CustomerServiceLog("force_rank", "Granting item " + getTemplateName(created_object) + " (" + created_object + ") to %TU for reaching rank " + rank, player, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
*/
|
|
return false;
|
|
}
|
|
|
|
boolean grantRankItems(obj_id player)
|
|
{
|
|
return grantRankItems(player, false);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the effects for an FRS attack
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param hit_result results
|
|
* @param weapon_data weapondat
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttack(obj_id player, obj_id defender, hit_result results, weapon_data weapondat)
|
|
{
|
|
//LOG("force_rank", "force_rank.performFRSAttack");
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("force_rank", "force_rank.performFRSAttack -- player is invalid.");
|
|
return false;
|
|
}
|
|
if (!isIdValid(defender))
|
|
{
|
|
LOG("force_rank", "force_rank.performFRSAttack -- defender is invalid.");
|
|
return false;
|
|
}
|
|
if (results == null)
|
|
{
|
|
LOG("force_rank", "force_rank.performFRSAttack -- results is null.");
|
|
return false;
|
|
}
|
|
if (weapondat == null)
|
|
{
|
|
LOG("force_rank", "force_rank.performFRSAttack -- weapondat is null.");
|
|
return false;
|
|
}
|
|
if (!isPlayer(player))
|
|
return false;
|
|
|
|
int council = getCouncilAffiliation(player);
|
|
if (council < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.performFRSAttack -- " + player + " has an invalid council affiliation.");
|
|
return false;
|
|
}
|
|
|
|
int damage = results.damage;
|
|
obj_id weapon_id = weapondat.id;
|
|
|
|
// Dark FRS powers
|
|
if (council == 1)
|
|
{
|
|
int envy_rating = getEnhancedSkillStatisticModifier(player, "frs_dark_envy");
|
|
//LOG("force_rank", "envy_rating ->" + envy_rating);
|
|
if (envy_rating > 0)
|
|
performFRSAttackEnvy(player, defender, weapon_id, damage, envy_rating);
|
|
|
|
int suffering_rating = getEnhancedSkillStatisticModifier(player, "frs_dark_suffering");
|
|
//LOG("force_rank", "suffering_rating ->" + suffering_rating);
|
|
if (suffering_rating > 0)
|
|
performFRSAttackSuffering(player, defender, weapon_id, damage, suffering_rating);
|
|
}
|
|
else
|
|
{
|
|
// Light FRS powers
|
|
int vigilance_rating = getEnhancedSkillStatisticModifier(player, "frs_light_vigilance");
|
|
if (vigilance_rating > 0)
|
|
performFRSAttackVigilance(player, defender, weapon_id, damage, vigilance_rating);
|
|
|
|
int wisdom_rating = getEnhancedSkillStatisticModifier(player, "frs_light_wisdom");
|
|
if (wisdom_rating > 0)
|
|
performFRSAttackWisdom(player, defender, weapon_id, damage, wisdom_rating);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the Envy attack effect. Envy drains force power
|
|
* from the defender and gives a little of it to the wielder
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param obj_id weapon
|
|
* @param int damage
|
|
* @param int rating
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttackEnvy(obj_id player, obj_id defender, obj_id weapon, int damage, int rating)
|
|
{
|
|
//LOG("force_rank", "1force_rank.performFRSAttackEnvy");
|
|
// Envy only works on Jedi
|
|
if (!isJedi(player))
|
|
return false;
|
|
|
|
if (damage < 1)
|
|
return false;
|
|
|
|
if (rating > 100)
|
|
rating = 100;
|
|
|
|
// Calculate the drain amount.
|
|
int drain = (int)(damage * ((float)rating / 200.0f));
|
|
if (drain < 1)
|
|
drain = 1;
|
|
|
|
|
|
// Calculate the return amount
|
|
int gain = (int)(drain * ((float)rating / 100.0f));
|
|
if (gain < 1)
|
|
gain = 1;
|
|
|
|
if (!jedi.hasForcePower(defender, drain))
|
|
{
|
|
drain = getForcePower(defender);
|
|
if (drain == 0)
|
|
return false;
|
|
}
|
|
|
|
//LOG("force_rank", "damage ->" + damage + " gain ->" + gain + " drain ->" + drain);
|
|
//LOG("force_rank", "Force power ->" + getForcePower(player) + " / " + getForcePower(defender));
|
|
alterForcePower(defender, -drain);
|
|
alterForcePower(player, gain);
|
|
//LOG("force_rank", "Force power ->" + getForcePower(player) + " / " + getForcePower(defender));
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = new string_id("cbt_spam", "frs_dark_envy_drain");
|
|
pp.actor.set(player);
|
|
pp.target.set(defender);
|
|
pp.digitInteger = drain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, true, false);
|
|
pp.stringId = new string_id("cbt_spam", "frs_dark_envy_gain");
|
|
pp.digitInteger = gain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, false, false);
|
|
playClientEffectLoc(player, "clienteffect/frs_dark_envy.cef" , getLocation(defender), 1.5f);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the Suffering attack effect. Suffering debuffs
|
|
* a player's secondary and tertiary health and action stats.
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param obj_id weapon
|
|
* @param int damage
|
|
* @param int rating
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttackSuffering(obj_id player, obj_id defender, obj_id weapon, int damage, int rating)
|
|
{
|
|
//LOG("force_rank", "force_rank.performFRSAttackSuffering");
|
|
|
|
if (isJedi(defender))
|
|
{
|
|
// If the defender still has force power, he isn't affected by this.
|
|
if (getForcePower(defender) > 0)
|
|
return false;
|
|
}
|
|
|
|
int drain = (int)(damage * ((float)rating / 300.0f));
|
|
if (drain < 1)
|
|
drain = 1;
|
|
|
|
int current_val = 0;
|
|
int[] attribs = {1, 2, 4, 5};
|
|
for (int i = 0; i < attribs.length; i++)
|
|
{
|
|
int current_attrib = getAttrib(defender, attribs[i]);
|
|
if (current_attrib - 1 <= drain)
|
|
{
|
|
drain = current_attrib - 1;
|
|
if (drain < 1)
|
|
continue;
|
|
}
|
|
|
|
// If the modifier already exists, add the new one in.
|
|
if (hasAttribModifier(defender, "force_rank.suffering_" + attribs[i]))
|
|
{
|
|
attrib_mod[] mods = getAttribModifiers(defender, attribs[i]);
|
|
for (int j = 0; j < mods.length; j++)
|
|
{
|
|
string name = mods[j].getName();
|
|
if (name != null && name.equals("force_rank.suffering_" + attribs[i]))
|
|
{
|
|
int val = mods[j].getValue();
|
|
//LOG("force_rank", "name ->" + name + " val ->" + val);
|
|
if (val != 0)
|
|
{
|
|
removeAttribOrSkillModModifier(defender, "force_rank.suffering_" + attribs[i]);
|
|
current_val = Math.abs(val);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//LOG("force_rank", "drain ->" + drain + current_val);
|
|
addAttribModifier(defender, "force_rank.suffering_" + attribs[i], attribs[i], -(drain + current_val), DEBUFF_DURATION, 0.0f, 0.0f, false, false, false);
|
|
}
|
|
|
|
|
|
// Add one buff icon for the collective debuff.
|
|
addBuffIcon(defender, "force_rank.suffering", DEBUFF_DURATION);
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = new string_id("cbt_spam", "frs_dark_suffering");
|
|
pp.actor.set(player);
|
|
pp.target.set(defender);
|
|
pp.digitInteger = drain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, true, false);
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the Vengeance attack effect. Vengeance causes
|
|
* wounds to those that damage the Jedi.
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param int damage
|
|
* @param int rating
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttackVengeance(obj_id player, obj_id defender, int damage, int rating)
|
|
{
|
|
/*
|
|
int wound = (int)(damage * ((float)rating / 200.0f));
|
|
//LOG("force_rank", "damage ->" + damage + " rating ->" + rating + " wound ->" + wound);
|
|
|
|
addWound(defender, HEALTH, wound);
|
|
addWound(defender, ACTION, wound);
|
|
addWound(defender, MIND, wound);
|
|
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = new string_id("cbt_spam", "frs_dark_vengeance");
|
|
pp.actor.set(player);
|
|
pp.target.set(defender);
|
|
pp.digitInteger = wound;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, true, false);
|
|
*/
|
|
playClientEffectLoc(player, "clienteffect/frs_dark_vengeance.cef" , getLocation(defender), 1.5f);
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the Vigilance attack effect. Vigiliance damages
|
|
* the defender's force power.
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param obj_id weapon
|
|
* @param int damage
|
|
* @param int rating
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttackVigilance(obj_id player, obj_id defender, obj_id weapon, int damage, int rating)
|
|
{
|
|
//LOG("force_rank", "1force_rank.performFRSAttackVigilance");
|
|
// Envy only works on Jedi
|
|
if (!isJedi(player))
|
|
return false;
|
|
|
|
if (damage < 1)
|
|
return false;
|
|
|
|
if (rating > 100)
|
|
rating = 100;
|
|
|
|
// Calculate the drain amount.
|
|
int drain = (int)(damage * ((float)rating / 100.0f));
|
|
if (drain < 1)
|
|
drain = 1;
|
|
|
|
if (!jedi.hasForcePower(defender, drain))
|
|
{
|
|
drain = getForcePower(defender);
|
|
if (drain == 0)
|
|
return false;
|
|
}
|
|
|
|
alterForcePower(defender, -drain);
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = new string_id("cbt_spam", "frs_light_vigilance");
|
|
pp.actor.set(player);
|
|
pp.target.set(defender);
|
|
pp.digitInteger = drain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, true, false);
|
|
playClientEffectLoc(player, "clienteffect/frs_light_vigilance.cef" , getLocation(defender), 1.5f);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the Wisdom attack effect. Wisdom drains pools
|
|
* and adds them to the Jedi.
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param obj_id weapon
|
|
* @param int damage
|
|
* @param int rating
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttackWisdom(obj_id player, obj_id defender, obj_id weapon, int damage, int rating)
|
|
{
|
|
//LOG("force_rank", "force_rank.performFRSAttackWisdom");
|
|
|
|
if (isJedi(defender))
|
|
{
|
|
// If the defender still has force power, he isn't affected by this.
|
|
if (getForcePower(defender) > 0)
|
|
return false;
|
|
}
|
|
|
|
int drain = (int)(damage * ((float)rating / 200.0f));
|
|
if (drain < 1)
|
|
drain = 1;
|
|
|
|
int gain = (int)(drain * ((float)rating / 100.0f));
|
|
if (gain < 1)
|
|
gain = 1;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
// drain mod pools from the defender and give them to the Jedi.
|
|
addAttribModifier(defender, i*3, -drain, 0.0f, 0.0f, MOD_POOL);
|
|
addAttribModifier(player, i*3, gain, 0.0f, 0.0f, MOD_POOL);
|
|
}
|
|
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = new string_id("cbt_spam", "frs_light_wisdom_drain");
|
|
pp.actor.set(player);
|
|
pp.target.set(defender);
|
|
pp.digitInteger = drain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, true, false);
|
|
pp.stringId = new string_id("cbt_spam", "frs_light_wisdom_gain");
|
|
pp.digitInteger = gain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, false, false);
|
|
playClientEffectLoc(player, "clienteffect/frs_light_wisdom.cef" , getLocation(defender), 1.5f);
|
|
|
|
return true;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* @brief Performs the Serenity attack effect. Serenity debuffs
|
|
* those that attack the Jedi.
|
|
*
|
|
* @param obj_id player
|
|
* @param obj_id defender
|
|
* @param int damage
|
|
* @param int rating
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean performFRSAttackSerenity(obj_id player, obj_id defender, int damage, int rating)
|
|
{
|
|
int drain = (int)(damage * ((float)rating / 400.0f));
|
|
if (drain < 1)
|
|
drain = 1;
|
|
|
|
int current_val = 0;
|
|
int[] attribs = {1, 3, 6};
|
|
for (int i = 0; i < attribs.length; i++)
|
|
{
|
|
int current_attrib = getAttrib(defender, attribs[i]);
|
|
if (current_attrib - 1 <= drain)
|
|
{
|
|
drain = current_attrib - 1;
|
|
if (drain < 1)
|
|
continue;
|
|
}
|
|
|
|
// If the modifier already exists, add the new one in.
|
|
if (hasAttribModifier(defender, "force_rank.serenity_" + attribs[i]))
|
|
{
|
|
attrib_mod[] mods = getAttribModifiers(defender, attribs[i]);
|
|
for (int j = 0; j < mods.length; j++)
|
|
{
|
|
string name = mods[j].getName();
|
|
if (name != null && name.equals("force_rank.serenity_" + attribs[i]))
|
|
{
|
|
int val = mods[j].getValue();
|
|
//LOG("force_rank", "name ->" + name + " val ->" + val);
|
|
if (val != 0)
|
|
{
|
|
removeAttribOrSkillModModifier(defender, "force_rank.serenity_" + attribs[i]);
|
|
current_val = Math.abs(val);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//LOG("force_rank", "drain ->" + drain + current_val);
|
|
addAttribModifier(defender, "force_rank.serenity_" + attribs[i], attribs[i], -(drain + current_val), DEBUFF_DURATION, 0.0f, 0.0f, false, false, false);
|
|
}
|
|
|
|
|
|
// Add one buff icon for the collective debuff.
|
|
addBuffIcon(defender, "force_rank.serenity", DEBUFF_DURATION);
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = new string_id("cbt_spam", "frs_light_serenity");
|
|
pp.actor.set(player);
|
|
pp.target.set(defender);
|
|
pp.digitInteger = drain;
|
|
combat.sendCombatSpamMessageProse(player, defender, pp, true, true, false);
|
|
playClientEffectLoc(player, "clienteffect/frs_light_serenity.cef" , getLocation(defender), 1.5f);
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// gets called from enclave_controller::msgVictimizedJediDeath as a result of dark jedi being killed (partially) by another dark jedi
|
|
// @params is a list of the @@victim, @@totalDamageToVictim and a number of @winnerObjId/@percentContributionFloat pairs
|
|
//
|
|
void handleCondemnedPlayerDeath(obj_id darkEnclave, dictionary params)
|
|
{
|
|
trace.log("force_rank", "force_rank::handledCondemnedPlayerDeath: -> Enter method");
|
|
if(!params.containsKey("victim") || !params.containsKey("totalDamageToVictim"))
|
|
{
|
|
trace.log("force_rank", "force_rank::handleCondemnedPlayerDeath: -> Missing vital params 'victim' and 'totalDamageToVictim'. Not validating Dark Jedi PvP ACTION death.", darkEnclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
// grab data from params
|
|
obj_id victim = params.getObjId("victim");
|
|
params.remove("victim");
|
|
|
|
int totalDamageTally = params.getInt("totalDamageToVictim");
|
|
params.remove("totalDamageToVictim");
|
|
|
|
java.util.Enumeration pKeys = params.keys();
|
|
obj_id[] winners = new obj_id[params.size()];
|
|
float[] contributions = new float[winners.length];
|
|
int s = 0;
|
|
float totalDarkJediDeathContrib = 0;
|
|
|
|
while(pKeys.hasMoreElements())
|
|
{
|
|
obj_id key = (obj_id)pKeys.nextElement();
|
|
winners[s] = key;
|
|
contributions[s] = params.getFloat(key);
|
|
totalDarkJediDeathContrib += contributions[s];
|
|
s++;
|
|
}
|
|
|
|
// setup data for the winners loop
|
|
resizeable obj_id[] suddenDeathWinners = new obj_id[0];
|
|
resizeable float[] suddenDeathContribs = new float[0];
|
|
boolean suddenDeath = false;
|
|
boolean demoteToZero = false;
|
|
obj_id curPlayer = null;
|
|
float totSDContribs = 0;
|
|
dictionary suddenDeathData = getAndValidatePvPActionData(ACTION_CANDIDATE_SUDDEN_DEATH, darkEnclave);
|
|
dictionary vendettaData = getAndValidatePvPActionData(ACTION_VENDETTA, darkEnclave);
|
|
dictionary banishmentData = getAndValidatePvPActionData(ACTION_BANISHMENT, darkEnclave);
|
|
dictionary purgeData = getAndValidatePvPActionData(ACTION_PURGE_COUNCIL, darkEnclave);
|
|
|
|
// we need to check against sudden death and vendetta data for each winner
|
|
for(int i = 0; i < winners.length; i++)
|
|
{
|
|
curPlayer = winners[i];
|
|
|
|
// check if this winner is part of sudden death rank
|
|
if(suddenDeathData != null)
|
|
{
|
|
if(bothArePartOfSameSuddenDeathRank(victim, curPlayer, darkEnclave, suddenDeathData))
|
|
{
|
|
suddenDeath = true; // victim will relinquish any votes + forfeit their petition
|
|
utils.addElement(suddenDeathWinners, curPlayer);
|
|
utils.addElement(suddenDeathContribs, contributions[i]); // need these to divy up the votes according to contribution
|
|
totSDContribs += contributions[i]; // keep a running total of the total contributions by sudden death winners
|
|
}
|
|
}
|
|
|
|
// check for vendetta against/from curPlayer. no need to check again if we're already getting demoted to zero though...
|
|
if(vendettaData != null && !demoteToZero)
|
|
{
|
|
if(isPartOfSameVendetta(victim, curPlayer, vendettaData))
|
|
{
|
|
demoteToZero = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if we're a banishment victim
|
|
if(banishmentData != null && !demoteToZero)
|
|
{
|
|
if(isPvPActionVictim(victim, banishmentData))
|
|
{
|
|
demoteToZero = true;
|
|
}
|
|
}
|
|
|
|
// and finally check for council purge
|
|
if(purgeData != null && !demoteToZero)
|
|
{
|
|
if(isPvPActionVictim(victim, purgeData))
|
|
{
|
|
demoteToZero = true;
|
|
}
|
|
}
|
|
|
|
// divy up the victim's votes, if necessary
|
|
if(suddenDeath)
|
|
{
|
|
float curContrib = 0.0f;
|
|
int victimsVotes = getVotesForPlayer(victim, darkEnclave);
|
|
int curWinnerVotes = 0;
|
|
|
|
if(victimsVotes > 0)
|
|
{
|
|
setVotesForPlayer(victim, 0, darkEnclave);
|
|
_clearPvPActionDataForPlayer(victim, new string[]{VAR_VICTIMS}, ACTION_CANDIDATE_SUDDEN_DEATH, darkEnclave);
|
|
|
|
sendSystemMessage(victim, new string_id("pvp_rating", "dark_jedi_kill_lost_votes"));
|
|
trace.log("force_rank", utils.getRealPlayerFirstName(victim) + " has lost " + victimsVotes + " votes for dying during the voting sudden-death period.", victim, trace.TL_CS_LOG | trace.TL_DEBUG);
|
|
|
|
int votesGained = 0;
|
|
|
|
for(int x = 0; x < suddenDeathWinners.length; x++)
|
|
{
|
|
curContrib = suddenDeathContribs[x] / totSDContribs; // this is the percentage of dmg done in regards total damage done by all sudden death jedi
|
|
curWinnerVotes = getVotesForPlayer(suddenDeathWinners[x], darkEnclave);
|
|
votesGained = (int)Math.floor((float)victimsVotes * curContrib);
|
|
trace.log("force_rank", utils.getRealPlayerFirstName(suddenDeathWinners[x]) + " has gained " + votesGained + " for killing " + utils.getRealPlayerFirstName(victim), suddenDeathWinners[x], trace.TL_CS_LOG| trace.TL_DEBUG);
|
|
|
|
setVotesForPlayer(suddenDeathWinners[x], curWinnerVotes + votesGained, darkEnclave);
|
|
|
|
// msg players
|
|
prose_package pp = new prose_package();
|
|
pp.target.set(utils.getRealPlayerFirstName(victim));
|
|
pp.digitInteger = votesGained;
|
|
pp.stringId = new string_id("pvp_rating", "dark_jedi_kill_won_votes");
|
|
//prose.getPackage(new string_id("force_rank", "dark_jedi_kill_won_votes"), victim, votesGained);
|
|
sendSystemMessageProse(suddenDeathWinners[x], pp);
|
|
}
|
|
}
|
|
}
|
|
|
|
// demote and clear out any outstanding pvp action target/inits.
|
|
if(demoteToZero)
|
|
{
|
|
demoteDeadPlayerToRankZero(victim, darkEnclave);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// teleports @player to a common's cell in the enclave, only if they are currently in an enclave.
|
|
// method works out which enclave they are in and which room they need to get kicked to
|
|
//
|
|
void moveEnclavedPlayerToNeutralCell(obj_id player)
|
|
{
|
|
if(arena.isPlayerInEnclave(player))
|
|
{
|
|
location curLoc = getLocation(player);
|
|
obj_id curCell = curLoc.cell;
|
|
obj_id enclave = getEnclave(player);
|
|
obj_id destCell = null;
|
|
float x = 0.0f;
|
|
float y = 0.0f;
|
|
float z = 0.0f;
|
|
string cellName = "";
|
|
|
|
if(curCell != null)
|
|
{
|
|
if(checkCellPermission(player, curCell, true))
|
|
{
|
|
// player has permission for current cell. no need to move.
|
|
//return;
|
|
// commenting return out for now, as you could be in a common cell that you have
|
|
// permission to, but you dont have permissions to the cells leading to that portion of the
|
|
// common cell.
|
|
}
|
|
}
|
|
|
|
if(force_rank.getCouncilAffiliation(player) == force_rank.DARK_COUNCIL)
|
|
{
|
|
cellName = "antechamber";
|
|
x = 0.0f;
|
|
y = -43.42f;
|
|
z = -31.26f;
|
|
}
|
|
else // light enclave
|
|
{
|
|
cellName = "lobby";
|
|
x = -0.02f;
|
|
y = -19.03f;
|
|
z = 35.41f;
|
|
}
|
|
|
|
string[] enclaveRooms = getCellNames(enclave);
|
|
if(utils.getElementPositionInArray(enclaveRooms, cellName) > -1)
|
|
{
|
|
destCell = getCellId(enclave, cellName);
|
|
if(isIdValid(destCell))
|
|
{
|
|
location newloc = new location(x, y, z);
|
|
newloc.cell = destCell;
|
|
setLocation(player, newloc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// @returns either "light" or "dark", depending on the @enclave alignment. the returned string is used by updateRoomPermissions()
|
|
// to pull the allowed ranks from the datatable
|
|
//
|
|
string getEnclaveAligmentString(obj_id enclave)
|
|
{
|
|
if(DEBUGGING)
|
|
{
|
|
return "test";
|
|
}
|
|
|
|
int alignmentVal = getCouncilAffiliation(enclave);
|
|
if (alignmentVal == -1)
|
|
{
|
|
trace.log("force_rank", "force_rank.getEnclaveAligmentString -- invalid coucil value on enclave " + enclave, enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return null;
|
|
}
|
|
string alignment;
|
|
if(alignmentVal == force_rank.DARK_COUNCIL)
|
|
{
|
|
alignment = "dark";
|
|
}
|
|
else
|
|
{
|
|
alignment = "light";
|
|
}
|
|
|
|
return alignment;
|
|
}
|
|
|
|
//
|
|
// Reads rank permission lists from a datatable and pulls names off of the enclave roster for each
|
|
// rank, updating the permission lists for each cell in the enclave. this method is usually called
|
|
// after the enclave gets its new data from the cluster data store. This does not alter permissions for commons areas, etc.
|
|
// To completely re-do all cell permissions, call refreshAllRoomPermissions.
|
|
//
|
|
void updateAllRoomPermissions(obj_id enclave)
|
|
{
|
|
// construct the column name so we can look up permissioned ranks for the individual rooms
|
|
string alignment = getEnclaveAligmentString(enclave);
|
|
if(alignment == null || alignment.length() < 1)
|
|
{
|
|
trace.log("force_rank", "...force_rank::updateRoomPermissions -> Error retrieving enclave alignment. Room permissions not updated.", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
string[] commonsAreaCells = dataTableGetStringColumn(JEDI_ROOM_PERMISSIONS_TABLE, alignment + DATA_COLUMN_COMMUNITY_CELLS);
|
|
string[] enclaveRooms = getCellNames(enclave);
|
|
string columnName = "";
|
|
int[] allowedRanks = new int[0];
|
|
|
|
for(int i = 0; i < enclaveRooms.length; i++)
|
|
{
|
|
if(utils.getElementPositionInArray(commonsAreaCells, enclaveRooms[i]) > -1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
columnName = alignment + "_" + enclaveRooms[i];
|
|
allowedRanks = dataTableGetIntColumnNoDefaults(JEDI_ROOM_PERMISSIONS_TABLE, columnName);
|
|
|
|
if(allowedRanks == null || allowedRanks.length < 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// make the actual adjustment to the permissions list
|
|
adjustPermissionListForRoom(enclave, enclaveRooms[i], allowedRanks);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
resizeable obj_id[] playerNamesToIds(string[] playerNames)
|
|
{
|
|
resizeable obj_id[] players = new obj_id[0];
|
|
obj_id player = null;
|
|
|
|
for(int i = 0; i < playerNames.length; i++)
|
|
{
|
|
player = getPlayerIdFromFirstName(playerNames[i]);
|
|
if(isIdValid(player) && player != null)
|
|
{
|
|
utils.addElement(players, player);
|
|
}
|
|
}
|
|
|
|
return players;
|
|
}
|
|
|
|
//
|
|
// adjusts the permissions list for one room in the @enclave, given the @cellName and an
|
|
// integer array describing the @allowedRanks into the given cell
|
|
//
|
|
void adjustPermissionListForRoom(obj_id enclave, string cellName, int[] allowedRanks)
|
|
{
|
|
obj_id cellId = getCellId(enclave, cellName);
|
|
if(!isIdValid(cellId))
|
|
{
|
|
trace.log("force_rank", "...enclave_gate_keeper::adjustPermissionsListForRoom -> Bunk cellId for cell " + cellName + ". Permissions list not updated.", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
// clear out allow list for the cell
|
|
clearCellAllowList(cellId);
|
|
|
|
// set new allow list
|
|
string[] allowedPlayers = null;
|
|
|
|
for(int i = 0; i < allowedRanks.length; i++)
|
|
{
|
|
allowedPlayers = force_rank.getPlayersInForceRank(enclave, allowedRanks[i]);
|
|
if(allowedPlayers == null || allowedPlayers.length < 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for(int x = 0; x < allowedPlayers.length; x++)
|
|
{
|
|
permissionsAddAllowed(cellId, allowedPlayers[x]);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// sets EVERY cell in the @enclave to private and clear all ban/allow lists from the cells
|
|
//
|
|
void setAllCellsPrivate(obj_id enclave)
|
|
{
|
|
string[] cellNames = getCellNames(enclave);
|
|
|
|
obj_id cellId = null;
|
|
|
|
if (cellNames != null)
|
|
{
|
|
for(int i = 0; i < cellNames.length; i++)
|
|
{
|
|
cellId = getCellId(enclave, cellNames[i]);
|
|
permissionsMakePrivate(cellId);
|
|
|
|
clearCellBanList(cellId);
|
|
clearCellAllowList(cellId);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// clears everyone off of the ban list for a given @cell
|
|
//
|
|
void clearCellBanList(obj_id cell)
|
|
{
|
|
string[] banned = permissionsGetBanned(cell);
|
|
if(banned == null || banned.length < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(int i = 0; i < banned.length; i++)
|
|
{
|
|
permissionsRemoveBanned(cell, banned[i]);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// whipes everyone off of the allow list for a given @cell
|
|
//
|
|
void clearCellAllowList(obj_id cell)
|
|
{
|
|
string[] allowed = permissionsGetAllowed(cell);
|
|
if(allowed == null || allowed.length < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(int i = 0; i < allowed.length; i++)
|
|
{
|
|
permissionsRemoveAllowed(cell, allowed[i]);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// reads the JEDI_ROOM_PERMISSIONS_TABLE table for commons room data for the specified @enclave.
|
|
// Found under column [alignment]_community_cells, aka DATA_COLUMN_COMMUNITY_CELLS
|
|
//
|
|
void setCommonsRoomsToPublic(obj_id enclave)
|
|
{
|
|
// construct the column name so we can look up permissioned ranks for the individual rooms
|
|
string alignment = getEnclaveAligmentString(enclave);
|
|
if(alignment == null || alignment.length() < 1)
|
|
{
|
|
trace.log("force_rank", "force_rank::setCommonRoomsToPublic -> Error retrieving enclave alignment. Commons Area cells permissions not updated.", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
string[] commonsAreaCells = dataTableGetStringColumn(JEDI_ROOM_PERMISSIONS_TABLE, alignment + DATA_COLUMN_COMMUNITY_CELLS);
|
|
if(commonsAreaCells == null || commonsAreaCells.length < 1)
|
|
{
|
|
trace.log("force_rank", "force_rank::setCommonsRoomsToPublic -> No commons area cells found for " + alignment + " enclave. All rooms remain private.", enclave, trace.TL_WARNING | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
obj_id cellId = null;
|
|
for(int i = 0; i < commonsAreaCells.length; i++)
|
|
{
|
|
//LOG("force_rank", "cell ->" + commonsAreaCells[i]);
|
|
cellId = getCellId(enclave, commonsAreaCells[i]);
|
|
if(!isIdValid(cellId))
|
|
{
|
|
trace.log("force_rank", "force_rank::setCommonRoomsToPublic -> Bunk Commons Area Cell ID for cell name " + commonsAreaCells[i] + ". Cell not set to public.", enclave, trace.TL_WARNING | trace.TL_DEBUG);
|
|
}
|
|
permissionsMakePublic(cellId);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// check to see if @item has access permission for @cell
|
|
//
|
|
boolean checkCellPermission(obj_id item, obj_id cell, boolean silent)
|
|
{
|
|
if(isGod(item))
|
|
{
|
|
sendSystemMessageTestingOnly(item, "god access granted to this area");
|
|
return true;
|
|
}
|
|
|
|
if(!isMob(item))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
obj_id enclave = getTopMostContainer(cell);
|
|
if(!hasScript(enclave, force_rank.SCRIPT_ENCLAVE_CONTROLLER))
|
|
{
|
|
trace.log("force_rank", "force_rank::checkCellPermission -- " + enclave + " is not an enclave building.", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
if(!silent)
|
|
{
|
|
sendSystemMessage(item, new string_id("pvp_rating", "enclave_deny_entry"));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
string alignment = force_rank.getEnclaveAligmentString(enclave);
|
|
string cellName = getCellName(cell);
|
|
string columnName = alignment + "_" + cellName;
|
|
|
|
if(alignment == null || alignment.length() < 1)
|
|
{
|
|
trace.log("force_rank", "force_rank::checkCellPermission-> Error retrieving enclave alignment.", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
if(!silent)
|
|
{
|
|
sendSystemMessage(item, new string_id("pvp_rating", "enclave_deny_entry"));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if((isIdValid(item)) && (isPlayer(item)) && (force_rank.isForceRanked(item)) && (force_rank.isPlayersEnclave(enclave, item)))
|
|
{
|
|
string[] commonsAreaCells = dataTableGetStringColumn(force_rank.JEDI_ROOM_PERMISSIONS_TABLE, alignment + force_rank.DATA_COLUMN_COMMUNITY_CELLS);
|
|
if(utils.getElementPositionInArray(commonsAreaCells, cellName) > -1)
|
|
{
|
|
pet_lib.packAllCurrentPets(item, new string_id("pvp_rating", "enclave_deny_pet_entry"));
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
int[] allowedRanks = dataTableGetIntColumnNoDefaults(force_rank.JEDI_ROOM_PERMISSIONS_TABLE, columnName);
|
|
int rank = force_rank.getForceRank(item);
|
|
if(utils.getElementPositionInArray(allowedRanks, rank) >= 0)
|
|
{
|
|
pet_lib.packAllCurrentPets(item, new string_id("pvp_rating", "enclave_deny_pet_entry"));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
expelFromBuilding(item);
|
|
}
|
|
|
|
if(!silent)
|
|
{
|
|
sendSystemMessage(item, new string_id("pvp_rating", "enclave_deny_entry"));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// resets all the scripts on the cells for the permission system
|
|
void setCellScripts(obj_id enclave)
|
|
{
|
|
string[] enclaveRooms = getCellNames(enclave);
|
|
obj_id cellId = null;
|
|
|
|
for(int i = 0; i < enclaveRooms.length; i++)
|
|
{
|
|
cellId = getCellId(enclave, enclaveRooms[i]);
|
|
if(!isIdValid(cellId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
attachScript(cellId, "systems.gcw.enclave_cell");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void makeAllCellsPublic(obj_id enclave)
|
|
{
|
|
string[] enclaveRooms = getCellNames(enclave);
|
|
obj_id cellId = null;
|
|
|
|
for(int i = 0; i < enclaveRooms.length; i++)
|
|
{
|
|
cellId = getCellId(enclave, enclaveRooms[i]);
|
|
if(!isIdValid(cellId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
permissionsMakePublic(cellId);
|
|
}
|
|
}
|
|
|
|
//
|
|
// method should be called when all room permissions, including the public rooms need to be updated.
|
|
// method used mainly by maintenance triggers (attach, load, etc)
|
|
//
|
|
void refreshAllRoomPermissions(obj_id enclave)
|
|
{
|
|
// make every cell in the enclave private and clear all ban/allow lists
|
|
setAllCellsPrivate(enclave);
|
|
|
|
// make any commons area public, any allow/ban list has already been cleared in the previous call to setAllCellsPrivate
|
|
setCommonsRoomsToPublic(enclave);
|
|
|
|
// set allow lists for ppl in rankings so they can get into the various rooms
|
|
updateAllRoomPermissions(enclave);
|
|
}
|
|
|
|
|
|
//
|
|
// Make @player1 a permanent enemy of @player2 and vice versa, if the flag is @turnOn, otherwise the two players will be peaced
|
|
//
|
|
void makePlayersPermaEnemies(obj_id player1, obj_id player2)
|
|
{
|
|
trace.log("force_rank", "Setting PEF for " + player1 + " and " + player2 + " - now enemies.", null, trace.TL_CS_LOG | trace.TL_DEBUG);
|
|
pvpSetPermanentPersonalEnemyFlag(player1, player2);
|
|
pvpSetPermanentPersonalEnemyFlag(player2, player1);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Make @player1 a permanent enemy of @player2 and vice versa, if the flag is @turnOn, otherwise the two players will be peaced
|
|
//
|
|
void makePlayersPermaFriends(obj_id player1, obj_id player2)
|
|
{
|
|
trace.log("force_rank", "Making players " + utils.getRealPlayerFirstName(player1) + " and " + utils.getRealPlayerFirstName(player2) + " friends. (not really)", null, trace.TL_DEBUG);
|
|
|
|
//pvpRemovePermanentPersonalEnemyFlag(player1, player2); // doesn't exist currently
|
|
//pvpRemovePermanentPersonalEnemyFlag(player2, player1); // doesn't exist currently
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// make @player an enemy of everyone in @enemyGroup and vice versa
|
|
//
|
|
void makePlayerEnemyOfGroup(obj_id player, obj_id[] enemyGroup)
|
|
{
|
|
if(enemyGroup == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(int i = 0; i < enemyGroup.length; i++)
|
|
{
|
|
if(player != enemyGroup[i])
|
|
{
|
|
makePlayersPermaEnemies(player, enemyGroup[i]);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// make @player a friend of everyone in @friendGroup and vice versa
|
|
//
|
|
void makePlayerFriendsWithGroup(obj_id player, obj_id[] friendGroup)
|
|
{
|
|
if(friendGroup == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(int i = 0; i < friendGroup.length; i++)
|
|
{
|
|
if(player != friendGroup[i])
|
|
{
|
|
makePlayersPermaFriends(player, friendGroup[i]);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// make every member in @group1 a permanent enemy of @group2 and vice versa
|
|
//
|
|
void makePlayerGroupsEnemies(obj_id[] group1, obj_id[] group2)
|
|
{
|
|
if(group1 == null || group2 == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(int i = 0; i < group1.length; i++)
|
|
{
|
|
makePlayerEnemyOfGroup(group1[i], group2);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// just takes the arrays and dumps 'em into a dictionary. save myself some typing.
|
|
//
|
|
dictionary packageActionData(resizeable obj_id[] initz, resizeable obj_id[] victz, resizeable int[] startz)
|
|
{
|
|
dictionary d = new dictionary();
|
|
|
|
if(initz == null || initz.size() < 1 || victz == null || victz.size() < 1 || startz == null || startz.size() < 1)
|
|
{
|
|
//LOG("force_rank", "force_rank::packageActionData: -> Empty array(s) passed. Passing back empty dictionary.");
|
|
//LOG("force_rank", "force_rank::packageActionData: -> initiz.size()=" + initz.size() + ", victz.size()=" + victz.size() + ", startz.size()=" + startz.size());
|
|
// else dictionary.java will throw exceptions... bleh.
|
|
return d;
|
|
}
|
|
|
|
d.put("initiators", initz);
|
|
d.put("victims", victz);
|
|
d.put("times", startz);
|
|
|
|
return d;
|
|
}
|
|
|
|
//
|
|
// writes the @initiators and the @victims to the enclave given the @pvpAction of list pair it is (ACTION_VENDETTA, ACTION_BANISHMENT, etc)
|
|
//
|
|
void setPvPActionData(dictionary data, string pvpAction, obj_id darkEnclave)
|
|
{
|
|
if(!isIdValid(darkEnclave))
|
|
{
|
|
trace.log("force_rank", "force_rank::setPvPActionData -> darkEnclave ID not valid. Data not written.", darkEnclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
if(getCouncilAffiliation(darkEnclave) != DARK_COUNCIL)
|
|
{
|
|
trace.log("force_rank", "force_rank::setPvPActionData -> Non-DarkJedi-Enclave caller. Aborting.", darkEnclave, trace.TL_WARNING | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
if(data == null)
|
|
{
|
|
trace.log("force_rank", "force_rank::setPvPActionData -> @data == null. removing all action data for " + pvpAction, darkEnclave, trace.TL_DEBUG);
|
|
removeObjVar(darkEnclave, pvpAction);
|
|
return;
|
|
}
|
|
|
|
if(validatePvPActionData(data) == null)
|
|
{
|
|
if(!data.containsKey("victims"))
|
|
{
|
|
// arrays are just empty not mismatched lengths, etc... we need to remove the data as this indicates all actions odf pcpAction type are done.
|
|
trace.log("force_rank", "force_rank::setPvPActionData -> @data has no victim/starter/time data. removing all action data for " + pvpAction + " from enclave. this is means all actions of this type are done.", darkEnclave, trace.TL_DEBUG);
|
|
removeObjVar(darkEnclave, pvpAction);
|
|
}
|
|
else
|
|
{
|
|
trace.log("force_rank", "force_rank::setPvPActionData: -> pvp action data (" + pvpAction + ") invalid. not set to enclave.", darkEnclave, trace.TL_WARNING | trace.TL_DEBUG);
|
|
}
|
|
return;
|
|
}
|
|
|
|
obj_id[] inits = data.getObjIdArray("initiators");
|
|
obj_id[] victs = data.getObjIdArray("victims");
|
|
int[] startTms = data.getIntArray("times");
|
|
|
|
setObjVar(darkEnclave, pvpAction + VAR_INITIATORS, inits);
|
|
setObjVar(darkEnclave, pvpAction + VAR_VICTIMS, victs);
|
|
setObjVar(darkEnclave, pvpAction + VAR_START_TIMESTAMPS, startTms);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// The enclave keeps array pairs for initiators and victims for Vendettas, Banishments and council purges.
|
|
// this method pulls those arrays and validates them (makes sure they are at least of the same size)
|
|
// should the validation fail, the arrays are returned as nulls. if the arrays do no exist on the enclave
|
|
// object, zero length arrays are returned.
|
|
//
|
|
dictionary getAndValidatePvPActionData(string pvpAction, obj_id darkEnclave)
|
|
{
|
|
if(getCouncilAffiliation(darkEnclave) != DARK_COUNCIL)
|
|
{
|
|
trace.log("force_rank", "force_rank::getAndValidatePvPActionData -> Non-DarkJedi-Enclave. Aborting.", darkEnclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return null;
|
|
}
|
|
|
|
if(!isIdValid(darkEnclave))
|
|
{
|
|
trace.log("force_rank", "force_rank::getAndValidatePvPActionData -> darkEnclave ID not valid.", darkEnclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return null;
|
|
}
|
|
|
|
resizeable obj_id[] initiatorz = new obj_id[0];
|
|
if(hasObjVar(darkEnclave, pvpAction + VAR_INITIATORS))
|
|
{
|
|
initiatorz = getResizeableObjIdArrayObjVar(darkEnclave, pvpAction + VAR_INITIATORS);
|
|
}
|
|
|
|
resizeable obj_id[] victimz = new obj_id[0];
|
|
if(hasObjVar(darkEnclave, pvpAction + VAR_VICTIMS))
|
|
{
|
|
victimz = getResizeableObjIdArrayObjVar(darkEnclave, pvpAction + VAR_VICTIMS);
|
|
}
|
|
|
|
resizeable int[] timez = new int[0];
|
|
if(hasObjVar(darkEnclave, pvpAction + VAR_START_TIMESTAMPS))
|
|
{
|
|
timez = getResizeableIntArrayObjVar(darkEnclave, pvpAction + VAR_START_TIMESTAMPS);
|
|
if(timez == null)
|
|
{
|
|
LOG("force_rank", "Variable " + pvpAction + VAR_START_TIMESTAMPS + " returned a null array!");
|
|
}
|
|
}
|
|
|
|
dictionary actionData = packageActionData(initiatorz, victimz, timez);
|
|
|
|
return validatePvPActionData(actionData);
|
|
}
|
|
|
|
//
|
|
// returns @data if valid, or null if not valid of empty
|
|
//
|
|
dictionary validatePvPActionData(dictionary data)
|
|
{
|
|
if(data == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if(!data.containsKey("initiators") || !data.containsKey("victims") || !data.containsKey("times"))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
obj_id[] inits = data.getObjIdArray("initiators");
|
|
obj_id[] victs = data.getObjIdArray("victims");
|
|
int[] startTms = data.getIntArray("times");
|
|
|
|
if(victs == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
int len = victs.length;
|
|
if(inits == null || startTms == null || inits.length != len || startTms.length != len)
|
|
{
|
|
trace.log("force_rank", "force_rank::validatePvPActionData -> Victim/Initiator/TimeStamp arrays have mismatched length. Data not written.", null, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return null;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
//
|
|
// designed to be called when the enclave fires up (onInit). scrubs the data on the enclave and removes any
|
|
// expired PvPActions (vendetta, etc, etc), based on the ACTION_*_DURATION vars
|
|
//
|
|
void deleteExpiredPvPActions(obj_id darkEnclave)
|
|
{
|
|
resizeable obj_id[] initiatorz = new obj_id[0];
|
|
resizeable obj_id[] victimz = new obj_id[0];
|
|
resizeable int[] timez = new int[0];
|
|
string[] actions = {ACTION_VENDETTA, ACTION_PURGE_COUNCIL, ACTION_BANISHMENT};
|
|
int[] durations = {ACTION_VENDETTA_DURATION, ACTION_PURGE_COUNCIL_DURATION, ACTION_BANISHMENT_DURATION};
|
|
int now = getGameTime();
|
|
|
|
for(int i = 0; i < actions.length; i++)
|
|
{
|
|
dictionary data = getAndValidatePvPActionData(actions[i], darkEnclave);
|
|
|
|
if(data == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
utils.concatArrays(initiatorz, data.getObjIdArray("initiators"));
|
|
utils.concatArrays(victimz, data.getObjIdArray("victims"));
|
|
utils.concatArrays(timez, data.getIntArray("times"));
|
|
|
|
int x = 0;
|
|
while(x < timez.length)
|
|
{
|
|
if(now - timez[x] >= durations[x])
|
|
{
|
|
utils.removeElementAt(timez, x);
|
|
utils.removeElementAt(victimz, x);
|
|
utils.removeElementAt(initiatorz, x);
|
|
// don't increment iterator since we removed an element
|
|
|
|
// ToDo: Message players to let them know the action has ended. have to do it in email, since this
|
|
// method will only run OnInit and no player will be connected
|
|
}
|
|
else
|
|
{
|
|
x++;
|
|
}
|
|
}
|
|
|
|
dictionary newData = packageActionData(initiatorz, victimz, timez);
|
|
// write the data back to the enclave
|
|
setPvPActionData(newData, actions[i], darkEnclave);
|
|
|
|
timez.clear();
|
|
victimz.clear();
|
|
initiatorz.clear();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// clear out any pvp action that are registered on the @enclave for the @player is a part of. this should only be called as a result
|
|
// of dark jedi pvp due to some Pvp action imposed on @player. this method will handle sending out notification messages
|
|
//
|
|
void demoteDeadPlayerToRankZero(obj_id player, obj_id darkEnclave)
|
|
{
|
|
resizeable obj_id[] peaceTarget = new obj_id[0];
|
|
peaceTarget.add(player);
|
|
resizeable obj_id[] recips = new obj_id[0];
|
|
utils.concatArrays(recips, getAllPlayersInForceRank(darkEnclave, -1));
|
|
|
|
demoteForceRank(darkEnclave, utils.getRealPlayerFirstName(player), 0);
|
|
|
|
notifyPlayerOfPvPActionEnd(null, ACTION_BANISHMENT, peaceTarget, recips, false);
|
|
|
|
string[] lists = {VAR_VICTIMS, VAR_INITIATORS}; // clear actions for which @player is either a victim or an initiator
|
|
string[] actions = {ACTION_PURGE_COUNCIL, ACTION_CANDIDATE_SUDDEN_DEATH, ACTION_BANISHMENT, ACTION_VENDETTA};
|
|
|
|
for(int i = 0; i < actions.length; i++)
|
|
{
|
|
_clearPvPActionDataForPlayer(player, lists, actions[i], darkEnclave);
|
|
}
|
|
|
|
removeObjVar(player, VAR_NOTIFY_ENCLAVE_OF_DEATH);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// will erase any pvp action of type pvpCondition that involve @player.
|
|
// @whichLists will need to have VAR_VICTIMS or VAR_INITIATORS or both in it, depending on if you want to clear all the
|
|
// pvp conditions that @player is a target of, or to clear all the instances that @player initiated.
|
|
//
|
|
boolean _clearPvPActionDataForPlayer(obj_id player, string[] whichLists, string pvpAction, obj_id darkEnclave)
|
|
{
|
|
dictionary data = getAndValidatePvPActionData(pvpAction, darkEnclave);
|
|
|
|
if(data == null)
|
|
{
|
|
trace.log("force_rank", "force_rank::_clearPvPActionDataForPlayer: -> Method called but no " + pvpAction + " actions to clear for " + utils.getRealPlayerFirstName(player), player, trace.TL_WARNING | trace.TL_DEBUG);
|
|
return false;
|
|
}
|
|
|
|
resizeable obj_id[] inits = new obj_id[0];
|
|
utils.concatArrays(inits, data.getObjIdArray("initiators"));
|
|
|
|
resizeable obj_id[] victs = new obj_id[0];
|
|
utils.concatArrays(victs, data.getObjIdArray("victims"));
|
|
|
|
resizeable int[] startTms = new int[0];
|
|
utils.concatArrays(startTms, data.getIntArray("times"));
|
|
|
|
// grab initial index to see if @player exists at all in @whichList
|
|
for(int i = 0; i < whichLists.length; i++)
|
|
{
|
|
int idx = -1;
|
|
if(whichLists[i] == VAR_INITIATORS)
|
|
{
|
|
idx = utils.getElementPositionInArray(inits, player);
|
|
}
|
|
else if(whichLists[i] == VAR_VICTIMS)
|
|
{
|
|
idx = utils.getElementPositionInArray(victs, player);
|
|
}
|
|
else
|
|
{
|
|
trace.log("force_rank", "force_rank::clearAllPvPActionsForPlayer passed bad value for @whichList array . Bailing without clearing action status.", player, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
continue;
|
|
}
|
|
|
|
while(idx > -1)
|
|
{
|
|
inits = utils.removeElementAt(inits, idx);
|
|
victs = utils.removeElementAt(victs, idx);
|
|
startTms = utils.removeElementAt(startTms, idx);
|
|
|
|
if(whichLists[i] == VAR_INITIATORS)
|
|
{
|
|
idx = utils.getElementPositionInArray(inits, player);
|
|
}
|
|
else
|
|
{
|
|
idx = utils.getElementPositionInArray(victs, player);
|
|
}
|
|
}
|
|
}
|
|
|
|
dictionary newData = packageActionData(inits, victs, startTms);
|
|
|
|
// write the data back to the enclave
|
|
setPvPActionData(newData, pvpAction, darkEnclave);
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// returns @true or @false depending on whether or not @player1 & @player2 are part of the same vendetta. !!! @vendettaData is assumed to be valid !!!
|
|
//
|
|
boolean isPartOfSameVendetta(obj_id player1, obj_id player2, dictionary vendettaData)
|
|
{
|
|
resizeable obj_id[] initiatorz = new obj_id[0];
|
|
utils.concatArrays(initiatorz, vendettaData.getObjIdArray("initiators"));
|
|
|
|
resizeable obj_id[] victimz = new obj_id[0];
|
|
utils.concatArrays(victimz, vendettaData.getObjIdArray("victims"));
|
|
|
|
// see if player1 is the agressor in any vendetta
|
|
int idx = initiatorz.indexOf(player1);
|
|
while(idx > -1)
|
|
{
|
|
if(victimz[idx] == player2)
|
|
{
|
|
trace.log("force_rating", "force_rank::isPartOfSameVendetta: -> " + utils.getRealPlayerFirstName(player1) + " is same vendetta as " + utils.getRealPlayerFirstName(player2), player1, trace.TL_DEBUG);
|
|
return true;
|
|
}
|
|
// see if player1 has another vendetta registered for some reason
|
|
idx = initiatorz.indexOf(player1, idx+1);
|
|
}
|
|
|
|
// see if player1 is the victim of any vendetta
|
|
idx = victimz.indexOf(player1);
|
|
while(idx > -1)
|
|
{
|
|
if(initiatorz[idx] == player2)
|
|
{
|
|
trace.log("force_rating", "force_rank::isPartOfSameVendetta: -> " + utils.getRealPlayerFirstName(player1) + " is same vendetta as " + utils.getRealPlayerFirstName(player2), player1, trace.TL_DEBUG);
|
|
return true;
|
|
}
|
|
|
|
// see if player1 has another vendetta registered for some reason
|
|
idx = victimz.indexOf(player1, idx+1);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// @returns true or false depending on whether or not @player has initiated @pvpAction
|
|
//
|
|
boolean isPvPActionInitiator(obj_id player, dictionary actionData1)
|
|
{
|
|
obj_id[] initiatorz = actionData1.getObjIdArray("initiators");
|
|
|
|
// grab initial index to see if @player exists at all in @whichList
|
|
if(utils.getElementPositionInArray(initiatorz, player) > -1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// @returns true or false depending on whether or not @player has fallen victim @pvpAction !!! @actionData is presumed to be valid !!!
|
|
//
|
|
boolean isPvPActionVictim(obj_id player, dictionary actionData2)
|
|
{
|
|
obj_id[] victimz = actionData2.getObjIdArray("victims");
|
|
|
|
// grab initial index to see if @player exists at all
|
|
int idx = utils.getElementPositionInArray(victimz, player);
|
|
if(idx > -1)
|
|
{
|
|
trace.log("force_rank", "force_rank::isPvPActionVictim: -> " + utils.getRealPlayerFirstName(player) + " IS a victim.", player, trace.TL_DEBUG);
|
|
return true;
|
|
}
|
|
|
|
trace.log("force_rank", "force_rank::isPvPActionVictim: -> " + utils.getRealPlayerFirstName(player) + " is NOT a victim.", player, trace.TL_DEBUG);
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// @returns true or false, depending on whether or not @player is part of (either initiator OR victim) of the given @pvpAction
|
|
//
|
|
boolean isPartOfPvPAction(obj_id player,obj_id darkEnclave, dictionary actionData3)
|
|
{
|
|
return (isPvPActionInitiator(player, actionData3) || isPvPActionVictim(player, actionData3));
|
|
}
|
|
|
|
//
|
|
// @returns true or false if @player1 is part of the same rank as @player2 and they are both registered as being
|
|
// part of a ACTION_CANDIDATE_SUDDEN_DEATH pvp action
|
|
//
|
|
boolean bothArePartOfSameSuddenDeathRank(obj_id player1, obj_id player2, obj_id darkEnclave, dictionary suddenDeathData)
|
|
{
|
|
if(getForceRank(darkEnclave, utils.getRealPlayerFirstName(player1)) != getForceRank(darkEnclave, utils.getRealPlayerFirstName(player2)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(isPvPActionVictim(player1, suddenDeathData) && isPvPActionVictim(player2, suddenDeathData))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// private helper function that adds all council members to the ACTION_PURGE_COUNCIL list
|
|
//
|
|
boolean _initiateCouncilPurge(obj_id darkEnclave, obj_id purger)
|
|
{
|
|
obj_id[] members = getAllPlayersInForceRank(darkEnclave, COUNCIL_RANK_NUMBER);
|
|
if(members == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
trace.log("force_rank", "force_rank::_initiateCouncilPurge: -> Council rank (" + COUNCIL_RANK_NUMBER + ") has " + members.length + " valid members.", darkEnclave, trace.TL_DEBUG);
|
|
if(members.length < 1)
|
|
{
|
|
trace.log("force_rank", "force_rank::_initiateCouncilPurge: -> Council purge not done as there are no Council members to purge.", purger, trace.TL_WARNING | trace.TL_DEBUG);
|
|
return true;
|
|
}
|
|
|
|
// council purges should never overlap due to timing issues, so any existing council purge will be overwritten
|
|
resizeable obj_id[] victimz = new obj_id[0];
|
|
resizeable obj_id[] initiatorz = new obj_id[0];
|
|
resizeable int[] timez = new int[0];
|
|
|
|
int time = getGameTime();
|
|
|
|
for(int i = 0; i < members.length; i++)
|
|
{
|
|
if(members[i] != null/* && isIdValid(members[i])*/)
|
|
{
|
|
utils.addElement(victimz, members[i]);
|
|
utils.addElement(initiatorz, purger);
|
|
utils.addElement(timez, time);
|
|
}
|
|
}
|
|
|
|
if(victimz.size() > 0)
|
|
{
|
|
dictionary data = packageActionData(initiatorz, victimz, timez);
|
|
setPvPActionData(data, ACTION_PURGE_COUNCIL, darkEnclave);
|
|
}
|
|
|
|
|
|
// send notifications to all players
|
|
resizeable obj_id[] recips = new obj_id[0];
|
|
utils.concatArrays(recips, getAllPlayersInForceRank(darkEnclave, -1));
|
|
|
|
notifyPlayerOfPvPActionStart(purger, ACTION_PURGE_COUNCIL, victimz, recips, darkEnclave);
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// @returns true or false depending on wether or not the call was successful
|
|
// @initiator will be aded as an initiator and @allVictims as the...victim for the given
|
|
// @pvpAction. @allVictims may be null if the pvpAction is ACTION_PURGE_COUNCIL, as the
|
|
// @victim parm is ignored for this action since everyone who is currently listed in the
|
|
// council will automagically be added as victims.
|
|
//
|
|
boolean startPvPAction(obj_id initiator, resizeable obj_id[] allVictims, string pvpAction, obj_id darkEnclave)
|
|
{
|
|
trace.log("force_rank", "force_rank::startPvPAction: -> " + pvpAction + " started by " + initiator, initiator, trace.TL_CS_LOG | trace.TL_DEBUG);
|
|
if(pvpAction == ACTION_PURGE_COUNCIL)
|
|
{
|
|
// _initiateCouncilPurge does the messaging for council purges
|
|
return _initiateCouncilPurge(darkEnclave, initiator);
|
|
}
|
|
|
|
dictionary data = getAndValidatePvPActionData(pvpAction, darkEnclave);
|
|
if(allVictims == null || allVictims.length < 1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
resizeable obj_id[] initiatorz = new obj_id[0];
|
|
resizeable obj_id[] victimz = new obj_id[0];
|
|
resizeable int[] timez = new int[0];
|
|
int time = getGameTime();
|
|
|
|
if(data != null)
|
|
{
|
|
utils.concatArrays(initiatorz, data.getObjIdArray("initiators"));
|
|
utils.concatArrays(victimz, data.getObjIdArray("victims"));
|
|
utils.concatArrays(timez, data.getIntArray("times"));
|
|
}
|
|
|
|
for(int i = 0; i < allVictims.length; i++)
|
|
{
|
|
utils.addElement(initiatorz, initiator);
|
|
utils.addElement(timez, time);
|
|
}
|
|
|
|
utils.concatArrays(victimz, allVictims);
|
|
|
|
dictionary newData = packageActionData(initiatorz, victimz, timez);
|
|
|
|
// write the data back to the enclave
|
|
setPvPActionData(newData, pvpAction, darkEnclave);
|
|
|
|
string victimList = "";
|
|
for(int i = 0; i < allVictims.length; i++)
|
|
{
|
|
victimList += "" + allVictims[i] + ",";
|
|
}
|
|
trace.log("force_rank", "Dark Jedi PvP Action Started: " + pvpAction + ". Initiator: " + initiator + ", Victims: " + victimList, null, trace.TL_CS_LOG | trace.TL_DEBUG);
|
|
|
|
// notify the targets and initiators that the action has been initiated.
|
|
// the actual flagging gets done in the message handler player_force_rank::pvpActionMessage
|
|
|
|
resizeable obj_id[] recips = new obj_id[0];
|
|
|
|
if(pvpAction.equals(ACTION_VENDETTA))
|
|
{
|
|
recips.add(initiator);
|
|
recips.add(victimz[0]);
|
|
}
|
|
else if(pvpAction.equals(ACTION_BANISHMENT))
|
|
{
|
|
utils.concatArrays(recips, getAllPlayersInForceRank(darkEnclave, -1));
|
|
}
|
|
else if(pvpAction.equals(ACTION_CANDIDATE_SUDDEN_DEATH))
|
|
{
|
|
utils.concatArrays(recips, allVictims); // in this case only the victims need to be notified
|
|
}
|
|
|
|
// send the notification messages to recips. Msg recipients will start the PEFs
|
|
notifyPlayerOfPvPActionStart(initiator, pvpAction, allVictims, recips, darkEnclave);
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// @theInitiator -> person who started the @pvpAction, or in case of CANDIDATE_SUDDEN_DEATH, the enclave
|
|
// @pvpAction -> the ACTION_* to start
|
|
// @actionTargets -> victims of said action.
|
|
// @msgRecipients -> people who need to be notified of this action starting, all of which who will make everyone in @actionTargets their enemy
|
|
//
|
|
void notifyPlayerOfPvPActionStart(obj_id theInitiator, string pvpAction, resizeable obj_id[] actionTargets, resizeable obj_id[] msgRecipients, obj_id darkEnclave)
|
|
{
|
|
if(msgRecipients == null || msgRecipients.length < 1)
|
|
{
|
|
trace.log("force_rank", "force_rank::notifyPlayerOfPvPActionStart: -> @msgRecipients null or zero length. No one notified.", theInitiator, trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
dictionary parms = new dictionary();
|
|
|
|
parms.put("initiator", theInitiator);
|
|
parms.put("pvpAction", pvpAction);
|
|
parms.put("actionTargets", actionTargets);
|
|
parms.put("enclave", darkEnclave);
|
|
|
|
for(int i = 0; i < msgRecipients.length; i++)
|
|
{
|
|
messageTo(msgRecipients[i], "msgPvPActionStart", parms, 0, false);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// @killer is the person who ended the @pvpAction due to killing the @actionTargets, or null if @actionTimedOut
|
|
// @pvpAction is the ACTION_* that has come to an end
|
|
// @actionTargets are the people who need to be peaced as a result of this action ending
|
|
//
|
|
void notifyPlayerOfPvPActionEnd(obj_id killer, string pvpAction, resizeable obj_id[] peaceTargets, resizeable obj_id[] msgRecipients, boolean actionTimedOut)
|
|
{
|
|
if(msgRecipients == null || msgRecipients.length < 1 || peaceTargets == null || peaceTargets.length < 1)
|
|
{
|
|
trace.log("force_rank", "force_rank::notifyPlayerOfPvPActionEnd: -> @msgRecipients null or zero length. No one notified.", killer, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
return;
|
|
}
|
|
|
|
dictionary parms = new dictionary();
|
|
|
|
if(killer != null)
|
|
{
|
|
parms.put("killer", killer);
|
|
}
|
|
|
|
parms.put("pvpAction", pvpAction);
|
|
parms.put("peaceTargets", peaceTargets);
|
|
parms.put("actionTimedOut", actionTimedOut);
|
|
|
|
for(int i = 0; i < msgRecipients.length; i++)
|
|
{
|
|
messageTo(msgRecipients[i], "msgPvPActionEnd", parms, 0, false);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// returns a list of players that are at war with @player due to a vendetta. !!!@pvpAction is assumed to be valid!!! this::validatePvPActionData
|
|
//
|
|
obj_id[] getMyVendettaEnemies(dictionary vendettaData, obj_id player)
|
|
{
|
|
resizeable obj_id[] initiatorz = new obj_id[0];
|
|
resizeable obj_id[] victimz = new obj_id[0];
|
|
resizeable obj_id[] vEnemies = new obj_id[0];
|
|
|
|
utils.concatArrays(initiatorz, vendettaData.getObjIdArray("initiators"));
|
|
utils.concatArrays(victimz, vendettaData.getObjIdArray("victims"));
|
|
|
|
// see if player is the agressor in any vendetta
|
|
int idx = initiatorz.indexOf(player);
|
|
while(idx > -1)
|
|
{
|
|
utils.addElement(vEnemies, victimz[idx]);
|
|
idx = initiatorz.indexOf(player, idx+1);
|
|
}
|
|
|
|
// see if player is the victim of any vendetta
|
|
idx = victimz.indexOf(player);
|
|
while(idx > -1)
|
|
{
|
|
utils.addElement(vEnemies, initiatorz[idx]);
|
|
idx = victimz.indexOf(player, idx+1);
|
|
}
|
|
|
|
trace.log("force_rating", "force_rank::getMyVendettaEnemies: -> " + utils.getRealPlayerFirstName(player) + " has " + vEnemies.length + " vendettas.", player, trace.TL_DEBUG);
|
|
return vEnemies;
|
|
}
|
|
|
|
obj_id[] getMySuddenDeathEnemies(dictionary suddenDeathData, obj_id player, obj_id darkEnclave)
|
|
{
|
|
resizeable obj_id[] candidateVictims = new obj_id[0];
|
|
resizeable obj_id[] enemies = new obj_id[0];
|
|
|
|
if(!isPvPActionVictim(player, suddenDeathData))
|
|
{
|
|
return enemies;
|
|
}
|
|
|
|
utils.concatArrays(candidateVictims, suddenDeathData.getObjIdArray("victims"));
|
|
|
|
int playerRank = getForceRank(darkEnclave, utils.getRealPlayerFirstName(player));
|
|
if(playerRank < 1)
|
|
{
|
|
return new obj_id[0];
|
|
}
|
|
|
|
for(int i = 0; i < candidateVictims.length; i++)
|
|
{
|
|
if((candidateVictims[i] != player) && (getForceRank(darkEnclave, utils.getRealPlayerFirstName(candidateVictims[i])) == playerRank))
|
|
{
|
|
utils.addElement(enemies, candidateVictims[i]);
|
|
}
|
|
}
|
|
|
|
return enemies;
|
|
}
|
|
|
|
|
|
obj_id[] getEnemiesForPvPAction(obj_id player, string pvpAction, obj_id darkEnclave)
|
|
{
|
|
dictionary data = getAndValidatePvPActionData(pvpAction, darkEnclave);
|
|
if(data == null)
|
|
{
|
|
return new obj_id[0];
|
|
}
|
|
|
|
if(pvpAction.equals(ACTION_VENDETTA))
|
|
{
|
|
return getMyVendettaEnemies(data, player);
|
|
}
|
|
|
|
if(pvpAction.equals(ACTION_CANDIDATE_SUDDEN_DEATH))
|
|
{
|
|
return getMySuddenDeathEnemies(data, player, darkEnclave);
|
|
}
|
|
|
|
// left is ACTION_BANISHMENT || ACTION_PURGE_COUNCIL ... all of which are ALL enemies to everyone
|
|
|
|
return data.getObjIdArray("victims");
|
|
}
|
|
|
|
//
|
|
// called by player_force_rank on init to get an updated list of PEFd enemies
|
|
//
|
|
void requestPEFs(obj_id player)
|
|
{
|
|
if(!hasObjVar(player, VAR_MY_ENCLAVE_ID))
|
|
{
|
|
getEnclaveObjId(player, getCouncilAffiliation(player), "enclaveIdResponse");
|
|
return;
|
|
}
|
|
|
|
obj_id myEnclave = getObjIdObjVar(player, VAR_MY_ENCLAVE_ID);
|
|
if(getForceRank(myEnclave, utils.getRealPlayerFirstName(player)) < 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dictionary parms = new dictionary();
|
|
parms.put("sender", player);
|
|
messageTo(myEnclave, "PEFSynchRequest", parms, 0, false);
|
|
|
|
trace.log("force_rank", "force_rank::requestPEFs-> requesting enemy list from enclave", player, trace.TL_DEBUG);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// @returns a list of players that are considered the enemies of @player given data stored on the @enclave
|
|
//
|
|
obj_id[] getCurrentDarkJediEnemies(obj_id player, obj_id enclave)
|
|
{
|
|
resizeable obj_id[] enemies = new obj_id[0];
|
|
|
|
dictionary banishmentData = getAndValidatePvPActionData(ACTION_BANISHMENT, enclave);
|
|
dictionary purgeData = getAndValidatePvPActionData(ACTION_PURGE_COUNCIL, enclave);
|
|
|
|
|
|
// if player is target of either a council purge or a banishment, then ALL other players in the ranks are their enemy
|
|
if((purgeData != null && isPvPActionVictim(player, purgeData)) || (banishmentData != null && isPvPActionVictim(player, banishmentData)))
|
|
{
|
|
trace.log("force_rank", "force_rank::getCurrentDarkJediEnemies: -> " + utils.getRealPlayerFirstName(player) + " is victim of purge/banishment. Returning ALL rank members as enemy.", player, trace.TL_DEBUG);
|
|
obj_id[] enemies2 = getAllPlayersInForceRank(enclave, -1);
|
|
utils.concatArrays(enemies, enemies2);
|
|
}
|
|
else
|
|
{
|
|
trace.log("force_rank", "force_rank::getCurrentDarkJediEnemies: -> " + utils.getRealPlayerFirstName(player) + " is NOT victim of purge/banishment. Checking for specific enemies...", player, trace.TL_DEBUG);
|
|
utils.concatArrays(enemies, getEnemiesForPvPAction(player, ACTION_VENDETTA, enclave));
|
|
utils.concatArrays(enemies, getEnemiesForPvPAction(player, ACTION_BANISHMENT, enclave));
|
|
utils.concatArrays(enemies, getEnemiesForPvPAction(player, ACTION_PURGE_COUNCIL, enclave));
|
|
utils.concatArrays(enemies, getEnemiesForPvPAction(player, ACTION_CANDIDATE_SUDDEN_DEATH, enclave));
|
|
}
|
|
|
|
return enemies;
|
|
}
|
|
|
|
//
|
|
// convenience method to return @true or @false, depending on whether or not the @player is force ranked
|
|
//
|
|
boolean isForceRanked(obj_id player)
|
|
{
|
|
return (getForceRank(player) >= 0);
|
|
}
|
|
|
|
//
|
|
// @returns true or false, depending on wether or not the @pet belongs to a factioned player
|
|
//
|
|
boolean canForceRankedPetEnterEnclave(obj_id pet, obj_id enclave)
|
|
{
|
|
if(pet_lib.isPet(pet))
|
|
{
|
|
if(!pet_lib.hasMaster(pet))
|
|
{
|
|
// not a pet that we can validate.
|
|
return false;
|
|
}
|
|
|
|
obj_id master = getMaster(pet); // pet's master has already been validated in previous call to pet_lib.hasMaster
|
|
|
|
// if the pet's master is force ranked, let it through
|
|
return (isForceRanked(master) && (isPlayersEnclave(enclave, master)));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// @returns true or false, depending on whether or not the @player has access to the @enclave
|
|
//
|
|
boolean isPlayersEnclave(obj_id enclave, obj_id player)
|
|
{
|
|
if (getCouncilAffiliation(enclave) == getCouncilAffiliation(player))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
//
|
|
// @creates terminals for the Enclaves. Returns false on error or no terminals created.
|
|
//
|
|
|
|
boolean createEnclaveTerminals(obj_id enclave)
|
|
{
|
|
if (!isIdValid(enclave))
|
|
{
|
|
trace.log("force_rank", "force_rank.createEnclaveTerminals -- enclave is invalid", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
|
|
return false;
|
|
}
|
|
if (!hasScript(enclave, force_rank.SCRIPT_ENCLAVE_CONTROLLER))
|
|
{
|
|
trace.log("force_rank", "force_rank.createEnclaveTerminals -- " + enclave + " is not an enclave building.", enclave, trace.TL_ERROR_LOG | trace.TL_DEBUG);
|
|
|
|
return false;
|
|
}
|
|
|
|
// Check to see if the enclave already has terminals.
|
|
obj_id voting_terminal = getVotingTerminal(enclave);
|
|
obj_id arena_terminal = getArenaTerminal(enclave);
|
|
obj_id chal_voting_terminal = getChallengeVotingTerminal(enclave);
|
|
|
|
if (isIdValid(voting_terminal))
|
|
{
|
|
if (getCouncilAffiliation(enclave) == DARK_COUNCIL)
|
|
{
|
|
if (isIdValid(arena_terminal))
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (isIdValid(chal_voting_terminal))
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Clean up the old stuff and make new stuff
|
|
if (isIdValid(voting_terminal))
|
|
destroyObject(voting_terminal);
|
|
|
|
if (isIdValid(arena_terminal))
|
|
destroyObject(arena_terminal);
|
|
|
|
if (isIdValid(chal_voting_terminal))
|
|
destroyObject(chal_voting_terminal);
|
|
|
|
int numRows = dataTableGetNumRows (JEDI_TERMINAL_DATATABLE);
|
|
string area = getCurrentSceneName();
|
|
|
|
for (int i = 0; i < numRows; i++)
|
|
{
|
|
dictionary row = dataTableGetRow(JEDI_TERMINAL_DATATABLE, i);
|
|
if (row == null)
|
|
continue;
|
|
|
|
if (row.getInt("Council") == getCouncilAffiliation(enclave))
|
|
{
|
|
float x = row.getFloat("x");
|
|
float y = row.getFloat("y");
|
|
float z = row.getFloat("z");
|
|
float rot = row.getFloat("Rotation");
|
|
string cell_name = row.getString("Cell");
|
|
if (cell_name == null || cell_name.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.createEnclaveTerminals -- cell name is null for " + enclave);
|
|
continue;
|
|
}
|
|
string template = row.getString("Template");
|
|
if (template == null || cell_name.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.createEnclaveTerminals -- can't find template " + template + " for " + enclave);
|
|
continue;
|
|
}
|
|
obj_id cell = getCellId(enclave, cell_name);
|
|
if (cell == null || cell_name.length() < 1)
|
|
{
|
|
LOG("force_rank", "force_rank.createEnclaveTerminals -- unknown cell name " + row.getString("Cell") + " for " + enclave);
|
|
continue;
|
|
}
|
|
|
|
location loc = new location(x, y, z, area, cell);
|
|
obj_id newTerminal = createObjectInCell(template, enclave, cell_name, loc);
|
|
LOG("force_rank", "force_rank.createEnclaveTerminals -- creating new terminal " + newTerminal + " for " + enclave);
|
|
//LOG("force_rank", "force_rank.createEnclaveTerminals -- terminal: " + newTerminal);
|
|
setYaw(newTerminal, rot);
|
|
// UPDATE 11/14/14: No need for persisting objects anymore.
|
|
//persistObject(newTerminal);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int getPetitionInterval()
|
|
{
|
|
string config = getConfigSetting("GameServer", "frsPetitionInterval");
|
|
int value = utils.stringToInt(config);
|
|
if (value > 0)
|
|
return value;
|
|
else
|
|
return PETITION_INTERVAL;
|
|
}
|
|
|
|
int getVoteInterval()
|
|
{
|
|
string config = getConfigSetting("GameServer", "frsVoteInterval");
|
|
int value = utils.stringToInt(config);
|
|
if (value > 0)
|
|
return value;
|
|
else
|
|
return VOTING_INTERVAL;
|
|
}
|
|
|
|
int getAcceptanceInterval()
|
|
{
|
|
string config = getConfigSetting("GameServer", "frsAcceptanceInterval");
|
|
int value = utils.stringToInt(config);
|
|
if (value > 0)
|
|
return value;
|
|
else
|
|
return ACCEPTANCE_INTERVAL;
|
|
}
|
|
|
|
int getDemotionInterval()
|
|
{
|
|
string config = getConfigSetting("GameServer", "frsDemotionInterval");
|
|
int value = utils.stringToInt(config);
|
|
if (value > 0)
|
|
return value;
|
|
else
|
|
return REQUEST_DEMOTION_DURATION;
|
|
}
|
|
|
|
int getXpInterval()
|
|
{
|
|
string config = getConfigSetting("GameServer", "frsXpInterval");
|
|
int value = utils.stringToInt(config);
|
|
if (value > 0)
|
|
return value;
|
|
else
|
|
return XP_MAINTENANCE_INTERVAL;
|
|
}
|
|
|
|
|
|
|
|
/**** PRIVATE FUNCTIONS ************************************************
|
|
|
|
/***********************************************************************
|
|
* @brief requests an update from the cluster wide data system
|
|
*
|
|
* @param string player player first name
|
|
* @param int council
|
|
* @param int rank
|
|
* @param boolean lock_data
|
|
*
|
|
* @return return boolean
|
|
*********************************************************************/
|
|
boolean _updateForceRankData(obj_id source, int council, int data_mode, string params, string handler, boolean lock_data)
|
|
{
|
|
// Datamodes *****************
|
|
// 0: Enclave data save -- not used with this function
|
|
// 1: Request rank member list
|
|
// 2: Request pvp board data
|
|
// 3: Promote player
|
|
// 4: Demote player
|
|
// 5: Demote player (enclave authoritative)
|
|
// 6: Enclave obj_id
|
|
// 7: Update pvp board data.
|
|
// 8: Reset cluster data
|
|
// 9: Rename rank member
|
|
|
|
if (!isIdValid(source))
|
|
{
|
|
LOG("force_rank", "force_rank._updateForceRankData -- source is invalid.");
|
|
return false;
|
|
}
|
|
if (params == null)
|
|
{
|
|
LOG("force_rank", "force_rank._updateForceRankData -- params is null.");
|
|
return false;
|
|
}
|
|
if (handler == null)
|
|
{
|
|
LOG("force_rank", "force_rank._updateForceRankData -- handler is null.");
|
|
return false;
|
|
}
|
|
|
|
// Update the Clusterwide data.
|
|
int request_id = getClusterWideData(force_rank.CLUSTER_DATA_NAME, force_rank.STRING_CLUSTER_ENCLAVE_NAME + council, lock_data, source);
|
|
utils.setScriptVar(source, SCRIPT_VAR_DATA_REQUEST + request_id, data_mode);
|
|
utils.setScriptVar(source, SCRIPT_VAR_PARAMS_REQUEST + request_id, params);
|
|
utils.setScriptVar(source, SCRIPT_VAR_HANDLER_REQUEST + request_id, handler);
|
|
if (!hasScript(source, SCRIPT_DATA_HANDLER))
|
|
attachScript(source, SCRIPT_DATA_HANDLER);
|
|
|
|
return true;
|
|
}
|
|
|