[BNW] Lua Problem - TeamMeet crashing the game if a particular team initiates the meeting

Karatekid5

Warlord
Joined
Nov 11, 2012
Messages
197
Location
Pennsylvania
So I'm working on a script that is intended to have one civ's cities flipped to another civ when meeting them for the first time. The issue I am having is that if the absorber civ (Royal Woods) initiates the meeting with the target civ (Loch Loud) the code works perfectly, but if Loch Loud initiates a meeting with Royal Woods instead the game simply crashes. Basically, if Loch Loud's Team is iFirstTeam under any circumstance (even if I empty out everything in the "if iFirstTeam == AngusTeam then" statement the game still crashes, so it isn't anything to do with what is contained within it) the game crashes. I also tested by swapping out the IDs oft he two civs with vanilla civs and the issue persists, but sometimes it's the "if iSecondTeam == AngusTeam then" that's crashing the game instead. It has nothing to do with either civ specifically. Just for whatever reason "iCivLochLoud" initiating a First Meeting causes the game to crash.

Anyone know what's going on? What is making the game crash? Here's the whole script:


Code:
print("THE TOWN IS NAMED FOR YOU!")

local iCivLochLoud = GameInfoTypes.CIVILIZATION_KK5_LOCH_LOUD
local iCivRoyalWoods = GameInfoTypes.CIVILIZATION_KK5_ROYAL_WOODS
local iHappinessBuilding = GameInfoTypes.BUILDING_LOUD_ANGUS_HAPPINESS
local iWorkerPolicy = GameInfoTypes.POLICY_LOUD_ANGUS_LAZY
local iCastle = GameInfoTypes.BUILDING_CASTLE

local AngusTeam
local AngusPlayer
local iUnitLela = GameInfoTypes.UNIT_LOUD_DRAGON_LELA


local tCanTrain = {
[GameInfoTypes.UNIT_CARAVAN] = true,
[GameInfoTypes.UNIT_CARGO_SHIP] = true,
[GameInfoTypes.UNIT_NUCLEAR_MISSILE] = true,
[GameInfoTypes.UNIT_GUIDED_MISSILE] = true,
[GameInfoTypes.UNIT_ATOMIC_BOMB] = true,
[GameInfoTypes.UNIT_SCOUT] = true,
[GameInfoTypes.UNIT_LOUD_DRAGON_LELA] = true,
[GameInfoTypes.UNIT_LOUD_1600_FRIGATE] = true
}


for row in DB.Query("SELECT ID FROM Units WHERE CombatClass = 'UNITCOMBAT_ARCHER'") do
    tCanTrain[row.ID] = true
end



for row in DB.Query("SELECT ID FROM Units WHERE CivilianAttackPriority = 'CIVILIAN_ATTACK_PRIORITY_HIGH'") do
    tCanTrain[row.ID] = true
end

for row in DB.Query("SELECT ID FROM Units WHERE CivilianAttackPriority = 'CIVILIAN_ATTACK_PRIORITY_HIGH_EARLY_GAME_ONLY'") do
    tCanTrain[row.ID] = true
end

for row in DB.Query("SELECT ID FROM Units WHERE CivilianAttackPriority = 'CIVILIAN_ATTACK_PRIORITY_LOW'") do
    tCanTrain[row.ID] = true
end


-- ============================================================================
-- Check if Angus is present in-game
-- ============================================================================

function AngusCheck(player)
    for playerID, player in pairs(Players) do
        local player = Players[playerID];
        if player:GetCivilizationType() == iCivLochLoud then          
            GameEvents.PlayerCityFounded.Add(AngusAddHappiness)
            GameEvents.TeamMeet.Add(AngusAbsorbed)
            GameEvents.PlayerCanTrain.Add(AngusTrainConditions)
            AngusTeam = player:GetTeam()
            AngusPlayer = player
            if player:HasPolicy(iWorkerPolicy) == false then
               player:SetNumFreePolicies(1)
               player:SetNumFreePolicies(0)
               player:SetHasPolicy(iWorkerPolicy, true)
            end
            if Game.GetElapsedGameTurns() == 0 then
               AngusStartDragonDelete(player)
               print("EXTRA DRAGONS DELETED!")
            end      
        end
    end
end


-- ============================================================================
-- Check if Angus has met a team containing Lincoln and give all cities to Lincoln if so (usually he'll just have his capital).
-- ============================================================================

function AngusAbsorbed(iFirstTeam, iSecondTeam)
    local FirstTeam = Teams[iFirstTeam]
    local SecondTeam = Teams[iSecondTeam]
    if iFirstTeam == AngusTeam or iSecondTeam == AngusTeam then
       print("Angus' Team met someone!")
           if iFirstTeam == AngusTeam then
             for _, pPlayer in pairs(GetPlayersFromTeam(iSecondTeam)) do
                print("Angus is the first team in the function! Checking who's on the other team...")
                if pPlayer:GetCivilizationType() == iCivRoyalWoods then
                  GrabAngusUnits()
                  print("THE LOUDS HAVE RETURNED!")
                  Events.AudioPlay2DSound("AS2D_KK5_LOUD_LOUDS_HAVE_RETURNED")
                  pPlayer:ChangeGoldenAgeTurns(20)
                  local tCityTable = {}
                  for city in AngusPlayer:Cities() do
                    if city ~= nil then
                       table.insert(tCityTable, city)
                       city:SetNumRealBuilding(iCastle, 1)
                    end
                  end
                  for i,city in ipairs(tCityTable) do
                      pPlayer:AcquireCity(city, false, true)
                  end
                end

             end
           elseif iSecondTeam == AngusTeam then
              for _, pPlayer in pairs(GetPlayersFromTeam(iFirstTeam)) do
                print("Angus is the second team in the function! Checking who's on the other team...")
                if pPlayer:GetCivilizationType() == iCivRoyalWoods then
                  GrabAngusUnits()
                  print("THE LOUDS HAVE RETURNED!")
                  pPlayer:ChangeGoldenAgeTurns(20)
                  Events.AudioPlay2DSound("AS2D_KK5_LOUD_LOUDS_HAVE_RETURNED")
                  local tCityTable = {}
                  for city in AngusPlayer:Cities() do
                    if city ~= nil then
                       table.insert(tCityTable, city)
                       city:SetNumRealBuilding(iCastle, 1)
                    end
                  end
                  for i,city in ipairs(tCityTable) do
                      pPlayer:AcquireCity(city, false, true)
                  end
                end
             end
           end
    end
end

-- ============================================================================
-- Give Angus his UA Dummy Building
-- ============================================================================

function AngusAddHappiness(iPlayer, iPlotX, iPlotY)
 local pPlayer = Players[iPlayer]

 if (pPlayer:GetCivilizationType() == iCivLochLoud) then
   local pPlot = Map.GetPlot(iPlotX, iPlotY)
   local AngusFoundedCity = pPlot:GetPlotCity()
   AngusFoundedCity:SetNumRealBuilding(iHappinessBuilding, 1)
 end
end



Events.SequenceGameInitComplete.Add(AngusCheck)


function GetPlayersFromTeam(iTeam, iCivilizationType)
    local tPlayers = {};
    for iPlayer = 0, GameDefines.MAX_MAJOR_CIVS - 1, 1 do
        local pPlayer = Players[iPlayer]
        if pPlayer:IsAlive() and pPlayer:GetTeam() == iTeam and (iCivilizationType == nil or pPlayer:GetCivilizationType() == iCivilizationType) then
              tPlayers[#tPlayers + 1] = pPlayer
        end
    end
    return tPlayers
end

function GrabAngusUnits(pPlayer)
   local tUnitsTable = {}
   for pUnit in AngusPlayer:Units() do
       if not pUnit:IsDead() and not pUnit:IsDelayedDeath() then
          table.insert(tUnitsTable, pUnit:GetID())
        end
    end
    for i,iUnitID in ipairs(tUnitsTable) do
         AngusPlayer:GetUnitByID(iUnitID):Kill()
    end
end

function AngusTrainConditions(playerID, unitType)
  local pPlayer = Players[playerID]
  if pPlayer:GetCivilizationType() == iCivLochLoud then
      if tCanTrain[unitType] then
          return true
      else
          return false
      end
  else
   return true
  end
end


function AngusStartDragonDelete(pPlayer)
   local tDragonTable = {}
   for pUnit in AngusPlayer:Units() do
       if not pUnit:IsDead() and not pUnit:IsDelayedDeath() and pUnit:GetUnitType() == iUnitLela then
          table.insert(tDragonTable, pUnit:GetID())
        end
    end
    for i,iUnitID in ipairs(tDragonTable) do
         AngusPlayer:GetUnitByID(iUnitID):Kill()
    end
end
 
Last edited:
So, I'll preface this by saying I don't know much about Lua or the way it interacts with the game... But isn't it possible that the TeamMeet event is triggered for both civilizations, and therefore when it's triggered for the second one, some assumption the code makes is incorrect? E.g. I see that when iterating over cities you check for a nil value:
Code:
for city in AngusPlayer:Cities() do
    if city ~= nil then
But when iterating over units in GrabAngusUnits you just try and access a member without checking for nil value:
Code:
for pUnit in AngusPlayer:Units() do
    if not pUnit:IsDead() and not pUnit:IsDelayedDeath() then

I'm just not sure if the for loop is ever entered if those iterables are empty, but your city~=nil check made me think that it is the case
 
Top Bottom