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

1783 lines
51 KiB
Plaintext

//include library.quests;
//include library.ai;
include library.battlefield;
include library.regions;
include library.group;
include library.badge;
//questStatus consts
const int IS_ON_QUEST =1;
const int COMPLETED_QUEST = 2;
const int FAILED_QUEST =3;
//Set the questStatus for player on QuestID
void setQuestStatus( obj_id player, string questId, int questStatus )
{
setObjVar(player, "themeparkQuestFlags."+ questId, questStatus);
if ( ( questStatus == quests.COMPLETED_QUEST ) || ( questStatus == quests.FAILED_QUEST ) )
{
clearAllWaypoints( player, questId );
removeObjVar( player, questId );
}
}
boolean hasQuest( obj_id player, string QUEST_ID )
{
if ( getQuestStatus( player, QUEST_ID ) == IS_ON_QUEST )
return true;
else
return false;
}
//remove Quest Status and all quest flags for player on QuestId
void removeQuestStatus( obj_id player, string questId)
{
removeObjVar(player, "themeparkQuestFlags."+ questId);
clearAllWaypoints( player, questId );
removeObjVar( player, questId );
}
//get the questStatus for player on QuestId
int getQuestStatus( obj_id player, string questId)
{
if ( !hasObjVar(player, "themeparkQuestFlags."+ questId ) )
{
return 0;
}
return getIntObjVar( player, "themeparkQuestFlags."+ questId );
}
//flag questId completed for player, and remove all quest flags
void completeQuest( obj_id player, string questId)
{
setQuestStatus( player, questId, quests.COMPLETED_QUEST );
}
//returns true if player has completed questId
boolean hasCompletedQuest( obj_id player, string questId )
{
return ( getQuestStatus( player, questId) == quests.COMPLETED_QUEST );
}
//set quest flagname to value for player on questId
void setQuestFlag( obj_id player, string questId, string flagname, int value )
{
setObjVar(player, questId + ".Flags."+ flagname, value);
}
//return value of quest flag for player on questId
int getQuestFlag(obj_id player, string questId, string flagname)
{
if ( !hasObjVar(player, questId + ".Flags." + flagname ))
{
return 0;
}
return getIntObjVar( player, questId + ".Flags." + flagname );
}
//remove quest flagname for player on questId
void removeQuestFlag(obj_id player, string questId, string flagname)
{
removeObjVar( player, questId + ".Flags." + flagname );
}
/* -----------------3/7/2002 5:55PM------------------
* Infiltration Quest Flags:
* --------------------------------------------------*/
const int CAN_INFILTRATE = 1;
const int COMPLETED_INFILTRATE = 2;
boolean canInfiltrate( obj_id player, string questId )
{
return hasObjVar(player, "themeparkQuestFlags.INFILTRATION." + questId);
}
void setInfiltrateFlag( obj_id player, string questId, int canInfiltrate )
{
if ( canInfiltrate == CAN_INFILTRATE || canInfiltrate == COMPLETED_INFILTRATE)
setObjVar(player, "themeparkQuestFlags.INFILTRATION."+ questId, canInfiltrate);
else
removeObjVar(player, "themeparkQuestFlags.INFILTRATION."+ questId);
}
void removeInfiltrateFlag( obj_id player, string questId )
{
removeObjVar(player, "themeparkQuestFlags.INFILTRATION."+ questId);
}
int getInfiltrateFlag( obj_id player, string questId )
{
return getIntObjVar(player, "themeparkQuestFlags.INFILTRATION." + questId);
}
/* -----------------4/2/2002 3:13PM------------------
* Waypoint and location Target stuff:
* --------------------------------------------------*/
obj_id addQuestLocationTarget( obj_id player, string questId, string name, location loc, float radius )
{
addLocationTarget( name, loc, radius );
obj_id waypoint = createWaypointInDatapad( player, loc );
if (!isIdValid(waypoint))
return null;
setWaypointVisible( waypoint, true);
setWaypointActive( waypoint, true);
setObjVar( player, questId + ".waypoint." + name, waypoint );
return waypoint;
}
obj_id addThemeParkWaypoint( obj_id player, string questId, string name, location loc, float radius, string display, string file, string entry )
{
addLocationTarget( name, loc, radius );
obj_id waypoint = createWaypointInDatapad( player, loc );
setWaypointActive( waypoint, true);
setObjVar( player, questId + ".waypoint." + name, waypoint );
setObjVar (player, "game_created", 1);
setWaypointName ( waypoint, display );
setObjVar (player, questId + ".entry", entry);
setObjVar (player, questId + ".file", file);
setObjVar (waypoint, "player", player);
setObjVar (player, "questID", questId);
return waypoint;
}
/*
obj_id addQuestToken( obj_id player, string questId, string name, location loc, float radius, string display )
{
addLocationTarget( name, loc, radius );
obj_id token = createToken( "object/mobile/jabba_the_hutt.iff", loc );
obj_id datapad = getObjectInSlot( player , "datapad");
putIn( token, datapad );
obj_id waypoint = getTokenWaypoint (token);
if (waypoint == null)
{
debugSpeakMsg (getSelf(), "No Waypoint Loc");
}
else
{
setWaypointVisible( waypoint, true);
setWaypointActive( waypoint, true);
setObjVar( player, questId + ".token." + name, waypoint);
setObjVar (player, "game_created", 1);
setName ( token, display );
}
return token;
}
*/
void clearQuestLocationTarget( obj_id player, string questId, string name )
{
if ( hasObjVar( player, questId + ".waypoint." + name ) )
{
obj_id waypoint = getObjIdObjVar( player, questId + ".waypoint." + name );
setWaypointVisible( waypoint, false);
setWaypointActive( waypoint, false);
destroyObject( waypoint );
removeLocationTarget (name);
removeObjVar( player, questId + ".waypoint." + name );
return;
}
}
void clearAllWaypoints( obj_id player, string questId )
{
if ( !hasObjVar( player, questId + ".waypoint" ))
return;
obj_var_list waypointList = getObjVarList( player, questId + ".waypoint" );
if(waypointList == null) // Redundant check since we already make sure the player has the obj var
return; // before we retrieve the list, but better safe than sorry...
int count = waypointList.getNumItems();
for ( int i=0; i < count; ++i )
{
obj_var waypointVar = waypointList.getObjVar( i );
obj_id waypoint = waypointVar.getObjIdData();
setWaypointVisible( waypoint, false);
setWaypointActive( waypoint, false);
destroyObject( waypoint );
}
removeObjVar( player, questId + ".waypoint" );
}
/* -----------------4/10/2002 4:52PM-----------------
* This function spawns _template_ at _loc_
* and makes it attack _target_
*
* e.g. "spawnAttacker( "../stormtrooper.iff", getLocation(target), target);
* will spawn a stormtroopers and make it attack Target.
*
* The function returns the obj_id of the npc spawned.
*
* The function attaches npcdeath to the npc spawned
* which causes the npc to emit a message to target
* when it dies
* messageHandler npcDestroyed
* --------------------------------------------------*/
obj_id spawnAttacker( string msgHandlerName, string template, location loc, obj_id target )
{
obj_id attacker = createObject( template, loc );
//ai.aiAttack( attacker, target );
setObjVar( attacker, "quests.target", target );
setObjVar( attacker, "quests.msgHandlerName", msgHandlerName );
attachScript( attacker, "theme_park.utils.npcdeath" );
return attacker;
}
obj_id spawnAttacker( string template, location loc, obj_id target )
{
obj_id attacker = createObject( template, loc );
//ai.aiAttack( attacker, target );
return attacker;
}
/* -----------------4/10/2002 5:06PM-----------------
* This function spawns multiple attackers within a couple meters
* of the location passed to it and returns their obj_id's in an
* array of obj_id's.
* --------------------------------------------------*/
obj_id[] spawnAttackers( string msgHandlerName, int number, string template, location loc, obj_id target )
{
obj_id[] attackers = new obj_id[ number ];
for ( int i = 0; i < number; i++ )
{
location newloc = new location( loc );
newloc.x = loc.x + rand( -2, +2 );
newloc.z = loc.z + rand( -2, +2 );
attackers[ i ] = spawnAttacker( msgHandlerName, template, newloc, target );
}
return attackers;
}
obj_id[] spawnAttackers( int number, string template, location loc, obj_id target )
{
obj_id[] attackers = new obj_id[ number ];
for ( int i = 0; i < number; i++ )
{
location newloc = new location( loc );
newloc.x = loc.x + rand( -2, +2 );
newloc.z = loc.z + rand( -2, +2 );
attackers[ i ] = spawnAttacker( template, newloc, target );
}
return attackers;
}
location chooseNearbyLocation( obj_id self )
{
location loc = new location( getLocation( self ) );
switch ( rand(1,4) )
{
case 1 :
loc.x = loc.x + 20;
break;
case 2 :
loc.x = loc.x - 20;
break;
case 3 :
loc.y = loc.y + 20;
break;
case 4 :
loc.y = loc.y -20;
break;
}
return loc;
}
location getTargetLocation (obj_id self)
{
obj_id containedBy = getTopMostContainer (self);
location target = new location();
int x = 0;
while (x < 10)
{
location here = getLocation (self);
region quest = locations.getCityRegion(here);
location questLoc = locations.getGoodLocationOutsideOfRegion(quest, 100f, 100f, 100f);
if (questLoc != null)
{
target = questLoc;
}
x = x + 1;
}
return target;
}
string getConvoType( obj_id self )
{
string convoType = "npc_mission/static_businessman_deliver";
string type = "businessman";
if(checkForSerendipity(self) == false)
{
if (!hasObjVar (self, "questType"))
{
int questType = rand (1,4);
switch (questType)
{
case 1:
type = "businessman";
break;
case 2:
type = "criminal";
break;
case 3:
type = "noble";
break;
case 4:
type = "scientist";
break;
}
convoType = "npc_mission/static_" + type + "_deliver";
}
else
{
type = getStringObjVar (self, "questType");
convoType = "npc_mission/static_" + type + "_deliver";
}
setObjVar (self, "questType", type);
return convoType;
}
else
{
type = getCreatureName(self);
convoType = "npc_mission/static_" + type + "_deliver";
setObjVar (self, "questType", type);
return convoType;
}
}
string getDataTableName( obj_id self )
{
string datatable = "datatables/npc/static_quest/businessman_deliveries.iff";
string type = "businessman";
if (checkForSerendipity(self) == false)
{
if (!hasObjVar (self, "questType"))
{
int questType = rand (1,4);
switch (questType)
{
case 1:
type = "businessman";
break;
case 2:
type = "criminal";
break;
case 3:
type = "noble";
break;
case 4:
type = "scientist";
break;
}
datatable = "datatables/npc/static_quest/" + type + "_deliveries.iff";
}
else
{
type = getStringObjVar (self, "questType");
datatable = "datatables/npc/static_quest/" + type + "_deliveries.iff";
}
setObjVar (self, "questType", type);
return datatable;
}
else
{
type = getCreatureName(self);
setObjVar (self, "questType", type);
datatable = "datatables/npc/static_quest/" + type + "_deliveries.iff";
return datatable;
}
}
string getType ( obj_id self )
{
string type = "businessman";
if (checkForSerendipity(self) == false)
{
if (!hasObjVar (self, "questType"))
{
int questType = rand (1,4);
switch (questType)
{
case 1:
type = "businessman";
break;
case 2:
type = "criminal";
break;
case 3:
type = "noble";
break;
case 4:
type = "scientist";
break;
}
}
else
{
type = getStringObjVar (self, "questType");
}
return type;
}
else
{
type = getCreatureName(self);
}
return type;
}
boolean checkForSerendipity (obj_id self)
{
const string npcType = getCreatureName(self);
if (npcType == "noble" || npcType == "scientist" || npcType == "criminal" || npcType == "businessman")
{
return true;
}
else
{
return false;
}
}
boolean checkForItem(obj_id inv)
{
string datatable = quests.getDataTableName(getSelf());
int questNum = getIntObjVar (getSelf(), "quest");
string giveMe = dataTableGetString (datatable, 0, questNum);
boolean hadIt = false;
obj_id[] contents = getContents(inv);
for ( int i = 0; i < contents.length; i++ )
{
string itemInInventory = getTemplateName (contents[i]);
if (itemInInventory == giveMe)
{
destroyObject (contents[i]);
hadIt = true;
}
}
return hadIt;
}
location getThemeParkLocation (obj_id self)
{
location target = null;
int x = 0;
while (x < 10)
{
location here = getLocation (self);
//LOG("quests", "here is "+here);
obj_id bldg = getTopMostContainer (self);
if (bldg == null)
{
return null;
}
location building = getLocation (bldg);
//LOG("quests", "building is "+building);
region[] rgnFoos = getRegionsWithGeographicalAtPoint(building, regions.GEO_CITY);
if(rgnFoos==null)
{
region[] rgnTest = getRegionsAtPoint(building);
if(rgnTest==null)
{
return null;
}
else
{
rgnFoos = rgnTest;
}
}
region quest = rgnFoos[0];
//LOG("quest", "rgnFoos[0] name is "+rgnFoos[0].getName());
if (quest == null)
{
quest = locations.getCityRegion (building);
if (quest == null)
{
return null;
}
}
location questLoc = locations.getGoodLocationOutsideOfRegion(quest, 64f, 64f, 100f, false, true);
//LOG("quest", "questLoc is "+questLoc);
if (questLoc != null)
{
target = questLoc;
//LOG("quest", "target is "+target);
}
//LOG("quest", "questLoc2 is "+questLoc);
x = x + 1;
}
//Crack monkey stuff that has to be done to get a proper Y-Height
if (target != null)
{
float xCoord = target.x;
float zCoord = target.z;
float newY = getHeightAtLocation (xCoord, zCoord);
target.y = newY;
}
return target;
}
void giveThemeParkReward (obj_id self, obj_id player, int questNum)
{
string datatable = getStringObjVar (self, "quest_table");
datatable = "datatables/theme_park/" + datatable + ".iff";
string questID = dataTableGetString (datatable, questNum, "temp_objvar");
string gatingString = dataTableGetString (datatable, questNum, "overall_objvar");
string playerScript = dataTableGetString (datatable, questNum, "player_script");
string CONVO = dataTableGetString (datatable, questNum, "convo");
string messageCONVO = "theme_park/messages";
int gating = getIntObjVar (player, gatingString);
if (group.isGrouped(player))
{
Vector party = group.getPCMembersInRange(player);
if ( party != null )
{
for ( int i = 0; i < party.size(); i++ )
{
int partyMemberGating = getIntObjVar ((obj_id)party.elementAt(i), gatingString);
if (partyMemberGating == 0)
{
partyMemberGating = 1;
}
if (gating == partyMemberGating)
{
gating = gating + 1;
setObjVar (player, gatingString, gating);
setObjVar ((obj_id)party.elementAt(i), gatingString, gating);
}
}
}
}
else
{
gating = gating + 1;
setObjVar (player, gatingString, gating);
}
string type = dataTableGetString (datatable, questNum, "quest_type");
if (type == "rescue" || type == "escort")
{
obj_id vip = getObjIdObjVar (player, questID + ".vip");
messageTo (vip, "stopFollowing", null, 0, true);
}
//adding to detect & award badge for completeing theme park
int badgeReward = dataTableGetInt (datatable, questNum, "badge_reward");
string badgeName = getCollectionSlotName(badgeReward);
if ((badgeReward != 0) && (badgeName != null) && (badgeName.length() > 0))
{
if(!badge.hasBadge(player, badgeName))
{
// you get the badge for completing a themepark
badge.grantBadge(player, badgeName);
//return;
}
}
obj_id playerInv = utils.getInventoryContainer(player);
string reward = dataTableGetString (datatable, questNum, "reward");
string reward2 = dataTableGetString (datatable, questNum, "reward2");
string reward3 = dataTableGetString (datatable, questNum, "reward3");
string reward4 = dataTableGetString (datatable, questNum, "reward4");
if (reward != null && reward != "" && reward != "none")
{
obj_id rewardObject = createObject (reward, playerInv, "");
string_id gift = new string_id (messageCONVO, "theme_park_reward");
sendSystemMessage (player, gift);
string objvar = dataTableGetString (datatable, questNum, "reward_objvar");
int value = dataTableGetInt (datatable, questNum, "reward_objvar_value");
if (objvar != null)
{
setObjVar (rewardObject, objvar, value);
}
}
if (reward2 != null && reward2 != "" && reward2 != "none")
{
obj_id rewardObject2 = createObject (reward2, playerInv, "");
string_id gift2 = new string_id (messageCONVO, "theme_park_reward");
sendSystemMessage (player, gift2);
string objvar2 = dataTableGetString (datatable, questNum, "reward2_objvar");
int value2 = dataTableGetInt (datatable, questNum, "reward2_objvar_value");
if (objvar2 != null)
{
setObjVar (rewardObject2, objvar2, value2);
}
}
if (reward3 != null && reward3 != "" && reward2 != "none")
{
obj_id rewardObject3 = createObject (reward3, playerInv, "");
string_id gift3 = new string_id (messageCONVO, "theme_park_reward");
sendSystemMessage (player, gift3);
string objvar3 = dataTableGetString (datatable, questNum, "reward3_objvar");
int value3 = dataTableGetInt (datatable, questNum, "reward3_objvar_value");
if (objvar3 != null)
{
setObjVar (rewardObject3, objvar3, value3);
}
}
if (reward4 != null && reward4 != "" && reward2 != "none")
{
obj_id rewardObject4 = createObject (reward4, playerInv, "");
string_id gift4 = new string_id (messageCONVO, "theme_park_reward");
sendSystemMessage (player, gift4);
string objvar4 = dataTableGetString (datatable, questNum, "reward4_objvar");
int value4 = dataTableGetInt (datatable, questNum, "reward4_objvar_value");
if (objvar4 != null)
{
setObjVar (rewardObject4, objvar4, value4);
}
}
int credits = dataTableGetInt (datatable, questNum, "credits");
if (credits != 0)
{
string_id fake = new string_id();
dictionary params = new dictionary();
group.systemPayoutToGroup("reasonID", player, credits, fake, "returnHandler", params);
//money.bankTo(money.ACCT_JABBA, player, credits);
string_id credsMessage = new string_id (messageCONVO, "theme_park_credits");
sendSystemMessage (player, credsMessage);
}
string factionReward = dataTableGetString (datatable, questNum, "faction reward");
string factionReward2 = dataTableGetString (datatable, questNum, "faction_reward2");
string factionReward3 = dataTableGetString (datatable, questNum, "faction_reward3");
string factionReward4 = dataTableGetString (datatable, questNum, "faction_reward4");
if (factionReward != "none")
{
int factionAmt = dataTableGetInt (datatable, questNum, "faction_reward_amount");
if (factionAmt != 0)
{
factions.addFactionStanding(player,factionReward,factionAmt);
}
}
if (factionReward2 != "none")
{
int factionAmt2 = dataTableGetInt (datatable, questNum, "faction_reward2_amount");
if (factionAmt2 != 0)
{
factions.addFactionStanding(player,factionReward2,factionAmt2);
}
}
if (factionReward3 != "none")
{
int factionAmt3 = dataTableGetInt (datatable, questNum, "faction_reward3_amount");
if (factionAmt3 != 0)
{
factions.addFactionStanding(player,factionReward3,factionAmt3);
}
}
if (factionReward4 != "none")
{
int factionAmt4 = dataTableGetInt (datatable, questNum, "faction_reward4_amount");
if (factionAmt4 != 0)
{
factions.addFactionStanding(player,factionReward4,factionAmt4);
}
}
obj_id waypoint = getObjIdObjVar (player, questID + ".waypointhome");
if (waypoint != null)
{
destroyWaypointInDatapad(waypoint, player);
}
removeObjVar (player, questID);
removeObjVar (player, "quest_table");
removeObjVar (player, "questNum");
if (hasScript (player, playerScript))
{
detachScript (player, playerScript);
}
return;
}
// ---------------------------------------------------------------------
// Used by Force Sensitive Quests and beyond
// ---------------------------------------------------------------------
int getQuestId(String questName)
{
return dataTableSearchColumnForString(questName, 0, "datatables/player/quests.iff");
}
// ---------------------------------------------------------------------
String getParentQuestName(String questName)
{
int questRow = getQuestId(questName);
if(questRow > -1)
{
return dataTableGetString("datatables/player/quests.iff", questRow, "PARENT");
}
return null;
}
// ---------------------------------------------------------------------
boolean isComplete(String questName, obj_id player)
{
return isQuestComplete(player, getQuestId(questName));
}
// ---------------------------------------------------------------------
boolean canActivate(String questName, obj_id player)
{
// a quest can be activated if:
// it has no parent
// OR
// it has a parent, but the parent quest has been completed
// AND
// the target quest is not active
// AND
// the target quest has not been completed
boolean result = false;
// bail out if the quest is already active
if(! isActive(questName, player))
{
// bail out if the parent hasn't been completed
String parentQuestName = getParentQuestName(questName);
if(parentQuestName != null && parentQuestName.length() > 0)
{
if(isComplete(parentQuestName, player))
{
if(! isComplete(questName, player))
{
LOG("newquests", (questName + " is available because the parent quest has been completed and " + questName + " has not been completed"));
result = true;
}
else
{
LOG("newquests", (questName + " has already been completed"));
}
}
else
{
LOG("newquests", (questName + " has a parent, " + parentQuestName + " but the parent quest is not complete"));
}
}
else
{
if(! isActive(questName, player))
{
if(! isComplete(questName, player))
{
// quest has no parent, the quest can be activated
result = true;
}
}
}
}
else
{
LOG("newquests", (questName + " is active"));
}
LOG("newquests", ("canActivate(" + questName + ", " + player + ") returned " + result));
return result;
}
// ---------------------------------------------------------------------
boolean isActive(String questName, obj_id player)
{
boolean result = false;
int questRow = getQuestId(questName);
if(questRow > -1)
{
result = isQuestActive(player, questRow);
}
return result;
}
// ---------------------------------------------------------------------
void activate(String questName, obj_id player, obj_id questGiver)
{
if(questName == null)
return;
if(questName.length() < 1)
return;
LOG("newquests", "attempting to activate quest " + questName + " for player " + player + " npc " + questGiver);
// open the quests datatable, retrieve quest information and setup the variables
// associated with the quest
string datatable = "datatables/player/quests.iff";
int questRow = getQuestId(questName);
if(questRow > -1)
{
LOG("newquests", "found " + questName + " id=" + questRow);
if(canActivate(questName, player))
{
String scriptName = dataTableGetString(datatable, questRow, "ATTACH_SCRIPT");
// todo: deatch script doesn't detach the script? Always attempt to attach the script
if(scriptName != null && scriptName.length() > 0)
{
LOG("newquests", "attaching script " + scriptName + " to player " + player + " for quest " + questName);
attachScript(player, scriptName);
}
LOG("newquests", "activating quest " + questName + " for player " + player);
if(questGiver != null)
{
String objvarname = "questlib." + questName + ".quest_giver";
LOG("newquests", "quests: activate setObjVar(" + player + ", " + objvarname + ", " + questGiver + ")");
setObjVar(player, objvarname, questGiver);
questGiver = getObjIdObjVar(player, objvarname);
LOG("newquests", "quests: activate, checking getObjIdObVar for quest giver. questGiver = " + questGiver);
}
activateQuest(player, questRow);
int row = dataTableSearchColumnForString(questName, "NAME", "datatables/player/quests.iff");
int isVisible = dataTableGetInt ("datatables/player/quests.iff", row, "SHOW_SYSTEM_MESSAGES");
if(isVisible != 0)
{
string_id sid = new string_id ("quest/quests", "quest_journal_updated");
sendSystemMessage(player, sid);
}
}
else
{
LOG("newquests", "quest " + questName + " for player " + player + " could not be activated");
}
}
else
{
LOG("newquests", "could not activate quest " + questName + " for player " + player + " because the quest could not be found in " + datatable);
}
}
// ---------------------------------------------------------------------
void complete(String questName, obj_id player, boolean succeeded)
{
LOG("newquest", "quests: complete(" + questName + ", " + player + ", " + succeeded + ")");
// send localized system message to player when a task is completed
// if it is marked "visible" in the quests data table
int row = dataTableSearchColumnForString(questName, "NAME", "datatables/player/quests.iff");
int isVisible = dataTableGetInt ("datatables/player/quests.iff", row, "SHOW_SYSTEM_MESSAGES");
//LOG("newquest", "isVisible ->" + isVisible);
if(isVisible != 0)
{
String entry = getDataEntry(questName, "JOURNAL_ENTRY_SUMMARY");
if(entry != null && entry.length() > 0)
{
String[] entries = split(entry, ':');
if(entries.length > 1)
{
string_id qid = utils.unpackString(entry);
//string_id qid = new string_id(entries[0], entries[1]);
sendSystemMessage(player, qid);
}
}
if(succeeded)
{
string_id sid = new string_id ("quest/quests", "task_complete");
sendSystemMessage (player, sid);
}
else
{
string_id sid = new string_id ("quest/quests", "task_failure");
sendSystemMessage (player, sid);
}
}
obj_id questGiver = null;
String objvarname = "questlib." + questName + ".quest_giver";
if(hasObjVar(player, objvarname))
{
questGiver = getObjIdObjVar(player, objvarname);
LOG("newquests", "quests: hasObjVar(" + player + ", " + objvarname + ") = true. setting questGiver=" + questGiver);
}
else
{
LOG("newquests", "quests: hasObjVar(" + player + ", " + objvarname + ") = false");
}
deactivate(questName, player);
completeQuest(player, getQuestId(questName));
Object[] params = new Object[3];
params[0] = player;
params[1] = questName;
params[2] = new Boolean(succeeded);
script_entry.runScripts("OnForceSensitiveQuestCompleted", params);
if(hasObjVar(player, "questlib." + questName))
{
removeObjVar(player, "questlib." + questName);
}
// activate the next task
String[] nextTasks = null;
if(succeeded)
{
String taskList = getDataEntry(questName, "TASK_ON_COMPLETE");
nextTasks = split(taskList, ';');
}
else
{
String taskList = getDataEntry(questName, "TASK_ON_FAIL");
nextTasks = split(taskList, ';');
}
if(nextTasks != null && nextTasks.length > 0)
{
int iter = 0;
for(iter = 0; iter < nextTasks.length; ++iter)
{
activate(nextTasks[iter], player, questGiver);
}
}
if(hasObjVar(player, "quest." + questName))
{
removeObjVar(player, "quest." + questName);
}
}
// ---------------------------------------------------------------------
void deactivate(String questName, obj_id player)
{
// open the quests datatable, retrieve quest information and setup the variables
// associated with the quest
string datatable = "datatables/player/quests.iff";
int questRow = getQuestId(questName);
if(questRow > -1)
{
String scriptName = dataTableGetString(datatable, questRow, "ATTACH_SCRIPT");
if(hasScript(player, scriptName))
{
int i = 0;
int columnCount = dataTableGetNumRows(datatable);
for(i = 0; i < columnCount; ++i)
{
if(i != questRow)
{
String s = dataTableGetString(datatable, i, "ATTACH_SCRIPT");
if(s != null && s == scriptName && isQuestActive(player, i))
{
// don't detach!
LOG("newquests", "not detaching script " + scriptName + " beacuse quest " + i + " is currently active and uses " + scriptName);
return;
}
}
}
LOG("newquests", "deatching script " + scriptName + " from player " + player);
detachScript(player, scriptName);
}
deactivateQuest(player, questRow);
}
}
// ---------------------------------------------------------------------
String[] getActiveQuestsWithScript(String scriptName, obj_id player)
{
resizeable String[] result = new Vector();
string datatable = "datatables/player/quests.iff";
int it = 0;
int columnCount = dataTableGetNumRows(datatable);
for(it = 0; it < columnCount; ++it)
{
String s = dataTableGetString(datatable, it, "ATTACH_SCRIPT");
if(s != null)
{
if(s == scriptName)
{
String taskName = dataTableGetString(datatable, it, "NAME");
if(isActive(taskName, player))
{
result.add(taskName);
}
}
}
}
return result;
}
// ---------------------------------------------------------------------
String getDataEntry(String questName, String columnName)
{
String result = null;
string datatable = "datatables/player/quests.iff";
int questRow = getQuestId(questName);
if(questRow > -1)
{
result = dataTableGetString(datatable, questRow, columnName);
}
return result;
}
// ---------------------------------------------------------------------
String getDataEntry(int questId, String columnName)
{
String result = null;
if(questId > -1)
{
result = dataTableGetString("datatables/player/quests.iff", questId, columnName);
}
return result;
}
// ---------------------------------------------------------------------
location getTheaterLocationTarget(obj_id self, int questRow) {
location result = null;
string questName = quests.getDataEntry(questRow, "NAME");
if(questName == null || questName.equals("") || !isActive(questName, self))
return null;
string target = "";
float radius = 64.0f;
float parameter = 1024.0f;
location waitForPlanetWarp = null;
// boolean waitForPlanetWarp = false;
boolean haveParameter = false;
if(hasObjVar(self, "quest." + questName + ".parameter"))
radius = getFloatObjVar(self, "quest." + questName + ".parameter");
if(hasObjVar(self, "quest." + questName + ".target")) {
target = getStringObjVar(self, "quest." + questName + ".target");
} else {
string parameterString = quests.getDataEntry(questRow, "PARAMETER");
if(parameterString != null && !parameterString.equals("")) {
LOG("newquests", "GET THEATER LOCATION TARGET: parsing parameter string: " + parameterString);
string[] params = split(parameterString, ':');
for(int i = 0; i < params.length; i++) {
if(Character.isDigit(params[i].charAt(0))) {
parameter = utils.stringToFloat(params[i]);
haveParameter = true;
LOG("newquests", "GET THEATER LOCATION TARGET: search radius parameter found: " + parameter);
}
}
}
target = quests.getDataEntry(questRow, "TARGET");
}
if (hasObjVar(self, "theaterRecoveryTarget"))
{
result = getLocationObjVar(self, "theaterRecoveryTarget");
if(result != null)
{
addLocationTarget(questName, result, radius);
return result;
}
}
if(target == null || target.equals(""))
return null;
boolean havePlanet = false;
string[] tokens = split(target, ':');
string planet = null;
if(tokens.length > 1)
havePlanet = true;
if(havePlanet) {
if(tokens[0].indexOf(".iff") < 0)
planet = tokens[0];
else
planet = tokens[1];
}
if(haveParameter && (parameter < 0))
{
parameter = -parameter;
parameter = rand(parameter - 200.0f, parameter + 200.0f);
}
if(!havePlanet && !haveParameter) {
int attempts = 0;
while(result == null && attempts < 15) {
++attempts;
result = locations.getRandomGoodLocation(getLocation(self), 800.0f, 1500.0f, 32.0f);
if(result != null)
LOG("newquests", "GET THEATER LOCATION TARGET: no planet/no parameter - good location attempt: " + result.toString());
else
LOG("newquests", "GET THEATER LOCATION TARGET: no planet/no parameter - good location attempt: null");
}
} else if(!havePlanet && haveParameter) {
int attempts = 0;
while(result == null && attempts < 15) {
++attempts;
result = locations.getRandomGoodLocation(getLocation(self), parameter - 200.0f, parameter + 600.0f, 32.0f);
if(result != null)
LOG("newquests", "GET THEATER LOCATION TARGET: no planet/parameter - good location attempt: " + result.toString());
else
LOG("newquests", "GET THEATER LOCATION TARGET: no planet/parameter - good location attempt: null");
}
} else if(havePlanet && haveParameter) {
string currentScene = getCurrentSceneName();
if(currentScene != null && currentScene == planet) {
int attempts = 0;
while(result == null && attempts < 15) {
++attempts;
result = locations.getRandomGoodLocation(getLocation(self), parameter - 200.0f, parameter + 600.0f, 32.0f);
if(result != null)
LOG("newquests", "GET THEATER LOCATION TARGET: planet/parameter - good location attempt: " + result.toString());
else
LOG("newquests", "GET THEATER LOCATION TARGET: planet/parameter - good location attempt: null");
}
} else {
LOG("newquests", "GET THEATER LOCATION TARGET: planet/parameter - good location fall through: waiting for planet warp");
waitForPlanetWarp = new location(0.0f, 0.0f, 0.0f, planet);
// waitForPlanetWarp = true;
}
} else if(havePlanet && !haveParameter) {
string currentScene = getCurrentSceneName();
if(currentScene != null && currentScene == planet) {
int attempts = 0;
while(result == null && attempts < 15) {
++attempts;
result = locations.getRandomGoodLocation(getLocation(self), 800.0f, 1500.0f, 32.0f);
if(result != null)
LOG("newquests", "GET THEATER LOCATION TARGET: planet/no parameter - good location attempt: " + result.toString());
else
LOG("newquests", "GET THEATER LOCATION TARGET: planet/no parameter - good location attempt: null");
}
} else {
LOG("newquests", "GET THEATER LOCATION TARGET: planet/parameter - good location fall through: waiting for planet warp");
waitForPlanetWarp = new location(0.0f, 0.0f, 0.0f, planet);
// waitForPlanetWarp = true;
}
}
if(result != null) {
region r = battlefield.getBattlefield(result);
if(r != null) {
if(isGod(self))
sendSystemMessageTestingOnly(self, "GOD MODE - WARNING: The good location chosen for the theater lies within a battlefield");
LOG("newquests", "the good location chosen for the theater lies within a battlefield: " + result.toString());
}
LOG("newquests", "GET THEATER LOCATION TARGET: good location found: " + result.toString());
setObjVar(self, "quest." + questName + ".selected_location", result);
if (!hasObjVar(self, "theaterRecoveryTarget"))
{
if ( (questName == "fs_theater_final") || (questName == "fs_theater_camp") )
{
setObjVar(self, "theaterRecoveryTarget", result);
}
}
addLocationTarget(questName, result, radius);
} else if(waitForPlanetWarp != null) {
// } else if(waitForPlanetWarp) {
setObjVar(self, "quest." + questName + ".generate", waitForPlanetWarp);
}
return result;
}
// ---------------------------------------------------------------------
location getLocationTarget(obj_id self, int questRow)
{
location result = null;
// get the quest name from the row
String questName = quests.getDataEntry(questRow, "NAME");
if(questName != null && questName.length() > 0 && isActive(questName, self))
{
LOG("newquests", "initializing location task " + questName);
float radius = 64.0f;
boolean waitForPlanetWarp = false;
if(hasObjVar(self, "quest." + questName + ".parameter"))
{
radius = getFloatObjVar(self, "quest." + questName + ".parameter");
LOG("newquests", "the target location radius is overridden by an object variable. radius = " + radius);
}
else
{
LOG("newquests", "default target radius of 64 meters will be used");
}
// set up location target
if(hasObjVar(self, "quest." + questName + ".target"))
{
result = getLocationObjVar(self, "quest." + questName + ".target");
if(result != null)
{
// the location target is overidden by an object variable
//addLocationTarget("questName", result, radius);
LOG("newquests", "location target for " + questName + " is overridden by an object variable. new location is " + result);
}
else
{
LOG("newquests", "location target for " + questName + " was supposed to be overridden, but the location could not be retrieved from the location object variable quest." + questName + ".target");
}
}
else
{
String planetName = null;
obj_id cell = null;
boolean haveCell = false;
float x = 0.0f;
boolean haveX = false;
float z = 0.0f;
boolean haveZ = false;
float parameter = 1024.0f;
boolean haveParameter = false;
boolean haveTarget = false;
String parameterString = quests.getDataEntry(questRow, "PARAMETER");
if(parameterString != null && parameterString.length() > 0)
{
LOG("newquests", "location parsing PARAMETER=" + parameterString);
parameter = utils.stringToFloat(parameterString);
haveParameter = true;
}
LOG("newquests", "location PARAMETER set to " + parameter);
// use the location specified in the data table
String locationString = quests.getDataEntry(questRow, "TARGET");
if(locationString != null && locationString.length() > 0)
{
haveTarget = true;
LOG("newquests", "location parsing TARGET \"" + locationString + "\"");
// target location is specified in the data table,
// parse it
string[] tokens = split(locationString, ':');
if(tokens.length > 0)
{
LOG("newquests", "location parsing " + tokens.length + " tokens");
String s = tokens[0];
if(!Character.isDigit(s.charAt(0)))
{
planetName = tokens[0];
LOG("newquests", "location parsed " + tokens[0] + " as the target planet");
if(tokens.length > 2)
{
LOG("newquests", "location parsing " + tokens[1] + " as x coordinate");
x = utils.stringToFloat(tokens[1]);
haveX = true;
LOG("newquests", "location parsing " + tokens[2] + " as z coordinate");
z = utils.stringToFloat(tokens[2]);
haveZ = true;
if(tokens.length > 3)
{
LOG("newquests", "location parsing " + tokens[3] + " as a cell ID");
cell = utils.stringToObjId(tokens[3]);
haveCell = true;
}
}
}
else
{
LOG("newquests", "location first token is a number");
if(tokens.length > 1)
{
x = utils.stringToFloat(tokens[0]);
z = utils.stringToFloat(tokens[1]);
}
}
}
}
// create the location target
if(! haveTarget && !haveParameter)
{
// generate a random location on the current planet
// 1024 meters away
int attempts = 0;
while(result == null && attempts < 15)
{
++attempts;
result = locations.getRandomGoodLocation(getLocation(self), 800.0f, 1200.0f, 32.0f);
LOG("newquests", "location generating a random location about 1 kilometer away " + result);
}
}
else if(! haveTarget && haveParameter)
{
// generate a random location on the planet about
// 'parameter' meters away
result = locations.getRandomGoodLocation(getLocation(self), parameter - 100.0f, parameter + 100.0f, 32.0f);
LOG("newquests", "location generating a random location between " + (parameter - 100.0f) + " and " + (parameter + 100.0f) + " meters away");
}
else if(planetName != null && !haveX && !haveZ && !haveCell && haveParameter)
{
// generate a random location on the target planet about
// 'parameter' meters away from wherever the player arrives on
// the planet (if it's not the current planet), or if planetName
// specifies THIS planet, generate a location about 'parameter'
// meters away
String currentScene = getCurrentSceneName();
if(currentScene != null && currentScene == planetName)
{
result = locations.getRandomGoodLocation(getLocation(self), parameter - 100.0f, parameter + 100.0f, 32.0f);
LOG("newquests", "location generating a random location on " + planetName + " between " + (parameter - 100.0f) + " and " + (parameter + 100.0f) + " meters away");
}
else
{
// need to select a location on login
waitForPlanetWarp = true;
LOG("newquests", "location generating a random location on " + planetName + " between " + (parameter - 100.0f) + " and " + (parameter + 100.0f) + " meters away");
}
}
else if(planetName != null && !haveX && !haveZ && !haveCell && !haveParameter)
{
// generate a random location on the target planet
// about 'parameter' meters away from wherever the player
// arrives on the planet, or if planetName specifies
// THIS planet, generate a location about 1024 meters awawy
string currentScene = getCurrentSceneName();
if(currentScene != null && currentScene == planetName)
{
result = locations.getRandomGoodLocation(getLocation(self), parameter - 800.0f, 1200.0f, 32.0f);
LOG("newquests", "location generating a random location on " + planetName + " between 800 and 1200 meters away");
}
else
{
// need to select a location on login
waitForPlanetWarp = true;
LOG("newquests", "location a location will be generated when the player travels to " + planetName);
}
}
else if(planetName != null && haveX && haveZ && !haveCell && !haveParameter)
{
// generate a location at the requested coordinates
result = new location();
result.x = x;
result.z = z;
result.area = planetName;
LOG("newquests", "location generating a location at " + result);
}
else if(planetName != null && haveX && haveZ && !haveCell && haveParameter)
{
// generate a location with a sensitivity radius of 'parameter' meters
result = new location();
result.x = x;
result.z = z;
result.area = planetName;
radius = parameter;
LOG("newquests", "location generating a location at " + result);
}
else if(planetName != null && haveX && haveZ && haveCell && !haveParameter)
{
// generate a location in the cell at the coordinates with a sensitivity
// of 8 meters
result = new location();
result.x = x;
result.z = z;
result.area = planetName;
result.cell = cell;
LOG("newquests", "location generating a location at " + result);
}
else if(planetName != null && haveX && haveZ && haveCell && haveParameter)
{
result = new location();
result.x = x;
result.z = z;
result.area = planetName;
result.cell = cell;
radius = parameter;
LOG("newquests", "location generating a location at " + result);
}
}
if(result != null)
{
setObjVar(self, "quest." + questName + ".selected_location", result);
addLocationTarget(questName, result, radius);
LOG("newquests", "location adding location target at " + result);
}
else if(waitForPlanetWarp == true)
{
setObjVar(self, "quest." + questName + ".generate", waitForPlanetWarp);
}
}
return result;
}
// ---------------------------------------------------------------------
boolean isMyQuest(int questRow, String scriptName)
{
boolean result = false;
String s = getDataEntry(questRow, "ATTACH_SCRIPT");
if((s != null) && (scriptName != null) && (s == scriptName))
{
result = true;
}
return result;
}
// ---------------------------------------------------------------------
obj_id getTargetForQuest(obj_id self, String questName)
{
deltadictionary scriptVars = self.getScriptVars();
String objvarname = "encounter.target." + questName;
obj_id result = scriptVars.getObjId(objvarname);
LOG("newquests", "quest target " + objvarname + "=" + result + " self=" + self);
return result;
}
// ---------------------------------------------------------------------
int getQuestIdForTarget(obj_id self, obj_id target)
{
// determine if the target object is used for one of the player's
// active tasks. Return the quest row in the quests.tab data table
int result = -1;
String objvarname = "questname";
if(isIdValid(target))
{
if(hasObjVar(target, objvarname))
{
// this is the name of the task which may have spawned the target, which
// is cross-referenced by the TARGET quests table parameter or an override
// objvar quest.<quest name>.target on the player
String encounterQuestName = getStringObjVar(target, objvarname);
if(encounterQuestName != null && encounterQuestName.length() > 0)
{
// the target object has a questname variable, it might be
// a target for the player's task
int numRows = dataTableGetNumRows("datatables/player/quests.iff");
int iter = 0;
for(iter = 0; iter < numRows; ++iter)
{
if(isQuestActive(self, iter))
{
LOG("newquests", "destroy - checking active quest " + iter);
if(quests.isMyQuest(iter, "quest.task.destroy"))
{
LOG("newquest", "destroy - active quest " + iter + " is a destroy task");
String questName = quests.getDataEntry(iter, "NAME");
String targetName = null;
objvarname = "quest." + questName + ".target";
if(hasObjVar(self, objvarname))
{
targetName = getStringObjVar(self, objvarname);
LOG("newquests", "destroy - target is overriden by objvar " + objvarname + " target=" + targetName);
}
else
{
targetName = quests.getDataEntry(iter, "TARGET");
LOG("newquests", "destroy - using data table target name " + targetName);
}
if(targetName != null && targetName.length() > 0)
{
if(targetName == encounterQuestName)
{
// this object might be for our task
objvarname = targetName + ".holder";
LOG("newquests", "destroy - target is a quest target, maybe for this player, checking to see if the target has a holder objvar (" + objvarname +")");
if(hasObjVar(target, objvarname))
{
obj_id holder = getObjIdObjVar(target, objvarname);
LOG("newquests", "destroy - target has the " + objvarname + " objvar. It is set to " + holder);
if(holder == self)
{
LOG("newquests", "destroy - target is ours");
// bingo! We're the target's quest source
result = iter;
break;
}
}
else
{
LOG("newquests", "destroy - target does not have the " + objvarname + " objvar");
}
}
}
}
}
}
}
else
{
LOG("newquests", "destroy - encounterName could not be determined");
}
}
else
{
LOG("newquests", "the " + objvarname + " objvar was not present");
}
}
else
{
LOG("newquests", "destroy - target id " + target + " is not valid");
}
return result;
}
// ---------------------------------------------------------------------
boolean doEncounterSpawn(obj_id self, int questRow)
{
// this is an encounter quest/task activation
// track whether the encounter spawn succeeds
boolean success = false;
LOG("newquests", "encounter activating");
// get the name of the qust from the quests data table
String questName = quests.getDataEntry(questRow, "NAME");
// object variable name for overriding the data table
// defaults for spawning a creature from creatures.tab
String objvarname = "quest." + questName + ".target";
// set creatureName to the override or to the data table entry
// in quests.tab
String creatureName = null;
if(hasObjVar(self, objvarname))
{
// an objvar is overriding the data table entry
creatureName = getStringObjVar(self, objvarname);
LOG("newquests", "encounter - target is overridden by " + objvarname + " (" + creatureName + ")");
}
else
{
// get the creature name from the data table (used to spawn
// from creatures.tab)
creatureName = quests.getDataEntry(questRow, "TARGET");
LOG("newquests", "encounter - target is " + creatureName);
}
// select a nearby location ahead of the player to spawn the target
LOG("newquests", "encounter - getting a spawn location");
float yaw = getYaw(self);
location spawnLocation = utils.getLocationInArc(self, yaw-30, yaw+30, 48.0f);
location l = locations.getGoodLocationAroundLocation(spawnLocation, 8, 8, 64, 64, false, true);
if(l != null)
{
// location was successfully retrieved
LOG("newquests", "encounter - found a location " + l);
if(creatureName != null && creatureName.length() > 0)
{
// the creature name is valid, either from the quests data table
// or overridden in the quest.<task name>.target object variable
// on the player
LOG("newquests", "encounter - attempting to spawn " + creatureName);
obj_id target = create.createCreature(creatureName, l, true);
if(target != null)
{
// the creature spawned successfully, set some object
// variables that might be used by other tasks tracking
// this encounter (destroy, for example)
LOG("newquests", "encounter - " + creatureName + " spawned");
objvarname = "questname";
setObjVar(target, objvarname, questName);
objvarname = questName + ".holder";
setObjVar(target, objvarname, self);
deltadictionary scriptVars = self.getScriptVars();
objvarname = "encounter.target." + questName;
scriptVars.put(objvarname, target);
LOG("newquests", "encounter - adding " + target + " to " + objvarname + " script variable");
// when calling quests.complete(), advise the quest
// library that the encounter spawned successfully
success = true;
}
}
}
else
{
LOG("newquests", "encounter - failed to get a spawn location");
}
return success;
}
// ---------------------------------------------------------------------
obj_id createSpawner(string spawner, location loc, string datatable)
{
return createSpawner(spawner, loc, datatable, null);
}
// ---------------------------------------------------------------------
obj_id createSpawner(string spawner, location loc, string datatable, obj_id parent)
{
if (spawner == null || spawner.length() < 1)
{
LOG("quest", "quests.createSpawner -- spawner is null or empty");
return null;
}
if (loc == null)
{
LOG("quest", "quests.createSpawner -- loc is null");
return null;
}
if (datatable == null || datatable.length() < 1)
{
LOG("quest", "quests.createSpawner -- datatable is null or empty");
return null;
}
int index = dataTableSearchColumnForString(spawner, "type", datatable);
if (index == -1)
{
LOG("quest", "quests.createSpawner -- can't find spawner " + spawner + " within datatable " + datatable);
return null;
}
dictionary row = dataTableGetRow(datatable, index);
if (row == null)
{
LOG("quest", "quests.createSpawner -- can't find data in row " + index + " for datatable " + datatable);
return null;
}
int pulse = row.getInt("pulse");
int max_spawn = row.getInt("max_spawn");
int max_population = row.getInt("max_population");
int expire = row.getInt("expire");
obj_id spawner_object = createObject("object/tangible/spawning/quest_spawner.iff", loc);
if (!isIdValid(spawner_object))
{
LOG("quest", "quests.createSpawner -- can't create spawner object.");
return null;
}
setObjVar(spawner_object, "quest_spawner.type", spawner);
setObjVar(spawner_object, "quest_spawner.pulse", pulse);
setObjVar(spawner_object, "quest_spawner.max_spawn", max_spawn);
setObjVar(spawner_object, "quest_spawner.max_pop", max_population);
if (expire > 1)
setObjVar(spawner_object, "quest_spawner.time_expired" , expire + getGameTime());
else
setObjVar(spawner_object, "quest_spawner.time_expired", 0);
setObjVar(spawner_object, "quest_spawner.datatable", datatable);
if(parent != null)
setObjVar(spawner_object, "quest_spawner.parent", parent);
return spawner_object;
}
obj_id getQuestGiver(String questName, obj_id player)
{
obj_id result = null;
String objvarname = "questlib." + questName + ".quest_giver";
if(hasObjVar(player, objvarname))
{
result = getObjIdObjVar(player, objvarname);
}
return result;
}
obj_id getQuestGiver(int questRow, obj_id player)
{
return getQuestGiver(getDataEntry(questRow, "NAME"), player);
}
/**
* Checks for an objvar without matching list objvars "below" it.
* e.g. match quest.wait_for_tasks without matching quest.wait_for_tasks.*
* This is a workaround for objvar collision between
* quest.task.wait_for_tasks and quest.task.ground.wait_for_tasks
*/
boolean safeHasObjVar(obj_id self, String objvarName)
{
obj_var ov = getObjVar(self, objvarName);
// An obj_var is not an obj_var_list if its internal name == the full name you are looking for.
if (ov != null && (ov.getName().equals(objvarName)))
{
return true;
}
return false;
}