local LD = require("design.LevelDesignLibrary")
local DL = require("design.DesignerLibrary")
thisObj = nil
thisLevel = nil
player = nil
son = nil
parent = nil
startDestination = nil
previousDestination = nil
endDestination = nil
lineCompleted = false
maxLifetime = 4
timeBetweenLines = 0.075
concussionFrequency = 1
concussionDelay = 0
attackLength = 30
timeLimit = 0
local shockwaveGO, SNDShockwave
local shockwaveTable = {}
local initAudio = false
local groundDebugVectorOffset = engine.Vector.New(0, 1, 0)
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  parent = obj:GetEffectObjectCreator()
  timeLimit = game.GetGameTime() + maxLifetime
  if parent:PickupIsAcquired("Baldur_IceMode") then
    timeBetweenLines = 0.5
    concussionFrequency = 4
  end
  if parent:PickupIsAcquired("Baldur_FireMode") then
    timeBetweenLines = 0.125
    concussionFrequency = 1.5
  end
  startDestination = obj.WorldPosition
  previousDestination = startDestination
  endDestination = LD.GetPointAlongLine(startDestination, thisObj.WorldPosition + thisObj:GetWorldForward() * attackLength, attackLength)
  shockwaveGO = thisObj:FindSingleGOByName("Shockwave")
  if shockwaveGO ~= nil then
    SNDShockwave = shockwaveGO:FindSingleSoundEmitterByName("SNDbaldurGroundShockwave00")
  else
    print("//////////////////////// " .. tostring(shockwaveGO) .. " is nil")
  end
  GetNextConcussionLocation()
end
function GetNextConcussionLocation()
  if timeLimit < game.GetGameTime() then
    Cleanup()
    return
  end
  local nextLocation = LD.GetPointAlongLine(previousDestination, endDestination, concussionFrequency)
  if nextLocation == nil then
    Cleanup()
    return
  end
  if (startDestination - nextLocation):Length() > (startDestination - endDestination):Length() then
    nextLocation = endDestination
    lineCompleted = true
  end
  if player ~= nil and player:IsPlayingMove("MOV_HitSuperRicochet") then
    Cleanup()
    return
  end
  if PathIsObstructed(previousDestination + groundDebugVectorOffset, nextLocation + groundDebugVectorOffset) then
    Cleanup()
    return
  end
  local closestPoint = game.NavMesh.ClosestPoint(nextLocation)
  if closestPoint == nil then
    Cleanup()
    return
  end
  local nextLocation_y = closestPoint.y
  nextLocation = engine.Vector.New(nextLocation.x, nextLocation_y, nextLocation.z)
  table.insert(shockwaveTable, nextLocation)
  engine.DrawLine(previousDestination, nextLocation, 16711680, 0.5)
  engine.DrawFillSphere(nextLocation, 0.1, 16711680, 0.5)
  _G.StartLevelTimer(concussionDelay, function()
    TriggerConcussion(nextLocation)
  end)
  previousDestination = nextLocation
  LD.TrackEmitterOnLine(shockwaveTable, player, shockwaveGO)
  LD.CallFunctionAfterDelay(function()
    if not lineCompleted then
      GetNextConcussionLocation()
    else
      Cleanup()
    end
  end, timeBetweenLines)
end
function TriggerConcussion(nextLocation)
  local concussionParams = {}
  if parent:PickupIsAcquired("Baldur_IceMode") then
    concussionParams = {
      Tweak = "CNC_ICEMODE_GROUNDSPIKE_UNBLOCKABLE",
      WorldLocation = nextLocation,
      GameObject = parent,
      EnemyId = parent:GetID()
    }
  elseif parent:PickupIsAcquired("Baldur_FireMode") then
    concussionParams = {
      Tweak = "CNC_FIREMODE_LEAPSTOMP_MORTAR",
      WorldLocation = nextLocation,
      GameObject = parent,
      EnemyId = parent:GetID()
    }
  else
    concussionParams = {
      Tweak = "CNC_BALDUR_GROUND_SHOCKWAVE",
      WorldLocation = nextLocation,
      GameObject = parent,
      EnemyId = parent:GetID()
    }
  end
  if initAudio == false then
    LD.PlaySound(SNDShockwave, "SND_CHR_Baldur_Ice_Wave_Projectile_LP")
    initAudio = true
  end
  game.Combat.PlayConcussion(concussionParams)
end
function PathIsObstructed(point01, point02)
  local collisionParams = {
    SourceGameObject = thisObj,
    ExcludeGameObject = thisObj,
    EntityType = game.CollisionType.New("kInvisibleBarrier", "kEnvironment")
  }
  local hit = game.World.RaycastCollision(point01, point02, collisionParams)
  if hit then
    if hit.GameObject:IsBreakable() then
      return false
    end
    return true
  end
  return false
end
function Cleanup()
  thisObj:Destroy()
end
function OnSaveCheckpoint(level, obj)
  return {}
end
function OnRestoreCheckpoint(level, obj, savedInfo)
end
