align-to-ground
--Private values
Script.minTargetDistance = 1.0
function Script:Start()
  self.targetPos = self.entity:GetPosition()
  -- create pivot that is the real controller
  self.pivot = Pivot:Create()
  self.pivot:SetPosition(self.entity:GetPosition(true), true)
  self.pivot:SetMass(1)
  self.pivot:SetPhysicsMode(Entity.CharacterPhysics)
  self.pivot:SetCollisionType(Collision.Character)

  self.pivot:SetPickMode(0)
  self.entity:SetPickMode(0)
  self.entity:SetNavigationMode(true, true)
  self.originalInclinationQuat = Quat()
end
function Script:GoToPosition( pos )
  self.targetPos = Vec3(pos.x, pos.y, pos.z)
  if self.pivot:GoToPoint(pos, self.speed, self.acceleration) then
   --System:Print("unit "..self.entity:GetKeyValue("name", "").." responded. ")
  else
   self.pivot:Stop()
   --System:Print("unit "..self.entity:GetKeyValue("name", "").." cannot go there. ")
  end
end
function Script:UpdateWorld()
  -- set model position to pivot position
  self.entity:SetPosition(self.pivot:GetPosition(true), true)
  -- disable model picking
  self.entity:SetPickMode(0)

  local world = World:GetCurrent()
  local pickinfo = PickInfo()
  local pivotPos = self.pivot:GetPosition()
  local rayStart = Vec3(pivotPos.x, pivotPos.y+1, pivotPos.z)
  local rayEnd = Vec3(rayStart.x, rayStart.y-50, rayStart.z)
  -- pick the ground normal for rotation
  if (world:Pick(rayStart,rayEnd,pickinfo,0.1,true,Collision.Scene)) then
   local interpolateSpeed = 0.07

   local terrainNormal = pickinfo.normal
   local localYRel = terrainNormal.y
   local localY = Vec3( 0, localYRel, 0 )
   local weight = 0.1
   local newNormal = localY * ( 1 - weight ) + terrainNormal * weight
   local inclinationAngle = Math:ACos(localY:Dot(newNormal))

   local newNormalCross = localY:Cross( newNormal )
   local inclinationAxis = newNormalCross:Normalize()
   inclinationAxis = inclinationAxis:Inverse() --not exactly sure why
   local inclination = Quat( inclinationAngle, inclinationAxis )
   local inclinationSlerp = self.originalInclinationQuat:Slerp( inclination, interpolateSpeed / Time:GetSpeed() )
   self.entity:SetRotation(inclinationSlerp)
   self.originalInclinationQuat = inclinationSlerp -- save interpolated quaternion
   --turn model to rotation of controller
   local pivotRotation = self.pivot:GetRotation(true)
   self.entity:Turn(0,pivotRotation.y,0)
  end
  -- reenable model picking
  self.entity:SetPickMode(Entity.SpherePick)
  local selfPosition = self.entity:GetPosition(true)
  -- is entity near destination stop pathfinding
  if selfPosition:DistanceToPoint(self.targetPos) < self.minTargetDistance then
   self.pivot:Stop()
   --System:Print("unit "..self.entity:GetKeyValue("name", "").." reached destination. ")
  end
end
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License