//::////////////////////////////////////////////////// //:: 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); }