Files
dsrc/sku.0/sys.server/compiled/game/script/library/space_quest.scriptlib
T
2013-09-10 23:17:15 -07:00

1989 lines
62 KiB
Plaintext

//------------------------------------------------
// space_quest.scriptlib
// Jeff Freeman, Brandon Reinhart
//------------------------------------------------
//------------------------------------------------
// Includes
//------------------------------------------------
include library.money;
include library.prose;
include library.utils;
include library.skill;
include library.space_utils;
include library.space_transition;
include library.group;
include library.features;
//------------------------------------------------
// Constants
//------------------------------------------------
//
const string QUEST_OBJECT_TEMPLATE = "object/mission/base_mission_object.iff";
// Quest manager info.
const string QUEST_MANAGER = "questManager";
// General quest object objvars.
const string QUEST_TYPE = "questType";
const string QUEST_NAME = "questName";
const string QUEST_OWNER = "questOwner";
const string QUEST_ZONE = "questZone";
const string QUEST_DUTY = "duty";
const string QUEST_DELAY = "delay";
const string QUEST_TRIGGER_EVENT = "trigger.triggerEvent";
const string QUEST_TRIGGER_SC = "trigger.triggerSC";
const string QUEST_TRIGGER_ARG = "trigger.triggerArg";
const string QUEST_TRIGGER_ARG2 = "trigger.triggerArg2";
const string QUEST_TRIGGER_ON = "trigger.triggerOn";
const string QUEST_TRIGGER_ENDS = "trigger.triggerEnds";
const string QUEST_TRIGGER_ENDS_NEW = "trigger.triggerEndsMission";
const string QUEST_TRIGGER_DELAY = "trigger.triggerDelay";
// Auto Reward objvars.
const string QUEST_AUTO_REWARD = "autoReward";
const string QUEST_AUTO_REWARD_FROM = "autoRewardFrom";
const string QUEST_AUTO_REWARD_SUBJECT = "autoRewardSubject";
const string QUEST_AUTO_REWARD_BODY = "autoRewardBody";
// Quest status objvar.
const string QUEST_STATUS = "space_quest";
const string QUEST_STATUS_SERIES = "space_quest.series";
// Quest status flags.
const int QUEST_FAILED = 1;
const int QUEST_WON = 2;
const int QUEST_ABORTED = 4;
const int QUEST_RECEIVED_REWARD = 8;
const int QUEST_GROUP_QUEST_IN_PROGRESS = 16;
// Quest series flags.
const int QUEST_SERIES_COMPLETED = 1;
// Patrol vars.
const int PATROL_NAV_RADIUS = 150;
// Escort vars.
const int ESCORT_ROAM_TOLERANCE = 1000;
// Strings
const string_id SID_REQUIRES_JTL = new string_id( "space/quest", "jtl_required" );
const string_id SID_QUEST_RECEIVED = new string_id( "space/quest", "quest_received" );
const string_id SID_QUEST_IN_PROGRESS = new string_id( "space/quest", "quest_in_progress" );
const string_id SID_QUEST_FAILED = new string_id( "space/quest", "quest_failed" );
const string_id SID_QUEST_WON = new string_id( "space/quest", "quest_won" );
const string_id SID_QUEST_ENDED = new string_id( "space/quest", "quest_ended" );
const string_id SID_QUEST_ABORTED = new string_id( "space/quest", "quest_aborted" );
const string_id SID_QUEST_REWARDED = new string_id( "space/quest", "quest_rewarded" );
const string_id SID_QUEST_UPDATE_S = new string_id( "space/quest", "quest_update_s" );
const string_id SID_QUEST_UPDATE_IS = new string_id( "space/quest", "quest_update_is" );
const string_id SID_QUEST_ALERT_S = new string_id( "space/quest", "quest_alert_s" );
const string_id SID_ESCORT_UPDATE = new string_id( "space/quest", "escort_update" );
const string_id SID_DUTY_RECEIVED = new string_id( "space/quest", "duty_received" );
//const string_id SID_DUTY_IN_PROGRESS = new string_id( "space/quest", "duty_in_progress" );
//const string_id SID_DUTY_FAILED = new string_id( "space/quest", "duty_failed" );
//const string_id SID_DUTY_WON = new string_id( "space/quest", "duty_won" );
const string_id SID_DUTY_ABORTED = new string_id( "space/quest", "duty_aborted" );
//const string_id SID_DUTY_REWARDED = new string_id( "space/quest", "duty_rewarded" );
const string_id SID_DUTY_UPDATE_S = new string_id( "space/quest", "duty_update_s" );
const string_id SID_DUTY_UPDATE_IS = new string_id( "space/quest", "duty_update_is" );
const string_id SID_DUTY_ALREADY = new string_id( "space/quest", "duty_already" );
const string_id SID_GROUP_QUEST_RECEIVED = new string_id( "space/quest", "quest_received_group" );
const string_id SID_GROUP_QUEST_WON = new string_id( "space/quest", "quest_won_group" );
const string_id SID_GROUP_QUEST_ENDED = new string_id( "space/quest", "quest_ended_group" );
const string_id SID_GROUP_QUEST_FAILED = new string_id( "space/quest", "quest_failed_group" );
const string_id SID_GROUP_QUEST_ABORTED = new string_id( "space/quest", "quest_aborted_group" );
const string_id SID_GROUP_QUEST_IN_PROGRESS = new string_id( "space/quest", "quest_in_progress_group" );
const string_id SID_QUEST_REWARD = new string_id( "space/quest", "quest_reward" );
const string_id SID_QUEST_REWARD_OBJECT = new string_id( "space/quest", "quest_reward_object" );
const string_id GROUP_QUEST_RECEIVED = new string_id( "space/quest", "group_quest_received" );
const string_id GROUP_QUEST_FAILED = new string_id( "space/quest", "group_quest_failed" );
const string_id GROUP_QUEST_WON = new string_id( "space/quest", "group_quest_won" );
const string_id GROUP_QUEST_ABORTED = new string_id( "space/quest", "group_quest_aborted" );
// Music
const string MUSIC_QUEST_RECEIVED = "sound/music_themequest_acc_criminal.snd";
const string MUSIC_QUEST_WON = "sound/music_themequest_victory_rebel.snd";
const string MUSIC_QUEST_FAILED = "sound/music_themequest_fail_criminal.snd";
const string MUSIC_QUEST_ABORTED = "sound/music_themequest_fail_criminal.snd";
const string MUSIC_QUEST_EVENT = "sound/music_event_danger.snd";
const string MUSIC_QUEST_ESCORT_ARRIVAL = "sound/mus_quest_escort_arrival.snd";
const string MUSIC_QUEST_BOSS_COMING = "sound/mus_quest_boss_coming.snd";
const string MUSIC_QUEST_CAPTURE_OP = "sound/mus_quest_theme_docking.snd";
const string MUSIC_QUEST_MISSION_START = "sound/mus_quest_theme_opening.snd";
// Alerts
const string ALERT_DROID_WARNING = "clienteffect/space_droid_warning.iff";//"sound/dro_r2_2_warn.snd";
const string ALERT_DROID_DANGER = "clienteffect/space_droid_danger.iff";//"sound/dro_r2_3_danger.snd";
//------------------------------------------------------------------------------------------------
// Quest Logic Methods
//
// These are public interface functions, to be called from conversation
// scripts on quest NPCs.
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// hasQuest
// Used to see if the player has any quest.
//
// obj_id player - The player you are checking.
// returns boolean - True if the player is on a quest.
//------------------------------------------------
boolean hasQuest( obj_id player )
{
if ( !isIdValid( player ) )
return false;
obj_id datapad = utils.getPlayerDatapad( player );
if ( isIdValid( datapad ) )
{
// Search for any quest in the datapad.
obj_id[] dpobjs = getContents( datapad );
for ( int i=0; i<dpobjs.length; i++ )
{
if ( hasObjVar( dpobjs[i], QUEST_NAME ) )
return true;
}
}
return false;
}
//------------------------------------------------
// hasQuest
// Used to see if the player has a quest of a given type.
//
// obj_id player - The player you are checking.
// string questType - The type of quest you are looking for.
// returns boolean - True if the player is on the quest.
//------------------------------------------------
boolean hasQuest( obj_id player, string questType )
{
return (_getQuest( player, questType ) != null);
}
obj_id _getQuest( obj_id player, string questType )
{
if ( !isIdValid( player ) )
return null;
if ( questType == null )
return null;
obj_id datapad = utils.getPlayerDatapad( player );
if ( isIdValid( datapad ) )
{
// Search for a quest in the datapad that has a specific name.
obj_id[] dpobjs = getContents( datapad );
for ( int i=0; i<dpobjs.length; i++ )
{
if ( hasObjVar( dpobjs[i], QUEST_TYPE ) )
{
string tname = getStringObjVar( dpobjs[i], QUEST_TYPE );
if ( questType.equals( tname ) )
return dpobjs[i];
}
}
}
return null;
}
//------------------------------------------------
// hasQuest
// Used to see if the player has a specific quest.
//
// obj_id player - The player you are checking.
// string questType- The table/type of quest you are looking for.
// string questName - The quest to look for.
// returns boolean - True if the player is on the quest.
//------------------------------------------------
boolean hasQuest( obj_id player, string questType, string questName )
{
return (_getQuest( player, questType, questName ) != null);
}
obj_id _getQuest( obj_id player, string questType, string questName )
{
if ( !isIdValid( player ) )
return null;
if ( (questName == null) || (questType == null) )
return null;
obj_id datapad = utils.getPlayerDatapad( player );
if ( isIdValid( datapad ) )
{
// Search for a quest in the datapad that has a specific name.
obj_id[] dpobjs = getContents( datapad );
for ( int i=0; i<dpobjs.length; i++ )
{
if ( hasObjVar( dpobjs[i], QUEST_NAME ) )
{
string qname = getStringObjVar( dpobjs[i], QUEST_NAME );
string tname = getStringObjVar( dpobjs[i], QUEST_TYPE );
if ( questName.equals( qname ) && questType.equals( tname ) )
return dpobjs[i];
}
}
}
return null;
}
//------------------------------------------------
// grantQuest
// Assigns a specific quest to the player.
//
// obj_id player - The player to give a quest to.
// string questType - The quest table (by type) to look in.
// string questName - The quest to assign.
// returns boolean - True if the player was successfully assigned the quest.
//------------------------------------------------
boolean grantQuest( obj_id player, string questType, string questName )
{
return grantQuest( player, questType, questName, false, false );
}
boolean grantQuest( obj_id player, string questType, string questName, boolean splitQuest )
{
return grantQuest( player, questType, questName, splitQuest, false );
}
boolean grantQuest( obj_id player, string questType, string questName, boolean splitQuest, boolean ignoreDelay )
{
if ( !isIdValid( player ) )
return false;
if ( !features.isSpaceEdition(player) )
{
//gimme your money!
sendSystemMessage( player, SID_REQUIRES_JTL );
return false;
}
// Enforce single quest?
// if ( hasQuest( player ) && !splitQuest )
// return false;
// Enforce no duped quests.
if ( hasQuest( player, questType, questName ) )
return false;
// Determine the desired quest table.
string qTable = "datatables/spacequest/"+questType+"/"+questName+".iff";
// Is this a duty?
boolean duty = false;
if ( questType.indexOf( "_duty" ) > 0 )
duty = true;
// Make sure the file exists.
dictionary questInfo = dataTableGetRow( qTable, 0 );
if ( questInfo == null )
{
sendSystemMessageTestingOnly( player, "grantQuest: Unable to find quest table " + qTable );
return false;
}
// Is this on a timer?
if ( !duty )
{
int delay = dataTableGetInt( qTable, 0, "questDelay" );
if ( !ignoreDelay && (delay > 0) )
{
dictionary outparams = new dictionary();
outparams.put( QUEST_TYPE, questType );
outparams.put( QUEST_NAME, questName );
space_utils.notifyObject( player, "registerDelayedQuest", outparams );
return true;
}
}
// Setup the quest.
if ( _setupQuest( player, questType, questName, qTable, duty ) )
{
// We're all set.
// Notify the player.
string_id title = new string_id( "spacequest/"+questType+"/"+questName, "title" );
prose_package pp;
if ( duty )
pp = prose.getPackage( SID_DUTY_RECEIVED, title );
else
pp = prose.getPackage( SID_QUEST_RECEIVED, title );
sendQuestSystemMessage( player, pp );
// GROUP: Notify our group.
_groupNotify( player, SID_GROUP_QUEST_RECEIVED, title );
// Play music.
if ( !splitQuest )
play2dNonLoopingMusic( player, MUSIC_QUEST_RECEIVED );
// Log it.
string groupString = "GROUP:0";
if ( group.isGrouped( player ) )
{
obj_id groupId = getGroupObject( player );
int numMembers = getGroupSize( groupId );
if ( numMembers > 0 )
{
groupString = "GROUP:"+numMembers;
}
}
CustomerServiceLog( "space_quest", "QUEST_STARTED|V1|"+groupString+"|TIME:"+getGameTime()+"|PLAYER:"+player+"|TYPE:"+questType+"|NAME:"+questName+"|ZONE:"+getCurrentSceneName() );
return true;
}
else
{
sendSystemMessageTestingOnly( player, "Failed to grantQuest '" + questType + ":" + questName + "'." );
return false;
}
}
//------------------------------------------------
// grantGroupQuest
// Assigns a specific quest to the player, but flags the group for a group reward.
//------------------------------------------------
boolean grantGroupQuest( obj_id player, string questType, string questName )
{
boolean result = grantQuest( player, questType, questName );
flagGroupQuest( player, questType, questName );
return result;
}
void flagGroupQuest( obj_id player, string questType, string questName )
{
if ( group.isGrouped( player ) )
{
obj_id gid = getGroupObject( player );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null && members.length >= 0 )
{
for ( int i=0; i<members.length; i++ )
{
if ( members[i] != player )
sendSystemMessage( members[i], GROUP_QUEST_RECEIVED );
//_setQuestFlag( members[i], questType, questName, QUEST_GROUP_QUEST_IN_PROGRESS );
utils.setScriptVar( members[i], "group_space_quest."+questType+"."+questName, 1 );
}
}
}
}
boolean isOnGroupQuest( obj_id player, string questType, string questName )
{
// int questStatus = _getQuestStatus( player, questType, questName );
// return ((questStatus & QUEST_GROUP_QUEST_IN_PROGRESS) != 0);
return utils.hasScriptVar( player, "group_space_quest."+questType+"."+questName );
}
boolean isOnThisGroupQuest( obj_id quest, obj_id player )
{
string questName = getStringObjVar( quest, QUEST_NAME );
string questType = getStringObjVar( quest, QUEST_TYPE );
obj_id owner = getObjIdObjVar( quest, QUEST_OWNER );
if ( owner == player )
return true;
if ( group.isGrouped( owner ) )
{
obj_id gid = getGroupObject( owner );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null && members.length >= 0 )
{
for ( int i=0; i<members.length; i++ )
{
if ( members[i] == player )
{
return isOnGroupQuest( player, questType, questName );
}
}
}
}
return false;
}
boolean flagQuestGroup( obj_id missionObj, int flag )
{
string questName = getStringObjVar( missionObj, QUEST_NAME );
string questType = getStringObjVar( missionObj, QUEST_TYPE );
obj_id owner = getObjIdObjVar( missionObj, QUEST_OWNER );
if ( group.isGrouped( owner ) )
{
obj_id gid = getGroupObject( owner );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null && members.length >= 0 )
{
for ( int i=0; i<members.length; i++ )
{
if ( isOnGroupQuest( members[i], questType, questName ) )
{
if ( members[i] != owner )
{
if ( flag == QUEST_FAILED )
sendSystemMessage( members[i], GROUP_QUEST_FAILED );
else if ( flag == QUEST_WON )
sendSystemMessage( members[i], GROUP_QUEST_WON );
else if ( flag == QUEST_ABORTED )
sendSystemMessage( members[i], GROUP_QUEST_ABORTED );
}
_setQuestFlag( members[i], questType, questName, flag );
//_clearQuestFlag( members[i], questType, questName, QUEST_GROUP_QUEST_IN_PROGRESS );
utils.removeScriptVar( members[i], "group_space_quest."+questType+"."+questName );
}
}
}
}
return true;
}
//------------------------------------------------
// canTakeGroupQuest
// Checks to see if the player is grouped and can accept a group quest.
// Should be called prior to assigning a group task.
//------------------------------------------------
boolean canTakeGroupQuest( obj_id player, int minGroupSize )
{
if ( group.isGrouped( player ) )
{
obj_id gid = getGroupObject( player );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null && members.length >= minGroupSize )
return true;
}
return false;
}
//------------------------------------------------
// hasCompletedQuest
// Indicates if the quest is completed (but not whether it was successful or a failure).
//
// obj_id player - The player to check.
// string questType - The quest type.
// string questName - The quest name.
// returns boolean - True if the player finished the quest.
//------------------------------------------------
boolean hasCompletedQuest( obj_id player, string questType, string questName )
{
return hasObjVar( player, QUEST_STATUS + "." + questType + "." + questName );
}
boolean hasCompletedQuestRecursive( obj_id player, string questType, string questName )
{
int recNum = utils.getIntScriptVar( player, "recursiveCheck" );
recNum++;
utils.setScriptVar( player, "recursiveCheck", recNum );
if ( recNum > 20 )
{
debugSpeakMsg( player, "This quest " + questType + ":" + questName + " is BAD DATA REF'ING ITSELF!" );
utils.removeScriptVar( player, "recursiveCheck" );
return false;
}
if ( !hasObjVar( player, QUEST_STATUS + "." + questType + "." + questName ))
{
utils.removeScriptVar( player, "recursiveCheck" );
return false;//You're not done.
}
// Does this mission have a split?
string qTable = "datatables/spacequest/"+questType+"/"+questName+".iff";
dictionary questInfo = dataTableGetRow( qTable, 0 );
if ( questInfo == null )
{
utils.removeScriptVar( player, "recursiveCheck" );
return false;//this is fucked, no quest info!
}
int splittype = questInfo.getInt( "triggerSplitCondition" );
string splitmission = questInfo.getString( "triggerArg" );
if ( (splitmission == null) || splitmission.equals( "" ) || (splittype == 2) )
{
utils.removeScriptVar( player, "recursiveCheck" );
return true;//we know you completed this mission, as it has no split, you must be done
}
else
{
//check the next one
java.util.StringTokenizer st = new java.util.StringTokenizer( splitmission, ":" );
string rtype = st.nextToken();
string rname = st.nextToken();
return hasCompletedQuestRecursive( player, rtype, rname);
}
}
//------------------------------------------------
// Quest Status Queries
// ! Return value is invalid if hasCompletedQuest != true
//
// obj_id player - The player to check.
// string questType - The quest type.
// string questName - The quest name.
// returns boolean - True if the condition is correct.
//------------------------------------------------
boolean hasFailedQuest( obj_id player, string questType, string questName )
{
return _testQuestFlag( player, questType, questName, QUEST_FAILED );
}
boolean hasFailedQuestRecursive( obj_id player, string questType, string questName )
{
return _recursiveFlagTest( player, questType, questName, QUEST_FAILED );
}
boolean hasWonQuest( obj_id player, string questType, string questName )
{
return _testQuestFlag( player, questType, questName, QUEST_WON );
}
boolean hasWonQuestRecursive( obj_id player, string questType, string questName )
{
return _recursiveFlagTestLast( player, questType, questName, QUEST_WON );
}
boolean hasAbortedQuest( obj_id player, string questType, string questName )
{
return _testQuestFlag( player, questType, questName, QUEST_ABORTED );
}
boolean hasAbortedQuestRecursive( obj_id player, string questType, string questName )
{
return _recursiveFlagTest( player, questType, questName, QUEST_ABORTED );
}
boolean hasReceivedReward( obj_id player, string questType, string questName )
{
return _testQuestFlag( player, questType, questName, QUEST_RECEIVED_REWARD );
}
boolean _recursiveFlagTest( obj_id player, string questType, string questName, int flag )
{
int recNum = utils.getIntScriptVar( player, "recursiveCheck" );
recNum++;
utils.setScriptVar( player, "recursiveCheck", recNum );
if ( recNum > 20 )
{
debugSpeakMsg( player, "This quest " + questType + ":" + questName + " is BAD DATA REF'ING ITSELF!" );
utils.removeScriptVar( player, "recursiveCheck" );
return false;
}
boolean test = _testQuestFlag( player, questType, questName, flag );
if ( test )
{
utils.removeScriptVar( player, "recursiveCheck" );
return true;
}
// Does this mission have a split?
string qTable = "datatables/spacequest/"+questType+"/"+questName+".iff";
dictionary questInfo = dataTableGetRow( qTable, 0 );
if ( questInfo == null )
{
utils.removeScriptVar( player, "recursiveCheck" );
return false;
}
int splittype = questInfo.getInt( "triggerSplitCondition" );
string splitmission = questInfo.getString( "triggerArg" );
if ( (splitmission == null) || splitmission.equals( "" ) || (splittype == 2) )
{
utils.removeScriptVar( player, "recursiveCheck" );
return _testQuestFlag( player, questType, questName, flag );
}
else
{
java.util.StringTokenizer st = new java.util.StringTokenizer( splitmission, ":" );
string rtype = st.nextToken();
string rname = st.nextToken();
return _recursiveFlagTest( player, rtype, rname, flag );
}
}
// Finds the last mission in a chain and tests the flag.
boolean _recursiveFlagTestLast( obj_id player, string questType, string questName, int flag )
{
// Does this mission have a split?
string qTable = "datatables/spacequest/"+questType+"/"+questName+".iff";
dictionary questInfo = dataTableGetRow( qTable, 0 );
if ( questInfo == null )
return false;
int splittype = questInfo.getInt( "triggerSplitCondition" );
string splitmission = questInfo.getString( "triggerArg" );
if ( (splitmission == null) || splitmission.equals( "" ) || (splittype == 2) )
{
return _testQuestFlag( player, questType, questName, flag );
}
else
{
java.util.StringTokenizer st = new java.util.StringTokenizer( splitmission, ":" );
string rtype = st.nextToken();
string rname = st.nextToken();
return _recursiveFlagTest( player, rtype, rname, flag );
}
}
//------------------------------------------------
// Quest Status Setters
// Marks the quest status.
//
// obj_id player - The player who is on the quest.
// obj_id missionObj- Id of the mission in question.
// returns boolean - True if the quest was successfully marked.
//------------------------------------------------
boolean setQuestFailed( obj_id player, obj_id missionObj )
{
return setQuestFailed( player, missionObj, true );
}
boolean setQuestFailed( obj_id player, obj_id missionObj, boolean canSplit )
{
string questName = getStringObjVar( missionObj, QUEST_NAME );
string questType = getStringObjVar( missionObj, QUEST_TYPE );
dictionary webster = new dictionary();
webster.put ("questName", questName);
// Notify the player.
string_id title = new string_id( "spacequest/"+questType+"/"+questName, "title" );
prose_package pp = prose.getPackage( SID_QUEST_FAILED, title );
sendQuestSystemMessage( player, pp );
// GROUP: Notify the group.
_groupNotify( player, SID_GROUP_QUEST_FAILED, title );
// Play the sad music.
play2dNonLoopingMusic( player, MUSIC_QUEST_FAILED );
// Flag the quest.
_setQuestFlag( player, questType, questName, QUEST_FAILED );
flagQuestGroup( missionObj, QUEST_FAILED );
// Remove the quest journal entry.
_removeQuestJournalEntry( player, questType+"/"+questName );
// Log it.
string groupString = "GROUP:0";
if ( group.isGrouped( player ) )
{
obj_id groupId = getGroupObject( player );
int numMembers = getGroupSize( groupId );
if ( numMembers > 0 )
{
groupString = "GROUP:"+numMembers;
}
}
CustomerServiceLog( "space_quest", "QUEST_FAILED|V1|"+groupString+"|TIME:"+getGameTime()+"|PLAYER:"+player+"|TYPE:"+questType+"|NAME:"+questName+"|ZONE:"+getCurrentSceneName() );
// Check for an end of mission split.
if ( (getIntObjVar( missionObj, QUEST_TRIGGER_EVENT ) == 1) && canSplit )
{
int triggerD = getIntObjVar( missionObj, QUEST_TRIGGER_DELAY );
int triggerSC = getIntObjVar( missionObj, QUEST_TRIGGER_SC );
if ( (triggerSC == 2) || (triggerSC == 3) ) // Split on a fail or tree case.
{
dictionary params = new dictionary();
params.put( "quest", missionObj );
params.put( "failure", true );
params.put( "ends", true );
setObjVar( missionObj, "noAbort", 1 );
messageTo( player, "doSpecialEvent", params, triggerD+5, false );
}
else
{
_removeQuest( player, questType, questName );
messageTo( player, "groundSpaceFailed", webster, 1, false );
}
}
else
{
_removeQuest( player, questType, questName );
messageTo( player, "groundSpaceFailed", webster, 1, false );
}
return true;
}
boolean setQuestWon( obj_id player, obj_id missionObj )
{
return setQuestWon( player, missionObj, true );
}
boolean setQuestWon( obj_id player, obj_id missionObj, boolean wsplit )
{
string questName = getStringObjVar( missionObj, QUEST_NAME );
string questType = getStringObjVar( missionObj, QUEST_TYPE );
dictionary webster = new dictionary();
webster.put ("questName", questName);
// Send mission over messages:
// If a duty mission, tell them the mission ended.
// otherwise, tell them mission won.
string_id title = new string_id( "spacequest/"+questType+"/"+questName, "title" );
prose_package pp;
if ( hasObjVar( missionObj, QUEST_DUTY ) )
{
// Notify the player.
pp = prose.getPackage( SID_QUEST_ENDED, title );
sendQuestSystemMessage( player, pp );
// GROUP: Notify the group.
_groupNotify( player, SID_GROUP_QUEST_ENDED, title );
}
else
{
// Notify the player.
pp = prose.getPackage( SID_QUEST_WON, title );
sendQuestSystemMessage( player, pp );
// GROUP: Notify the group.
_groupNotify( player, SID_GROUP_QUEST_WON, title );
}
_setQuestFlag( player, questType, questName, QUEST_WON );
flagQuestGroup( missionObj, QUEST_WON );
// Log it.
string groupString = "GROUP:0";
if ( group.isGrouped( player ) )
{
obj_id groupId = getGroupObject( player );
int numMembers = getGroupSize( groupId );
if ( numMembers > 0 )
{
groupString = "GROUP:"+numMembers;
}
}
CustomerServiceLog( "space_quest", "QUEST_WON|V1|"+groupString+"|TIME:"+getGameTime()+"|PLAYER:"+player+"|TYPE:"+questType+"|NAME:"+questName+"|ZONE:"+getCurrentSceneName() );
// Flag the main quest journal entry as finished.
int questid = questGetQuestId( "spacequest/"+questType+"/"+questName );
if ( (questid != 0) && questIsQuestActive( questid, player ) )
questCompleteQuest( questid, player );
// Is there an auto reward to give the player?
if ( hasObjVar( missionObj, QUEST_AUTO_REWARD ) )
{
int autoReward = getIntObjVar( missionObj, QUEST_AUTO_REWARD );
string_id autoRewardEmailFrom = new string_id ( "spacequest/"+questType+"/"+questName, "autorewardfrom" );
string_id autoRewardEmailSubject = new string_id ( "spacequest/"+questType+"/"+questName, "autorewardsubject" );
string_id autoRewardEmailBody = new string_id ( "spacequest/"+questType+"/"+questName, "autorewardbody" );
// Wire the player the money.
money.bankTo( money.ACCT_SPACE_QUEST_REWARD, player, autoReward );
pp = prose.getPackage( SID_QUEST_REWARD, autoReward );
sendQuestSystemMessage( player, pp );
// Send the player the mail.
string player_name = getName( player );
string body_oob = chatMakePersistentMessageOutOfBandBody( null, autoRewardEmailBody );
chatSendPersistentMessage( "@"+autoRewardEmailFrom.toString(), player_name, "@" + autoRewardEmailSubject.toString(), null, body_oob );
// Flag us as having received the reward.
_setQuestFlag( player, questType, questName, QUEST_RECEIVED_REWARD );
}
// Play the happy music.
play2dNonLoopingMusic( player, MUSIC_QUEST_WON );
// Check for an end of mission split.
if ( wsplit && (getIntObjVar( missionObj, QUEST_TRIGGER_EVENT ) == 1) )
{
int triggerOn = getIntObjVar( missionObj, QUEST_TRIGGER_ON );
int triggerSC = getIntObjVar( missionObj, QUEST_TRIGGER_SC );
int triggerD = getIntObjVar( missionObj, QUEST_TRIGGER_DELAY );
boolean split = false;
if ( triggerSC == 0 )
split = (triggerOn == -1); // Support for the old style
else if ( (triggerSC == 1) || (triggerSC == 3) )
split = true;
if ( split )
{
dictionary params = new dictionary();
params.put( "quest", missionObj );
webster.put ("quest", missionObj );
params.put( "ends", true );
setObjVar( missionObj, "noAbort", 1 );
messageTo( player, "doSpecialEvent", params, triggerD+5, false );
}
else
{
_removeQuest( player, questType, questName );
messageTo( player, "groundSpaceWinner", webster, 1, false );
}
}
else
{
_removeQuest( player, questType, questName );
messageTo( player, "groundSpaceWinner", webster, 1, false );
}
return true;
}
boolean setQuestAborted( obj_id player, obj_id missionObj )
{
string questName = getStringObjVar( missionObj, QUEST_NAME );
string questType = getStringObjVar( missionObj, QUEST_TYPE );
dictionary webster = new dictionary ();
webster.put ("questName", questName);
// Notify the player.
string_id title = new string_id( "spacequest/"+questType+"/"+questName, "title" );
prose_package pp;
if ( hasObjVar( missionObj, QUEST_DUTY ) )
pp = prose.getPackage( SID_DUTY_ABORTED, title );
else
pp = prose.getPackage( SID_QUEST_ABORTED, title );
sendQuestSystemMessage( player, pp );
// GROUP: Notify the group.
_groupNotify( player, SID_GROUP_QUEST_ABORTED, title );
_setQuestFlag( player, questType, questName, QUEST_ABORTED );
flagQuestGroup( missionObj, QUEST_ABORTED );
_removeQuest( player, questType, questName );
messageTo( player, "groundSpaceFailed", webster, 1, false );
// Play music.
play2dNonLoopingMusic( player, MUSIC_QUEST_ABORTED );
// Remove the quest journal entry.
_removeQuestJournalEntry( player, questType+"/"+questName );
// Log it.
string groupString = "GROUP:0";
if ( group.isGrouped( player ) )
{
obj_id groupId = getGroupObject( player );
int numMembers = getGroupSize( groupId );
if ( numMembers > 0 )
{
groupString = "GROUP:"+numMembers;
}
}
CustomerServiceLog( "space_quest", "QUEST_ABORTED|V1|"+groupString+"|TIME:"+getGameTime()+"|PLAYER:"+player+"|TYPE:"+questType+"|NAME:"+questName+"|ZONE:"+getCurrentSceneName() );
return true;
}
boolean setSilentQuestAborted( obj_id player, obj_id missionObj )
{
string questName = getStringObjVar( missionObj, QUEST_NAME );
string questType = getStringObjVar( missionObj, QUEST_TYPE );
dictionary webster = new dictionary ();
webster.put ("questName", questName);
_setQuestFlag( player, questType, questName, QUEST_ABORTED );
flagQuestGroup( missionObj, QUEST_ABORTED );
_removeQuest( player, questType, questName );
messageTo( player, "groundSpaceFailed", webster, 1, false );
// Remove the quest journal entry.
_removeQuestJournalEntry( player, questType+"/"+questName );
// Log it.
string groupString = "GROUP:0";
if ( group.isGrouped( player ) )
{
obj_id groupId = getGroupObject( player );
int numMembers = getGroupSize( groupId );
if ( numMembers > 0 )
{
groupString = "GROUP:"+numMembers;
}
}
CustomerServiceLog( "space_quest", "QUEST_ABORTED|V1|"+groupString+"|TIME:"+getGameTime()+"|PLAYER:"+player+"|TYPE:"+questType+"|NAME:"+questName+"|ZONE:"+getCurrentSceneName() );
return true;
}
// Should be called after the quest is failed/won/aborted.
// Should be called from the quest conversation reward event.
boolean setQuestRewarded( obj_id player, string questType, string questName )
{
// Notify the player.
string_id title = new string_id( "spacequest/"+questType+"/"+questName, "title" );
prose_package pp = prose.getPackage( SID_QUEST_REWARDED, title );
sendQuestSystemMessage( player, pp );
_setQuestFlag( player, questType, questName, QUEST_RECEIVED_REWARD );
// Play music.
play2dNonLoopingMusic( player, MUSIC_QUEST_WON );
return true;
}
// Internal function used to flag a quest as "in progress."
// A quest in progress is failed upon death.
boolean _setQuestInProgress( obj_id quest )
{
return _setQuestInProgress( quest, false );
}
boolean _setQuestInProgress( obj_id quest, boolean music )
{
if ( hasObjVar( quest, "in_progress" ) )
return false;
// Mark as in progress.
setObjVar( quest, "in_progress", 1 );
// Notify the player.
obj_id player = getObjIdObjVar( quest, QUEST_OWNER );
string questName = getStringObjVar( quest, QUEST_NAME );
string questType = getStringObjVar( quest, QUEST_TYPE );
string_id title = new string_id( "spacequest/"+questType+"/"+questName, "title" );
prose_package pp = prose.getPackage( SID_QUEST_IN_PROGRESS, title );
sendQuestSystemMessage( player, pp );
// Music.
if ( music )
play2dNonLoopingMusic( player, space_quest.MUSIC_QUEST_MISSION_START );
// GROUP: Notify the group.
_groupNotify( player, SID_GROUP_QUEST_IN_PROGRESS, title );
return true;
}
boolean isQuestInProgress( obj_id quest )
{
if ( hasObjVar( quest, "in_progress" ) )
return true;
else
return false;
}
// Message the player with a quest update.
void showQuestUpdate( obj_id quest, string_id update_id )
{
// Notify the player.
obj_id player = getObjIdObjVar( quest, QUEST_OWNER );
string questName = getStringObjVar( quest, QUEST_NAME );
prose_package pp;
if ( hasObjVar( quest, QUEST_DUTY ) )
pp = prose.getPackage( SID_DUTY_UPDATE_S, update_id );
else
pp = prose.getPackage( SID_QUEST_UPDATE_S, update_id );
sendQuestSystemMessage( player, pp );
_groupNotify( player, pp );
}
// Message the player with a quest update.
void showQuestUpdate( obj_id quest, string_id update_id, int count )
{
// Notify the player.
obj_id player = getObjIdObjVar( quest, QUEST_OWNER );
string questName = getStringObjVar( quest, QUEST_NAME );
prose_package pp;
if ( hasObjVar( quest, QUEST_DUTY ) )
pp = prose.getPackage( SID_DUTY_UPDATE_IS, update_id, count );
else
pp = prose.getPackage( SID_QUEST_UPDATE_IS, update_id, count );
sendQuestSystemMessage( player, pp );
_groupNotify( player, pp );
}
// Message the player with a quest update.
void showQuestAlert( obj_id player, string_id update_id )
{
// Notify the player.
prose_package pp = prose.getPackage( SID_QUEST_ALERT_S, update_id );
sendQuestSystemMessage( player, pp );
_groupNotify( player, pp );
}
// Message the player with an escort update.
void showEscortUpdate( obj_id quest, string_id update_id )
{
// Notify the player.
obj_id player = getObjIdObjVar( quest, QUEST_OWNER );
string questName = getStringObjVar( quest, QUEST_NAME );
prose_package pp = prose.getPackage( SID_ESCORT_UPDATE, update_id );
sendQuestSystemMessage( player, pp );
_groupNotify( player, pp );
}
// Give the player a reward for a quest.
void giveReward( obj_id player, string questType, string questName, int credits )
{
giveReward( player, questType, questName, credits, null );
}
void giveReward( obj_id player, string questType, string questName, int credits, string obj )
{
// Flag as rewarded.
setQuestRewarded( player, questType, questName );
// Wire the player the money.
if ( credits > 0 )
{
money.bankTo( money.ACCT_SPACE_QUEST_REWARD, player, credits );
prose_package pp = prose.getPackage( SID_QUEST_REWARD, credits );
sendQuestSystemMessage( player, pp );
}
// Give the player an object.
if ( obj != null )
{
obj_id newItem = createObjectInInventoryAllowOverload( obj, player );
string objectName = utils.packStringId (getNameStringId(newItem));
prose_package pp = prose.getPackage( SID_QUEST_REWARD_OBJECT, objectName );
sendQuestSystemMessage( player, pp );
}
}
void clearQuestFlags( obj_id player, string questType, string questName )
{
removeObjVar( player, QUEST_STATUS + "." + questType + "." + questName );
int questNum = questGetQuestId("spacequest/"+questType+"/"+questName);
debugSpeakMsg(player, "Quest ID is" + questNum);
questClearQuest(questNum, player);
obj_id quest = _getQuest(player, questType, questName);
if(isIdValid(quest) && exists(quest))
setQuestAborted(player, quest);
}
//------------------------------------------------------------------------------------------------
// Internal Quest Management
//
// These are private functions that shouldn't be called from outside the library or internal quest scripts.
//------------------------------------------------------------------------------------------------
//------------------------------------------------
// _getQuestId
//------------------------------------------------
int _getQuestId( String questName )
{
return dataTableSearchColumnForString( questName, 0, "datatables/player/quests.iff" );
}
//------------------------------------------------
// _setupQuest
// Sets up the player object quest info.
//
// obj_id player - The player to give a quest to.
// string questType - The quest table (by type) to look in.
// dictionary questInfo-The quest datatable row.
// returns boolean - True if the quest setup was successful.
//------------------------------------------------
boolean _setupQuest( obj_id player, string questType, string questName, string qTable, boolean duty )
{
// Don't let them take another duty quest.
if ( duty && _hasDutyQuest( player ) )
{
sendQuestSystemMessage( player, SID_DUTY_ALREADY );
return false;
}
// Get the player's datapad. We store mission data in there.
obj_id datapad = utils.getPlayerDatapad( player );
if ( !isIdValid( datapad ) )
{
sendSystemMessageTestingOnly( player, "_setupQuest: Unable to get datapad for player " + player );
return false;
}
// Create a quest object for the player.
// For now we are using ground mission objects.
obj_id missionObj = createObject( QUEST_OBJECT_TEMPLATE, datapad, "" );
if ( !isIdValid( missionObj ) )
{
sendSystemMessageTestingOnly( player, "_setupQuest: Unable to create a mission object for quest." );
return false;
}
// Get the first line of the quest data. "questInfo"
dictionary questInfo = dataTableGetRow( qTable, 0 );
// Write the quest info to the mission object.
setObjVar( missionObj, QUEST_OWNER, player );
setObjVar( missionObj, QUEST_NAME, questName );
setObjVar( missionObj, QUEST_TYPE, questType );
setObjVar( missionObj, QUEST_ZONE, questInfo.getString( "questZone" ) );
setObjVar( missionObj, "self", missionObj );
if ( duty )
setObjVar( missionObj, QUEST_DUTY, duty );
// Setup some mission object data.
setMissionDescription( missionObj, new string_id( "spacequest/"+questType+"/"+questName, "title_d" ) );
setMissionTitle( missionObj, new string_id( "space/quest", questType ) );
if ( questType == "space_battle" || questType == "space_mining_destroy" )
{
setMissionType( missionObj, questType );
}
else if ( questType == "assassinate" )
{
setMissionType( missionObj, "space_assassination" );
}
else if ( questType == "inspect" )
{
setMissionType( missionObj, "space_inspection" );
}
else if ( questType == "destroy_surpriseattack" )
{
setMissionType( missionObj, "space_surprise_attack" );
}
else if ( questType == "delivery_no_pickup" )
{
setMissionType( missionObj, "space_delivery" );
}
else
{
setMissionType( missionObj, "space_"+questType );
}
// Auto Rewards: Cash rewards wired to the player with an email. Any quest can have an auto reward.
// Narrative quests should probably require you to return to the quest giver or some other person, though.
int autoReward = questInfo.getInt( "autoReward" );
if ( autoReward > 0 )
setObjVar( missionObj, QUEST_AUTO_REWARD, autoReward );
// Quest triggers: Special events that happen during the quest.
int triggerEvent = questInfo.getInt( "triggerEvent" );
if ( triggerEvent > 0 )
{
setObjVar( missionObj, QUEST_TRIGGER_EVENT, triggerEvent );
setObjVar( missionObj, QUEST_TRIGGER_SC, questInfo.getInt( "triggerSplitCondition" ) );
setObjVar( missionObj, QUEST_TRIGGER_ARG, questInfo.getString( "triggerArg" ) );
setObjVar( missionObj, QUEST_TRIGGER_ARG2, questInfo.getString( "triggerArg2" ) );
setObjVar( missionObj, QUEST_TRIGGER_ON, questInfo.getInt( "triggerOn" ) );
if ( questInfo.getInt( "triggerEnds" ) == 1 )
setObjVar( missionObj, QUEST_TRIGGER_ENDS, 1 );
if ( questInfo.getInt( "triggerEndsMission" ) == 1 )
setObjVar( missionObj, QUEST_TRIGGER_ENDS, 1 );
setObjVar( missionObj, QUEST_TRIGGER_DELAY, questInfo.getInt( "triggerDelay" ) );
}
// Activate the root quest journal entry.
int questid = questGetQuestId( "spacequest/"+questType+"/"+questName );
if ( (questid != 0 ) && (questCanActivateQuest( questid, player ) == 0) )
questActivateQuest( questid, player, null );
// Attach quest scripts.
attachScript( missionObj, "space.quest_logic." + questType );
// Attach player quest script.
if ( !hasScript( player, "space.quest_logic.player_spacequest" ) )
attachScript( player, "space.quest_logic.player_spacequest" );
// Clear completion flags associated with this quest.
_clearQuestFlag( player, questType, questName, QUEST_ABORTED );
_clearQuestFlag( player, questType, questName, QUEST_FAILED );
_clearQuestFlag( player, questType, questName, QUEST_WON );
return true;
}
//------------------------------------------------
// _removeQuest
// Removes the quest object from the player.
//
// obj_id player - The player to give a quest to.
// string questType - The quest table (by type) to look in.
// string questName - The quest name.
// returns boolean - True if removal was successful.
//------------------------------------------------
boolean _removeQuest( obj_id player, string questType, string questName )
{
obj_id missionObj = _getQuest( player, questType, questName );
_removeQuest( player, missionObj );
return true;
}
boolean _removeQuest( obj_id player, obj_id missionObj )
{
_removeMissionCriticalShips( player, missionObj );
destroyObject( missionObj );
return true;
}
//------------------------------------------------
// _hasDutyQuest
//------------------------------------------------
boolean _hasDutyQuest( obj_id player )
{
obj_id datapad = utils.getPlayerDatapad( player );
if ( isIdValid( datapad ) )
{
// Search for any quest in the datapad.
obj_id[] dpobjs = getContents( datapad );
for ( int i=0; i<dpobjs.length; i++ )
{
if ( hasObjVar( dpobjs[i], QUEST_DUTY ) )
return true;
}
}
return false;
}
//------------------------------------------------
// Quest status flag control methods.
//------------------------------------------------
int _getQuestStatus( obj_id player, string questType, string questName )
{
return getIntObjVar( player, QUEST_STATUS + "." + questType + "." + questName );
}
int _setQuestStatus( obj_id player, string questType, string questName, int flags )
{
setObjVar( player, QUEST_STATUS + "." + questType + "." + questName, flags );
return flags;
}
boolean _testQuestFlag( obj_id player, string questType, string questName, int flag )
{
if ( hasCompletedQuest( player, questType, questName ) )
{
int questStatus = _getQuestStatus( player, questType, questName );
return ((questStatus & flag) != 0);
}
return false;
}
void _setQuestFlag( obj_id player, string questType, string questName, int flag )
{
int questStatus = _getQuestStatus( player, questType, questName );
questStatus |= flag;
_setQuestStatus( player, questType, questName, questStatus );
}
void _clearQuestFlag( obj_id player, string questType, string questName, int flag )
{
int questStatus = _getQuestStatus( player, questType, questName );
questStatus = questStatus & ~flag;
_setQuestStatus( player, questType, questName, questStatus );
}
//------------------------------------------------
// setQuestSeriesFlag
// Sets a quest series flag. Used to track player progress through groups of quests.
//------------------------------------------------
boolean hasCompletedQuestSeries( obj_id player, string questSeries )
{
int flags = getIntObjVar( player, QUEST_STATUS_SERIES + "." + questSeries );
return ((flags & QUEST_SERIES_COMPLETED) != 0);
}
void setQuestSeriesFlag( obj_id player, string questSeries, int flag )
{
int flags = getIntObjVar( player, QUEST_STATUS_SERIES + "." + questSeries );
flags |= flag;
setObjVar( player, QUEST_STATUS_SERIES + "." + questSeries, flags );
}
void clearQuestSeriesFlags( obj_id player, string questSeries )
{
removeObjVar( player, QUEST_STATUS_SERIES + "." + questSeries );
}
/* -----------------12/9/2003 11:13AM----------------
* Familiarity Tracking System
*
* How it works: Rather than tracking how familiar every NPC is with
* a given player, this system allows the scripter to get/set a
* familiarity level with an arbitrary string label. e.g. Rather
* than tracking the player's individual familiarity with 5 different
* NPCs in a given quest series, assign the quest series a single
* familiarity label. Conversation scripts can then check the
* familiary level of the player with that label, and make assumptions
* based on that. e.g. If the familiarity level is 0, then none of
* the NPCs have ever talked to the player. Once the player talks
* to the first NPC, set the familiarity to one. Once the player
* talks to another NPC in that quest series, set that same familiarity
* level to 5. When the player returns to talk to either of these NPCs,
* the convo script can assume the 1st NPC knows the player if
* familiary is >= 1, and can assume the 2nd NPC also knows the player
* if familiarity is >= 5, and so on.
*
* --------------------------------------------------*/
const string FAMILIARITY_LIST = "familiarity.";
/** setFamiliarity( obj_id player, string label, int value )
*
* Sets the familiarity level of player to a specific value for the given label
*
* player - the player whose level you want to set
* label - the label you want to set the level with
* value - the value you want to set the level to
*
* returns nothing
*/
void setFamiliarity( obj_id player, string label, int value )
{
if ( !isPlayer(player) )
return;//only set these on players
setObjVar( player, FAMILIARITY_LIST + label, value );
}
/** getFamiliarity( obj_id player, string label)
*
* gets the familiarity level of player with a specific label
*
* player - the player whose level you want to set
* label - the label you want to set the level with
*
* returns the value of the player's familiarity with this label
*/
int getFamiliarity( obj_id player, string label )
{
return (getIntObjVar( player, FAMILIARITY_LIST + label));
}
/** adjustFamiliarity( obj_id player, string label, int value)
*
* gets the familiarity level of player with a specific label
*
* player - the player whose level you want to set
* label - the label you want to set the level with
* value - the +/- value you want to add/subtract from the
* player's familiarity level with the given label
*
* returns the value of the player's familiarity with this label
*/
int adjustFamiliarity( obj_id player, string label, int value )
{
int currentFamiliarity = getFamiliarity( player, label );
currentFamiliarity += value;
setFamiliarity( player, label, currentFamiliarity );
return currentFamiliarity;
}
/** clearFamiliarity( obj_id player, string label )
*
* erases the familiarity level of player with a specific label
*
* player - the player whose level you want to set
* label - the label you want to set the level with
*
* returns nothing
*/
void clearFamiliarity( obj_id player, string label )
{
removeObjVar( player, FAMILIARITY_LIST + label );
}
boolean isPlayerQualifiedForSkill(obj_id objPlayer, string strSkill)
{
boolean boolHasSkills = skill.hasRequiredSkillsForSkillPurchase(objPlayer, strSkill);
boolean boolHasXp = skill.hasRequiredXpForSkillPurchase(objPlayer, strSkill);
if((boolHasSkills)&&(boolHasXp))
{
return true;
}
return false;
}
//------------------------------------------------
// getRandomPositionInSphere
//------------------------------------------------
transform getRandomPositionInSphere( transform trStartPosition, float fltMinRadius, float fltMaxRadius )
{
float fltDistance = rand( fltMinRadius, fltMaxRadius );
vector vctOffset= vector.randomUnit().multiply( fltDistance );
transform transform_w = trStartPosition;
transform_w = transform_w.move_p( vctOffset );
return transform_w;
}
//------------------------------------------------
// cleanArray
//------------------------------------------------
void cleanArray( obj_id quest, string objVar, string[] array )
{
if ( array == null )
return;
// Clean off any dead space at the end.
int k = 0;
for ( int i=0; i<array.length; i++ )
{
if ( !array[i].equals( "" ) )
k++;
}
if ( k == 0 )
return;
string[] newarray = new string[k];
for ( int i=0; i<k; i++ )
{
newarray[i] = array[i];
}
setObjVar( quest, objVar, newarray );
}
//------------------------------------------------
// cleanArray
//------------------------------------------------
void cleanArray( obj_id quest, string objVar, int[] array )
{
if ( array == null )
return;
// Clean off any dead space at the end.
int k = 0;
for ( int i=0; i<array.length; i++ )
{
if ( array[i] != -1 )
k++;
}
if ( k == 0 )
return;
int[] newarray = new int[k];
for ( int i=0; i<k; i++ )
{
newarray[i] = array[i];
}
setObjVar( quest, objVar, newarray );
}
//------------------------------------------------
// hasShip
//------------------------------------------------
boolean hasShip(obj_id player)
{
obj_id[] shipControlDevices = space_transition.findShipControlDevicesForPlayer(player);
if (shipControlDevices != null && shipControlDevices.length > 0)
return true;
return false;
}
//------------------------------------------------
// hasCertifiedShip
//------------------------------------------------
boolean hasCertifiedShip(obj_id player)
{
if(!isIdValid(player) || !isPlayer(player))
return false;
obj_id[] shipControlDevices = space_transition.findShipControlDevicesForPlayer(player);
if(shipControlDevices == null || shipControlDevices.length == 0)
return false;
for(int i = 0; i < shipControlDevices.length; i++)
{
obj_id ship = space_transition.getShipFromShipControlDevice(shipControlDevices[i]);
if(!isIdValid(ship))
return false;
if(hasCertificationsForItem(player, ship))
{
string template = getTemplateName(ship);
if(template.endsWith("player_sorosuub_space_yacht.iff")) // Don't count the luxury yacht in this check
continue;
else
return true;
}
}
return false;
}
//------------------------------------------------
// hasCertifiedNonNewbieShip
//------------------------------------------------
boolean hasCertifiedNonNewbieShip(obj_id player)
{
if(!isIdValid(player) || !isPlayer(player))
return false;
obj_id[] shipControlDevices = space_transition.findShipControlDevicesForPlayer(player);
if(shipControlDevices == null || shipControlDevices.length == 0)
return false;
for(int i = 0; i < shipControlDevices.length; i++)
{
obj_id ship = space_transition.getShipFromShipControlDevice(shipControlDevices[i]);
if(!isIdValid(ship))
return false;
if(hasCertificationsForItem(player, ship))
{
string template = getTemplateName(ship);
if(template.endsWith("player_basic_tiefighter.iff"))
continue;
else if(template.endsWith("player_basic_z95.iff"))
continue;
else if(template.endsWith("player_basic_hutt_light.iff"))
continue;
else if(template.endsWith("player_sorosuub_space_yacht.iff")) // Don't count the luxury yacht in this check
continue;
else
return true;
}
}
return false;
}
//------------------------------------------------
// canGrantNewbieShip
//------------------------------------------------
boolean canGrantNewbieShip(obj_id player)
{
if(hasCertifiedShip(player))
return false;
if(!space_transition.isPlayerBelowShipLimit(player))
return false;
return true;
}
//------------------------------------------------
// grantNewbieShip
//
// valid factions:
// "imperial", "rebel", "neutral"
//------------------------------------------------
void grantNewbieShip( obj_id player, string faction )
{
obj_id datapad = utils.getDatapad( player );
if ( !isIdValid(datapad) )
return;
string pcd = null;
string ship = null;
if ( faction.equals( "imperial" ) )
{
pcd = "object/intangible/ship/tiefighter_pcd.iff";
ship = "object/ship/player/player_prototype_tiefighter.iff";
}
else if ( faction.equals( "rebel" ) )
{
pcd = "object/intangible/ship/z95_pcd.iff";
ship = "object/ship/player/player_prototype_z95.iff";
}
else if ( faction.equals( "neutral" ) )
{
pcd = "object/intangible/ship/hutt_light_s01_pcd.iff";
ship = "object/ship/player/player_prototype_hutt_light.iff";
}
obj_id opcd = createObject( pcd, datapad, "");
if ( !isIdValid(opcd) )
sendSystemMessageTestingOnly( player, "Critical failure: Could not create a pcd for the player!" );
else
{
obj_id oship = createObject( ship, opcd, "");
if ( isIdValid( oship ) )
{
setOwner( oship, player );
if ( faction.equals( "imperial" ) )
{
setShipComponentMass(oship, ship_chassis_slot_type.SCST_reactor , 1500); //reactor mass
setShipReactorEnergyGenerationRate(oship, 8000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_engine, 1500); //engine mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_engine, 2000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_shield_0, 1500); //shield mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_shield_0, 2000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_armor_0, 1500); //armor mass 1
setShipComponentMass(oship, ship_chassis_slot_type.SCST_armor_1, 1500); //armor mass 2
setShipComponentMass(oship, ship_chassis_slot_type.SCST_capacitor, 1500); //capacitor mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_capacitor, 2000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_weapon_0, 1500); //weapon mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_weapon_0, 2000);
}
else if ( faction.equals( "rebel" ) || faction.equals( "neutral" ))
{
setShipComponentMass(oship, ship_chassis_slot_type.SCST_reactor , 1500); //reactor mass
setShipReactorEnergyGenerationRate(oship, 8000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_engine, 1500); //engine mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_engine, 2000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_shield_0, 1500); //shield mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_shield_0, 2000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_armor_0, 1500); //armor mass 1
setShipComponentMass(oship, ship_chassis_slot_type.SCST_armor_1, 1500); //armor mass 2
setShipComponentMass(oship, ship_chassis_slot_type.SCST_capacitor, 1500); //capacitor mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_capacitor, 2000);
setShipComponentMass(oship, ship_chassis_slot_type.SCST_weapon_0, 1500); //weapon mass
setShipComponentEnergyMaintenanceRequirement(oship, ship_chassis_slot_type.SCST_weapon_0, 2000);
}
}
else
sendSystemMessageTestingOnly( player, "Critical failure: Could not create a ship for the player's pcd!" );
}
}
//------------------------------------------------
// _groupNotify
//
// Messages the player's group, but not the player.
//------------------------------------------------
void _groupNotify( obj_id player, string_id mid, string_id s1 )
{
if ( group.isGrouped( player ) )
{
obj_id gid = getGroupObject( player );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null )
{
for ( int i=0; i<members.length; i++ )
{
if ( members[i] == player )
continue;
prose_package pp = prose.getPackage( mid, s1, getName( player ) );
sendQuestSystemMessage( members[i], pp );
}
}
}
}
void _groupNotify( obj_id player, prose_package pp )
{
if ( group.isGrouped( player ) )
{
obj_id gid = getGroupObject( player );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null )
{
for ( int i=0; i<members.length; i++ )
{
if ( members[i] == player )
continue;
sendQuestSystemMessage( members[i], pp );
}
}
}
}
void _groupNotify( obj_id player, string_id mid )
{
if ( group.isGrouped( player ) )
{
obj_id gid = getGroupObject( player );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null )
{
for ( int i=0; i<members.length; i++ )
{
if ( members[i] == player )
continue;
sendQuestSystemMessage( members[i], mid );
}
}
}
}
//------------------------------------------------
// sendQuestMessage
//------------------------------------------------
void sendQuestMessage( obj_id player, prose_package pp )
{
sendQuestSystemMessage( player, pp );
_groupNotify( player, pp );
}
void sendQuestMessage( obj_id player, string_id mid )
{
sendQuestSystemMessage( player, mid );
_groupNotify( player, mid );
}
//------------------------------------------------
// groupTaunt
//
// Directs a taunt to the player's group.
//------------------------------------------------
void groupTaunt( obj_id ship, obj_id player, prose_package pp )
{
if ( !isIdValid( player ) || !exists( player ) )
return;
if ( group.isGrouped( player ) )
{
obj_id gid = getGroupObject( player );
obj_id[] members = space_utils.getSpaceGroupMemberIds( gid );
if ( members != null )
{
space_utils.tauntArray( ship, new Vector(Arrays.asList(members)), pp );
}
}
else
{
_tauntShip( ship, space_transition.getContainingShip( player ), pp );
}
}
//------------------------------------------------
// _removeQuestJournalEntry
//------------------------------------------------
void _removeQuestJournalEntry( obj_id player, string quest )
{
quest = "spacequest/" + quest;
int questid = questGetQuestId( quest );
if ( questid != 0 )
questClearQuest( questid, player );
}
//------------------------------------------------
// _addMissionCriticalShip
//------------------------------------------------
void _addMissionCriticalShip( obj_id player, obj_id quest, obj_id ship )
{
addMissionCriticalObject( player, ship );
}
//------------------------------------------------
// _removeMissionCriticalShip
//------------------------------------------------
void _removeMissionCriticalShip( obj_id player, obj_id quest, obj_id ship )
{
removeMissionCriticalObject( player, ship );
}
//------------------------------------------------
// _isMissionCriticalShip
//------------------------------------------------
boolean _isMissionCriticalShip( obj_id player, obj_id quest, obj_id ship )
{
return isMissionCriticalObject( player, ship );
}
//------------------------------------------------
// _removeMissionCriticalShips
//------------------------------------------------
void _removeMissionCriticalShips( obj_id player, obj_id quest )
{
clearMissionCriticalObjects( player );
}
//------------------------------------------------
// _tauntShip
//------------------------------------------------
void _tauntShip( obj_id ship, obj_id target, prose_package pp )
{
if ( isIdValid( target ) && isIdValid( ship ) )
space_utils.tauntShip( target, ship, pp, true, true, false, false );
}
//------------------------------------------------
// _tauntShips
//------------------------------------------------
void _tauntShips( obj_id ship, obj_id[] targets, prose_package pp )
{
for ( int i=0; i<targets.length; i++ )
{
if ( isIdValid( targets[i] ) && isIdValid( ship ) )
space_utils.tauntShip( targets[i], ship, pp, true, true, false, false );
}
}
//------------------------------------------------
// notifyMissions
//
// Utility that forwards a message to quest objects.
// Search method should probably be optimized?
//------------------------------------------------
void notifyMissions( obj_id player, string msg, dictionary params )
{
obj_id datapad = utils.getPlayerDatapad( player );
if ( isIdValid( datapad ) )
{
// Search for any quest in the datapad.
obj_id[] dpobjs = getContents( datapad );
for ( int i=0; i<dpobjs.length; i++ )
{
if ( hasObjVar( dpobjs[i], space_quest.QUEST_NAME ) )
{
space_utils.notifyObject( dpobjs[i], msg, params );
}
}
}
}
//------------------------------------------------
// cleanupOnUnload
//
// Implemented procedurally because messages don't work during unload from memory.
//------------------------------------------------
void cleanupOnUnload( obj_id player )
{
obj_id datapad = utils.getPlayerDatapad( player );
if ( isIdValid( datapad ) )
{
// Search for any quest in the datapad.
obj_id[] dpobjs = getContents( datapad );
for ( int i=0; i<dpobjs.length; i++ )
{
if ( hasObjVar( dpobjs[i], QUEST_NAME ) )
{
string type = getStringObjVar( dpobjs[i], QUEST_TYPE );
// Assassinate
if ( type.equals( "assassinate" ) || type.equals( "recovery" ) )
{
// Clean up the ships as we have left the zone.
if ( isQuestInProgress( dpobjs[i] ) )
{
recoveryCleanUpShips( dpobjs[i] );
}
}
}
}
}
}
//------------------------------------------------
// recoveryCleanUpShips
//
// Since we can't use static methods, this is recovery mission specific logic
// that resides here so that it can be easily used in cleanupOnUnload.
//------------------------------------------------
void recoveryCleanUpShips( obj_id quest )
{
// Warp out the main ship.
obj_id ship = getObjIdObjVar( quest, "target" );
if ( isIdValid( ship ) && exists( ship ) )
{
if ( !ship.isBeingDestroyed() )
{
destroyObjectHyperspace( ship );
}
}
// Warp out the remaining escort fighters.
obj_id[] escorts = getObjIdArrayObjVar( quest, "escorts" );
if ( escorts != null )
{
for ( int i=0; i<escorts.length; i++ )
{
if ( isIdValid( escorts[i] ) && exists( escorts[i] ) )
{
destroyObjectHyperspace( escorts[i] );
}
}
}
}
//------------------------------------------------
// findQuestLocation
//
// return the object for the nav point requested
//------------------------------------------------
obj_id findQuestLocation(obj_id quest, obj_id player, string navName, string type)
{
obj_id questManager = getNamedObject(QUEST_MANAGER);
if (isIdValid(questManager))
{
obj_id[] navs = utils.getObjIdArrayScriptVar(questManager, type+"_list");
if (navs == null)
{
debugServerConsoleMsg(questManager, "Quest Manager: Warning! Zone " + getCurrentSceneName() + " has not been initialized properly, but has been queried for a quest!");
return null;
}
for (int i = 0; i < navs.length; ++i)
{
string curNavName = getStringObjVar(navs[i], "nav_name");
if (curNavName != null && curNavName.equals(navName))
return navs[i];
}
}
debugServerConsoleMsg(questManager, "Error: Failed to find nav point '" + navName + "'. The nav point object may not exist or your server may need to specify 'createZoneObjects=1'");
return null;
}