Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
901 lines
38 KiB
Plaintext
901 lines
38 KiB
Plaintext
//::///////////////////////////////////////////////
|
||
//:: Teleport include
|
||
//:: prc_inc_teleport
|
||
//::///////////////////////////////////////////////
|
||
/** @file
|
||
This include contains operations to maintain
|
||
an array of metalocations used as teleport target
|
||
locations on a PC. In addition, there is a function
|
||
for starting a conversation for the PC to select a
|
||
location from their array.
|
||
|
||
All the operations work only on PCs, as there is no
|
||
AI that could have NPCs take any advantage of the
|
||
system.
|
||
*/
|
||
//:://////////////////////////////////////////////
|
||
//:: Created By: Ornedan
|
||
//:: Created On: 29.05.2005
|
||
//:://////////////////////////////////////////////
|
||
|
||
#include "prc_inc_combat"
|
||
#include "inc_dynconv"
|
||
|
||
///////////////////////
|
||
/* Public Constants */
|
||
///////////////////////
|
||
|
||
/**
|
||
* The name of the array where GetTeleportingObjects() stores the creatures it has
|
||
* determined should teleport with the current spell.
|
||
*/
|
||
const string PRC_TELEPORTING_OBJECTS_ARRAY = "PRC_TeleportingObjectList";
|
||
|
||
/**
|
||
* The number of the teleport quickselection slots. Also the index number of the highest slot,
|
||
* as they are numbered starting from 1.
|
||
*/
|
||
const int PRC_NUM_TELEPORT_QUICKSELECTS = 2;
|
||
|
||
/**
|
||
* A constant for the value of slot parameter used when accessing the active quickselection.
|
||
*/
|
||
const int PRC_TELEPORT_ACTIVE_QUICKSELECTION = -1;
|
||
|
||
|
||
//////////////////////////////////////////////////
|
||
/* Function prototypes */
|
||
//////////////////////////////////////////////////
|
||
|
||
/**
|
||
* Starts the conversation for selecting the target location for a teleport.
|
||
* Once the PC has made his/her/it's selection, the result is stored on the
|
||
* PC and the callbackscript is run.
|
||
*
|
||
* @param oPC The PC that will make the selection.
|
||
* @param sCallbackScript The name of the script to run once the PC has made
|
||
* their decision.
|
||
* @param sCallbackVar The name of the local variable where the PC's choice
|
||
* will be stored.
|
||
* @param bMeta If this is TRUE, the result will be stored as a
|
||
* metalocation. Otherwise it will be stored as a location.
|
||
* @param bForce If this is TRUE, an attempt will be made to make sure
|
||
* the PC will make the choice. ClearAllActions will be
|
||
* called to prevent other activity from interfering with
|
||
* the conversation strating and the PC will not be allowed
|
||
* to abort the conversation.
|
||
*/
|
||
void ChooseTeleportTargetLocation(object oPC, string sCallbackScript, string sCallbackVar,
|
||
int bMeta = FALSE, int bForce = FALSE);
|
||
|
||
/**
|
||
* Returns the first teleport target location in the array and initialises
|
||
* the iteration counter for calls to GetNextStoredTeleportTargetLocation().
|
||
*
|
||
* @param oPC The PC on whose array to operate.
|
||
* @return The first element of the array or the location of oPC if the
|
||
* array is empty.
|
||
*/
|
||
struct metalocation GetFirstStoredTeleportTargetLocation(object oPC);
|
||
|
||
/**
|
||
* Returns the element at the current value of the iteration counter and
|
||
* increments the counter.
|
||
*
|
||
* @param oPC The PC on whose array to operate.
|
||
* @return The next element in the array or null metalocation if the
|
||
* iteration has reached the end of the array or if the iteration
|
||
* counter hasn't been initialised.
|
||
*
|
||
* @see GetFirstStoredTeleportTargetLocation
|
||
*/
|
||
struct metalocation GetNextStoredTeleportTargetLocation(object oPC);
|
||
|
||
/**
|
||
* Returns the teleport target location stored at the given index in the array.
|
||
* This function does not interfere with the iteration counter used by
|
||
* GetFirstStoredTeleportTargetLocation and GetNextStoredTeleportTargetLocation.
|
||
*
|
||
* @param oPC The PC on whose array to operate.
|
||
* @param nInd The array index from which to retrieve the location.
|
||
* @return The teleport target location stored at the given index, or null
|
||
* metalocation if the index was out of array bounds.
|
||
*/
|
||
struct metalocation GetNthStoredTeleportTargetLocation(object oPC, int nInd);
|
||
|
||
/**
|
||
* Returns the number of elements in the teleport target locations array on the
|
||
* PC.
|
||
*
|
||
* @param oPC The PC on whose array to operate.
|
||
* @return The number of locations stored in the array.
|
||
*/
|
||
int GetNumberOfStoredTeleportTargetLocations(object oPC);
|
||
|
||
/**
|
||
* Checks whether the PC has a teleport quickselection active and if so,
|
||
* whether it contains a valid metalocation.
|
||
*
|
||
* @param oPC The PC whose quickselection to check.
|
||
* @param nSlot The quickselection slot to check. Valid values are PRC_TELEPORT_ACTIVE_QUICKSELECTION,
|
||
* which checks the active quickselection and numbers from 1 to PRC_NUM_TELEPORT_QUICKSELECTS.
|
||
*
|
||
* @return TRUE if the PC has a quickselection active and it is
|
||
* a valid metalocation, FALSE otherwise.
|
||
*/
|
||
int GetHasTeleportQuickSelection(object oPC, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION);
|
||
|
||
/**
|
||
* Gets the given creature's active teleport quickselection, if any.
|
||
*
|
||
* @param oPC The PC whose quickselection to check.
|
||
* @param bClear Whether to clear the quickselection after getting it.
|
||
* @return The PC's active quickselection, or null metalocation
|
||
* if there is none.
|
||
*/
|
||
struct metalocation GetActiveTeleportQuickSelection(object oPC, int bClear = FALSE);
|
||
|
||
/**
|
||
* Gets the contents of one of the given creature's quickselect slots. Or the
|
||
* active quickselection if the slot parameter is -1.
|
||
*
|
||
* @param oPC The PC whose quickselection to get.
|
||
* @param nSlot The slot to get from. Valid values are PRC_TELEPORT_ACTIVE_QUICKSELECTION,
|
||
* which returns the active quickselection and numbers from 1 to PRC_NUM_TELEPORT_QUICKSELECTS.
|
||
*
|
||
* @return The quickselection in the given slot, or null metalocation if the
|
||
* slot was empty. Also returns null metalocation on error.
|
||
*/
|
||
struct metalocation GetTeleportQuickSelection(object oPC, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION);
|
||
|
||
/**
|
||
* Sets one of the PC's teleport quickselections to the given value.
|
||
* Has no effect on error.
|
||
*
|
||
* @param oPC The PC whose quickselection to set.
|
||
* @param mlocL The metalocation to be stored.
|
||
*
|
||
* @param nSlot The slot to store the metalocation in. Valid values are PRC_TELEPORT_ACTIVE_QUICKSELECTION,
|
||
* which sets the active quickselection and numbers from 1 to PRC_NUM_TELEPORT_QUICKSELECTS.
|
||
*/
|
||
void SetTeleportQuickSelection(object oPC, struct metalocation mlocL, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION);
|
||
|
||
/**
|
||
* Deletes the contents of a teleport quickselection slot on the given creature.
|
||
*
|
||
* @param oPC The PC whose quickselection to delete.
|
||
* @param nSlot The quickselection slot to clear.
|
||
*/
|
||
void RemoveTeleportQuickSelection(object oPC, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION);
|
||
|
||
/**
|
||
* Removes the teleport target location last returned by GetFirstStoredTeleportTargetLocation
|
||
* or GetNextStoredTeleportTargetLocation from the PCs array.
|
||
* Resets the iteration counter to prevent possible errors.
|
||
*
|
||
* @param oPC The PC on whose array to operate.
|
||
*/
|
||
void RemoveCurrentTeleportTargetLocation(object oPC);
|
||
|
||
/**
|
||
* Removes the teleport target location at the given index in the PCs array. The
|
||
* elements after the removed index will be moved down so there will not be empty
|
||
* elements in the middle of the array.
|
||
* Resets the iteration counter to prevent possible errors.
|
||
*
|
||
* @param oPC The PC on whose array to operate.
|
||
* @param nInd The index from which to delete.
|
||
*/
|
||
void RemoveNthTeleportTargetLocation(object oPC, int nInd);
|
||
|
||
/**
|
||
* Adds a location to the end of the teleport target array of the given PC.
|
||
* Implemented by constructing a metalocation out of locToAdd and sName and
|
||
* calling AddTeleportTargetLocationAsMeta.
|
||
*
|
||
* @param oPC The PC to whose teleport target location array the
|
||
* location is to be added.
|
||
* @param locToAdd The location to store.
|
||
* @param sName The name of the teleport target location.
|
||
*
|
||
* @return TRUE if the addition was successfull, FALSE otherwise.
|
||
*/
|
||
int AddTeleportTargetLocation(object oPC, location locToAdd, string sName);
|
||
|
||
/**
|
||
* Adds a metalocation to the end of the teleport target array of the given PC.
|
||
*
|
||
* @param oPC The PC to whose teleport target location array the
|
||
* metalocation is to be added.
|
||
* @param mlocToAdd The metalocation to store.
|
||
*
|
||
* @return TRUE if the addition was successfull, FALSE otherwise.
|
||
*/
|
||
int AddTeleportTargetLocationAsMeta(object oPC, struct metalocation mlocToAdd);
|
||
|
||
/**
|
||
* Creates a map pin for each of the given PC's teleport target locations that do not
|
||
* have a map pin created for them yet. Is not totally reliable.
|
||
* Known problems:
|
||
* Cannot detect if a map pin created for a location has been deleted.
|
||
*
|
||
* @param oPC The PC for whom to create the map pins.
|
||
*/
|
||
void TeleportLocationsToMapPins(object oPC);
|
||
|
||
/**
|
||
* This function checks whether the given creature can teleport from
|
||
* it's current location. It is intended to be run within teleport
|
||
* spellscripts.
|
||
*
|
||
* @param oCreature A creature casting a teleportation spell.
|
||
* @param lTarget The location the creature is going to teleport to.
|
||
* @param bInform If this is true, the creature is sent a message if
|
||
* it is not allowed to teleport.
|
||
* @param bPublic Used as the bBroadcastToFaction parameter of
|
||
* FloatingTextStringOnCreature() when informing oCreature
|
||
* of error.
|
||
* @return TRUE if the creature can teleport, FALSE if it can't.
|
||
*/
|
||
int GetCanTeleport(object oCreature, location lTarget, int bMovesCreature = FALSE, int bInform = FALSE, int bPublic = FALSE);
|
||
|
||
/**
|
||
* Common code for teleportation spells that:
|
||
* 1) Always teleport the caster.
|
||
* 2) Can be used to teleport other willing targets within touch range.
|
||
* 2b) The amount of these additional targets is limited to
|
||
* 1 / 3 caster|manifester levels.
|
||
*
|
||
* The results will be stored in a local array on the caster,
|
||
* retrievable using functions from inc_array.
|
||
* The name of the array is contained within the constant PRC_TELEPORTING_OBJECTS_ARRAY.
|
||
*
|
||
* @param oCaster The object casting the teleportation spell
|
||
* @param nCasterLvl The caster level of oCaster when casting the spell in question.
|
||
* @param bSelfOrParty If this is TRUE, willing creatures (party members)
|
||
* within 10ft of oCaster are taken along. If FALSE,
|
||
* only the caster is teleported.
|
||
*/
|
||
void GetTeleportingObjects(object oCaster, int nCasterLvl, int bSelfOrParty);
|
||
|
||
/**
|
||
* Determines whether the given teleportation target location can be used, or whether
|
||
* the effect causing the teleportation errors, changing the target location.
|
||
* Any inter-area teleportation effects should use this check even if they normally
|
||
* always work correctly.
|
||
*
|
||
* @param lOriginal The original destination of the teleport.
|
||
* @param oUser The user of the teleportation causing effect.
|
||
* @param bNormallyErroless Whether the effect causing the teleprotation can normally
|
||
* error. May be overridden by variables set on the target area.
|
||
* @param bRecursing Whether the function was called again due to Mishap being
|
||
* rolled or not. This should always be left FALSE.
|
||
*
|
||
* @return Either lOrignal, or another location based on the error roll.
|
||
*/
|
||
location GetTeleportError(location lOriginal, object oUser, int bNormallyErroless = FALSE, int bRecursing = FALSE);
|
||
|
||
/**
|
||
* Increments a marker on the target that will cause it to be unable to be
|
||
* teleported. ie. GetCanTeleport() will return FALSE for the target.
|
||
* Uses of DisallowTeleport() stack, so for example, if the function has
|
||
* been called twice for a particular target, that target needs to have
|
||
* AllowTeleport called on it twice before it can teleport again (or once with
|
||
* the bClearAll parameter TRUE)
|
||
*
|
||
* @param oTarget Target object to forbide the teleportation of.
|
||
*/
|
||
void DisallowTeleport(object oTarget);
|
||
|
||
/**
|
||
* Reverse of DisallowTeleport(), a call to this function makes the target
|
||
* eligible for teleportation again.
|
||
* NOTE: multiple forbiddances stack, and by default uses of this function
|
||
* only reduces the forbiddace.
|
||
*
|
||
* @param oTarget Target to allow teleportation for again.
|
||
* @param bClearAll If TRUE, fully clears the forbiddance marker, otherwise
|
||
* just decrements the value by one.
|
||
*/
|
||
void AllowTeleport(object oTarget, int bClearAll = FALSE);
|
||
|
||
/**
|
||
* Performs full attack on eligible target at the end of a teleport sequence
|
||
*
|
||
* @param oPC The caller
|
||
*/
|
||
void ShadowPounce(object oPC);
|
||
|
||
//////////////////////////////////////////////////
|
||
/* Internal Constants - nothing to see here :D */
|
||
//////////////////////////////////////////////////
|
||
|
||
/// Internal constant - Name of the array where the teleport target locations are stored.
|
||
const string PRC_TELEPORT_ARRAY_NAME = "PRC_TeleportLocation_Array";
|
||
/// Internal constant - Name of personal switch telling whether to create map pins for a particular PC's stored locations.
|
||
const string PRC_TELEPORT_CREATE_MAP_PINS = "PRC_Teleport_CreateMapPins";
|
||
/// Internal constant - Name of personal switch telling how long the listener will wait for the player to speak a name when a new location is stored.
|
||
const string PRC_TELEPORT_NAMING_TIMER_VARNAME = "PRC_Teleport_NamingListenerDuration";
|
||
/// Internal constant - Name of personal swithc telling whether to automatically store the latest location the character rested at
|
||
const string PRC_TELEPORT_ONREST_MARKLOCATION = "PRC_Teleport_OnRest_MarkLocation";
|
||
|
||
|
||
//////////////////////////////////////////////////
|
||
/* Function defintions */
|
||
//////////////////////////////////////////////////
|
||
|
||
void ChooseTeleportTargetLocation(object oPC, string sCallbackScript, string sCallbackVar,
|
||
int bMeta = FALSE, int bForce = TRUE)
|
||
{
|
||
/* // The system is only useful to PCs. If it is at some point implemented for NPCs, change this.
|
||
if(!GetIsPC(oPC)) return;*/
|
||
|
||
// Make sure the PC has the feats for marking locations
|
||
ExecuteScript("prc_tp_mgmt_eval", oPC);
|
||
|
||
int nSpellID = GetSpellId();
|
||
|
||
// Handle Word of Recall spell
|
||
if(nSpellID == SPELL_WORD_OF_RECALL_SELF
|
||
|| nSpellID == SPELL_WORD_OF_RECALL_PARTY)
|
||
{
|
||
struct metalocation mlocL = GetLocalMetalocation(oPC, "PRC_WordOfRecall");
|
||
|
||
if(GetIsMetalocationInModule(mlocL))
|
||
{
|
||
// Store the return value under the requested name and as the requested type
|
||
if(bMeta)
|
||
SetLocalMetalocation(oPC, sCallbackVar, mlocL);
|
||
else
|
||
SetLocalLocation(oPC, sCallbackVar, MetalocationToLocation(mlocL));
|
||
|
||
// Break the script execution association between this one and the callback script
|
||
// by delaying it. Probably unnecessary, but it will clear potential interference
|
||
// caused by things done in this execution
|
||
DelayCommand(0.2f, ExecuteScript(sCallbackScript, oPC));
|
||
}
|
||
else
|
||
{
|
||
FloatingTextStrRefOnCreature(16789977, oPC, FALSE);
|
||
}
|
||
}
|
||
// Handle possible quickselection
|
||
else if(GetHasTeleportQuickSelection(oPC, PRC_TELEPORT_ACTIVE_QUICKSELECTION))
|
||
{
|
||
// Get the quickselected metalocation and clear it
|
||
struct metalocation mlocL = GetActiveTeleportQuickSelection(oPC, TRUE);
|
||
int bTransViaPlants = GetLocalInt(oPC, "PRC_TransportViaPlants");
|
||
DeleteLocalInt(oPC, "PRC_TransportViaPlants");
|
||
object oArea = GetAreaFromMetalocation(mlocL);
|
||
|
||
if((bTransViaPlants && GetIsAreaNatural(oArea) && !GetIsAreaInterior(oArea))
|
||
|| !bTransViaPlants)
|
||
{
|
||
// Store the return value under the requested name and as the requested type
|
||
if(bMeta)
|
||
SetLocalMetalocation(oPC, sCallbackVar, mlocL);
|
||
else
|
||
SetLocalLocation(oPC, sCallbackVar, MetalocationToLocation(mlocL));
|
||
|
||
// Break the script execution association between this one and the callback script
|
||
// by delaying it. Probably unnecessary, but it will clear potential interference
|
||
// caused by things done in this execution
|
||
DelayCommand(0.2f, ExecuteScript(sCallbackScript, oPC));
|
||
}
|
||
else
|
||
{
|
||
SendMessageToPCByStrRef(oPC, 16789931);
|
||
}
|
||
}
|
||
// We have to go look at the stored array, so make sure it contains at least one entry
|
||
else if(!GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME))
|
||
{// "You do not have any locations marked for teleporting to!"
|
||
SendMessageToPCByStrRef(oPC, 16825305);
|
||
|
||
// Store the PC's location
|
||
if(bMeta)
|
||
SetLocalMetalocation(oPC, sCallbackVar, LocationToMetalocation(GetLocation(oPC)));
|
||
else
|
||
SetLocalLocation(oPC, sCallbackVar, GetLocation(oPC));
|
||
|
||
// Break the script execution association between this one and the callback script
|
||
// by delaying it. Probably unnecessary, but it will clear potential interference
|
||
// caused by things done in this execution
|
||
DelayCommand(0.2f, ExecuteScript(sCallbackScript, oPC));
|
||
}
|
||
// No quickselection was active and there is at least one location to select, so run the
|
||
// conversation to find out where the user wants to go
|
||
else
|
||
{
|
||
SetLocalString(oPC, "PRC_TeleportTargetSelection_CallbackScript", sCallbackScript);
|
||
SetLocalString(oPC, "PRC_TeleportTargetSelection_ReturnStoreName", sCallbackVar);
|
||
SetLocalInt(oPC, "PRC_TeleportTargetSelection_ReturnAsMetalocation", bMeta);
|
||
|
||
StartDynamicConversation("prc_teleprt_conv", oPC,
|
||
bForce ? DYNCONV_EXIT_NOT_ALLOWED : DYNCONV_EXIT_ALLOWED_SHOW_CHOICE,
|
||
!bForce, bForce, oPC);
|
||
}
|
||
}
|
||
|
||
struct metalocation GetFirstStoredTeleportTargetLocation(object oPC)
|
||
{
|
||
// Return null if the array is empty
|
||
if(!GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME))
|
||
return LocationToMetalocation(GetLocation(oPC), "Error: No stored locations! Returned current location of " + GetName(oPC));
|
||
|
||
// Set the iterator value for subsequent calls to GetNextStoredTeleportTargetLocation()
|
||
SetLocalInt(oPC, "PRC_Teleport_Array_Iterator", 1);
|
||
// Clean away the iterator on script execution end
|
||
DelayCommand(0.0f, DeleteLocalInt(oPC, "PRC_Teleport_Array_Iterator"));
|
||
|
||
return GetPersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_0");
|
||
}
|
||
|
||
struct metalocation GetNextStoredTeleportTargetLocation(object oPC)
|
||
{
|
||
// Return null if GetFirstStoredTeleportTargetLocation() hasn't been called previously
|
||
int nInd = GetLocalInt(oPC, "PRC_Teleport_Array_Iterator");
|
||
if(!nInd) return GetNullMetalocation();
|
||
|
||
// If the iteration has reached the end of the array, delete the iteration counter and return null
|
||
if(nInd > GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME) - 1)
|
||
{
|
||
DeleteLocalInt(oPC, "PRC_Teleport_Array_Iterator");
|
||
return GetNullMetalocation();
|
||
}
|
||
|
||
// Increment iterator and return the value
|
||
SetLocalInt(oPC, "PRC_Teleport_Array_Iterator", nInd + 1);
|
||
return GetPersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_" + IntToString(nInd));
|
||
}
|
||
|
||
struct metalocation GetNthStoredTeleportTargetLocation(object oPC, int nInd)
|
||
{
|
||
// If out of lower or upper bound, return null
|
||
if(nInd < 0 || nInd > GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME) - 1)
|
||
return GetNullMetalocation();
|
||
|
||
// Return the nth stored location
|
||
return GetPersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_" + IntToString(nInd));
|
||
}
|
||
|
||
int GetNumberOfStoredTeleportTargetLocations(object oPC)
|
||
{
|
||
return GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME);
|
||
}
|
||
|
||
int GetHasTeleportQuickSelection(object oPC, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
{
|
||
//SendMessageToPC(oPC, "GetLocalInt(oPC, PRC_Teleport_Quickselection): " + IntToString(GetLocalInt(oPC, "PRC_Teleport_Quickselection")));
|
||
//SendMessageToPC(oPC, "GetIsMetalocationValid(GetLocalMetalocation(oPC, PRC_Teleport_Quickselection)): " + IntToString(GetIsMetalocationValid(GetLocalMetalocation(oPC, "PRC_Teleport_Quickselection"))));
|
||
if(nSlot < -1 || !nSlot || nSlot > PRC_NUM_TELEPORT_QUICKSELECTS)
|
||
return FALSE;
|
||
|
||
if(nSlot == PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
return GetLocalInt(oPC, "PRC_Teleport_Quickselection");/* &&
|
||
GetIsMetalocationValid(GetLocalMetalocation(oPC, "PRC_Teleport_Quickselection"));*/
|
||
else
|
||
return GetLocalInt(oPC, "PRC_Teleport_QuickSelection_" + IntToString(nSlot));
|
||
}
|
||
|
||
struct metalocation GetActiveTeleportQuickSelection(object oPC, int bClear = FALSE)
|
||
{
|
||
if(GetHasTeleportQuickSelection(oPC, PRC_TELEPORT_ACTIVE_QUICKSELECTION))
|
||
{
|
||
struct metalocation mlocL = GetLocalMetalocation(oPC, "PRC_Teleport_Quickselection");
|
||
if(bClear)
|
||
RemoveTeleportQuickSelection(oPC, PRC_TELEPORT_ACTIVE_QUICKSELECTION);
|
||
return mlocL;
|
||
}
|
||
else
|
||
return GetNullMetalocation();
|
||
}
|
||
|
||
struct metalocation GetTeleportQuickSelection(object oPC, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
{
|
||
// Make sure the slot is within allowed range
|
||
if(nSlot < -1 || !nSlot || nSlot > PRC_NUM_TELEPORT_QUICKSELECTS)
|
||
return GetNullMetalocation();
|
||
|
||
// The active quickselection was asked
|
||
if(nSlot == PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
return GetActiveTeleportQuickSelection(oPC, FALSE);
|
||
// The contents of a slot were asked, an the slot in question is not empty
|
||
else if(GetLocalInt(oPC, "PRC_Teleport_QuickSelection_" + IntToString(nSlot)))
|
||
return GetLocalMetalocation(oPC, "PRC_Teleport_QuickSelection_" + IntToString(nSlot));
|
||
// The slot is empty
|
||
else
|
||
return GetNullMetalocation();
|
||
}
|
||
|
||
void SetTeleportQuickSelection(object oPC, struct metalocation mlocL, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
{
|
||
// Make sure the slot is within allowed range
|
||
if(nSlot < -1 || !nSlot || nSlot > PRC_NUM_TELEPORT_QUICKSELECTS)
|
||
return;
|
||
|
||
// Set either the active selection, or a slot depending on nSlot
|
||
if(nSlot == PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
{
|
||
SetLocalInt(oPC, "PRC_Teleport_Quickselection", TRUE); // Mark quickselection as active
|
||
SetLocalMetalocation(oPC, "PRC_Teleport_Quickselection", mlocL);
|
||
}
|
||
else
|
||
{
|
||
SetLocalInt(oPC, "PRC_Teleport_QuickSelection_" + IntToString(nSlot), TRUE); // Mark quickselection as existing
|
||
SetLocalMetalocation(oPC, "PRC_Teleport_QuickSelection_" + IntToString(nSlot), mlocL);
|
||
}
|
||
}
|
||
|
||
void RemoveTeleportQuickSelection(object oPC, int nSlot = PRC_TELEPORT_ACTIVE_QUICKSELECTION)
|
||
{
|
||
DeleteLocalInt(oPC, "PRC_Teleport_Quickselection");
|
||
DeleteLocalMetalocation(oPC, "PRC_Teleport_Quickselection");
|
||
}
|
||
|
||
void RemoveCurrentTeleportTargetLocation(object oPC)
|
||
{
|
||
// Return if GetFirstStoredTeleportTargetLocation() or GetNextStoredTeleportTargetLocation() hasn't been called previously.
|
||
int nInd = GetLocalInt(oPC, "PRC_Teleport_Array_Iterator");
|
||
if(!nInd) return;
|
||
|
||
// Remove the location
|
||
RemoveNthTeleportTargetLocation(oPC, nInd);
|
||
|
||
// Delete the iteration counter to keep potential errors down.
|
||
DeleteLocalInt(oPC, "PRC_Teleport_Array_Iterator");
|
||
}
|
||
|
||
void RemoveNthTeleportTargetLocation(object oPC, int nInd)
|
||
{
|
||
// If out of lower or upper bound, return
|
||
if(nInd < 0 || nInd > GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME) - 1)
|
||
return;
|
||
|
||
// Get the index of the last element in the array and move elements back if needed
|
||
int nMax = GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME) - 1;
|
||
for(; nInd < nMax; nInd++)
|
||
{
|
||
SetPersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_" + IntToString(nInd),
|
||
GetPersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_" + IntToString(nInd + 1))
|
||
);
|
||
// Move the map pin existence marker if it's present
|
||
if(GetLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME + "_HasMapPin_" + IntToString(nInd + 1)))
|
||
SetLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME + "_HasMapPin_" + IntToString(nInd), TRUE);
|
||
}
|
||
|
||
// Remove the last element and mark the size change
|
||
DeletePersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_" + IntToString(nMax));
|
||
DeleteLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME + "_HasMapPin_" + IntToString(nMax));
|
||
SetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME, nMax);
|
||
|
||
// Delete the iteration counter to keep potential errors down.
|
||
DeleteLocalInt(oPC, "PRC_Teleport_Array_Iterator");
|
||
}
|
||
|
||
int AddTeleportTargetLocation(object oPC, location locToAdd, string sName)
|
||
{
|
||
return AddTeleportTargetLocationAsMeta(oPC, LocationToMetalocation(locToAdd, sName));
|
||
}
|
||
|
||
int AddTeleportTargetLocationAsMeta(object oPC, struct metalocation mlocToAdd)
|
||
{
|
||
// Make sure the metalocation is valid
|
||
if(!GetIsMetalocationValid(mlocToAdd))
|
||
{// "Location could not be marked due to technical limitations - unable to uniquely identify area."
|
||
SendMessageToPCByStrRef(oPC, 16825304);
|
||
return FALSE;
|
||
}
|
||
|
||
// Array size check. If no limit is defined via switch, default to 50.
|
||
int nInd = GetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME); // Array elements begin at index 0
|
||
int nMax = GetPRCSwitch(PRC_TELEPORT_MAX_TARGET_LOCATIONS) ?
|
||
GetPRCSwitch(PRC_TELEPORT_MAX_TARGET_LOCATIONS) :
|
||
50;
|
||
if(nInd >= nMax)
|
||
{// You have reached the maximum allowed teleport locations ( ).\nYou must remove at least one stored location before you can add new locations.
|
||
SendMessageToPC(oPC, GetStringByStrRef(16825294) + IntToString(nMax) + GetStringByStrRef(16825295));
|
||
return FALSE;
|
||
}
|
||
|
||
// All checks passed, store the location, increment array size and return
|
||
SetPersistantLocalMetalocation(oPC, PRC_TELEPORT_ARRAY_NAME + "_" + IntToString(nInd), mlocToAdd);
|
||
SetPersistantLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME, nInd + 1);
|
||
return TRUE;
|
||
}
|
||
|
||
void TeleportLocationsToMapPins(object oPC)
|
||
{
|
||
// This function is only useful for PCs
|
||
if(!GetIsPC(oPC)) return;
|
||
|
||
// Iterate over all stored metalocations
|
||
int nMax = GetNumberOfStoredTeleportTargetLocations(oPC);
|
||
int i;
|
||
for(; i < nMax; i++)
|
||
{
|
||
// Add map pins to those locations that do not already have one
|
||
if(!GetLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME + "_HasMapPin_" + IntToString(i)))
|
||
{
|
||
CreateMapPinFromMetalocation(GetNthStoredTeleportTargetLocation(oPC, i) , oPC);
|
||
SetLocalInt(oPC, PRC_TELEPORT_ARRAY_NAME + "_HasMapPin_" + IntToString(i), TRUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
int GetCanTeleport(object oCreature, location lTarget, int bMovesCreature = FALSE, int bInform = FALSE, int bPublic = FALSE)
|
||
{
|
||
int bReturn = TRUE;
|
||
// First, check global switch to turn off teleporting
|
||
if(GetPRCSwitch(PRC_DISABLE_TELEPORTATION))
|
||
bReturn = FALSE;
|
||
|
||
// If the creature would be actually moved around, do some extra tests
|
||
if(bMovesCreature)
|
||
{
|
||
// Check area-specific variables
|
||
object oSourceArea = GetArea(oCreature);
|
||
object oTargetArea = GetAreaFromLocation(lTarget);
|
||
// Teleportation is between areas
|
||
if(oSourceArea != oTargetArea)
|
||
{
|
||
// Check forbiddance variable on the current area
|
||
if(GetLocalInt(oSourceArea, PRC_DISABLE_TELEPORTATION_IN_AREA) & PRC_DISABLE_TELEPORTATION_FROM_AREA)
|
||
bReturn = FALSE;
|
||
// Check forbiddance variable on the target area
|
||
if(GetLocalInt(oTargetArea, PRC_DISABLE_TELEPORTATION_IN_AREA) & PRC_DISABLE_TELEPORTATION_TO_AREA)
|
||
bReturn = FALSE;
|
||
}
|
||
// Teleportation within an area
|
||
else if(GetLocalInt(oSourceArea, PRC_DISABLE_TELEPORTATION_IN_AREA) & PRC_DISABLE_TELEPORTATION_WITHIN_AREA)
|
||
bReturn = FALSE;
|
||
}
|
||
|
||
|
||
// Check forbiddance variable on the creature
|
||
if(GetLocalInt(oCreature, PRC_DISABLE_CREATURE_TELEPORT))
|
||
bReturn = FALSE;
|
||
|
||
// Tell the creature about failure, if necessary
|
||
if(bInform & !bReturn)
|
||
{
|
||
// "Something prevents your extra-dimensional movement!"
|
||
FloatingTextStrRefOnCreature(16825298, oCreature, bPublic);
|
||
}
|
||
|
||
return bReturn;
|
||
}
|
||
|
||
void GetTeleportingObjects(object oCaster, int nCasterLvl, int bSelfOrParty)
|
||
{
|
||
// Store list of objects to teleport in an array on the caster
|
||
// First, null the array
|
||
array_delete(oCaster, PRC_TELEPORTING_OBJECTS_ARRAY);
|
||
array_create(oCaster, PRC_TELEPORTING_OBJECTS_ARRAY);
|
||
|
||
// Init array index variable
|
||
int i = 0;
|
||
|
||
// Casting Dimension Door always teleports at least the caster
|
||
array_set_object(oCaster, PRC_TELEPORTING_OBJECTS_ARRAY, i++, oCaster);
|
||
|
||
// If teleporting party, get all faction members fitting in within 10 feet. (Should be dependent on caster's reach,
|
||
// but that would mean < Small creatures could not teleport their party at all and even Mediums with their 5 foot
|
||
// reach might have trouble considering the position tracking code's shakiness)
|
||
if(bSelfOrParty)
|
||
{
|
||
// Carry amount variables
|
||
int nMaxCarry = nCasterLvl / 3,
|
||
nCarry = 0,
|
||
nIncrease;
|
||
|
||
nMaxCarry += GetLevelByClass(CLASS_TYPE_WAYFARER_GUIDE, oCaster);
|
||
|
||
location lSelf = GetLocation(oCaster);
|
||
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(10.0f), lSelf);
|
||
while(GetIsObjectValid(oTarget))
|
||
{
|
||
// Check if the target is member of the same faction as the caster. If it is, teleport it along.
|
||
if(GetFactionEqual(oCaster, oTarget) && oTarget != oCaster)
|
||
{
|
||
// Calculate how many carry slots the creature would take
|
||
nIncrease = GetCreatureSize(oTarget) == CREATURE_SIZE_HUGE ? 4 :
|
||
GetCreatureSize(oTarget) == CREATURE_SIZE_LARGE ? 2 :
|
||
1;
|
||
|
||
// Add others if the caster can carry them
|
||
if(nCarry + nIncrease <= nMaxCarry)
|
||
{
|
||
nCarry += nIncrease;
|
||
array_set_object(oCaster, PRC_TELEPORTING_OBJECTS_ARRAY, i++, oTarget);
|
||
}
|
||
// Otherwise inform the caster that they couldn't take the creature along
|
||
else // "You do not have anough carrying capacity to teleport X"
|
||
SendMessageToPC(oCaster, GetStringByStrRef(16825302) + " " + GetName(oTarget));
|
||
}
|
||
|
||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, FeetToMeters(10.0f), lSelf);
|
||
}
|
||
}
|
||
/*
|
||
// Targeting one other being in addition to self. If it's hostile, it gets SR and a Will save.
|
||
else if(nSpellID = SPELLID_TELEPORT_TARGET)
|
||
{
|
||
object oTarget = PRCGetSpellTargetObject();
|
||
if(GetIsHostile())
|
||
{
|
||
PRCSignalSpellEvent(oTarget, TRUE, nSpellID); // Let the target know it was cast a spell at
|
||
|
||
//SR
|
||
if(!PRCDoResistSpell(oCaster, oTarget, nCasterLevel + SPGetPenetr()))
|
||
{
|
||
// Will save
|
||
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, PRCGetSaveDC(oTarget, oCaster), SAVING_THROW_TYPE_SPELL))
|
||
{
|
||
array_set_object(oCaster, PRC_TELEPORTING_OBJECTS_ARRAY, i++, oTarget);
|
||
} } }
|
||
// Not hostile, just add it to the list.
|
||
else
|
||
{
|
||
PRCSignalSpellEvent(oTarget, FALSE, nSpellID); // Let the target know it was cast a spell at
|
||
array_set_object(oCaster, PRC_TELEPORTING_OBJECTS_ARRAY, i++, oTarget);
|
||
}
|
||
}
|
||
*/
|
||
}
|
||
|
||
location GetTeleportError(location lOriginal, object oUser, int bNormallyErroless = FALSE, int bRecursing = FALSE)
|
||
{
|
||
if(DEBUG) DoDebug("prc_inc_teleport: GetTeleportError():\n"
|
||
+ "lOriginal = " + DebugLocation2Str(lOriginal) + "\n"
|
||
+ "oUser = " + DebugObject2Str(oUser) + "\n"
|
||
+ "bNormallyErroless = " + DebugBool2String(bNormallyErroless) + "\n"
|
||
+ "bRecursing = " + DebugBool2String(bRecursing) + "\n"
|
||
);
|
||
|
||
int nOverrideValue = GetLocalInt(GetAreaFromLocation(lOriginal), PRC_FORCE_TELEPORTATION_RESULT);
|
||
|
||
// If the effect cannot normally error and there is no override active, just return lOriginal
|
||
if(bNormallyErroless && !nOverrideValue)
|
||
return lOriginal;
|
||
|
||
// Roll for the result. If recursing from a mishap, roll d20 + 80, otherwise roll d100
|
||
int nRoll = bRecursing ? d20() + 80 : d100();
|
||
|
||
if (GetLevelByClass(CLASS_TYPE_WAYFARER_GUIDE, oUser) >= 3)
|
||
{
|
||
// Roll twice, take the better roll
|
||
int nRoll2 = bRecursing ? d20() + 80 : d100();
|
||
if (nRoll > nRoll2) nRoll = nRoll2;
|
||
}
|
||
|
||
// If an override value is specified, force the roll value. Override only applies in the first call, not on subsequent times
|
||
if(nOverrideValue && !bRecursing)
|
||
{
|
||
switch(nOverrideValue)
|
||
{
|
||
case PRC_FORCE_TELEPORTATION_RESULT_ONTARGET: nRoll = 1; break;
|
||
case PRC_FORCE_TELEPORTATION_RESULT_OFFTARGET: nRoll = 91; break;
|
||
case PRC_FORCE_TELEPORTATION_RESULT_WAYOFFTARGET: nRoll = 95; break;
|
||
case PRC_FORCE_TELEPORTATION_RESULT_MISHAP: nRoll = 99; break;
|
||
}
|
||
}
|
||
|
||
if (GetLocalInt(GetAreaFromLocation(lOriginal), "BlackLabyrinthTeleport")) nRoll = 91;
|
||
|
||
int nLabyrinth = GetLocalInt(oUser, "BlackLabyrinthTeleport");
|
||
if(!PRCMySavingThrow(SAVING_THROW_WILL, oUser, nLabyrinth, SAVING_THROW_TYPE_SPELL) && nLabyrinth) nRoll = 99;
|
||
else if (nLabyrinth) nRoll = 91;
|
||
|
||
if(DEBUG) DoDebug("prc_inc_teleport: GetTeleportError(): Roll is " + IntToString(nRoll) + ", forced = " + DebugBool2String(nOverrideValue));
|
||
|
||
/* On Target Off Target Way Off Target Mishap
|
||
* 01<30>90 91<39>94 95<39>98 99<39>100
|
||
*/
|
||
// On Target - Return original location
|
||
if(nRoll <= 90)
|
||
{
|
||
if(DEBUG) DoDebug("prc_inc_teleport: GetTeleportError(): On Target - Returning original location");
|
||
return lOriginal;
|
||
}
|
||
// Off Target - Get a random location in same area
|
||
else if(nRoll <= 94)
|
||
{
|
||
object oArea = GetAreaFromLocation(lOriginal);
|
||
int nAreaW = GetAreaWidth(oArea);
|
||
int nAreaH = GetAreaHeight(oArea);
|
||
|
||
vector vNew = Vector(Random(nAreaW) * 10.0f + 5.0f,
|
||
Random(nAreaH) * 10.0f + 5.0f,
|
||
GetPositionFromLocation(lOriginal).z
|
||
);
|
||
location lNew = Location(oArea, vNew, 0.0f);
|
||
if(DEBUG) DoDebug("prc_inc_teleport: GetTeleportError(): Off Target - Returning " + DebugLocation2Str(lNew));
|
||
return lNew;
|
||
}
|
||
// Way Off Target - Random location among stored teleport choices, or if there are no others, just stay where the user is
|
||
else if(nRoll <= 98)
|
||
{
|
||
int nLocs = GetNumberOfStoredTeleportTargetLocations(oUser);
|
||
int nRand = Random(nLocs);
|
||
location lReplacement = MetalocationToLocation(GetNthStoredTeleportTargetLocation(oUser, nRand));
|
||
|
||
if(DEBUG) DoDebug("prc_inc_teleport: GetTeleportError(): Way Off Target - Replacement location rolled: " + DebugLocation2Str(lReplacement) + "\n"
|
||
+ "Replacement location is useable: " + DebugBool2String(!(nLocs == 0 || lReplacement == lOriginal))
|
||
);
|
||
|
||
if(nLocs == 0 || lReplacement == lOriginal)
|
||
return GetLocation(oUser);
|
||
else
|
||
return lReplacement;
|
||
}
|
||
// Mishap:
|
||
// You and anyone else teleporting with you have gotten <20>scrambled.<2E>
|
||
// You each take 1d10 points of damage, and you reroll on the chart to see where you wind up.
|
||
// For these rerolls, roll 1d20+80. Each time <20>Mishap<61> comes up, the characters take more damage and must reroll.
|
||
else
|
||
{
|
||
if(DEBUG) DoDebug("prc_inc_teleport: GetTeleportError(): Mishap - damaging people");
|
||
object oTarget;
|
||
int i;
|
||
for(i = 0; i < array_get_size(oUser, PRC_TELEPORTING_OBJECTS_ARRAY); i++)
|
||
{
|
||
oTarget = array_get_object(oUser, PRC_TELEPORTING_OBJECTS_ARRAY, i);
|
||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d10(), DAMAGE_TYPE_MAGICAL), oTarget);
|
||
}
|
||
|
||
return GetTeleportError(lOriginal, oUser, bNormallyErroless, TRUE);
|
||
}
|
||
}
|
||
|
||
void DisallowTeleport(object oTarget)
|
||
{
|
||
if(DEBUG) DoDebug("DisallowTeleport():\n"
|
||
+ "oTarget = " + DebugObject2Str(oTarget) + "\n"
|
||
+ "\n"
|
||
+ "New blocking variable value: " + IntToString(GetLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT) + 1) + "\n"
|
||
);
|
||
SetLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT,
|
||
GetLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT) + 1
|
||
);
|
||
}
|
||
|
||
void AllowTeleport(object oTarget, int bClearAll = FALSE)
|
||
{
|
||
if(DEBUG) DoDebug("AllowTeleport():\n"
|
||
+ "oTarget = " + DebugObject2Str(oTarget) + "\n"
|
||
+ "bClearAll = " + DebugBool2String(bClearAll) + "\n"
|
||
+ "\n"
|
||
+ "Old blocking variable value: " + IntToString(GetLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT))
|
||
);
|
||
int nValue = GetLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT) - 1;
|
||
if((nValue > 0) && !bClearAll)
|
||
SetLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT, nValue);
|
||
else
|
||
DeleteLocalInt(oTarget, PRC_DISABLE_CREATURE_TELEPORT);
|
||
|
||
if(DEBUG) DoDebug("New blocking variable value: " + (((nValue > 0) && !bClearAll) ? IntToString(nValue) : "Deleted"));
|
||
}
|
||
|
||
void ShadowPounce(object oPC)
|
||
{
|
||
if (GetHasFeat(FEAT_SHADOW_POUNCE, oPC))
|
||
{
|
||
location lTarget = GetLocation(oPC);
|
||
// Use the function to get the closest creature as a target
|
||
object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
||
while(GetIsObjectValid(oAreaTarget))
|
||
{
|
||
if(oAreaTarget != oPC && // Not you
|
||
GetIsInMeleeRange(oPC, oAreaTarget) && // They must be in melee range
|
||
GetIsEnemy(oAreaTarget, oPC)) // Only enemies
|
||
{
|
||
PerformAttackRound(oAreaTarget, oPC, EffectVisualEffect(VFX_IMP_NEGATIVE_ENERGY), 0.0, 0, 0, 0, TRUE, "Shadow Pounce Hit", "Shadow Pounce Miss", FALSE, FALSE, TRUE);
|
||
break; //End loop
|
||
}
|
||
//Select the next target within the spell shape.
|
||
oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
||
}
|
||
}
|
||
} |