mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-31 00:15:54 -04:00
922 lines
34 KiB
Plaintext
922 lines
34 KiB
Plaintext
/**
|
|
* Title: veteran_deprecated.scriptlib
|
|
* Description: handles the veteran reward system
|
|
*/
|
|
|
|
/***** INCLUDES ********************************************************/
|
|
|
|
include library.features;
|
|
|
|
/***** CONSTANTS *******************************************************/
|
|
|
|
// !!!NOTE: all time values are in days
|
|
const int UNENTITLED_TIME_LIMIT = 14; // time a player may be unentitled before losing veteran status
|
|
const int MONTHS_PER_MILESTONE = 3;
|
|
const int DAYS_PER_MONTH = 30;
|
|
const int DAYS_PER_MILESTONE = MONTHS_PER_MILESTONE * DAYS_PER_MONTH;
|
|
const int REWARD_FLAGS_SIZE = ((12 / MONTHS_PER_MILESTONE) * 10) / 32 + 1; // 10 years of rewards, 1 bit per milestone
|
|
const int MAX_MILESTONE = REWARD_FLAGS_SIZE * 32;
|
|
|
|
// base string table
|
|
const string VETERAN_STRING_TABLE = "veteran";
|
|
|
|
// the rewards datatable data
|
|
const string REWARDS_DATATABLE = "datatables/veteran/rewards.iff";
|
|
const string REWARDS_COLUMN_TEMPLATE = "template";
|
|
const string REWARDS_COLUMN_SCRIPT = "script";
|
|
const string REWARDS_COLUMN_MILESTONE = "milestone"; // this is base-1, we need to convert it to base-0 when we read it
|
|
const string REWARDS_COLUMN_ONETIME = "oneTime";
|
|
const string REWARDS_COLUMN_NOTRADE = "noTrade";
|
|
const string REWARDS_COLUMN_NODELETE = "noDelete";
|
|
const string REWARDS_COLUMN_NOMOVE = "noMove";
|
|
const string REWARDS_COLUMN_REQUIREDGAMEFEATUREBITANY = "requiredGameFeatureBitAny";
|
|
const string REWARDS_COLUMN_REQUIREDGAMEFEATUREBITALL = "requiredGameFeatureBitAll";
|
|
const string REWARDS_COLUMN_REQUIREDSUBSCRIPTIONFEATUREBITANY = "requiredSubscriptionFeatureBitAny";
|
|
const string REWARDS_COLUMN_REQUIREDSUBSCRIPTIONFEATUREBITALL = "requiredSubscriptionFeatureBitAll";
|
|
|
|
// the emotes datatable data
|
|
const string EMOTES_DATATABLE = "datatables/veteran/emotes.iff";
|
|
const string EMOTES_COLUMN_EMOTE = "emote";
|
|
const string EMOTES_COLUMN_GROUP = "group";
|
|
|
|
// callback when a player selects a reward
|
|
const string HANDLER_SELECT_VETERAN_REWARD = "handleVeteranRewardSelected";
|
|
// callback when a player selects a milestone
|
|
const string HANDLER_SELECT_VETERAN_MILESTONE = "handleVeteranMilestoneSelected";
|
|
// callback when a player responds to the cofirmation window when
|
|
// the milestone of the selected reward doesn not match the milestone
|
|
// that the player is claiming
|
|
const string HANDLER_SELECT_VETERAN_REWARD_CONFIRM = "handleVeteranRewardConfirmed";
|
|
|
|
const string OBJVAR_TIME_ACTIVE = "veteran.timeActive";
|
|
const string OBJVAR_REWARDS_RECEIVED = "veteran.rewardsReceived";
|
|
const string OBJVAR_MILESTONES_NOTIFIED = "veteran.milestonesNotified";
|
|
const string OBJVAR_ONETIME_REWARDS_RECEIVED = "veteran.onetime";
|
|
const string OBJVAR_VETERAN_EMOTES = "veteran.emotes";
|
|
|
|
// one year anniversary rewards
|
|
const string OBJVAR_ONE_YEAR_ANNIVERSARY = "anniversary.oneYear";
|
|
const string OBJVAR_ONE_YEAR_ANNIVERSARY_OVERRIDE = "anniversary.override";
|
|
const string TEMPLATE_ONE_YEAR_ANNIVERSARY = "object/tangible/veteran_reward/one_year_anniversary/painting_";
|
|
const string_id SID_ONE_YEAR_ANNIVERSARY = new string_id(VETERAN_STRING_TABLE, "one_year_anniversary");
|
|
const string_id SID_ONE_YEAR_ANNIVERSARY_SUBJECT = new string_id(VETERAN_STRING_TABLE, "one_year_anniversary_subject");
|
|
const string_id SID_ONE_YEAR_ANNIVERSARY_FROM = new string_id(VETERAN_STRING_TABLE, "one_year_anniversary_from");
|
|
const string_id SID_ONE_YEAR_ANNIVERSARY_INVENTORY_FULL = new string_id(VETERAN_STRING_TABLE, "one_year_inventory_full");
|
|
const string_id SID_ONE_YEAR_ANNIVERSARY_INVENTORY_FULL_SUBJECT = new string_id(VETERAN_STRING_TABLE, "one_year_inventory_full_subject");
|
|
const int ONE_YEAR_ANNIVERSARY_REWARD_COUNT = 9;
|
|
const int MIN_ONE_YEAR_ANNIVERSARY_TIME = 30; // one (30 day) month
|
|
|
|
// Flash speeder replacement cost
|
|
const int FLASH_SPEEDER_COST = 20000;
|
|
|
|
// return codes from canGetRewardAtIndex
|
|
const int CAN_GET_REWARD_SUCCESS = 0;
|
|
const int CAN_GET_REWARD_FAIL_INADEQUATE_MILESTONE = 1;
|
|
const int CAN_GET_REWARD_FAIL_ALREADY_CLAIMED = 2;
|
|
const int CAN_GET_REWARD_FAIL_INADEQUATE_SUBSCRIPTION = 3;
|
|
|
|
// return codes from givePlayerReward
|
|
const int GIVE_PLAYER_REWARD_SUCCESS = 0;
|
|
const int GIVE_PLAYER_REWARD_FAILED = 1;
|
|
const int GIVE_PLAYER_REWARD_MORE_PROCESSING_REQUIRED = 2;
|
|
|
|
// objvars for testing the system. These are also in serverScript/ScriptMethodsPlayerAccount.cpp
|
|
const string OBJVAR_FAKE_VETERAN = "_testVeteran";
|
|
const string OBJVAR_FAKE_VETERAN_TOTAL_TIME = OBJVAR_FAKE_VETERAN + ".total_time";
|
|
const string OBJVAR_FAKE_VETERAN_ENTITLED_TIME = OBJVAR_FAKE_VETERAN + ".entitled_time";
|
|
const string OBJVAR_FAKE_VETERAN_LOGIN_TIME = OBJVAR_FAKE_VETERAN + ".login_time";
|
|
const string OBJVAR_FAKE_VETERAN_ENTITLED_LOGIN_TIME = OBJVAR_FAKE_VETERAN + ".entitled_login_time";
|
|
|
|
const string SCRIPTVAR_VETERAN_LOGGED_IN = "veteran.loggedIn";
|
|
const string SCRIPTVAR_SELECTED_REWARD = "veteran.selectedReward";
|
|
const string SCRIPTVAR_SELECTED_MILESTONE = "veteran.selectedMilestone";
|
|
const string SCRIPTVAR_AVAILABLE_MILESTONES = "veteran.milestones";
|
|
|
|
const string_id SID_VETERAN_NEW_REWARD = new string_id(VETERAN_STRING_TABLE, "new_reward");
|
|
const string_id SID_VETERAN_NEW_REWARD_SUBJECT = new string_id(VETERAN_STRING_TABLE, "new_reward_subject");
|
|
const string_id SID_VETERAN_NEW_REWARD_FROM = new string_id(VETERAN_STRING_TABLE, "new_reward_from");
|
|
const string_id SID_VETERAN_NEW_REWARD_MSGBOX = new string_id(VETERAN_STRING_TABLE, "new_reward_msgbox");
|
|
const string_id SID_VETERAN_SELECT_MILESTONE_PROMPT = new string_id(VETERAN_STRING_TABLE, "select_milestone");
|
|
const string_id SID_VETERAN_SELECT_REWARD_PROMPT = new string_id(VETERAN_STRING_TABLE, "select_reward");
|
|
const string_id SID_VETERAN_SELECT_REWARD_CONFIRM = new string_id(VETERAN_STRING_TABLE, "select_reward_confirm");
|
|
const string_id SID_VETERAN_TIME_ACTIVE = new string_id(VETERAN_STRING_TABLE, "time_active");
|
|
const string_id SID_VETERAN_SELF_TIME_ACTIVE = new string_id(VETERAN_STRING_TABLE, "self_time_active");
|
|
const string_id SID_NOT_ELIGIBLE = new string_id(VETERAN_STRING_TABLE, "not_eligible");
|
|
const string_id SID_REWARD_GIVEN = new string_id(VETERAN_STRING_TABLE, "reward_given");
|
|
const string_id SID_REWARD_ERROR = new string_id(VETERAN_STRING_TABLE, "reward_error");
|
|
const string_id SID_SYSTEM_INACTIVE = new string_id(VETERAN_STRING_TABLE, "system_inactive");
|
|
const string_id SID_INVALID_TARGET = new string_id(VETERAN_STRING_TABLE, "invalid_target");
|
|
const string_id SID_MILESTONE_OUT_OF_RANGE = new string_id(VETERAN_STRING_TABLE, "milestone_out_of_range");
|
|
const string_id SID_HAS_MILESTONE = new string_id(VETERAN_STRING_TABLE, "has_milestone");
|
|
const string_id SID_HAS_NOT_MILESTONE = new string_id(VETERAN_STRING_TABLE, "has_not_milestone");
|
|
const string_id SID_OK = new string_id(VETERAN_STRING_TABLE, "ok");
|
|
const string_id SID_ACTIVE_MONTHS_CLEARED = new string_id(VETERAN_STRING_TABLE, "active_months_cleared");
|
|
const string_id SID_BAD_MILESTONE = new string_id(VETERAN_STRING_TABLE, "bad_milestone");
|
|
const string_id SID_BAD_REWARD = new string_id(VETERAN_STRING_TABLE, "bad_reward");
|
|
const string_id SID_DAYS = new string_id(VETERAN_STRING_TABLE, "days");
|
|
const string_id SID_RANK = new string_id(VETERAN_STRING_TABLE, "rank");
|
|
const string_id SID_UNAVAILABLE = new string_id(VETERAN_STRING_TABLE, "unavailable");
|
|
const string_id SID_UNAVAILABLE_CLAIMED = new string_id(VETERAN_STRING_TABLE, "unavailable_claimed");
|
|
const string_id SID_UNAVAILABLE_NEEDS_EXPANSION = new string_id(VETERAN_STRING_TABLE, "unavailable_needs_expansion");
|
|
const string_id SID_UNAVAILABLE_NOT_ENOUGH_MILESTONE= new string_id(VETERAN_STRING_TABLE, "unavailable_not_enough_milestone");
|
|
const string_id SID_UNKNOWN = new string_id(VETERAN_STRING_TABLE, "unknown");
|
|
|
|
|
|
/***** FUNCTIONS *******************************************************/
|
|
|
|
/**
|
|
* Updates the amount of time a player has accumulated for their veteran reward(s).
|
|
*/
|
|
void updateVeteranTime(obj_id player)
|
|
{
|
|
if ( !isIdValid(player) )
|
|
return;
|
|
|
|
if ( !"true".equals(getConfigSetting("GameServer", "enableVeteranRewards")) )
|
|
return;
|
|
|
|
// make sure this function only gets run when the player actually logs in, not warps to another
|
|
// planet, etc.
|
|
if ( player.getScriptVars().hasKey(SCRIPTVAR_VETERAN_LOGGED_IN) )
|
|
return;
|
|
player.getScriptVars().put(SCRIPTVAR_VETERAN_LOGGED_IN, true);
|
|
|
|
// get the player's account info
|
|
dictionary timeData = getAccountTimeData(player);
|
|
if ( timeData == null )
|
|
{
|
|
// this is OK, it means that the platform system currently does not
|
|
// have access to the player's entitlement information (db may be down,
|
|
// for example); we'll try again the next time the player logs in
|
|
return;
|
|
}
|
|
|
|
int totalEntitledTime = timeData.getInt("total_entitled_time");
|
|
if ( !hasObjVar(player, OBJVAR_TIME_ACTIVE) )
|
|
{
|
|
// initialize the player's time
|
|
setObjVar(player, OBJVAR_TIME_ACTIVE, totalEntitledTime);
|
|
setObjVar(player, OBJVAR_REWARDS_RECEIVED, new int[REWARD_FLAGS_SIZE]);
|
|
setObjVar(player, OBJVAR_MILESTONES_NOTIFIED, new int[REWARD_FLAGS_SIZE]);
|
|
}
|
|
else
|
|
{
|
|
// update the player's time
|
|
setObjVar(player, OBJVAR_TIME_ACTIVE, totalEntitledTime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests if a player can get a veteran reward.
|
|
*/
|
|
boolean canGetReward(obj_id player)
|
|
{
|
|
// see if the player is qualified to receive any reward
|
|
int[] milestones = getVeteranRewardMilestones(player);
|
|
|
|
// nope, not qualified
|
|
return ( (milestones != null) && (milestones.length >= 1) );
|
|
}
|
|
|
|
/**
|
|
* Sends a message to a player for what rewards (or milestones) they can choose and lets them choose one.
|
|
*/
|
|
boolean requestVeteranRewards(obj_id player)
|
|
{
|
|
if ( !isIdValid(player) )
|
|
return false;
|
|
|
|
int[] milestones = getVeteranRewardMilestones(player);
|
|
if ( (milestones == null) || (milestones.length < 1) )
|
|
{
|
|
// tell the player no rewards are available
|
|
return false;
|
|
}
|
|
|
|
// get all the possible milestone player has achieved
|
|
int veteranTime = getIntObjVar(player, OBJVAR_TIME_ACTIVE);
|
|
if ( veteranTime <= 0)
|
|
{
|
|
CustomerServiceLog("veteran", "requestVeteranRewards called for player %TU with no active time", player);
|
|
return false;
|
|
}
|
|
|
|
int firstMilestone = veteranTime / DAYS_PER_MILESTONE;
|
|
if ( firstMilestone < 1 )
|
|
return false;
|
|
|
|
if ( firstMilestone > MAX_MILESTONE )
|
|
{
|
|
CustomerServiceLog("veteran", "requestVeteranRewards called for player %TU who has a milestone " + firstMilestone + " which is greater than the maximum supported milestone " + MAX_MILESTONE, player);
|
|
firstMilestone = MAX_MILESTONE;
|
|
}
|
|
|
|
// ask the player which milestone they would like to claim a reward from
|
|
string daysText = getString(SID_DAYS);
|
|
string alreadyClaimedText = getString(SID_UNAVAILABLE_CLAIMED);
|
|
Vector milestonesText = new Vector();
|
|
for ( int i = 0; i < firstMilestone; ++i )
|
|
{
|
|
// for now, only display the 180 days milestone
|
|
if (i == 1)
|
|
{
|
|
if ( checkVeteranMilestone(player, (i + 1)) )
|
|
milestonesText.add(((i + 1) * DAYS_PER_MILESTONE) + daysText + " (" + alreadyClaimedText + ")");
|
|
else
|
|
milestonesText.add(((i + 1) * DAYS_PER_MILESTONE) + daysText);
|
|
}
|
|
}
|
|
|
|
int pid = sui.listbox(player, player, "@" + SID_VETERAN_SELECT_MILESTONE_PROMPT, sui.OK_CANCEL, sui.DEFAULT_TITLE,
|
|
milestonesText, HANDLER_SELECT_VETERAN_MILESTONE, true);
|
|
if ( pid < 0 )
|
|
{
|
|
CustomerServiceLog("veteran", "Could not create sui reward list for player %TU, error = " + pid, player);
|
|
return false;
|
|
}
|
|
|
|
player.getScriptVars().put(SCRIPTVAR_AVAILABLE_MILESTONES, milestones);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Sends a message to a player for what rewards they can choose and lets them choose one.
|
|
*/
|
|
boolean requestVeteranRewards(obj_id player, int milestone)
|
|
{
|
|
if ( !isIdValid(player) )
|
|
return false;
|
|
|
|
// build a list of all the rewards, marking those that are not available
|
|
// to be claimed with the appropriate text on the item
|
|
string daysText = getString(SID_DAYS);
|
|
string rankText = getString(SID_RANK);
|
|
string unavailableText = getString(SID_UNAVAILABLE);
|
|
string alreadyClaimedText = getString(SID_UNAVAILABLE_CLAIMED);
|
|
string needsExpansionText = getString(SID_UNAVAILABLE_NEEDS_EXPANSION);
|
|
string notEnoughMilestoneText = getString(SID_UNAVAILABLE_NOT_ENOUGH_MILESTONE);
|
|
string unknownText = getString(SID_UNKNOWN);
|
|
|
|
Vector availableRewards = new Vector();
|
|
int numRows = dataTableGetNumRows(REWARDS_DATATABLE);
|
|
for ( int i = 0; i < numRows; ++i )
|
|
{
|
|
string name = getRewardNameAtIndex(i);
|
|
if ( name != null )
|
|
{
|
|
boolean oneShot = dataTableGetInt(REWARDS_DATATABLE, i, REWARDS_COLUMN_ONETIME) != 0;
|
|
if ( oneShot )
|
|
name += " *";
|
|
|
|
boolean noTrade = dataTableGetInt(REWARDS_DATATABLE, i, REWARDS_COLUMN_NOTRADE) != 0;
|
|
if ( noTrade )
|
|
{
|
|
if ( oneShot )
|
|
name += "#";
|
|
else
|
|
name += " #";
|
|
}
|
|
|
|
int rewardMilestone = dataTableGetInt(REWARDS_DATATABLE, i, REWARDS_COLUMN_MILESTONE);
|
|
|
|
name += " (";
|
|
name += Integer.toString(rewardMilestone * DAYS_PER_MILESTONE);
|
|
name += daysText;
|
|
name += ", ";
|
|
name += rankText;
|
|
name += Integer.toString(rewardMilestone);
|
|
name += ")";
|
|
|
|
int canGetRewardStatus = canGetRewardAtIndex(player, i, milestone);
|
|
if ( canGetRewardStatus != CAN_GET_REWARD_SUCCESS )
|
|
{
|
|
if ( canGetRewardStatus == CAN_GET_REWARD_FAIL_INADEQUATE_MILESTONE )
|
|
name = name + " (" + notEnoughMilestoneText + ")";
|
|
else if ( canGetRewardStatus == CAN_GET_REWARD_FAIL_ALREADY_CLAIMED )
|
|
name = name + " (" + alreadyClaimedText + ")";
|
|
else if ( canGetRewardStatus == CAN_GET_REWARD_FAIL_INADEQUATE_SUBSCRIPTION )
|
|
name = name + " (" + needsExpansionText + ")";
|
|
else
|
|
name = name + " (" + unavailableText + ")";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
availableRewards.add(unknownText);
|
|
}
|
|
|
|
availableRewards.add(name);
|
|
}
|
|
|
|
int pid = sui.listbox(player, player, "@" + SID_VETERAN_SELECT_REWARD_PROMPT, sui.OK_CANCEL, sui.DEFAULT_TITLE,
|
|
availableRewards, HANDLER_SELECT_VETERAN_REWARD, true);
|
|
if ( pid < 0 )
|
|
{
|
|
CustomerServiceLog("veteran", "Could not create sui reward list for player %TU, error = " + pid, player);
|
|
return false;
|
|
}
|
|
|
|
player.getScriptVars().put(SCRIPTVAR_SELECTED_MILESTONE, milestone);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the milestones that a player can claim a reward from.
|
|
*/
|
|
int[] getVeteranRewardMilestones(obj_id player)
|
|
{
|
|
int veteranTime = getIntObjVar(player, OBJVAR_TIME_ACTIVE);
|
|
if ( veteranTime <= 0)
|
|
{
|
|
CustomerServiceLog("veteran", "getVeteranRewardMilestones called for player %TU with no active time", player);
|
|
return null;
|
|
}
|
|
|
|
int firstMilestone = veteranTime / DAYS_PER_MILESTONE;
|
|
if ( firstMilestone < 1 )
|
|
return null;
|
|
|
|
if ( firstMilestone > MAX_MILESTONE )
|
|
{
|
|
CustomerServiceLog("veteran", "getVeteranRewardMilestones called for player %TU who has a milestone " + firstMilestone + " which is greater than the maximum supported milestone " + MAX_MILESTONE, player);
|
|
firstMilestone = MAX_MILESTONE;
|
|
}
|
|
|
|
int[] veteranRewards = getIntArrayObjVar(player, OBJVAR_REWARDS_RECEIVED);
|
|
if ( veteranRewards == null)
|
|
{
|
|
CustomerServiceLog("veteran", "getVeteranRewardMilestones called for player %TU with no rewards flags", player);
|
|
veteranRewards = new int[REWARD_FLAGS_SIZE];
|
|
setObjVar(player, OBJVAR_REWARDS_RECEIVED, veteranRewards);
|
|
}
|
|
|
|
// get the index for every milestone not flagged
|
|
Vector milestoneVector = new Vector();
|
|
for ( int i = 0; i < firstMilestone; ++i )
|
|
{
|
|
// see if the player already gained a reward for the milestone
|
|
int index = i / 32;
|
|
int mask = 0x00000001 << (i - index * 32);
|
|
if ( (veteranRewards[index] & mask) == 0 )
|
|
{
|
|
// note we change from base-0 to base-1 here
|
|
milestoneVector.add(new Integer(i + 1));
|
|
}
|
|
}
|
|
|
|
if ( milestoneVector.size() < 1 )
|
|
return null;
|
|
|
|
// convert the milestone vector to an array
|
|
int[] milestoneArray = new int[milestoneVector.size()];
|
|
for ( int i = 0; i < milestoneArray.length; ++i )
|
|
{
|
|
milestoneArray[i] = ((Integer)(milestoneVector.elementAt(i))).intValue();
|
|
}
|
|
return milestoneArray;
|
|
}
|
|
|
|
/**
|
|
* Give the player the award they selected.
|
|
*/
|
|
int givePlayerReward(obj_id player, int rewardIndex, boolean checkMilestoneMismatch)
|
|
{
|
|
if ( !isIdValid(player) )
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
|
|
if ( !player.getScriptVars().hasKey(SCRIPTVAR_SELECTED_MILESTONE) )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward could not find SCRIPTVAR_SELECTED_MILESTONE for player %TU with reward index " +
|
|
rewardIndex, player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
int milestone = player.getScriptVars().getInt(SCRIPTVAR_SELECTED_MILESTONE);
|
|
|
|
// don't need to log anything here, it means player tried
|
|
// to select a reward from the "read-only" rewards page;
|
|
// we don't need to spam the log when this happens
|
|
if ( milestone < 1 )
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
|
|
// possible hacker, passed an item index that's greater than the max index
|
|
if ( rewardIndex >= dataTableGetNumRows(REWARDS_DATATABLE) )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward could not find reward for player %TU with reward index " +
|
|
rewardIndex + " for milestone " + milestone, player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
// double check again to make sure that he is eligible for this
|
|
// milestone, and he has not claimed a reward for this milestone
|
|
int veteranTime = getIntObjVar(player, OBJVAR_TIME_ACTIVE);
|
|
if ( veteranTime <= 0 )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward called for player %TU with no active time", player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
int firstMilestone = veteranTime / DAYS_PER_MILESTONE;
|
|
if ( firstMilestone > MAX_MILESTONE )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward called for player %TU who has a milestone " + firstMilestone + " which is greater than the maximum supported milestone " + MAX_MILESTONE, player);
|
|
firstMilestone = MAX_MILESTONE;
|
|
}
|
|
|
|
if ( milestone > firstMilestone )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward called for player %TU with requested milestone " + milestone + " which is greater than the actual milestone " + firstMilestone, player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
if ( checkVeteranMilestone(player, milestone) )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward called for player %TU who has already claimed the reward for milestone " + milestone, player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
// can the player get this reward?
|
|
int canGetRewardStatus = canGetRewardAtIndex(player, rewardIndex, milestone);
|
|
if ( canGetRewardStatus != CAN_GET_REWARD_SUCCESS )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward could not grant reward for player %TU with reward index " +
|
|
rewardIndex + " for milestone " + milestone + ", error code " + canGetRewardStatus, player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
// get confirmation from the player if the milestone level for the reward
|
|
// they have chosen does not match the reward milestone that they are using
|
|
if ( checkMilestoneMismatch )
|
|
{
|
|
int rewardMilestone = dataTableGetInt(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_MILESTONE);
|
|
if ( rewardMilestone != milestone )
|
|
{
|
|
int pid = sui.msgbox(player, player, "@" + SID_VETERAN_SELECT_REWARD_CONFIRM, sui.YES_NO, HANDLER_SELECT_VETERAN_REWARD_CONFIRM);
|
|
if ( pid < 0 )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward could not create sui reward confirmation message box for player %TU, error = " + pid, player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
// save off the selected reward index, so that after
|
|
// confirmation, we'll know which reward to give
|
|
player.getScriptVars().put(SCRIPTVAR_SELECTED_REWARD, rewardIndex);
|
|
|
|
return GIVE_PLAYER_REWARD_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
}
|
|
|
|
int templateCrc = dataTableGetInt(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_TEMPLATE);
|
|
obj_id reward = createObjectInInventoryAllowOverload(templateCrc, player);
|
|
if ( !isIdValid(reward) )
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward could not create reward for reward index " + rewardIndex +
|
|
", template crc " + templateCrc + " for player %TU", player);
|
|
return GIVE_PLAYER_REWARD_FAILED;
|
|
}
|
|
|
|
CustomerServiceLog("veteran", "givePlayerReward has given player %TU item " +
|
|
getName(reward) + " (" + reward + ") for milestone " + milestone, player);
|
|
|
|
// mark the reward as no trade, if necessary
|
|
boolean noTrade = dataTableGetInt(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_NOTRADE) != 0;
|
|
if ( noTrade )
|
|
setObjVar(reward, "noTrade", true);
|
|
|
|
// mark the reward as no delete, if necessary
|
|
boolean noDelete = dataTableGetInt(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_NODELETE) != 0;
|
|
if ( noDelete )
|
|
attachScript(reward, "item.special.nodestroy");
|
|
|
|
// mark the reward as no move, if necessary
|
|
boolean noMove = dataTableGetInt(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_NOMOVE) != 0;
|
|
if ( noMove )
|
|
attachScript(reward, "item.special.nomove");
|
|
|
|
// update the player's rewards flag for the month of the first reward
|
|
if ( !hasObjVar(player, OBJVAR_REWARDS_RECEIVED))
|
|
{
|
|
CustomerServiceLog("veteran", "givePlayerReward called for player %TU with no rewards flags", player);
|
|
}
|
|
setVeteranMilestone(player, milestone);
|
|
|
|
// if the reward is a one-time reward, flag the player as having received it
|
|
boolean oneShot = dataTableGetInt(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_ONETIME) != 0;
|
|
if ( oneShot )
|
|
{
|
|
int[] onetimes = getIntArrayObjVar(player, OBJVAR_ONETIME_REWARDS_RECEIVED);
|
|
int[] onetimesNew;
|
|
if ( onetimes != null)
|
|
{
|
|
onetimesNew = new int[onetimes.length + 1];
|
|
for ( int i = 0; i < onetimes.length; ++i )
|
|
onetimesNew[i] = onetimes[i];
|
|
onetimesNew[onetimes.length] = templateCrc;
|
|
}
|
|
else
|
|
{
|
|
onetimesNew = new int[1];
|
|
onetimesNew[0] = templateCrc;
|
|
}
|
|
setObjVar(player, OBJVAR_ONETIME_REWARDS_RECEIVED, onetimesNew);
|
|
}
|
|
|
|
// attach the reward-specific script (if any) to the reward
|
|
string script = dataTableGetString(REWARDS_DATATABLE, rewardIndex, REWARDS_COLUMN_SCRIPT);
|
|
if ( script != null && script.length() > 0 )
|
|
{
|
|
attachScript(reward, script);
|
|
}
|
|
|
|
cleanupPlayerData(player);
|
|
return GIVE_PLAYER_REWARD_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Cleans up temporary data we've stored on a player.
|
|
*/
|
|
void cleanupPlayerData(obj_id player)
|
|
{
|
|
if ( !isIdValid(player) )
|
|
return;
|
|
|
|
player.getScriptVars().remove(SCRIPTVAR_SELECTED_REWARD);
|
|
player.getScriptVars().remove(SCRIPTVAR_SELECTED_MILESTONE);
|
|
player.getScriptVars().remove(SCRIPTVAR_AVAILABLE_MILESTONES);
|
|
}
|
|
|
|
/**
|
|
* Returns the reward name from the rewards datatable at a given index.
|
|
*/
|
|
string getRewardNameAtIndex(int index)
|
|
{
|
|
string name = null;
|
|
|
|
int templateCrc = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_TEMPLATE);
|
|
string_id nameId = getNameFromTemplate(templateCrc);
|
|
if ( nameId != null)
|
|
name = "@" + nameId;
|
|
else
|
|
CustomerServiceLog("veteran", "Could not find reward at index " + index);
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Checks to see if a player can get the reward at a given index in the reward datatable.
|
|
*
|
|
* @param index the reward index to check
|
|
*
|
|
* @return int indicating success or failure
|
|
*/
|
|
int canGetRewardAtIndex(obj_id player, int index, int milestone)
|
|
{
|
|
// Note that the check is done in the order that we want to
|
|
// communicate to the player as to why the reward is unavailable
|
|
|
|
// if the reward is a one time reward, make sure the player hasn't received the award;
|
|
int templateCrc = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_TEMPLATE);
|
|
boolean oneShot = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_ONETIME) != 0;
|
|
if ( oneShot )
|
|
{
|
|
int[] onetimes = getIntArrayObjVar(player, OBJVAR_ONETIME_REWARDS_RECEIVED);
|
|
if ( onetimes != null )
|
|
{
|
|
for ( int i = 0; i < onetimes.length; ++i )
|
|
{
|
|
if ( onetimes[i] == templateCrc )
|
|
return CAN_GET_REWARD_FAIL_ALREADY_CLAIMED;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if the reward requires certain subscription bits, check for that
|
|
int requiredBit = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_REQUIREDGAMEFEATUREBITANY);
|
|
if (requiredBit > 0)
|
|
{
|
|
int game_bits = getGameFeatureBits(player);
|
|
if ((game_bits & requiredBit) == 0)
|
|
return CAN_GET_REWARD_FAIL_INADEQUATE_SUBSCRIPTION;
|
|
}
|
|
|
|
requiredBit = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_REQUIREDGAMEFEATUREBITALL);
|
|
if (requiredBit > 0)
|
|
{
|
|
int game_bits = getGameFeatureBits(player);
|
|
if ((game_bits & requiredBit) != requiredBit)
|
|
return CAN_GET_REWARD_FAIL_INADEQUATE_SUBSCRIPTION;
|
|
}
|
|
|
|
requiredBit = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_REQUIREDSUBSCRIPTIONFEATUREBITANY);
|
|
if (requiredBit > 0)
|
|
{
|
|
int sub_bits = getSubscriptionFeatureBits(player);
|
|
if ((sub_bits & requiredBit) == 0)
|
|
return CAN_GET_REWARD_FAIL_INADEQUATE_SUBSCRIPTION;
|
|
}
|
|
|
|
requiredBit = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_REQUIREDSUBSCRIPTIONFEATUREBITALL);
|
|
if (requiredBit > 0)
|
|
{
|
|
int sub_bits = getSubscriptionFeatureBits(player);
|
|
if ((sub_bits & requiredBit) != requiredBit)
|
|
return CAN_GET_REWARD_FAIL_INADEQUATE_SUBSCRIPTION;
|
|
}
|
|
|
|
// the rewards's milestone cannot exceed the specified milestone
|
|
int rewardMilestone = dataTableGetInt(REWARDS_DATATABLE, index, REWARDS_COLUMN_MILESTONE);
|
|
if ( rewardMilestone > milestone )
|
|
return CAN_GET_REWARD_FAIL_INADEQUATE_MILESTONE;
|
|
|
|
return CAN_GET_REWARD_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Returns if a veteran milestone is set on a player or not.
|
|
*
|
|
* @param player the player
|
|
* @milestone the milestone to check. The milestone is expected to be base-1
|
|
*
|
|
* @return true if the milestone is set, false if not
|
|
*/
|
|
boolean checkVeteranMilestone(obj_id player, int milestone)
|
|
{
|
|
if ( milestone < 1 || milestone > MAX_MILESTONE )
|
|
return false;
|
|
|
|
int[] rewardsReceived = getIntArrayObjVar(player, OBJVAR_REWARDS_RECEIVED);
|
|
if ( rewardsReceived == null)
|
|
return false;
|
|
|
|
// go from base-1 to base-0
|
|
--milestone;
|
|
int index = milestone / 32;
|
|
int mask = 0x00000001 << (milestone - index * 32);
|
|
return (rewardsReceived[index] & mask) != 0;
|
|
}
|
|
|
|
/**
|
|
* Returns if a notification for a veteran milestone achievement has been sent or not.
|
|
*
|
|
* @param player the player
|
|
* @milestone the milestone to check. The milestone is expected to be base-1
|
|
*
|
|
* @return true if the notification has been sent, false if not
|
|
*/
|
|
boolean checkMilestoneNotified(obj_id player, int milestone)
|
|
{
|
|
if ( milestone < 1 || milestone > MAX_MILESTONE )
|
|
return false;
|
|
|
|
int[] milestonesNotified = getIntArrayObjVar(player, OBJVAR_MILESTONES_NOTIFIED);
|
|
if ( milestonesNotified == null)
|
|
return false;
|
|
|
|
// go from base-1 to base-0
|
|
--milestone;
|
|
int index = milestone / 32;
|
|
int mask = 0x00000001 << (milestone - index * 32);
|
|
return (milestonesNotified[index] & mask) != 0;
|
|
}
|
|
|
|
/**
|
|
* Sets a milestone flag on a player.
|
|
*
|
|
* @param player the player
|
|
* @milestone the milestone to set. The milestone is expected to be base-1
|
|
*/
|
|
void setVeteranMilestone(obj_id player, int milestone)
|
|
{
|
|
if ( milestone < 1 || milestone > MAX_MILESTONE )
|
|
return;
|
|
|
|
int[] rewardsReceived = getIntArrayObjVar(player, OBJVAR_REWARDS_RECEIVED);
|
|
if ( rewardsReceived == null)
|
|
rewardsReceived = new int[REWARD_FLAGS_SIZE];
|
|
|
|
// go from base-1 to base-0
|
|
--milestone;
|
|
int index = milestone / 32;
|
|
int mask = 0x00000001 << (milestone - index * 32);
|
|
rewardsReceived[index] |= mask;
|
|
setObjVar(player, OBJVAR_REWARDS_RECEIVED, rewardsReceived);
|
|
}
|
|
|
|
/**
|
|
* Sets a flag indicating a notification for a veteran milestone achievement has been sent
|
|
*
|
|
* @param player the player
|
|
* @milestone the milestone to set. The milestone is expected to be base-1
|
|
*/
|
|
void setMilestoneNotified(obj_id player, int milestone)
|
|
{
|
|
if ( milestone < 1 || milestone > MAX_MILESTONE )
|
|
return;
|
|
|
|
int[] milestonesNotified = getIntArrayObjVar(player, OBJVAR_MILESTONES_NOTIFIED);
|
|
if ( milestonesNotified == null)
|
|
milestonesNotified = new int[REWARD_FLAGS_SIZE];
|
|
|
|
// go from base-1 to base-0
|
|
--milestone;
|
|
int index = milestone / 32;
|
|
int mask = 0x00000001 << (milestone - index * 32);
|
|
milestonesNotified[index] |= mask;
|
|
setObjVar(player, OBJVAR_MILESTONES_NOTIFIED, milestonesNotified);
|
|
}
|
|
|
|
/**
|
|
* Clears a milestone flag on a player.
|
|
*
|
|
* @param player the player
|
|
* @milestone the milestone to clear. The milestone is expected to be base-1
|
|
*/
|
|
void clearVeteranMilestone(obj_id player, int milestone)
|
|
{
|
|
if ( milestone < 1 || milestone > MAX_MILESTONE )
|
|
return;
|
|
|
|
int[] rewardsReceived = getIntArrayObjVar(player, OBJVAR_REWARDS_RECEIVED);
|
|
if ( rewardsReceived == null)
|
|
rewardsReceived = new int[REWARD_FLAGS_SIZE];
|
|
|
|
// clear the flag indicating a notification has been sent for the milestone
|
|
clearMilestoneNotified(player, milestone);
|
|
|
|
// go from base-1 to base-0
|
|
--milestone;
|
|
int index = milestone / 32;
|
|
int mask = 0x00000001 << (milestone - index * 32);
|
|
rewardsReceived[index] &= ~mask;
|
|
setObjVar(player, OBJVAR_REWARDS_RECEIVED, rewardsReceived);
|
|
}
|
|
|
|
/**
|
|
* Clears the flag indicating a notification for a veteran milestone achievement has been sent
|
|
*
|
|
* @param player the player
|
|
* @milestone the milestone to clear. The milestone is expected to be base-1
|
|
*/
|
|
void clearMilestoneNotified(obj_id player, int milestone)
|
|
{
|
|
if ( milestone < 1 || milestone > MAX_MILESTONE )
|
|
return;
|
|
|
|
int[] milestonesNotified = getIntArrayObjVar(player, OBJVAR_MILESTONES_NOTIFIED);
|
|
if ( milestonesNotified == null)
|
|
milestonesNotified = new int[REWARD_FLAGS_SIZE];
|
|
|
|
// go from base-1 to base-0
|
|
--milestone;
|
|
int index = milestone / 32;
|
|
int mask = 0x00000001 << (milestone - index * 32);
|
|
milestonesNotified[index] &= ~mask;
|
|
setObjVar(player, OBJVAR_MILESTONES_NOTIFIED, milestonesNotified);
|
|
}
|
|
|
|
/**
|
|
* Makes sure a target object is a veteran.
|
|
*/
|
|
boolean checkVeteranTarget(obj_id target)
|
|
{
|
|
if ( isIdValid(target) && isPlayer(target) )
|
|
{
|
|
if ( hasObjVar(target, veteran_deprecated.OBJVAR_TIME_ACTIVE) )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
sendSystemMessage(getSelf(), veteran_deprecated.SID_SYSTEM_INACTIVE);
|
|
}
|
|
else
|
|
sendSystemMessage(getSelf(), veteran_deprecated.SID_INVALID_TARGET);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gives a reward to players for the one year anniversary of the game. The player's
|
|
* character must have been created at least a month ago.
|
|
*
|
|
* @param player the player to give the reward to
|
|
*/
|
|
void giveOneYearAnniversaryReward(obj_id player)
|
|
{
|
|
// make sure the system is enabled
|
|
if (!"true".equals(getConfigSetting("GameServer", "enableOneYearAnniversary")))
|
|
return;
|
|
|
|
if ( !isPlayer(player) )
|
|
return;
|
|
|
|
// make sure the player hasn't already gotten the reward
|
|
if ( hasObjVar(player, OBJVAR_ONE_YEAR_ANNIVERSARY ) )
|
|
return;
|
|
|
|
// make sure the player has been around long enough
|
|
int playerBorn = getPlayerBirthDate(player);
|
|
int existTime = getCurrentBirthDate() - playerBorn;
|
|
// check player time override
|
|
if ( hasObjVar(player, OBJVAR_ONE_YEAR_ANNIVERSARY_OVERRIDE ) )
|
|
{
|
|
existTime = getIntObjVar(player, OBJVAR_ONE_YEAR_ANNIVERSARY_OVERRIDE);
|
|
CustomerServiceLog("one_year_anniversary", "Using override time of " + existTime + " for player %TU", player);
|
|
}
|
|
// debugServerConsoleMsg(null, "OneYearAnniversary: player date = " + playerBorn + ", current date = " +
|
|
// getCurrentBirthDate() + ", exist time = " + existTime);
|
|
if ( playerBorn < 0 || existTime < MIN_ONE_YEAR_ANNIVERSARY_TIME )
|
|
return;
|
|
|
|
obj_id inventory = utils.getInventoryContainer(player);
|
|
if ( !isIdValid(inventory) )
|
|
return;
|
|
|
|
// make sure there is enough room in the player's inventory
|
|
int free = getVolumeFree(inventory);
|
|
if ( free == 0 )
|
|
{
|
|
// tell the player to make room and reenter the game
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = SID_ONE_YEAR_ANNIVERSARY_INVENTORY_FULL;
|
|
utils.sendMail( SID_ONE_YEAR_ANNIVERSARY_INVENTORY_FULL_SUBJECT, pp, player,
|
|
"@" + SID_ONE_YEAR_ANNIVERSARY_FROM );
|
|
return;
|
|
}
|
|
|
|
int rewardNum = rand(1, ONE_YEAR_ANNIVERSARY_REWARD_COUNT);
|
|
string rewardName = TEMPLATE_ONE_YEAR_ANNIVERSARY;
|
|
if ( rewardNum < 10)
|
|
rewardName += "0";
|
|
rewardName += rewardNum;
|
|
obj_id reward = createObject(rewardName + ".iff", inventory, "");
|
|
if ( !isIdValid(reward) )
|
|
{
|
|
CustomerServiceLog("one_year_anniversary", "WARNING: Error creating one year anniversary reward " +
|
|
rewardName + ".iff for player %TU", player);
|
|
return;
|
|
}
|
|
|
|
// set the one year objvar to so the player will only get one reward
|
|
setObjVar(player, OBJVAR_ONE_YEAR_ANNIVERSARY, reward );
|
|
|
|
CustomerServiceLog("one_year_anniversary", "Gave player %TU one year anniversary reward " + reward, player);
|
|
|
|
// let the player know they've gotten a reward
|
|
prose_package pp = new prose_package();
|
|
pp.stringId = SID_ONE_YEAR_ANNIVERSARY;
|
|
utils.sendMail( SID_ONE_YEAR_ANNIVERSARY_SUBJECT, pp, player, "@" + SID_ONE_YEAR_ANNIVERSARY_FROM );
|
|
}
|
|
|
|
/**
|
|
* Checks to see if the player is eligible for the Flash Speeder reward.
|
|
* This is given for preordering JTL.
|
|
*
|
|
* @param player player to check
|
|
* @return boolean true if a reward is granted.
|
|
*/
|
|
boolean checkFlashSpeederReward(obj_id player)
|
|
{
|
|
if (!isIdValid(player))
|
|
{
|
|
LOG("flash_speeder", "veteran_deprecated.checkFlashSpeeder: Player is invalid.");
|
|
return false;
|
|
}
|
|
if (!isPlayer(player))
|
|
{
|
|
LOG("flash_speeder", "veteran_deprecated.checkFlashSpeeder: " + player + " is not a player.");
|
|
return false;
|
|
}
|
|
if (isUsingAdminLogin(player))
|
|
{
|
|
return false;
|
|
}
|
|
string config = getConfigSetting("GameServer", "flashSpeederReward");
|
|
//LOG("flash_speeder", "config ->" + config);
|
|
if (config != null && config.equals("true"))
|
|
{
|
|
int sub_bits = getGameFeatureBits(player);
|
|
if (hasObjVar(player, "flash_speeder.eligible"))
|
|
sub_bits = getIntObjVar(player, "flash_speeder.eligible");
|
|
|
|
if ((features.isSpaceEdition(player) && utils.checkBit(sub_bits, 3)) || features.isJPCollectorEdition(player)) // 3 is the JtL pre-order bit.
|
|
{
|
|
if (!hasObjVar(player, "flash_speeder.granted"))
|
|
{
|
|
// Give the player a flash speeder deed and e-mail him about it.
|
|
createObjectInInventoryAllowOverload("object/tangible/deed/vehicle_deed/speederbike_flash_deed.iff", player);
|
|
|
|
CustomerServiceLog("flash_speeder", "%TU has received a JtL pre-order Flash Speeder.", player);
|
|
|
|
string_id sub = new string_id(VETERAN_STRING_TABLE, "flash_speeder_granted_sub");
|
|
string_id body = new string_id(VETERAN_STRING_TABLE, "flash_speeder_granted_body");
|
|
utils.sendMail(sub, body, player, "System");
|
|
|
|
setObjVar(player, "flash_speeder.granted", 1);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|