require("lib/lincoln")

Globals = {
  persistedValue = 0,
  canTalkToLady = false,
  hasTalkedToLady = false,
  isOfficierSoldierOOA = false,
  isOfficierRobbed = false,
  isOfficierMoneyTaken = false,
  canTalkToAllan = true,
  hasTalkedToAllan = false,
  isAllanFreed = false,
  canAllanMove = false,
  allanSafeLevel = 0,
  canTalkToHusband = false,
  hasTalkedToHusband = false,
  isPathToSherwoodClear = false,
  moved = 0,
  isCivilianWalkedHome = false,
  isCorpseReturned = false,
  victory = false,
}

function Initialize(seed)
  InitializeLincoln()
  DeactivateSherwoodSigns()

  AttachScrollToNPC(GetActor("Civilian_21"), GetScroll("Scroll_9"))

  DeactivateItems({
    GetItem("Stones_6"),
    GetItem("Money_9"),
    GetItem("Clovers_12"),
    GetItem("Money_13"),
    GetItem("Clovers_14")
  })

  DeactivateActors({
    GetActor("ManCivilianOld_4"),
    GetActor("Civilian_20"),
    GetActor("Soldier_48"),
    GetActor("Soldier_52"),
    GetActor("Soldier_53"),
    GetActor("Soldier_132b"),
    GetActor("Soldier_133b"),
    GetActor("Soldier_146"),
    GetActor("Soldier_147"),
    GetActor("Soldier_148"),
    GetActor("Soldier_149"),
    GetActor("Soldier_150"),
    GetActor("Soldier_151"),
    GetActor("Soldier_152"),
    GetActor("Soldier_153"),
    GetActor("Soldier_154"),
    GetActor("Soldier_155"),
    GetActor("Soldier_156"),
    GetActor("Soldier_157"),
  })
  Deactivate(GetActor("Husband_1")) --we don't lock his AI this way
end

function PostInitialize()
  AddObjective(0, true)

  StartSequence()
  SequenceDisplayPopupText(15)
  SequenceDisplayPopupText(0)

  EndSequence()

  -- Lock Door to Allan
  SetDoorLockedPC(GetDoorScript(25), true)
  SetDoorLockedPC(GetDoorScript(27), true)

-- Lock Door towards Dungeon Path - needed to free Civilian
SetDoorLockedPC(GetDoorScript(36), true)

  -- Lock Door to Dungeon - will not change to lockable during level
  SetDoorLockedPC(GetDoorScript(20), true)

  -- Lock Door to Soldier's chamber
  SetDoorLockedPC(GetDoorScript(28), true)
  --SetDoorLockedNPCVillain(GetDoorScript(28), true) -- will be unlocked after Allan is rescued

  -- Lock Door to House of dead Matthew - unlockable
  SetDoorLockedPC(GetDoorScript(33), true)
  SetDoorUnlockable(GetDoorScript(33), true)

  -- Lock East Tower
  SetDoorLockedPC(GetDoorScript(29), true)
  SetDoorLockedPC(GetDoorScript(30), true)
  SetDoorLockedPC(GetDoorScript(31), true)
  SetDoorLockedPC(GetDoorScript(32), true)

end

function Timer(secondsPassed)

  TalkToLady()
  KeysFromOfficierObtained()
  OfficierMoneyTaken()
  TalkToAllan()
  HusbandSoldiersOutOfAction()
  SoldiersOfficierOutOfAction()
  MonitorAllanEscape()
  LockCivilians()

end

function CheckVictoryCondition(secondsPassed)
  if Globals.victory then
    ChooseVictoryDefeatText(0)
    return 1
  end

  if not Globals.hasTalkedToAllan then
    if not HasAnyPCActionWhoIsInThisLevelOrCouldMaybeComeFromSherwood(28) then
      -- ChooseVictoryDefeatText(1) - not live due to missing German defeat entry
      return 2
    end
  end

end

function Finalize(unk)
end





--Functions



function TalkToLady()
  if Globals.canTalkToLady and not Globals.hasTalkedToLady then
    AttachScrollToNPC(GetActor("WomanCivilianPoor_7"), GetScroll("Scroll_10"))
    Globals.canTalkToLady = false
  end
end

function TalkToAllan() 
  if Globals.canTalkToAllan then
    local soldiers = { -- Group of desired Soldiers which need to be OutOfAction before Allan is free
      "Soldier_45",
      "Soldier_44",
      "Soldier_46",
      "Soldier_47",
      "Soldier_49",
    }


    local allOut = true 

    for _, soldierName in ipairs(soldiers) do
        if not IsActorOutOfAction(GetActor(soldierName)) then
            allOut = false 
            break
        end
    end

    if allOut and not Globals.hasTalkedToAllan then
        AttachScrollToNPC(GetActor("Allan_8"), GetScroll("Scroll_11"))
        Globals.canTalkToAllan = false
    end
  end
end

function KeysFromOfficierObtained()
  if (GetPersistentProperty(GetActor("Soldier_62"), PersistentProperty.money) == 0) and (not Globals.isOfficierRobbed) then
    StartSequence()
    SequenceDisplayPopupText(3)
    CompleteObjective(3)
    EndSequence()
    Globals.isOfficierRobbed = true
    SetDoorUnlockable(GetDoorScript(25), true)
    SetDoorUnlockable(GetDoorScript(27), true)
    SetDoorUnlockable(GetDoorScript(29), true)
    SetDoorUnlockable(GetDoorScript(30), true)
    SetDoorUnlockable(GetDoorScript(31), true)
    SetDoorUnlockable(GetDoorScript(32), true)
    SetDoorUnlockable(GetDoorScript(36), true)
  end
  
end

function OfficierMoneyTaken()
  if (GetPersistentProperty(GetActor("Soldier_84"), PersistentProperty.money) == 0) and (not Globals.isOfficierMoneyTaken) then
    StartSequence()
    CompleteObjective(6)
    EndSequence()
    Globals.isOfficierMoneyTaken = true
  end
  
end

function SoldiersOfficierOutOfAction()
  -- Check if the officer has been robbed

  if Globals.isOfficierSoldierOOA then
    return
  end

  -- Define the list of soldiers that need to be out of action
  local requiredSoldiers = {
      "Soldier_64", "Soldier_66", "Soldier_65", "Soldier_60", "Soldier_61", 
      "Soldier_58", "Soldier_59", "Soldier_62", "Soldier_67", "Soldier_68", 
      "Soldier_63"

  }

  -- Check if all required soldiers are out of action
  local allOut = true
  for _, soldier in ipairs(requiredSoldiers) do
      if not IsActorOutOfAction(GetActor(soldier)) then
          allOut = false
          break
      end
  end

  -- If all conditions are met, attach the scroll
  if allOut then
      UnlockAI(GetActor("ManCivilianPoor_3"))
      AttachScrollToNPC(GetActor("ManCivilianPoor_3"), GetScroll("Scroll_13"))
      Globals.isOfficierSoldierOOA = true
  end
end

function HusbandSoldiersOutOfAction()
  if IsActorOutOfAction(GetActor("Soldier_132b")) and IsActorOutOfAction(GetActor("Soldier_133b")) and (not Globals.canTalkToHusband) and (not Globals.hasTalkedToHusband) then
    AttachScrollToNPC(GetActor("Husband_1"), GetScroll("Scroll_12"))
    Globals.canTalkToHusband = true
  end
end

function MonitorAllanEscape()
  if Globals.hasTalkedToAllan then

      -- Define the single merged safety zone (all soldiers combined)
      local mergedSafetyZone = {
        
          "Soldier_46", "Soldier_47", "Soldier_49", "Soldier_44", "Soldier_45",
          "Soldier_51", "Soldier_83b", "Soldier_50", -- Soldiers on tower
          
          "Soldier_57", "Soldier_56", "Soldier_111", -- Soldiers on path to tower

          "Soldier_74b", "Soldier_69b", "Soldier_73b", "Soldier_72b", "Soldier_82b", "Soldier_125", 
          "Soldier_126", --Soldiers inside castle

          "Soldier_98b", "Soldier_99b", "Soldier_94b", "Soldier_93b", "Soldier_96b",
          "Soldier_95b", "Soldier_92b", "Soldier_91b", "Soldier_97b", "Soldier_104", 
          -- Soldiers close to Gate

          "Soldier_110", "Soldier_109", "Soldier_108", "Soldier_107", --Soldiers close to bridge to gate
          
          "Soldier_114", "Soldier_113", "Soldier_112", "Soldier_118", "Soldier_117", 
          -- Patrol on path to village
          
          "Soldier_150", "Soldier_151", "Soldier_152", "Soldier_153", "Soldier_154", 
          "Soldier_155", "Soldier_156", -- New patrol after escape alert

          "Soldier_134", "Soldier_135", "Soldier_141", -- Patrol at Bridge
          
          "Soldier_132", "Soldier_103", "Soldier_100b",
          "Soldier_102b", "Soldier_101b", "Soldier_64b", "Soldier_65b", "Soldier_133",
          "Soldier_39", "Soldier_40", "Soldier_68b", "Soldier_41", "Soldier_43",
          "Soldier_42", "Soldier_67b", "Soldier_66b" --Village and path to village
      }

      -- Define movement positions
      local finalPosition = GetLocation("Node_44")  -- Final position (only one step now)
      local initialPosition = GetLocation("Node_46") -- Initial position

      local allan = GetActor("Allan_8")

      -- If Allan does not exist, exit
      if allan == nil then
          return
      end

      -- If `Globals.allanSafeLevel` has not been set, initialize it
      if Globals.allanSafeLevel == nil then
          Globals.allanSafeLevel = 0
      end

      -- Check if Allan is **already at the final position**
      local finalDestinationReached = GetDistance(GetActorLocation(allan), finalPosition) < 5

      function IsGroupOutOfAction(soldierGroup)
          local activeSoldiers = {}
          for _, soldier in ipairs(soldierGroup) do
              if not IsActorOutOfAction(GetActor(soldier)) then
                  table.insert(activeSoldiers, soldier)
              end
          end

          if #activeSoldiers > 0 then
              print("⚠️ Some soldiers are still active. Active soldiers: " .. table.concat(activeSoldiers, ", "))
              return false -- At least one soldier is still active
          else
              print("✅ All soldiers are out of action. Allan can move.")
              return true -- All soldiers are out of action
          end
      end

      function CheckSoldierStatus()
          if finalDestinationReached then
              print("✅ Allan has reached the final destination. No further movement.")
              return
          end

          -- Allan stays at initial position until all soldiers in the merged zone are out of action
          if IsGroupOutOfAction(mergedSafetyZone) then
              Globals.allanSafeLevel = 1
              print("🏃 Allan is moving to the final position.")

              StartSequence()
              SequenceMove(allan, finalPosition, MovementStyle.running)
              EndSequence()
              
              finalDestinationReached = true  -- Allan will never move again
          else
              print("🛑 Allan remains at the initial position as some soldiers are still active.")
          end
      end

      CheckSoldierStatus()
  end
end

function LockCivilians()
  -- Get all civilians
  local husband = GetActor("Husband_1")
  local allan = GetActor("Allan_8")
  local civilian1 = GetActor("ManCivilianPoor_3")
  local civilian2 = GetActor("Civilian_9")

  -- **Check if Husband_1 should be locked or unlocked**
  if husband ~= nil then
      if Globals.canTalkToHusband then
          UnlockAI(husband)
      else
          LockAI(husband, false)
      end
  end

  -- **Check if Allan_8 should be locked or unlocked**
  if allan ~= nil then
      if Globals.canAllanMove then
          UnlockAI(allan)
      else
          LockAI(allan, false)
      end
  end

  -- Civilian 8 and Husband
  if Globals.isOfficierSoldierOOA == true then
    UnlockAI(civilian1)
    UnlockAI(civilian2)
  else
    LockAI(civilian1, false)
    LockAI(civilian2, false)
  end
end

-- Scrolls

ScrollRevealOfficiers = {
  Taken = function(actorSource)
    StartSequence()
    SequenceDisplayPopupText(7)
    SequenceLockUser()
    SequenceFreezeAll(true)
    SequenceScrollCameraTo(GetLocation("Node_29"))
    Then()
    SequenceTimer(15)
    Then()
    SequenceReveal(GetActor("Soldier_84"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceReveal(GetActor("Soldier_97"))
    Then()
    SequenceTimer(15)
    Then()
    SequenceScrollCameraTo(GetLocation("Node_30"))
    Then()
    SequenceTimer(15)
    Then()
    SequenceReveal(GetActor("Soldier_62"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceUnLockUser()
    SequenceFreezeAll(false)
    EndSequence()
    return 1
  end,
}

ScrollGateIsClosed = {
  Taken = function(actorSource)
    AddObjective(1, true)
    StartSequence()
    SequenceDisplayPopupText(8)
    SequenceLockUser()
    SequenceFreezeAll(true)
    SequenceScrollCameraTo(GetLocation("Node_15"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceUnLockUser()
    SequenceFreezeAll(false)
    EndSequence()
    return 1
  end,
}

ScrollDeadMatthew = {
  Taken = function(actorSource)
    StartSequence()
    SequenceLockUser()
    SequenceFreezeAll(true)
    SequenceScrollCameraTo(GetLocation("Node_30"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceDisplayPopupText(9)
    Then()
    SequenceTimer(25)
    Then()
    SequenceReveal(GetActor("Civilian_10"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceUnLockUser()
    SequenceFreezeAll(false)
    EndSequence()
    return 1
  end,
}

ScrollActivateStones = {
  Taken = function(actorSource)
    StartSequence()
    SequenceDisplayPopupText(10)
    EndSequence()
    Activate(GetItem("Stones_6"))
    return 1
  end,
}

ScrollLadyInGreen = {
  Taken = function(actorSource)
    StartSequence()
    SequenceDisplayPopupText(11)
    AddObjective(2, true)
    SequenceLockUser()
    SequenceFreezeAll(true)
    Then()
    SequenceScrollCameraTo(GetLocation("Node_32"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceReveal(GetActor("WomanCivilianPoor_7"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceUnLockUser()
    SequenceFreezeAll(false)
    EndSequence()

    Globals.canTalkToLady = true

    return 1
  end,
}

ScrollOrangeOfficierMoney = {
  Taken = function(actorSource)
    StartSequence()
    SequenceLockUser()
    SequenceFreezeAll(true)
    AddObjective(6, false)
    SequenceDisplayPopupText(12)
    SequenceScrollCameraTo(GetLocation("Node_29"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceUnLockUser()
    SequenceFreezeAll(false)
    EndSequence()
  return 1
  end,
}

ScrollHouseFromMatthew = {
  Taken = function(actorSource)
      StartSequence()
      SetDoorLockedNPCVillain(GetDoorScript(33), true)
      AddObjective(9, false)
      SequenceScrollCameraTo(GetActorLocation(actorSource))
      Then()
      SequenceDisplayPopupText(13)
      EndSequence()
  return 1
  end,
}

ScrollTreasureFountain = {
  Taken = function(actorSource)
    --can be used after Spellforge update
  return 1
  end,
}

-- Actors

CivilistHelpGate = {
  Taken = function(actorSource)
    AttachScrollToNPC(GetActor("Civilian_21"), God())
    StartSequence()
    SequenceScrollCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceDisplayPopupText(1)
    CompleteObjective(1)
    SequenceLockUser()
    SequenceFreezeAll(true)
    Then()
    SequenceCall(function ()
      StopActor(GetActor("Civilian_21"))
    end)
    Then()
    SequenceTimer(15)
    Then()
    SequenceFreezeAll(false)
    LockAI(GetActor("Civilian_21"), false)
    Then()
    SequenceMove(GetActor("Civilian_21"),GetLocation("Node_31"),MovementStyle.walking)
    Then()
    SequenceTurnTo(GetActor("Civilian_21"),GetLocation("Node_14"))
    Then()
    SequenceFreezeAll(true)
    Then()
    SequenceTimer(15)
    Then()
    SequenceScrollCameraTo(GetLocation("Node_15"))
    Then()
    SequenceTimer(15)
    Then()
    SequenceCall(RevealDrawBridge)
    Then()
    SequenceTimer(15)
    Then()
    SequenceReveal(GetActor("Civilian_20"))
    Then()
    SequenceTimer(15)
    Then()
    SequenceCall(function ()
      DrawBridgeRoom:ActivateDrawBridge(GetLocation("Node_15"))
    end)
    SequenceFreezeAll(false)
    Then()
    SequenceTimer(100)
    Then()
    SequenceUnLockUser()
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceCall(function ()
      StopActor(GetActor("Civilian_21")) -- Stoppt alle aktuellen Bewegungen
      UnlockAI(GetActor("Civilian_21"))
      AssignPatrol(GetActor("Civilian_21"), GetPatrol("Patrol_81"))

    end)
    EndSequence()
    
    return 1
  end,
}

GetHelpFromLady = {
  Taken = function(actorSource)
    AttachScrollToNPC(GetActor("WomanCivilianPoor_7"), God())
    StartSequence()
    SequenceDisplayPopupText(2)
    SequenceDisplayPopupText(5)
    CompleteObjective(2)
    AddObjective(3, true)
    AddObjective(8, false)
    SequenceLockUser()
    SequenceFreezeAll(true)
    Then()
    SequenceScrollCameraTo(GetLocation("Node_30"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceFreezeAll(false)
    SequenceUnLockUser()
    EndSequence()
    Globals.hasTalkedToLady = true
    return 1
  end,
}

AllanIsFreed = {
  Taken = function(actorSource)
    AttachScrollToNPC(GetActor("Allan_8"), God())
    StartSequence()
    SequenceDisplayPopupText(4)
    SequenceDisplayPopupText(17)
    -- Manage Objective: All Objectives are completed besides rescueing Allan out of the castle
    CompleteObjective(0)
    CompleteObjective(1)
    CompleteObjective(2)
    CompleteObjective(3)
    CompleteObjective(4)
    AddObjective(5, true)
    ActivateSherwoodSigns()

    --Set Scrolls which refer to now obsolete targets as collected
    UpdateScrollState(GetScroll("Scroll_2"), ScrollState.collected)
    UpdateScrollState(GetScroll("Scroll_5"), ScrollState.collected)

    SequenceLockUser()
    SequenceFreezeAll(true)
    SequenceCall(function()
      SetDoorLockedNPCVillain(GetDoorScript(28), false)
      ActivateActors({
        GetActor("Soldier_146"),
        GetActor("Soldier_147"),
        GetActor("Soldier_148"),
        GetActor("Soldier_150"),
        GetActor("Soldier_151"),
        GetActor("Soldier_152"),
        GetActor("Soldier_153"),
        GetActor("Soldier_154"),
        GetActor("Soldier_155"),
        GetActor("Soldier_156"),
        GetActor("Soldier_157"),
      })
    end)
    Then()
    SequenceTimer(25)
    Then()
    SequenceDisplayPopupText(18)
    Then()
    SequenceSetZoomLevel(ZoomLevel.default)
    Then()
    SequenceScrollCameraTo(GetLocation("Node_2"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceFreezeAll(false)
    SequenceLockAI(GetActor("Soldier_147"))
    SequenceLockAI(GetActor("Soldier_148"))
    Then()
    SequenceReveal(GetActor("Soldier_147"))
    SequenceReveal(GetActor("Soldier_148"))
    Then()
    SequenceMove(GetActor("Soldier_147"),GetLocation("Node_33"),MovementStyle.walking)
    Then()
    SequenceTurnTo(GetActor("Soldier_147"),GetLocation("Node_34"))
    Then()
    SequenceCall(function()
      SetNPCEmoticon(GetActor("Soldier_147"), 1, 30)
    end)
    Then()
    SequenceSpeak(GetActor("Soldier_147"),28)
    Then()
    SequenceTimer(50)
    Then()
    SequenceCall(function()
      SetNPCEmoticon(GetActor("Soldier_147"), 2, 30)
    end)
    Then()
    SequenceTimer(15)
    Then()
    SequenceMoveIntoBuilding(GetActor("Soldier_147"), GetLocation("Node_1"), MovementStyle.running)
    Then()
    SequenceTimer(25)
    Then()
    SequenceCall(function()
      SetNPCEmoticon(GetActor("Soldier_148"), 1, 30)
    end)
    Then()
    LockAI(GetActor("Soldier_148"), false)
    SequenceCall(function()
      Soldier_147Move(actorSource)
      Soldier_148Move(actorSource)
    end)
    EndSequence()
    
    return 1
  end,
}

function Soldier_147Move(actorSource)
  StartSequence()
  SequenceMove(GetActor("Soldier_147"),GetLocation("Node_35"),MovementStyle.running)
  Then()
  SequenceCall(function ()
    Globals.moved = Globals.moved + 1
  end)
  Then()
  SequenceCall(function ()
    FinishPreviousSequence(actorSource)
  end)
  EndSequence()
end

function Soldier_148Move(actorSource)
  StartSequence()
  SequenceMove(GetActor("Soldier_148"),GetLocation("Node_33"),MovementStyle.running)
  Then()
  SequenceCall(function ()
    Globals.moved = Globals.moved + 1
  end)
  Then()
  SequenceCall(function ()
    FinishPreviousSequence(actorSource)
  end)
  EndSequence()
end

function FinishPreviousSequence(actorSource)
  if  Globals.moved < 2 then
    return
  end
  StartSequence()
  SequenceTurnTo(GetActor("Soldier_147"),GetLocation("Node_34"))
  Then()
  SequenceTurnTo(GetActor("Soldier_148"),GetLocation("Node_34"))
  Then()    
  SequencePlayAnim(GetActor("Soldier_147"), 206)
  Then()
  SequenceSpeak(GetActor("Soldier_147"),15)
  Then()
  SequenceCall(function()
    SetNPCEmoticon(GetActor("Soldier_148"), 2, 100)
  end)
  Then()
  SequenceTimer(60)
  Then()
  SequenceSpeak(GetActor("Soldier_148"),76)
  Then()
  SequenceTimer(40)
  Then()
  SequenceTurnTo(GetActor("Soldier_147"),GetActorLocation(GetActor("Soldier_148")))
  Then()
  SequencePlayAnim(GetActor("Soldier_148"), 216)
  Then()
  SequenceFreezeAll(false)
  Then()
  SequenceCall(function()
      AssignPatrol(GetActor("Soldier_148"), GetPatrol("Patrol_12"))
      AlertNearbySoldiers()
  end)
  Then()
  SequenceUnlockAI(GetActor("Soldier_148"))
  EndSequence()
end

function AlertNearbySoldiers()
  -- Soldaten, die zu Soldier_148 laufen sollen
  local soldiersToMove = {
      "Soldier_135", "Soldier_134", "Soldier_141", "Soldier_143", "Soldier_142",
      "Soldier_144", "Soldier_119", "Soldier_120", "Soldier_121", "Soldier_122",
      "Soldier_123", "Soldier_150", "Soldier_151", "Soldier_152", "Soldier_153", 
      "Soldier_154", "Soldier_155", "Soldier_156", "Soldier_136", "Soldier_139",
      "Soldier_147", "Soldier_137", "Soldier_138", "Soldier_140", "Soldier_75b"
  }

  -- Soldaten, die nach der Bewegung eine Patrouille bekommen
  local patrolAssignments = {
      Soldier_134 = "Patrol_85",
      Soldier_135 = "Patrol_85",
      Soldier_141 = "Patrol_85",

      Soldier_142 = "Patrol_89",
      Soldier_143 = "Patrol_89",
      Soldier_144 = "Patrol_89",

      Soldier_119 = "Patrol_87",
      Soldier_120 = "Patrol_87",
      Soldier_121 = "Patrol_87",
      Soldier_122 = "Patrol_87",
      Soldier_123 = "Patrol_87",

      Soldier_150 = "Patrol_86",
      Soldier_151 = "Patrol_86",
      Soldier_152 = "Patrol_86",
      Soldier_153 = "Patrol_86",
      Soldier_154 = "Patrol_86",
      Soldier_155 = "Patrol_86",
      Soldier_156 = "Patrol_86",
  }

  local soldiersSeeking = {
    Soldier_75b = true,
    Soldier_136 = true,
    Soldier_137 = true,
    Soldier_138 = true,
    Soldier_139 = true,
    Soldier_140 = true,
    Soldier_147 = true,
  }

  local targetActor = GetActor("Soldier_148")
  local speakCounter = 0

  for _, soldierName in ipairs(soldiersToMove) do
    local actor = GetActor(soldierName)
    

    if actor == nil then
    else
      SetAIState(actor, AiState.script)
        -- Soldat entsperren & sichtbar machen
        UnlockAI(actor)
        Reveal(actor)

        -- Soldat bewegt sich zu Soldier_148
        StartSequence()
        Then()
        SequenceCall(function()
          SetNPCEmoticon(actor, 2, 100)
        end)
        SequenceMove(actor, ComputeLocationBetween(GetLocation("Node_37"), GetLocation("Node_38"), 0.009999999776482582 * Rand(100)), MovementStyle.running)
        Then()
        SequenceTimer(40) -- Kleine Verzögerung nach Ankunft
        Then()
        if speakCounter < 1 then
          SequenceSpeak(GetActor("Soldier_148"),69)
        end
        Then()
        -- SequencePlayAnim(GetActor("Soldier_148"), 216)
        Then()
        SequenceTimer(40)
        -- Falls Soldat eine Patrouille bekommen soll, weise sie zu
        if patrolAssignments[soldierName] then
            local patrol = GetPatrol(patrolAssignments[soldierName])
            if patrol == nil then
          
            else
                Then()
                SequenceCall(function()
                    AssignPatrol(actor, patrol)
                    UnlockAI(actor) -- Falls nötig
                    SetAIState(actor, AiState.default)
                end)
            end
        end
        
        if soldiersSeeking[soldierName] then
          print(soldiersSeeking[soldierName])
          
          Then()
          SequenceMove(actor, ComputeLocationBetween(GetLocation("Node_39"), GetLocation("Node_40"), 0.009999999776482582 * Rand(100)), MovementStyle.running)
          Then()
          SequenceCall(function()
              SetAIState(actor, AiState.seeking)
          end)
        end
        SequenceUnLockUser()
        EndSequence()
        Globals.canAllanMove = true
        print("Allan can move now")
        speakCounter = speakCounter + 1
        Globals.hasTalkedToAllan = true
    end
  end
end

RescueHusband = {
  Taken = function(actorSource)
    AttachScrollToNPC(GetActor("Husband_1"), God())

    StartSequence()
    SequenceDisplayPopupText(21)
    AddObjective(8, false)
    CompleteObjective(8)
    Activate(GetItem("Clovers_12"))
    Activate(GetItem("Money_13"))
    
    Then()
    SequenceCall(function()
        StopActor(GetActor("Husband_1"))
        UnlockAI(GetActor("Husband_1"))
        SetActorPosture(GetActor("Husband_1"), 0)
        print("✅ Husband_1 freigegeben")
    end)
    
    Then()
    SequenceTimer(10) -- Warten, um KI zu entsperren

    Then()
    SequenceCall(function()
        AssignPatrol(GetActor("Husband_1"), GetPatrol("Patrol_13"))
    end)

    EndSequence()
    
    return 1
  end,
}

GetHelpFromLady = {
  Taken = function(actorSource)
    AttachScrollToNPC(GetActor("WomanCivilianPoor_7"), God())
    StartSequence()
    SequenceDisplayPopupText(2)
    CompleteObjective(2)
    AddObjective(3, true)
    AddObjective(8, false)
    SequenceLockUser()
    SequenceFreezeAll(true)
    Then()
    SequenceScrollCameraTo(GetLocation("Node_30"))
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceTimer(25)
    Then()
    SequenceDisplayPopupText(5)
    Then()
    SequenceFreezeAll(false)
    SequenceUnLockUser()
    
    EndSequence()
    Globals.hasTalkedToLady = true
    return 1
  end,
}

CivilianReturnToHome = {
  Taken = function(actorSource)
    AttachScrollToNPC(GetActor("ManCivilianPoor_3"), God())
    AddObjective(4, true)
    AddObjective(7, false)
    StartSequence()
    SequenceScrollCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceDisplayPopupText(16)
    SequenceLockUser()
    SequenceFreezeAll(true)
    Then()
    SequenceTimer(25)
    Then()
    SequenceJumpCameraTo(GetActorLocation(actorSource))
    Then()
    SequenceFreezeAll(false)
    SequenceUnLockUser()
    SequenceCall(function ()
      StopActor(GetActor("ManCivilianPoor_3")) -- Stoppt alle aktuellen Bewegungen
      UnlockAI(GetActor("ManCivilianPoor_3"))
      AssignPatrol(GetActor("ManCivilianPoor_3"), GetPatrol("Patrol_31"))
      StopActor(GetActor("Civilian_9")) -- Stoppt alle aktuellen Bewegungen
      UnlockAI(GetActor("Civilian_9"))
      AssignPatrol(GetActor("Civilian_9"), GetPatrol("Patrol_29"))
    end)

    EndSequence()
    return 1
  end,
}

ReturnCorpse = {
  Enter = function(actor)
    if IsActorEqual(actor, GetActor("Civilian_10")) then
      if not IsActorActive(GetItem("Clovers_14")) then
        if (not Globals.isCorpseReturned) then
          Activate(GetItem("Clovers_14"))
          CompleteObjective(7)

          StartSequence()
          SequenceTurnTo(GetActor("Civilian_9"), GetActorLocation(GetActor("Civilian_10")))
          Then()
          SequenceDisplayPopupText(19)
          EndSequence()
          Globals.isCorpseReturned = true
        end
      end
    end
  end
}

-- Victory Zone Check
CheckVictoryZone = {
  Enter = function(actor)
    local targetZone = GetLocation("Node_45")
    local allan = GetActor("Allan_8")

    -- **Ermitteln, wie viele PCs in der Gruppe sind**
    local numberOfPCs = GetNumberOfPCs()

    -- Überprüfung, ob alle existierenden und lebenden PC-Charaktere in der Zone sind
    for i = 0, numberOfPCs - 1 do  -- **Lua Indizes starten bei 0!**
        local pc = GetPC(i)
        if pc ~= nil then
            if IsActorDead(pc) then
            elseif not IsInside(pc, targetZone) then
                return
            end
        end
    end

    -- Überprüfung, ob Allan_8 in der Zone ist
    if not IsInside(allan, targetZone) then
        return
    end

    Globals.victory = true
end
}

-- Targets

mecanisme_pont_levis_800001e9 = {
  ActivatedBySword = function(actorSource)
    DrawBridgeRoom:ActivateDrawBridge(GetLocation("Node_15"))
  end
}


-- Zones & Building Area Reveals

ZP06Sud_80000170 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      RevealWeaponRoom()
    end
  end
}

ZP06Est_80000171 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      RevealWeaponRoom()
    end
  end
}

ZP03TourOuest_80000173 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      RevealDungeonTower()
    end
  end
}

ZP01TourPtLevis_80000175 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      RevealDrawBridge()
    end
  end
}

ZP04CentralBas_80000177 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      if not IsPatchApplied(GetPatchScript(Battlement.patch)) then
        Battlement:Reveal()
        Activate(GetActor("Soldier_149"))
      end
    end
  end
}

ZP07Bas_80000178 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      RevealBedRoom()
    end
  end
}

ZP07Haut_80000179 = {
  Enter = function(actor)
    if IsActorPC(actor) then
      RevealBedRoom()
    end
  end
}

ZP05GdSalle_8000017a = {
  Enter = function(actor)
    if IsActorPC(actor) then
      if not IsPatchApplied(GetPatchScript(StairCase.patch)) then
        StairCase:Reveal()
      end
      if not IsPatchApplied(GetPatchScript(ThroneRoom.patch)) then
        ThroneRoom:Reveal()

        ActivateActors({GetActor("ManCivilianOld_4")})
      end
    end
  end
}

ZP09EscalierBas_8000017b = {
  Enter = function(actor)
    if IsActorPC(actor) and not IsPatchApplied(GetPatchScript(StairCase.patch)) then
      StairCase:Reveal()
    end
  end
}

ZP09EscalierHaut_8000017c = {
  Enter = function(actor)
    if IsActorPC(actor) and not IsPatchApplied(GetPatchScript(StairCase.patch)) then
      StairCase:Reveal()
    end
  end
}

RevealDrawBridge = function()
  if not IsPatchApplied(GetPatchScript(DrawBridgeRoom.patch)) then
    DrawBridgeRoom:Reveal()
    ActivateActors({GetActor("Civilian_20")})
  end
end

RevealWeaponRoom = function()
  if not IsPatchApplied(GetPatchScript(WeaponRoom.patch)) then
    WeaponRoom:Reveal()
    ActivateActors({
      GetActor("Soldier_48"),
      GetActor("Soldier_52"),
      GetActor("Soldier_53"),
    })
    Activate(GetItem("Money_9"))
  end
end

RevealDungeonTower = function()
  if not IsPatchApplied(GetPatchScript(DungeonTower.patch)) then
    DungeonTower:Reveal()

    ActivateActors({
      GetActor("Soldier_132b"),
      GetActor("Soldier_133b"),
    })
    Activate(GetActor("Husband_1"))
  end
end

RevealBedRoom = function()
  if not IsPatchApplied(GetPatchScript(BedRoom.patch)) then
    BedRoom:Reveal()
  end
end