All pastes #249565 Raw Edit

Unnamed

public text v1 · immutable
#249565 ·published 2006-11-15 22:39 UTC
rendered paste body
;
; Fix better connection after zone change (see zonechanged method)
;

#define NAVIGATE_NONE 0
#define NAVIGATION_ZONECHANGED 1
#define NAVIGATION_PLOT 2
#define NAVIGATION_FACING 3
#define NAVIGATION_MOTION 4
#define NAVIGATION_ARRIVED 5
#define NAVIGATION_OBJECTSCAN 6

#define NAVIGATION_GROW_LIMIT 16
#define NAVIGATION_PERCISION 5
#define NAVIGATION_TELEPORT_LIMIT 10

objectdef oNavigate inherits oBase
{
	variable string ConfigDir = "c:/program files/innerspace/scripts/bytebot/etc/"
	variable string ConfigFile = "map.xml"

	variable int LastObjectScan = 0
	
	variable point3f FinalDestination
	variable point3f CurrentDestination
	variable point3f LastPosition
	variable lnavregionref CurrentZone
	variable lnavregionref CurrentRegion
	variable lnavregionref PreviousRegion
	variable lnavpath CurrentPath
	variable int CurrentHop
	
        member SubZoneText()
        {
                return ${WoWScript[GetMinimapZoneText()]}
        }

        member ZoneText()
        {
                return ${WoWScript[GetRealZoneText()]}
        }

        member Continent()
        {
                WoWScript SetMapToCurrentZone()
		if ${WoWScript[GetMapContinents(),${WoWScript[GetCurrentMapContinent()]}](exists)}
		{
			return ${WoWScript[GetMapContinents(),${WoWScript[GetCurrentMapContinent()]}]}
		}
		return "Unknown"
        }

        method InitializeRegions()
        {
                variable string Continent
                variable int IdxContinent
                variable string Zone
                variable int IdxZone

		This:Echo["Generating empty map file."]
		
                LavishNav.Tree:AddChild[universe,Azeroth,-unique]

		LNavRegion[Azeroth]:AddChild[universe,"Unknown",-unique,-coordinatesystem]
                IdxContinent:Set[1]
                do
                {
                        Continent:Set[${WoWScript[GetMapContinents(),${IdxContinent}]}]
                        LNavRegion[Azeroth]:AddChild[universe,${This.Continent},-unique,-coordinatesystem]
                        IdxZone:Set[1]
                        do
                        {
                                Zone:Set[${WoWScript[GetMapZones(${IdxContinent}),${IdxZone}]}]
                                LNavRegion[${This.Continent}]:AddChild[universe,${Zone},-unique]
                                IdxZone:Inc
                        }
                        while ${WoWScript[GetMapZones(${IdxContinent}),${IdxZone}](exists)}
                        IdxContinent:Inc
                }
                while ${WoWScript[GetMapContinents(),${IdxContinent}](exists)}

        }

        method Save()
        {
                LNavRegion[Azeroth]:Export["${ConfigDir}${ConfigFile}"]
        }

        method Load()
        {
                variable filepath Dir = "${ConfigDir}"
                LavishNav:Clear

                if ${Dir.FileExists[${ConfigFile}]}
                {
                        if ${LNavRegion[Azeroth](exists)}
                        {
                                LNavRegion[Azeroth]:Remove
                        }
                        LavishNav:Import["${ConfigDir}${ConfigFile}"]
                }

                if !${LNavRegion[Azeroth](exists)}
                {
                        This:InitializeRegions
                        This:Save
                }
        }
	
	member MeX()
	{
		return ${Me.X}
	}
	
	member MeY()
	{
		return ${Me.Y}
	}
	
	member MeZ()
	{
		return ${Math.Calc[${Me.Z} + (${Me.Height} / 2)]}
	}
	
	method ZoneChanged()
	{
		variable string Region
		This:Debug["Zone changed to ${This.ZoneText}"]
		if !${LNavRegion[${This.ZoneText}](exists)}
		{
			LNavRegion[${This.Continent}]:AddChild[universe,${This.ZoneText},-unique]
		}

		CurrentZone:SetRegion[${LNavRegion[${This.ZoneText}].FQN}]
		This.CurrentRegion:SetRegion[${This.CurrentZone.BestContainer[${This.MeX},${This.MeY},${This.MeZ}].ID}]
		
		if !${Me.Dead} && !${Me.Buff[Ghost](exists)} && !${Me.Flying}
		{
			This.CurrentRegion:Connect[${This.PreviousRegion.FQN}]
		}
		
		Event[NAVIGATION_ZONECHANGED]:Execute
	}

	member Facing()
	{
		return ${ISXWoW.Facing} 
	}
	
	member Container(float X, float Y, float Z)
	{
		variable lnavregionref PointContainer
		PointContainer:SetRegion[${CurrentZone.NearestChild[${X},${Y},${Z}].FQN}]

		if ${PointContainer.Type.Equal[point]}
		{
			PointContainer:SetRegion[${PointContainer.Parent.FQN}]
		}
		return ${PointContainer.FQN}
	}
	
	
	member NeedPlot()
	{
		if ${Me.Flying} || !${Me(exists)}
		{
			return FALSE
		}
		
		if ${This.CurrentZone.ID} != ${This.CurrentRegion.ID}
		{
			return FALSE
		}
		return TRUE
	}

	method PlotObject(string ObjectGUID, string GroupName="")
	{
		variable objectref TargetObject
		if !${Object[${ObjectGUID}].GUID(exists)}
		{
			return
		}
		
		TargetObject:Set[${ObjectGUID}]
		This:PlotPoint[${TargetObject.Name},${TargetObject.X},${TargetObject.Y},${TargetObject.Z},${GroupName}]
	}
	
	method PlotPoint(string PointName, float X, float Y, float Z, string GroupName="")
	{
		This.CurrentZone:AddChild[point, ${PointName}, -unique, ${X}, ${Y}, ${Math.Calc[${Z} + (${Me.Height} / 2)]}]
		if ${GroupName.NotEqual[""]}
		{
			LNavRegionGroup[${GroupName}]:Add[${PointName}]
		}
		This:Debug["Added ${PointName} X: ${X} Y: ${Y} Z: ${Z}"]
	}
	
	method Plot()
	{
		variable point3f C1
		variable point3f C2
		variable string PointName

		C1.X:Set[${This.MeX}]
		C1.Y:Set[${This.MeY}]
		C1.Z:Set[${Me.Z} + 0.3]
		
		C2.X:Set[${This.MeX}]
		C2.Y:Set[${This.MeY}]
		C2.Z:Set[${Math.Calc[${Me.Z} + ${Me.Height}]}]
		
		do
		{
			C1.X:Dec
			C2.X:Inc
			C1.Y:Dec
			C2.Y:Inc
		}
		while !${This.BoxObstructed[${C1.X},${C1.Y},${C1.Z},${C2.X},${C2.Y},${C2.Z},FALSE]} && ${Math.Distance[${C1.X},${C2.X}]} < NAVIGATION_GROW_LIMIT 

		C1.X:Inc
		C2.X:Dec
		C1.Y:Inc
		C2.Y:Dec

		C1.Z:Set[${Me.Z}]
		
		if ${Math.Distance[${C1.X},${C2.X}]} > 0
		{
			PointName:Set["R${Time.Timestamp}${This.CurrentZone.ChildCount}"]
			This.CurrentZone:AddChild[box, ${PointName}, -unique, ${C1.X}, ${C2.X}, ${C1.Y}, ${C2.Y}, ${C1.Z}, ${C2.Z}]
			This:Debug["Added ${PointName} X: ${Math.Distance[${C1.X},${C2.X}]} Y: ${Math.Distance[${C1.Y},${C2.Y}]}"]
			This:ConnectNeighbours[${PointName}]
		}
	}
	
	member BoxObstructed(float X1, float Y1, float Z1, float X2, float Y2, float Z2, bool Contents = FALSE)
	{
		variable float MiddleX
		variable float MiddleY

		if ${Contents}
		{
			if ${X1} > ${X2}
			{
				MiddleX:Set[${Math.Calc[(${X1} - ${X2}) / 2]}]
				MiddleX:Set[${Math.Calc[${MiddleX} + ${X2}]}]
			} 
			else
			{
				MiddleX:Set[${Math.Calc[(${X2} - ${X1}) / 2]}]
				MiddleX:Set[${Math.Calc[${MiddleX} + ${X1}]}]
			}

			if ${Y1} > ${Y2}
			{
				MiddleY:Set[${Math.Calc[(${Y1} - ${Y2}) / 2]}]
				MiddleY:Set[${Math.Calc[${MiddleY} + ${Y2}]}]
			}
			else
			{
				MiddleY:Set[${Math.Calc[(${Y2} - ${Y1}) / 2]}]
				MiddleY:Set[${Math.Calc[${MiddleY} + ${Y1}]}]
			}

			if ${This.CollisionTest[${X1},${Y1},${Z1},${X2},${Y2},${Z2}]}
			{
				return TRUE
			}

			if ${This.CollisionTest[${X1},${Y2},${Z1},${X2},${Y1},${Z2}]}
			{
				return TRUE
			}

			if ${This.CollisionTest[${MiddleX},${Y1},${Z1},${MiddleX},${Y2},${Z2}]}
			{
				return TRUE
			}

			if ${This.CollisionTest[${X1},${MiddleY},${Z1},${X2},${MiddleY},${Z2}]}
			{
				return TRUE
			}
		}

		if ${This.CollisionTest[${X1},${Y1},${Z1},${X2},${Y1},${Z2}]}
		{
			return TRUE
		}

		if ${This.CollisionTest[${X1},${Y2},${Z1},${X2},${Y2},${Z2}]}
		{
			return TRUE
		}

		if ${This.CollisionTest[${X1},${Y1},${Z1},${X1},${Y2},${Z2}]}
		{
			return TRUE
		}

		if ${This.CollisionTest[${X2},${Y1},${Z1},${X2},${Y2},${Z2}]}
		{
			return TRUE
		}

		return FALSE
	}
	
	method ConnectNeighbours(string RegionName)
	{
		variable index:lnavregionref SurroundingRegions
		variable lnavregionref Region
		variable int RegionsFound
		variable int Index = 1
		variable int Count = 0
		
		Region:SetRegion[${RegionName}]
		RegionsFound:Set[${CurrentZone.DescendantsWithin[SurroundingRegions,${Math.Calc[(NAVIGATION_GROW_LIMIT) + 5]},${Region.CenterPoint.X},${Region.CenterPoint.Y},${Region.CenterPoint.Z}]}]

		if ${RegionsFound} > 0
		{
			do
			{
				if ${This.ShouldConnect[${Region.FQN},${SurroundingRegions.Get[${Index}].FQN}]}
				{
					Count:Inc
					Region:Connect[${SurroundingRegions.Get[${Index}].FQN}]
					SurroundingRegions.Get[${Index}]:Connect[${Region.FQN}]
					This:Debug["Connecting ${Region.FQN} to ${SurroundingRegions.Get[${Index}].FQN}"]
				}
			}
			while ${SurroundingRegions.Get[${Index:Inc}](exists)}
		}
		
		if ${Count} == 0
		{
			This:Debug["${Region.FQN} has no connections! possible gap in nav bla burp uhgh!"]
		}
	}

	member ShouldConnect(string RegionA, string RegionB)
	{
		variable lnavregionref RegionRefA
		variable lnavregionref RegionRefB
		
		if ${RegionA.Equal[${RegionB}]}
		{
			return FALSE
		}
	
		RegionRefA:SetRegion[${RegionA}]
		RegionRefB:SetRegion[${RegionB}]
		
		if ${This.RegionsObstructed[${RegionA},${RegionB}]}
		{
			return FALSE
		}
		
		if ${This.RegionsIntersect[${RegionA},${RegionB}]} || ${This.RegionsIntersect[${RegionB},${RegionA}]}
		{
			return TRUE
		}
		return FALSE
	}

	member RegionsObstructed(string RegionA, string RegionB)
	{
		variable lnavregionref RegionRefA
		variable lnavregionref RegionRefB
		variable int Side = 0
		
		if ${RegionA.Equal[${RegionB}]}
		{
			return FALSE
		}

		RegionRefA:SetRegion[${RegionA}]
		RegionRefB:SetRegion[${RegionB}]

		if ${RegionRefA.Type.NotEqual["Box"]} || ${RegionRefB.Type.NotEqual["Box"]}
		{
			return TRUE
		}
		
		if ${This.CollisionTest[${RegionRefA.X1},${RegionRefA.Y1},${RegionRefA.CenterPoint.Z},${RegionRefB.X1},${RegionRefB.Y1},${RegionRefB.CenterPoint.Z}]}
		{
			return TRUE
		}

		if ${This.CollisionTest[${RegionRefA.X2},${RegionRefA.Y1},${RegionRefA.CenterPoint.Z},${RegionRefB.X2},${RegionRefB.Y1},${RegionRefB.CenterPoint.Z}]}
		{
			return TRUE
		}

		if ${This.CollisionTest[${RegionRefA.X1},${RegionRefA.Y2},${RegionRefA.CenterPoint.Z},${RegionRefB.X1},${RegionRefB.Y2},${RegionRefB.CenterPoint.Z}]}
		{
			return TRUE
		}

		if ${This.CollisionTest[${RegionRefA.X2},${RegionRefA.Y2},${RegionRefA.CenterPoint.Z},${RegionRefB.X2},${RegionRefB.Y2},${RegionRefB.CenterPoint.Z}]}
		{
			return TRUE
		}
		
		return FALSE
	}
	
	member RegionsIntersect(string RegionA, string RegionB)
	{
		variable point3f P1
		variable point3f P2
		variable point3f P3
		variable point3f P4
		variable point3f P5
		variable point3f P6
		variable point3f P7
		variable point3f P8

		variable lnavregionref RA
		variable lnavregionref RB

		RA:SetRegion[${RegionA}]
		RB:SetRegion[${RegionB}]

		if ${RA.Type.NotEqual["Box"]} || ${RB.Type.NotEqual["Box"]}
		{
			return FALSE
		}

		P1.X:Set[${RB.X1}]
		P1.Y:Set[${RB.Y1}]
		P1.Z:Set[${RB.Z1}]
		P2.X:Set[${RB.X2}]
		P2.Y:Set[${RB.Y1}]
		P2.Z:Set[${RB.Z1}]
		P3.X:Set[${RB.X2}]
		P3.Y:Set[${RB.Y2}]
		P3.Z:Set[${RB.Z1}]
		P4.X:Set[${RB.X1}]
		P4.Y:Set[${RB.Y2}]
		P4.Z:Set[${RB.Z1}]
		P5.X:Set[${RB.X1}]
		P5.Y:Set[${RB.Y1}]
		P5.Z:Set[${RB.Z2}]
		P6.X:Set[${RB.X2}]
		P6.Y:Set[${RB.Y1}]
		P6.Z:Set[${RB.Z2}]
		P7.X:Set[${RB.X2}]
		P7.Y:Set[${RB.Y2}]
		P7.Z:Set[${RB.Z2}]
		P8.X:Set[${RB.X1}]
		P8.Y:Set[${RB.Y2}]
		P8.Z:Set[${RB.Z2}]

		if ${RA.Contains[${P1.X},${P1.Y},${P1.Z}]} || ${RA.Contains[${P2.X},${P2.Y},${P2.Z}]} || ${RA.Contains[${P3.X},${P3.Y},${P3.Z}]} || ${RA.Contains[${P4.X},${P4.Y},${P4.Z}]} || ${RA.Contains[${P5.X},${P5.Y},${P5.Z}]} || ${RA.Contains[${P6.X},${P6.Y},${P6.Z}]} || ${RA.Contains[${P7.X},${P7.Y},${P7.Z}]} || ${RA.Contains[${P8.X},${P8.Y},${P8.Z}]}
		{
			return TRUE
		}

		return FALSE
	}
	
	member DirectionObstructed(float Range)
	{
	;FIXME
		variable point3f DirectionPoint
		variable float Z
		
		Z:Set[${Math.Calc[${This.MeZ} + 0.2]}]
		
		DirectionPoint.X:Set[${Math.Cos[${Me.Heading}]} * ${Range}]
		DirectionPoint.Y:Set[${Math.Sin[${Me.Heading}]} * ${Range}]
		DirectionPoint.Z:Set[${Z}]
		
		return ${This.CollisionTest[${This.MeX},${This.MeY},${Z},${DirectionPoint.X},${DirectionPoint.Y},${Z}]}
	}
	
	member CollisionTest(float FromX, float FromY, float FromZ, float ToX, float ToY, float ToZ)
	{
		return ${Me.IsPathObstructed[${ToX},${ToY},${ToZ},999,${FromX}, ${FromY}, ${FromZ}]}
	}
	
	method PositionCheck()
	{
		if ${Math.Distance[${This.MeX},${This.MeY},${This.MeZ},${This.LastPosition.X},${This.LastPosition.Y},${This.LastPosition.Z}]} > NAVIGATION_TELEPORT_LIMIT
		{
			This:Echo["Teleport detected"]
			Event[NAVIGATION_TELEPORT]:Execute
		}
	}
	
	method SavePosition()
	{
		This.LastPosition.X:Set[${This.MeX}]
		This.LastPosition.Y:Set[${This.MeY}]
		This.LastPosition.Z:Set[${This.MeZ}]
	}
	/*
	 *
	 */

	member Arrived()
	{
		if ${Math.Distance[${This.MeX},${This.MeY},${This.MeZ},${This.FinalDestination.X},${This.FinalDestination.Y},${This.FinalDestination.Z}]} <= NAVIGATION_PERCISION
		{
			return TRUE
		}
	
		return FALSE
	}
	 
	member NeedMotion()
	{
		if ${This.FinalDestination.X} == 0 && ${This.FinalDestination.Y} == 0 && ${This.FinalDestination.Z} == 0
		{
			;We don't have a destination so we don't need motion
			return FALSE
		}

		if ${Math.Distance[${This.MeX},${This.MeY},${This.FinalDestination.X},${This.FinalDestination.Y}]} < NAVIGATION_PERCISION
		{
			;We arrived
			return FALSE
		}
		
		return TRUE
	}

	method FaceXY(float X, float Y)
	{
		Face ${X} ${Y}
	}

	member Moving()
	{
		if (${Movement.Moving} == 0)
		{
			return FALSE
		}
		
		return TRUE
	}

	method MoveToRegionGroup(string GroupName)
	{
		This:MoveToRegion[${This.ClosestRegion[${GroupName}]}]
	}
	
	method MoveToRegion(string RegionName)
	{
		variable lnavregionref Destination
		
		if !${This.RegionExists[${RegionName}]}
		{
			This:Debug["${RegionName} does not exist."]
			return
		}
		
		Destination:SetRegion[${RegionName}]
		This:MoveTo[${Destination.CenterPoint.X},${Destination.CenterPoint.Y},${Destination.CenterPoint.Z}]
	}
	
	method MoveTo(float X, float Y, float Z)
	{
		
		variable dijkstrapathfinder PathFinder

		This.FinalDestination.X:Set[${X}]
		This.FinalDestination.Y:Set[${Y}]
		This.FinalDestination.Z:Set[${Z}]

		This:Debug["MoveTo: ${X} ${Y} ${Z}"]
		
		if !${This.CurrentRegion.FQN(exists)}
		{
			This.CurrentRegion:SetRegion[${This.CurrentZone.BestContainer[${This.MeX},${This.MeY},${This.MeZ}].ID}]
		}
		
		if ${Math.Distance[${This.MeX},${This.MeY},${This.MeZ},${X},${Y},${Z}]} < 50 && !${This.CollisionTest[${This.MeX}, ${This.MeY}, ${This.MeZ}, ${X}, ${Y}, ${Z}]}
		{
			; Just a small distance use direct path
			This.CurrentDestination.X:Set[${X}]
			This.CurrentDestination.Y:Set[${Y}]
			This.CurrentDestination.Z:Set[${Z}]
		}
		else
		{
			This.CurrentHop:Set[1]
			This.CurrentPath:Clear
			PathFinder:SelectPath[${This.CurrentRegion.FQN},${This.Container[${X},${Y},${Z}]},This.CurrentPath]
			
			if ${This.CurrentPath.Hops} != 0
			{
				; We found a path
				This:Debug["Using lavishnav"]
				This.CurrentDestination.X:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.X}]
				This.CurrentDestination.Y:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.Y}]
				This.CurrentDestination.Z:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.Z}]
			}
			else
			{
				; We didn't find a path
				This:Debug["Using direct path"]
				This.CurrentDestination.X:Set[${X}]
				This.CurrentDestination.Y:Set[${Y}]
				This.CurrentDestination.Z:Set[${Z}]
			}
		}
		
		This:FaceXY[${This.CurrentDestination.X}, ${This.CurrentDestination.Y}]
	}

	method Stop()
	{
		move -stop
		face -stop
	}
	
	method ResetDestination()
	{
		This.FinalDestination.X:Set[0]
		This.FinalDestination.Y:Set[0]
		This.FinalDestination.Z:Set[0]
		This.CurrentHop:Set[1]
		This:Stop
	}
	
	method CheckMotion()
	{
		variable int HeadingDiff

		if !${This.Moving} && !${Math.Distance[${This.MeX},${This.MeY},${This.MeZ},${This.CurrentDestination.X},${This.CurrentDestination.Y},${This.CurrentDestination.Z}]} <= NAVIGATION_PERCISION
		{
			wowpress -hold moveforward
		}
		
		if ${This.DirectionObstructed[5]}
		{
			This:Debug["Going to collide!!!"]
			;[FIXME] dynamic collision adjusting
		}

		if ${Math.Distance[${This.MeX},${This.MeY},${This.MeZ},${This.CurrentDestination.X},${This.CurrentDestination.Y},${This.CurrentDestination.Z}]} <= NAVIGATION_PERCISION
		{
			This.CurrentHop:Inc
			if ${This.CurrentPath.Region[${This.CurrentHop}](exists)}
			{
				This.CurrentDestination.X:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.X}]
				This.CurrentDestination.Y:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.Y}]
				This.CurrentDestination.Z:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.Z}]
			}
			
			if ${This.CurrentHop} >= ${This.CurrentPath.Hops}
			{
				This.CurrentDestination.X:Set[${This.FinalDestination.X}]
				This.CurrentDestination.Y:Set[${This.FinalDestination.Y}]
				This.CurrentDestination.Z:Set[${This.FinalDestination.Z}]
			}
		}
		
		HeadingDiff:Set[${Math.Abs[${Me.Heading} - ${Me.HeadingTo[${This.CurrentDestination.X},${This.CurrentDestination.Y}]}]}]
		if ${HeadingDiff} > 30 && ${Math.Distance[${This.MeX},${This.MeY},${This.MeZ},${This.CurrentDestination.X},${This.CurrentDestination.Y},${This.CurrentDestination.Z}]} > NAVIGATION_PERCISION
		{
			This:FaceXY[${CurrentDestination.X},${CurrentDestination.Y}]
		}
	}
	
	member RegionDistance(string RegionName)
	{
		variable lnavregionref TargetRegion
		
		if !${This.RegionExists[${RegionName}]}
		{
			This:Debug["${RegionName} doesn't exist."]
			return -1
		}
		
		TargetRegion:SetRegion[${RegionName}]
		return ${Math.Distance[${This.MeX},${This.MeY},${TargetRegion.CenterPoint.X},${TargetRegion.CenterPoint.Y}]}
	}

	member ClosestRegion(string GroupName)
	{
		variable int Total

		Total:Set[${LNavRegionGroup[${GroupName}].Size}]
		if ${Total}
		{
			return ${LNavRegionGroup[${GroupName}].NearestRegion[${This.MeX},${This.MeY},${This.MeZ}].FQN}
		}
		return ""
	}
	
	member RandomRegion(string GroupName)
	{
		variable int Total
		variable int Current
		variable int TargetGroup
		variable iterator GroupIterator
		
		Current:Set[1]
		Total:Set[${LNavRegionGroup[${GroupName}].Size}]
		if ${Total}
		{
			TargetGroup:Set[${Math.Rand[${Total}]} + 1]
			LNavRegionGroup[${GroupName}]:GetIterator[GroupIterator]
			if ${GroupIterator:First(exists)}
			{
				do
				{
					if ${Current} == ${TargetGroup}
					{
						return ${GroupIterator.Key}
					}
					Current:Inc
				}
				while ${GroupIterator:Next(exists)}
			}
		}
		return ""
	}
	
	member RegionExists(string RegionName)
	{
		return ${LNavRegion[${RegionName}].FQN(exists)}
	}
	
	method PlotGameObject(string ObjectName, string GroupName="")
	{
		if !${This.RegionExists["${ObjectName}"]} && ${Object["${ObjectName}"](exists)}
		{
			This:PlotObject[${Object[${ObjectName}].GUID}, ${GroupName}]
		}
	}
	
	method ObjectScan()
	{
		This.LastObjectScan:Set[${LavishScript.RunningTime}]

		This:PlotGameObject["Silverwing Flag","Warsong Flag"]
	}
	
	/*
	 *
	 */
	
	member State()
	{
		if (${This.CurrentZone.ID} != ${LNavRegion[${This.ZoneText}].ID})
		{
			return NAVIGATION_ZONECHANGED
		}

		if ${This.NeedPlot}
		{
			return NAVIGATION_PLOT
		}

		if ${Math.Calc[${LavishScript.RunningTime} - ${This.LastObjectScan}]} > 2000
		{
			return NAVIGATION_OBJECTSCAN
		}
		
		if ${This.Arrived}
		{
			return NAVIGATION_ARRIVED
		}

		if ${ISXWoW.Facing}
		{
			return NAVIGATION_FACING
		}
	
		if ${This.NeedMotion}
		{
			return NAVIGATION_MOTION
		}
		
		return NAVIGATE_NONE
	}

	method Pulse(int Priority)
	{
		if !${Me(exists)}
		{
			This:ResetDestination
			return
		}

		This:PositionCheck
		This:SavePosition
		
		This.CurrentState:Set[${This.State}]
		This.CurrentRegion:SetRegion[${This.CurrentZone.BestContainer[${This.MeX},${This.MeY},${This.MeZ}].ID}]
		
		if ${This.PreviousRegion.ID} != ${This.CurrentRegion.ID}
		{
			This.PreviousRegion:SetRegion[${This.CurrentRegion.FQN}]
		}

		switch ${This.CurrentState}
		{
			case NAVIGATION_ZONECHANGED
				This:ZoneChanged
				break
			case NAVIGATION_FACING
				break
			case NAVIGATION_PLOT
				This:Plot
				break
			case NAVIGATION_OBJECTSCAN
				This:ObjectScan
				break
			case NAVIGATION_MOTION
				This:CheckMotion
				break
			case NAVIGATION_ARRIVED
				This:Debug["Arrived at destination"]
				This:ResetDestination
				break
			case NAVIGATE_NONE
				break
		}
	}

	method Plugin()
	{
		Event[CORE_EVENT_PULSE]:AttachAtom[${This.ObjectName}:Pulse]
		LavishScript:RegisterEvent[NAVIGATION_PLOTPOINT]
		LavishScript:RegisterEvent[NAVIGATION_ZONECHANGED]
		LavishScript:RegisterEvent[NAVIGATION_TELEPORT]
		LavishScript:RegisterEvent[NAVIGATION_MOVETO]

		Event[NAVIGATION_PLOTPOINT]:AttachAtom[${This.ObjectName}:PlotPoint]
		Event[NAVIGATION_MOVETO]:AttachAtom[${This.ObjectName}:MoveTo]
	}
	
	method Initialize()
	{
		This:Load
		This:ZoneChanged
		This:SavePosition
		This:ObjectScan
	}
	
	method Shutdown()
	{
		Event[CORE_EVENT_PULSE]:DetachAtom[${This.ObjectName}:Pulse]
		Event[NAVIGATION_PLOTPOINT]:DetachAtom[${This.ObjectName}:PlotPoint]
		Event[NAVIGATION_ZONECHANGED]:Unregister
		Event[NAVIGATION_PLOTPOINT]:Unregister
		Event[NAVIGATION_TELEPORT]:Unregister
		Event[NAVIGATION_MOVETO]:Unregister
		This:Save
	}
	
}