PRC8/nwn/nwnprc/trunk/include/x0_i0_transport.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
Updated AMS marker feats.  Removed arcane & divine marker feats.  Updated Dread Necromancer for epic progression. Updated weapon baseitem models.  Updated new weapons for crafting & npc equip.
 Updated prefix.  Updated release archive.
2024-02-11 14:01:05 -05:00

303 lines
10 KiB
Plaintext

//:://////////////////////////////////////////////////
//:: X0_I0_TRANSPORT
//:: Copyright (c) 2002 Floodgate Entertainment
//:://////////////////////////////////////////////////
/*
Functions for making creatures travel/transport to new locations.
*/
//:://////////////////////////////////////////////////
//:: Created By: Naomi Novik
//:: Created On: 09/12/2002
//:://////////////////////////////////////////////////
/**********************************************************************
* CONSTANTS
**********************************************************************/
/**********************************************************************
* FUNCTION PROTOTYPES
**********************************************************************/
// Target goes to specified destination object intelligently.
// If location is in same area, walk (or run) there.
// If location is in different area, walk (or run) to
// most appropriate door, area transition, or waypoint,
// then jump.
// If either of these fail, jump after fDelay seconds.
void TravelToObject(object oDest, object oTarget=OBJECT_SELF, int bRun=FALSE, float fDelay=10.0);
// Target goes to specified location intelligently. See
// TravelToObject for description.
void TravelToLocation(location lDest, object oTarget=OBJECT_SELF, int bRun=FALSE, float fDelay=10.0);
// Find nearest exit to target (either door or waypoint).
object GetNearestExit(object oTarget=OBJECT_SELF);
// Find best exit based on desired target area
object GetBestExit(object oTarget=OBJECT_SELF, object oTargetArea=OBJECT_INVALID);
// Transport a player and his/her associates to a waypoint.
// This does NOT transport the rest of the player's party,
// only their henchman, summoned, dominated, etc.
void TransportToWaypoint(object oPC, object oWaypoint);
// Transport a player and his/her associates to a location.
// This does NOT transport the rest of the player's party,
// only their henchman, summoned, dominated, etc.
void TransportToLocation(object oPC, location oLoc);
// Transport an entire party to a waypoint
void TransportAllToWaypoint(object oPC, object oWaypoint);
// Transport an entire party to a location
void TransportAllToLocation(object oPC, location lLoc);
/**********************************************************************
* FUNCTION PROTOTYPES
**********************************************************************/
// Target goes to specified destination object intelligently.
// If location is in same area, walk (or run) there.
// If location is in different area, walk (or run) to
// nearest waypoint or door, then jump.
// If either of these fail, jump after a timeout.
void TravelToObject(object oDest, object oTarget=OBJECT_SELF, int bRun=FALSE, float fDelay=10.0)
{
TravelToLocation(GetLocation(oDest), oTarget, bRun, fDelay);
}
// Target goes to specified location intelligently. See
// TravelToObject for description.
void TravelToLocation(location lDest, object oTarget=OBJECT_SELF, int bRun=FALSE, float fDelay=10.0)
{
object oDestArea = GetAreaFromLocation(lDest);
if (oDestArea == GetArea(oTarget)) {
AssignCommand(oTarget,
ActionForceMoveToLocation(lDest, bRun, fDelay));
} else {
object oBestExit = GetBestExit(oTarget, oDestArea);
AssignCommand(oTarget,
ActionForceMoveToObject(oBestExit, bRun, 1.0, fDelay));
int nObjType = GetObjectType(oBestExit);
if (nObjType == OBJECT_TYPE_DOOR) {
AssignCommand(oTarget, ActionOpenDoor(oBestExit));
}
AssignCommand(oTarget,
ActionJumpToLocation(lDest));
}
AssignCommand(oTarget, DelayCommand(fDelay, ClearAllActions()));
AssignCommand(oTarget, DelayCommand(fDelay, JumpToLocation(lDest)));
}
// Find nearest exit to target (either door or trigger or
// (failing those) waypoint).
object GetNearestExit(object oTarget=OBJECT_SELF)
{
object oCurArea = GetArea(oTarget);
object oNearDoor = GetNearestObject(OBJECT_TYPE_DOOR, oTarget);
if (GetArea(oNearDoor) != oCurArea)
oNearDoor = OBJECT_INVALID;
// Find nearest area transition trigger
int nTrig = 1;
object oNearTrig = GetNearestObject(OBJECT_TYPE_TRIGGER, oTarget);
while (GetIsObjectValid(oNearTrig)
&& GetArea(oNearTrig) == oCurArea
&& !GetIsObjectValid(GetTransitionTarget(oNearTrig)))
{
nTrig++;
oNearTrig = GetNearestObject(OBJECT_TYPE_TRIGGER, oTarget, nTrig);
}
if (GetArea(oNearTrig) != oCurArea)
oNearTrig = OBJECT_INVALID;
float fMaxDist = 10000.0;
float fDoorDist = fMaxDist;
float fTrigDist = fMaxDist;
if (GetIsObjectValid(oNearDoor)) {
fDoorDist = GetDistanceBetween(oNearDoor, oTarget);
}
if (GetIsObjectValid(oNearTrig)) {
fTrigDist = GetDistanceBetween(oNearTrig, oTarget);
}
if (fTrigDist < fDoorDist)
return oNearTrig;
if (fDoorDist < fTrigDist || fDoorDist < fMaxDist)
return oNearDoor;
// No door/area transition -- use waypoint as a backup exit
return GetNearestObject(OBJECT_TYPE_WAYPOINT, oTarget);
}
// Private function: find the best exit of the desired type.
object GetBestExitByType(object oTarget=OBJECT_SELF, object oTargetArea=OBJECT_INVALID, int nObjType=OBJECT_TYPE_DOOR)
{
object oCurrentArea = GetArea(oTarget);
int nDoor = 1;
object oDoor = GetNearestObject(nObjType, oTarget);
object oNearestDoor = oDoor;
object oDestArea = OBJECT_INVALID;
object oBestDoor = OBJECT_INVALID;
object oBestDestArea = OBJECT_INVALID;
while (GetIsObjectValid(oDoor) && GetArea(oDoor) == oCurrentArea) {
oDestArea = GetArea(GetTransitionTarget(oDoor));
// If we find a door that leads to the target
// area, use it
if (oDestArea == oTargetArea) {
return oDoor;
}
// If we find a door that leads to a different area,
// that might be good if we haven't already found one
// that leads to the desired area, or a closer door
// that leads to a different area.
if (oDestArea != oCurrentArea && !GetIsObjectValid(oBestDoor)) {
oBestDoor = oDoor;
}
// try the next door
nDoor++;
oDoor = GetNearestObject(nObjType, oTarget, nDoor);
}
// If we found a door that leads to a different area,
// return that one.
if (GetIsObjectValid(oBestDoor))
return oBestDoor;
// Otherwise, return the nearest, if it's in this area.
if (GetArea(oNearestDoor) == oCurrentArea)
return oNearestDoor;
return OBJECT_INVALID;
}
// Find best exit based on desired target area
object GetBestExit(object oTarget=OBJECT_SELF, object oTargetArea=OBJECT_INVALID)
{
if (!GetIsObjectValid(oTargetArea))
return GetNearestExit(oTarget);
// Try and find a door
object oBestDoor = GetBestExitByType(oTarget,
oTargetArea,
OBJECT_TYPE_DOOR);
if (GetIsObjectValid(oBestDoor)) {
if (GetTransitionTarget(oBestDoor) == oTargetArea) {
return oBestDoor;
}
}
// Try and find a trigger
object oBestTrigger = GetBestExitByType(oTarget,
oTargetArea,
OBJECT_TYPE_TRIGGER);
if (GetIsObjectValid(oBestTrigger)) {
if (GetTransitionTarget(oBestTrigger) == oTargetArea) {
return oBestTrigger;
}
}
if (GetIsObjectValid(oBestDoor))
return oBestDoor;
if (GetIsObjectValid(oBestTrigger))
return oBestTrigger;
return GetNearestExit(oTarget);
}
// Transport a player and his/her associates to a waypoint.
// This does NOT transport the rest of the player's party,
// only their henchman, summoned, dominated, etc.
void TransportToWaypoint(object oPC, object oWaypoint)
{
if (!GetIsObjectValid(oWaypoint)) {
return;
}
TransportToLocation(oPC, GetLocation(oWaypoint));
}
// Transport a player and his/her associates to a location.
// This does NOT transport the rest of the player's party,
// only their henchman, summoned, dominated, etc.
void TransportToLocation(object oPC, location oLoc)
{
// Jump the PC
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, JumpToLocation(oLoc));
// Not a PC, so has no associates
if (!GetIsPC(oPC))
return;
// Get all the possible associates of this PC
object oHench = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC);
object oDomin = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
object oFamil = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
object oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
object oAnimalComp = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
// Jump any associates
if (GetIsObjectValid(oHench)) {
AssignCommand(oHench, ClearAllActions());
AssignCommand(oHench, JumpToLocation(oLoc));
}
if (GetIsObjectValid(oDomin)) {
AssignCommand(oDomin, ClearAllActions());
AssignCommand(oDomin, JumpToLocation(oLoc));
}
if (GetIsObjectValid(oFamil)) {
AssignCommand(oFamil, ClearAllActions());
AssignCommand(oFamil, JumpToLocation(oLoc));
}
if (GetIsObjectValid(oSummon)) {
AssignCommand(oSummon, ClearAllActions());
AssignCommand(oSummon, JumpToLocation(oLoc));
}
if (GetIsObjectValid(oAnimalComp)) {
AssignCommand(oAnimalComp, ClearAllActions());
AssignCommand(oAnimalComp, JumpToLocation(oLoc));
}
}
// Transport an entire party with all associates to a waypoint.
void TransportAllToWaypoint(object oPC, object oWaypoint)
{
if (!GetIsObjectValid(oWaypoint)) {
return;
}
TransportAllToLocation(oPC, GetLocation(oWaypoint));
}
// Transport an entire party with all associates to a location.
void TransportAllToLocation(object oPC, location lLoc)
{
object oPartyMem = GetFirstFactionMember(oPC, TRUE);
while (GetIsObjectValid(oPartyMem)) {
TransportToLocation(oPartyMem, lLoc);
oPartyMem = GetNextFactionMember(oPC, TRUE);
}
TransportToLocation(oPC, lLoc);
}