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