mirror of
https://bitbucket.org/seefoe/dsrc.git
synced 2026-07-31 01:15:55 -04:00
1988 lines
62 KiB
Plaintext
1988 lines
62 KiB
Plaintext
//------------------------------------------------
|
|
// space_quest.scriptlib
|
|
//------------------------------------------------
|
|
|
|
//------------------------------------------------
|
|
// 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;
|
|
}
|
|
|