All pastes #236525 Raw Edit

Anonymous

public text v1 · immutable
·published 2006-11-03 21:13 UTC
rendered paste body
#define NAVIGATION_NONE 0
#define NAVIGATION_ZONE_CHANGED 1
#define NAVIGATION_PLOT 2
#define NAVIGATION_HOP 3
#define NAVIGATION_ARRIVED 4

#define NAVIGATION_DIRECT 0
#define NAVIGATION_MAP 1

#define NAVIGATION_GROW_LIMIT 50
#define NAVIGATION_GROW_Z_LIMIT 2

/*
 * Events:
 * REGION_ADDED [regionname]
 */

objectdef oNavigation inherits oBase
{
	variable string ConfigDir = "c:/program files/innerspace/scripts/etc/"
	variable string ConfigFile = "map.xml"
	variable int CurrentState = 0
	variable int PreviousState = 0

	variable int NavigationStart

	variable int CurrentMethod
	variable int CurrentHop
	variable lnavpath CurrentPath
	variable lnavregionref CurrentZone
	variable lnavregionref CurrentRegion
	variable point3f CurrentDestination
	variable lnavregionref PreviousRegion


        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 "Instance"
        }

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

                LavishNav.Tree:AddChild[universe,Azeroth,-unique]

		LNavRegion[Azeroth]:AddChild[universe,"Instance",-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
                }
        }

	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}]
	}

	/*
	 *
	 */

	member Arrived()
	{	
		switch ${This.CurrentMethod}
		{
			case NAVIGATION_MAP
				if ${This.CurrentHop} < ${This.CurrentPath.Hops}
				{
					return FALSE
				}
				break
			case NAVIGATION_DIRECT
				if ${Math.Distance[${Me.X},${Me.Y},${Me.Z},${This.CurrentDestination.X},${This.CurrentDestination.Y},${This.CurrentDestination.Z}]} < 5
				{
					return FALSE
				}
				break
		}
		return TRUE
	}

	member State()
	{
		if (${This.CurrentZone.ID} != ${LNavRegion[${This.ZoneText}].ID})
		{
			return NAVIGATION_ZONE_CHANGED
		}

		if (${This.CurrentZone.ID} == ${This.CurrentRegion.ID}) 
		{
			return NAVIGATION_PLOT
		}
	
		if !${This.Arrived} && !${Motion.NeedMotion}
		{
			return NAVIGATION_HOP
		}
		else
		{
			return NAVIGATION_ARRIVED
		}

		return NAVIGATION_NONE
	}

	method Pulse()
	{
		This.PreviousRegion:SetRegion[${This.CurrentRegion.ID}]
		This.CurrentRegion:SetRegion[${This.CurrentZone.BestContainer[${Me.X},${Me.Y},${Me.Z}].ID}]

		This.CurrentState:Set[${This.State}]
		if ${This.CurrentState} != ${This.PreviousState}
		{
			This.PreviousState:Set[${CurrentState}]
			This:OnStateChange
		}

		switch ${This.CurrentState}
		{
			case NAVIGATION_ZONE_CHANGED
				This:ZoneChanged
				break
			case NAVIGATION_PLOT
				This:PlotBox
				break
			case NAVIGATION_HOP
				This:MakeHop
				break
			case NAVIGATION_ARRIVED
				This:OnArrived
				break
			case NAVIGATION_NONE
				break
		}

		This:MapObjects
	}

	method OnStateChange()
	{
	}

	method OnArrived()
	{
	}

	/*
	 * Mapping stuff
	 */

	member IsMapped(float X, float Y, float Z)
	{
		variable lnavregionref Container
		
		Container:SetRegion[${This.CurrentZone.BestContainer[${X},${Y},${Z}].FQN}]
		if !${Container.Contains[${X},${Y},${Z}]}
		{
			return FALSE
		}
		
		return TRUE
	}
	 
	method MapObject(string ObjectName, string GroupName)
	{
		variable objectref Obj

		if !${Object[${ObjectName}](exists)}
		{
			return
		}
		
		Obj:Set[${Object[${ObjectName}].GUID}]
		
		if !${LNavRegion[${ObjectName}].FQN(exists)}
		{
			if !${This.IsMapped[${Obj.X},${Obj.Y},${Obj.Z}]}
			{
				This:Debug["Found ${ObjectName} but could not map it since ground has not been discovered yet."]
				return
			}
			
			This:PlotPoint["${ObjectName}",${Obj.X},${Obj.Y},${Obj.Z}]
			LNavRegionGroup[${GroupName}]:Add[${ObjectName}]
		}
	}
	 
	method MapObjects()
	{
		This:MapObject[Silverwing Flag,"Warsong Gulch Flag"]
		This:MapObject[Warsong Flag,"Warsong Gulch Flag"]
	}
	 
	method PlotPoint(string PointName, float X, float Y, float Z)
	{
		CurrentZone:AddChild[point,${PointName},-unique,${X},${Y},${Z}]
		Event["REGION_ADDED"]:Execute[${PointName}]
		This:Debug["Region added (${PointName}@${CurrentZone.FQN}) (X: ${X} Y: ${Y} Z: ${Z})"]
	}
	 
	method PlotBox()
	{
		variable float X1
		variable float X2
		variable float Y1
		variable float Y2
		variable float Z1
		variable float Z2
		variable string RegionName

		X1:Set[${Me.X}]
		X2:Set[${Me.X}]
		Y1:Set[${Me.Y}]
		Y2:Set[${Me.Y}]
		Z1:Set[${Math.Calc[${Me.Z} + 0.2]}]
		Z2:Set[${Math.Calc[${Me.Z} + 0.4]}]
		
		do
		{
			X1:Dec
			X2:Inc
			Y1:Dec
			Y2:Inc
		} 
		while ${This.IsCollisionFree[${X1},${Y1},${X2},${Y2},${Z1},FALSE]} && ${Math.Distance[${Me.X},${X1}]} < NAVIGATION_GROW_LIMIT

		do
		{
			Z1:Dec
		}
		while ${This.IsCollisionFree[${X1},${Y1},${X2},${Y2},${Z1},FALSE]} && ${Math.Distance[${Me.Z},${Z1}]} < NAVIGATION_GROW_Z_LIMIT

		do
		{
			Z2:Inc
		}
		while ${This.IsCollisionFree[${X1},${Y1},${X2},${Y2},${Z2},FALSE]} && ${Math.Distance[${Me.Z},${Z2}]} < NAVIGATION_GROW_Z_LIMIT

		Z1:Set[${Math.Calc[${Z1} - 0.5]}]
		Z2:Set[${Math.Calc[${Z2} + 0.5]}]
		
		RegionName:Set["R${Time.Timestamp}${CurrentZone.ChildCount}"]
		CurrentZone:AddChild[box,${RegionName},-unique,${X1},${X2},${Y1},${Y2},${Z1},${Z2}]
		This:Debug["Region added (${RegionName}@${CurrentZone.FQN}) (X: ${Math.Distance[${X1}, ${X2}]}, Y: ${Math.Distance[${Y1},${Y2}]}, Z: ${Math.Distance[${Z1},${Z2}]})"]
		Event["REGION_ADDED"]:Execute[${RegionName}]
		This:ConnectNeighbours[${RegionName}]
	}

	method ConnectNeighbours(string RegionName)
	{
		variable index:lnavregionref SurroundingRegions
		variable lnavregionref Region
		variable int RegionsFound
		variable int Index = 1

		Region:SetRegion[${RegionName}]
		RegionsFound:Set[${CurrentZone.DescendantsWithin[SurroundingRegions,${Math.Calc[(NAVIGATION_GROW_LIMIT * 2) + 5]},${Region.CenterPoint.X},${Region.CenterPoint.Y},${Region.CenterPoint.Z}]}]

		if ${RegionsFound} > 0
		{
			do
			{
				if ${This.ShouldConnect[${Region.FQN},${SurroundingRegions.Get[${Index}].FQN}]}
				{
					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)}
		}
	}

	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.CollisionTest[${RegionRefA.CenterPoint.X}, ${RegionRefA.CenterPoint.Y}, ${RegionRefA.CenterPoint.Z}, ${RegionRefB.CenterPoint.X}, ${RegionRefB.CenterPoint.Y}, ${RegionRefB.CenterPoint.Z}]}
		{
			return FALSE
		}
	
		if ${This.RegionsIntersect[${RegionA},${RegionB}]} || ${This.RegionsIntersect[${RegionB},${RegionA}]}
		{
			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 IsCollisionFree(float X1, float Y1, float X2, float Y2, float Z, bool Contents=TRUE)
	{
		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},${Z},${X2},${Y2},${Z}]}
			{
				return FALSE
			}

			if ${This.CollisionTest[${X1},${Y2},${Z},${X2},${Y1},${Z}]}
			{
				return FALSE
			}

			if ${This.CollisionTest[${MiddleX},${Y1},${Z},${MiddleX},${Y2},${Z}]}
			{
				return FALSE
			}

			if ${This.CollisionTest[${X1},${MiddleY},${Z},${X2},${MiddleY},${Z}]}
			{
				return FALSE
			}
		}

		if ${This.CollisionTest[${X1},${Y1},${Z},${X2},${Y1},${Z}]}
		{
			return FALSE
		}

		if ${This.CollisionTest[${X1},${Y2},${Z},${X2},${Y2},${Z}]}
		{
			return FALSE
		}

		if ${This.CollisionTest[${X1},${Y1},${Z},${X1},${Y2},${Z}]}
		{
			return FALSE
		}

		if ${This.CollisionTest[${X2},${Y1},${Z},${X2},${Y2},${Z}]}
		{
			return FALSE
		}

		return TRUE
	}

	member CollisionTest(float FromX, float FromY, float FromZ, float ToX, float ToY, float ToZ)
	{
		return ${Me.IsPathObstructed[${ToX},${ToY},${ToZ},999,${FromX}, ${FromY}, ${FromZ}]}
	}

	/*
	 * Pathfinding
	 */
	
	member NearestRegion(float X, float Y, float Z)
	{
		return ${This.CurrentZone.NearestChild[${X},${Y},${Z}].FQN}
	}

	member FindPath(float X, float Y, float Z)
	{
		variable lnavregionref DestinationRegion
		variable dijkstrapathfinder PathFinder
		
		This.CurrentHop:Set[1]
		This.CurrentDestination.X:Set[${X}]
		This.CurrentDestination.Y:Set[${Y}]
		This.CurrentDestination.Z:Set[${Z}]
		This.CurrentPath:Clear
		DestinationRegion:SetRegion[${This.NearestRegion[${X},${Y},${Z}]}]
		PathFinder:SelectPath[${This.CurrentRegion.FQN},${DestinationRegion.FQN},This.CurrentPath]

		if (${This.CurrentPath.Hops} == 0)
		{
			return FALSE
		}
		
		return TRUE
	}

	method NavigateTo(float X, float Y, float Z)
	{
		This.NavigationStart:Set[${LavishScript.RunningTime}]

		if !${This.FindPath[${X},${Y},${Z}]}
		{
			This.CurrentMethod:Set[NAVIGATION_DIRECT]
			This:Debug["Navigating to ${X} ${Y} ${Z} using direct path."]
		}
		else
		{
			This.CurrentMethod:Set[NAVIGATION_MAP]
			This:Debug["Navigating to ${X} ${Y} ${Z} using navigation map."]
		}
		Motion:MoveTo[${CurrentDestination.X},${CurrentDestination.Y},${CurrentDestination.Z}]
	}

	method MakeHop()
	{
		variable point3f DestinationPoint

		switch ${This.CurrentMethod}
		{
			case NAVIGATION_MAP
				;FIXME! Randomize region movement since we use ffm region
				DestinationPoint.X:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.X}]
				DestinationPoint.Y:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.Y}]
				DestinationPoint.Z:Set[${This.CurrentPath.Region[${This.CurrentHop}].CenterPoint.Z}]
				This.CurrentHop:Inc
				break
			case NAVIGATION_DIRECT
				DestinationPoint.X:Set[${This.CurrentDestination.X}]
				DestinationPoint.Y:Set[${This.CurrentDestination.Y}]
				DestinationPoint.Z:Set[${This.CurrentDestination.Z}]
				break
		}

		;FIXME! Moveto DestinationPoint
		Motion:MoveTo[${DestinationPoint.X},${DestinationPoint.Y},${DestinationPoint.Z}]
	}

	/*
	 *
	 */
	 
	method Initialize()
	{
		LavishScript:RegisterEvent["REGION_ADDED"]
		This:Load
		This:ZoneChanged
	}

	method Shutdown()
	{
		Event["REGION_ADDED"]:Unregister
		This:Save
	}
}