All pastes #247337 Raw Edit

Someone

public text v1 · immutable
#247337 ·published 2006-11-13 10:19 UTC
rendered paste body
#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 50
#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 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
                }
        }
	
	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}]
		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}, ${Z}]
		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[${Me.X}]
		C1.Y:Set[${Me.Y}]
		C1.Z:Set[${Math.Calc[${Me.Z} + 0.3]}]
		
		C2.X:Set[${Me.X}]
		C2.Y:Set[${Me.Y}]
		C2.Z:Set[${Math.Calc[${Me.Z} + 1]}]
		
		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} - 1]
		
		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

		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}]}
				{
					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 DirectionObstructed(float Range)
	{
		variable point3f DirectionPoint
		variable float Z
		
		Z:Set[${Math.Calc[${Me.Z} + 0.2]}]
		
		DirectionPoint.X:Set[${Math.Cos[${Me.Heading}]} * ${Range}]
		DirectionPoint.Y:Set[${Math.Cos[${Me.Heading}]} * ${Range}]
		DirectionPoint.Z:Set[${Z}]
		
		return ${This.CollisionTest[${Me.X},${Me.Y},${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[${Me.X},${Me.Y},${Me.Z},${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[${Me.X}]
		This.LastPosition.Y:Set[${Me.Y}]
		This.LastPosition.Z:Set[${Me.Z}]
	}
	/*
	 *
	 */

	member Arrived()
	{
		if ${Math.Distance[${Me.X},${Me.Y},${Me.Z},${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
		{
			return FALSE
		}

		if ${Math.Distance[${Me.X},${Me.Y},${This.FinalDestination.X},${This.FinalDestination.Y}]} > NAVIGATION_PERCISION
		{
			return TRUE
		}
		
		return FALSE
	}

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

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

	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[${Me.X},${Me.Y},${Me.Z}].ID}]
		}
		
		if ${Math.Distance[${Me.X},${Me.Y},${Me.Z},${X},${Y},${Z}]} < 40 && !${This.CollisionTest[${Me.X}, ${Me.Y}, ${Me.Z}, ${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["Found path!"]
				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["Direct!"]
				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
	}
	
	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[${Me.X},${Me.Y},${Me.Z},${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[${Me.X},${Me.Y},${Me.Z},${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[${Me.X},${Me.Y},${Me.Z},${This.CurrentDestination.X},${This.CurrentDestination.Y},${This.CurrentDestination.Z}]} > NAVIGATION_PERCISION
		{
			This:FaceXY[${CurrentDestination.X},${CurrentDestination.Y}]
		}
	}
	
	member RegionExists(string RegionName)
	{
		return ${LNavRegion[${RegionName}].FQN(exists)}
	}
	
	method PlotGameObject(string ObjectName, string GroupName="")
	{
		if !${This.RegionExists["${ObjectName}"]} && ${Object["${ObjectName}"](exists)}
		{
			This:PlotObject[${ObjectName}, ${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[${Me.X},${Me.Y},${Me.Z}].ID}]

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