1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Checking Lua outside of the game (MS-Windows)

Discussion in 'Civ5 - SDK / LUA' started by whoward69, Jun 29, 2016.

  1. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,518
    Location:
    Near Portsmouth, UK
    ModBuddy's support for Lua is not great. Most people write Lua and then start up the game to test it - which is a poor way to find syntax errors.

    There are several alternatives, mine is

    1) Download and install "Lua for Windows"
    2) From the Lua option now in the main menu, select SciTE
    3) From the File, Open ... dialog in SciTE, browse into the "~Documents\Firaxis ModBuddy" sub-directory, then into the sub-directory that's your mod
    4) In that sub-directory you should have three further sub-directories "Build", "Packages" and one named as your mod, browse into that one
    5) Browse into any sub-directories you use to organise files (LUA in my case) and Open the file you want to check - eg "C:\Users\{username}\Documents\Firaxis ModBuddy\Resolutions - Political Voting MP\Resolutions - Political Voting MP\LUA\ResolutionsPoliticalVoting.lua"
    6) On the toolbar, click the blue right pointing arrow head (the mouse over hover reads "Run Program")
    7) Correct any syntax errors, save the changes and click the blue arrow again - repeat until you have no syntax errors
    8) At some point you will get an error about GameInfo, GameInfoTypes, GameEvents or include() - this is the Lua environment looking for CivV globals and failing to find them.
    9) As you have been making changes directly to the Lua file(s) as ModBuddy reads them, rebuild the mod from within ModBuddy to deploy the changed files into the mod used by the game

    At this point your Lua syntax is correct and you can proceed with testing in-game - knowing that you are now only looking for logic errors (or typos related to game objects/methods)

    W
     
  2. LeeS

    LeeS Imperator Supporter

    Joined:
    Jul 23, 2013
    Messages:
    7,123
    Location:
    Illinois, USA
    Nice. This will save an enormous amount of time currently being lost from loading a mod into a game only to see one of those 'line 587: near = no )' sort of error messages in the lua log.
     
  3. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,518
    Location:
    Near Portsmouth, UK
    I probably should have posted this two years ago when I was using it to write/test/debug the river connection code.

    If you have some complex code to test, it may be quicker to create fake CivV Lua objects and test entirely within SciTE and only use the game for final acceptance tests - the spoiler has the code for the fake CivV objects needed to initially test the river connection code.

    Spoiler :
    Code:
    --
    -- MapSupport.lua
    --
    -- Bare minimum replacements for the DirectionTypes, Map and Plot objects to support testing of the RiverConnections code
    --
    
    --
    -- y=4  0   1   2   3   4   5
    -- y=3    0   1   2   3   4   5
    -- y=2  0   1   2   3   4   5
    -- y=1    0   1   2   3   4   5
    -- y=0  0   1   2   3   4   5
    --
    
    local gMapWidth = 8
    local gMapHeight = 5
    
    -- gRiverSegments[y][x][side] indicates if there is a river (not nil) and if so if the flow is clockwise (true) or anti-clockwise (false)
    -- only entries for DIRECTION_EAST (1), DIRECTION_SOUTHEAST (2) and DIRECTION_SOUTHWEST (3) are required if not nil (or for padding)
    local gRiverSegments = {
      -- y = 0
      {{},					{},					{},					{},						{},					{},						{},				{}},
      -- y = 1
      {{},					{},					{},					{},						{false, false},		{},						{},				{}},
      -- y = 2
      {{},					{true},				{nil, false, false},{nil, false, false},	{nil, false, false},{false, false, false},	{},				{}},
      -- y = 3
      {{},					{nil, nil, false},	{},					{},						{},					{false, false}, 		{},				{}},
      -- y = 4
      {{},					{},					{},					{},						{},					{}, 					{nil, false},	{}}
    }
    
    local gLakePlots = {
      -- y = 0
      {false, false, false, false, false, false, false, false},
      -- y = 1
      {false, false, false, false, false, false, false, false},
      -- y = 2
      {false, false, false, false, false, false, false, false},
      -- y = 3
      {false, false, false, false, false, false, false, false},
      -- y = 4
      {false, false, false, false, false, false, false, false}
    }
    
    local gSeaPlots = {
      -- y = 0
      {false, false, false, false, false, false, false, false},
      -- y = 1
      {false, false, false, false, false, false, false, false},
      -- y = 2
      {false, false, false, false, false, false, false, false},
      -- y = 3
      {false, false, false, false, false, false, false, false},
      -- y = 4
      {false, false, false, false, false, false, false, true }
    }
    
    local gMountainPlots = {
      -- y = 0
      {false, false, false, false, false, false, false, false},
      -- y = 1
      {false, false, false, false, false, false, false, false},
      -- y = 2
      {false, false, false, false, false, false, false, false},
      -- y = 3
      {false, false, false, false, false, false, false, false},
      -- y = 4
      {false, false, false, false, false, false, false, false}
    }
    
    DirectionTypes = {
    	NO_DIRECTION = -1,
    	DIRECTION_NORTHEAST = 0,
    	DIRECTION_EAST = 1,
    	DIRECTION_SOUTHEAST = 2,
    	DIRECTION_SOUTHWEST = 3,
    	DIRECTION_WEST = 4,
    	DIRECTION_NORTHWEST = 5,
    	NUM_DIRECTION_TYPES = 6
    }
    
    function Vector4(x, y, z, w)
      return {x=x, y=y, z=z, w=w}
    end
    
    Map = {
      rows = {},
    
      init = function()
        local self = Map
    
        for y = 0, gMapHeight-1, 1 do
    	  self.rows[y] = {}
    
    	  for x = 0, gMapWidth-1, 1 do
    	    self.rows[y][x] = Plot:new(x, y, gRiverSegments[y+1][x+1])
    	  end
    	end
      end,
    
    
      GetNumPlots = function()
        local self = Map
    
        return #self.rows * #self.rows[1]
      end,
    
      GetPlotByIndex = function(iPlotIndex)
        local self = Map
    
        return self.GetPlot(iPlotIndex % #self.rows[1], math.floor(iPlotIndex / #self.rows[1]))
      end,
    
      GetPlot = function(iPlotX, iPlotY)
        local self = Map
    
        return self.rows[iPlotY] and self.rows[iPlotY][iPlotX]
      end,
    
      PlotDirection = function(iPlotX, iPlotY, iDirection)
        local self = Map
    
        local iDeltaX = 0
    	local iDeltaY = 0
    
        if (iDirection == DirectionTypes.DIRECTION_EAST) then
    	  iDeltaX = 1
    	  iDeltaY = 0
        elseif (iDirection == DirectionTypes.DIRECTION_NORTHEAST) then
    	  iDeltaX = (iPlotY % 2)
    	  iDeltaY = 1
        elseif (iDirection == DirectionTypes.DIRECTION_SOUTHEAST) then
    	  iDeltaX = (iPlotY % 2)
    	  iDeltaY = -1
        elseif (iDirection == DirectionTypes.DIRECTION_SOUTHWEST) then
    	  iDeltaX = (iPlotY % 2) - 1
    	  iDeltaY = -1
        elseif (iDirection == DirectionTypes.DIRECTION_WEST) then
    	  iDeltaX = -1
    	  iDeltaY = 0
        elseif (iDirection == DirectionTypes.DIRECTION_NORTHWEST) then
    	  iDeltaX = (iPlotY % 2) - 1
    	  iDeltaY = 1
    	end
    
    	return self.GetPlot(iPlotX+iDeltaX, iPlotY+iDeltaY)
      end,
    }
    
    
    Plot = {
      new = function(self, iX, iY, segments)
        local me = {}
        setmetatable(me, self)
        self.__index = self
    
    	me.iX = iX
    	me.iY = iY
    
    	me.segments = segments
    
        return me
      end,
    
      toString = function(self)
        return string.format("Plot: %i, %i", self.iX, self.iY)
      end,
    
      GetPlotIndex = function(self)
        return self.iY * gMapWidth + self.iX
      end,
    
      GetX = function(self)
        return self.iX
      end,
    
      GetY = function(self)
        return self.iY
      end,
    
      IsWOfRiver = function(self)
        return self:IsRiverCrossing(DirectionTypes.DIRECTION_EAST)
      end,
    
      IsNWOfRiver = function(self)
        return self:IsRiverCrossing(DirectionTypes.DIRECTION_SOUTHEAST)
      end,
    
      IsNEOfRiver = function(self)
        return self:IsRiverCrossing(DirectionTypes.DIRECTION_SOUTHWEST)
      end,
    
      IsRiverCrossing = function(self, iDirection)
        return (self.segments[iDirection] ~= nil)
      end,
    
      IsRiverCrossingFlowClockwise = function(self, iDirection)
        return self.segments[iDirection]
      end,
    
      IsWater = function(self)
        return gSeaPlots[self.iY+1][self.iX+1] or self:IsLake()
      end,
    
      IsLake = function(self)
        return gLakePlots[self.iY+1][self.iX+1]
      end,
    
      IsMountain = function(self)
        return gMountainPlots[self.iY+1][self.iX+1]
      end,
    
      IsImpassable = function(self)
        return false
      end,
    }
    
    Map.init()
    
    --riverManager = RiverManager:new()
    --route = riverManager:getRiverRoute(1, 5, 1, 1, 3, false)
    
     

Share This Page