Need some help with LUA

Place to get help with not working mods / modding interface.
Post Reply
B1tchFight
Inserter
Inserter
Posts: 26
Joined: Thu Apr 21, 2016 8:53 am
Contact:

Need some help with LUA

Post by B1tchFight »

Hey guys,

I plan to change the Supply scenario to play it on MP. I managed to get it to work. The only issue I had was the timer because the Scenario is written as singleplayer. So I changed some of the lines and added a few loops to make it playable for more people.

I encountered a problem that I couldn't save the game. To be able to play it in MP I have to start it in SP, save it, load it as MP game. That worked until I added the loops. I couldn't figure out where the problem was and just deleted it and wanted to start again.

May someone help me changing this? :)

User avatar
Adil
Filter Inserter
Filter Inserter
Posts: 945
Joined: Fri Aug 15, 2014 8:36 pm
Contact:

Re: Need some help with LUA

Post by Adil »

You really should demonstrate your code instead of deleting it if you expect help.
And describing what exactly was the problem with load would be useful too.
I do mods. Modding wiki is friend, it teaches how to mod. Api docs is friend too...
I also update mods, some of them even work.
Recently I did a mod tutorial.

B1tchFight
Inserter
Inserter
Posts: 26
Joined: Thu Apr 21, 2016 8:53 am
Contact:

Re: Need some help with LUA

Post by B1tchFight »

I know I know ^^ But it was a mess. I started over and did it a bit better now. I just asked for help before I got to the point where it "stops".

As example I used the Supply mission control.lua and changed (I think) most of the important stuff to MP.

To give you a idea what this code should do (one day) :D All player see a Level overview in the upper left corner. Level 1 says "You need X amount of whatever" put this in a predefined chest and you are able to click "next" or let the time run out. In that case you put all materials in it and the time runs off you come to the next level. (or one of the players can click "next") This is supposed to go for a unlimited number of levels. (Already changed my code generator to do that. It's written in C and can spit out 100 levels+ in 1 sec. Just picking random materials as requirement based on the level an a random amount based on the level putting them together and all I have to do is to put this code into the control.lua. (I might store that in a separate file later) I use just 10 simple predefined materials so far for testing. But on level 100 I can require 100000 Iron plate for example)


I left out the lines I think they are working so far because they do not refer to a SP or MP function. I know this code is not clean. I don't have experiences with lua. That's why I checked out different mods to get a idea for the syntax since a lot of it is similar to c. I know quite some C so it's not hard to understand whats going on on the screen. Right now I have a problem on with the marked lines. It might be better to write the entire script from scratch but like I said my programming skills with lua are not good enough for that.


So far It's giving me a error. ^^ "attend to index global"

Do you need the entire control.lua content?

name = "level-start",
init = function(event)

for i, player in pairs(game.players) do -- loop to add the frame for the level information for all players
> local level = levels[global.level]
> local frame = game.players.gui.top.add{type="frame", name="frame", direction="vertical", caption = {"", {"level"}, " ", global.level}}
> frame.add{type="label", name="time_left"}
> frame.add{type="label", caption={"", {"required-items"}, ":"}, style="caption_label_style"}

global.accumulated = {}
global.required = {}
global.labels = {}
local table = frame.add{type="table", name="table", colspan=2}
local item_prototypes = game.item_prototypes
for index, item in pairs(level.requirements) do
table.add{type="label", caption=item_prototypes[item.name].localised_name}
table.add{type="label", caption="0/" .. item.count, name=item.name}
global.accumulated[item.name] = 0
global.required[item.name] = item.count
end --loop ends
end



if global.level < #levels then
local next_level = levels[global.level + 1]
frame.add{type="label", caption={"", {"next-level"}, ":"}, style="caption_label_style"}
local table = frame.add{type="table", colspan=2}
local item_prototypes = game.item_prototypes
for index, item in pairs(next_level.requirements) do
local diff;
if global.required[item.name] ~= nil then
diff = item.count - global.required[item.name]
else
diff = item.count
end
if diff ~= 0 then
table.add{type="label", caption=item_prototypes[item.name].localised_name}
end
if diff > 0 then
table.add{type="label", caption="+" .. diff}
elseif diff < 0 then
table.add{type="label", caption=diff}
end
end
end
global.level_started_at = event.tick
update_info()
end,
},
{
name = "level-progress",
update =
function(event)
local update_info_needed = false
local level = levels[global.level]
for index, chest in pairs(global.chests) do
local inventory = chest.get_inventory(defines.inventory.chest)
local contents = inventory.get_contents()
for itemname, count in pairs(contents) do
if global.accumulated[itemname] == nil then
goto continue
end
local counttoconsume = global.required[itemname] - global.accumulated[itemname]
if counttoconsume > count then
counttoconsume = count
end
if counttoconsume ~= 0 then
inventory.remove{name = itemname, count = counttoconsume}
global.accumulated[itemname] = global.accumulated[itemname] + counttoconsume
update_info_needed = true
end
::continue::
end
end
if update_info_needed then
update_info()
end
update_time_left()
end,

condition = function(event)
local level = levels[global.level]
local time_left = get_time_left()

local result = true
for index, item in pairs(level.requirements) do
local accumulated = global.accumulated[item.name]
if accumulated < item.count then
result = false
end
end

if result and game.player.gui.top.next_level == nil then
game.player.gui.top.add{type = "button", name = "next_level", caption={"next-level"}}
end

if time_left <= 0 then
if result == false then
game.set_game_state{game_finished=true, player_won=false}
game.player.set_ending_screen_data({"points-achieved", global.points})
return false
else
return true
end
end

return false
end,
action = function(event, story)
if game.player.gui.top.next_level ~= nil then
game.player.gui.top.next_level.destroy()
end
global.level = global.level + 1
local points_addition = (global.level - 1) * 10
game.player.print({"level-completed", global.level - 1, points_addition})
global.points = global.points + points_addition

if global.level < #levels + 1 then
game.player.gui.top.frame.destroy()
story_jump_to(story, "level-start")
end
end
},
{
action = function()
game.player.set_ending_screen_data({"points-achieved", global.points})
end
}
}
}

seronis
Fast Inserter
Fast Inserter
Posts: 225
Joined: Fri Mar 04, 2016 8:04 pm
Contact:

Re: Need some help with LUA

Post by seronis »

Code that isnt properly tabulated and formatted generally is not considered worth looking at. So if you ever need to post more than about a half dozen lines of code you should use a source code specific paste site or in the case of mods zip up the whole mod and post a download link.

ratchetfreak
Filter Inserter
Filter Inserter
Posts: 952
Joined: Sat May 23, 2015 12:10 pm
Contact:

Re: Need some help with LUA

Post by ratchetfreak »

B1tchFight wrote:I know I know ^^ But it was a mess. I started over and did it a bit better now. I just asked for help before I got to the point where it "stops".

As example I used the Supply mission control.lua and changed (I think) most of the important stuff to MP.

To give you a idea what this code should do (one day) :D All player see a Level overview in the upper left corner. Level 1 says "You need X amount of whatever" put this in a predefined chest and you are able to click "next" or let the time run out. In that case you put all materials in it and the time runs off you come to the next level. (or one of the players can click "next") This is supposed to go for a unlimited number of levels. (Already changed my code generator to do that. It's written in C and can spit out 100 levels+ in 1 sec. Just picking random materials as requirement based on the level an a random amount based on the level putting them together and all I have to do is to put this code into the control.lua. (I might store that in a separate file later) I use just 10 simple predefined materials so far for testing. But on level 100 I can require 100000 Iron plate for example)


I left out the lines I think they are working so far because they do not refer to a SP or MP function. I know this code is not clean. I don't have experiences with lua. That's why I checked out different mods to get a idea for the syntax since a lot of it is similar to c. I know quite some C so it's not hard to understand whats going on on the screen. Right now I have a problem on with the marked lines. It might be better to write the entire script from scratch but like I said my programming skills with lua are not good enough for that.


So far It's giving me a error. ^^ "attend to index global"

Do you need the entire control.lua content?

Code: Select all

   name = "level-start",
   init = function(event)
       
   for i, player in pairs(game.players) do  -- loop to add the frame for the level information for all players          
>     [b] local level = levels[global.level]
>     local frame = game.players[i].gui.top.add{type="frame", name="frame", direction="vertical", caption = {"", {"level"}, " ", global.level}}
>      frame.add{type="label", name="time_left"}
>      frame.add{type="label", caption={"", {"required-items"}, ":"}, style="caption_label_style"}[/b]
      global.accumulated = {}
      global.required = {}
      global.labels = {}
      local table = frame.add{type="table", name="table", colspan=2}
      local item_prototypes = game.item_prototypes
      for index, item in pairs(level.requirements) do
         table.add{type="label", caption=item_prototypes[item.name].localised_name}
         table.add{type="label", caption="0/" .. item.count, name=item.name}
         global.accumulated[item.name] = 0
         global.required[item.name] = item.count
      end --loop ends
   end



      if global.level < #levels then
      local next_level = levels[global.level + 1]         
      frame.add{type="label", caption={"", {"next-level"}, ":"}, style="caption_label_style"}
      local table = frame.add{type="table", colspan=2}
      local item_prototypes = game.item_prototypes
      for index, item in pairs(next_level.requirements) do
      local diff;
      if global.required[item.name] ~= nil then
         diff = item.count - global.required[item.name]
         else
         diff = item.count
      end
      if diff ~= 0 then
         table.add{type="label", caption=item_prototypes[item.name].localised_name}
      end
      if diff > 0 then
         table.add{type="label", caption="+" .. diff}
         elseif diff < 0 then
         table.add{type="label", caption=diff}
         end
      end
   end
   global.level_started_at = event.tick
   update_info()
end,
   },
   {
      name = "level-progress",
      update =
      function(event)
        local update_info_needed = false
        local level = levels[global.level]
        for index, chest in pairs(global.chests) do
          local inventory = chest.get_inventory(defines.inventory.chest)
          local contents = inventory.get_contents()
          for itemname, count in pairs(contents) do
            if global.accumulated[itemname] == nil then
              goto continue
            end
            local counttoconsume = global.required[itemname] - global.accumulated[itemname]
            if counttoconsume > count then
              counttoconsume = count
            end
            if counttoconsume ~= 0 then
              inventory.remove{name = itemname, count = counttoconsume}
              global.accumulated[itemname] = global.accumulated[itemname] + counttoconsume
              update_info_needed = true
            end
            ::continue::
          end
        end
        if update_info_needed then
          update_info()
        end
        update_time_left()
      end,

      condition = function(event)
        local level = levels[global.level]
        local time_left = get_time_left()

        local result = true
        for index, item in pairs(level.requirements) do
          local accumulated = global.accumulated[item.name]
          if accumulated < item.count then
            result = false
          end
        end

        if result and game.player.gui.top.next_level == nil then
          game.player.gui.top.add{type = "button", name = "next_level", caption={"next-level"}}
        end

        if time_left <= 0 then
          if result == false then
            game.set_game_state{game_finished=true, player_won=false}
            game.player.set_ending_screen_data({"points-achieved", global.points})
            return false
          else
            return true
          end
        end

        return false
      end,
      action = function(event, story)
        if game.player.gui.top.next_level ~= nil then
          game.player.gui.top.next_level.destroy()
        end
        global.level = global.level + 1
        local points_addition = (global.level - 1) * 10
        game.player.print({"level-completed", global.level - 1, points_addition})
        global.points = global.points + points_addition

        if global.level < #levels + 1 then
          game.player.gui.top.frame.destroy()
          story_jump_to(story, "level-start")
        end
      end
    },
    {
      action = function()
        game.player.set_ending_screen_data({"points-achieved", global.points})
      end
    }
  }
}
you should use code tags for code, it'll keep indentation and show it in the scrollable subwindow;

User avatar
Adil
Filter Inserter
Filter Inserter
Posts: 945
Joined: Fri Aug 15, 2014 8:36 pm
Contact:

Re: Need some help with LUA

Post by Adil »

Well, that's a lot of code, but not sufficient to determine what's the problem. When game errorrs, it provides exact number at which error occured. Simply scouring codesheet for typos is not enjoyable when script size gets over a dozen of lines. For such cases it is better to provide the complete mod, if you can't localize the bug source.

I see no place in the code, where init() is called. But my guess would be, that you try to call it from on_load().

on_load() is crappy place these days, despite the intuition, it is completely unlike the on_init() these days. Unlike latter, during the call code function inside on_load() cannot access any not-pure-lua object which is all API including game.players .

And generally, you don't need that handler anyway. For example in you case you should create your gui elements during on_player_created event.
I do mods. Modding wiki is friend, it teaches how to mod. Api docs is friend too...
I also update mods, some of them even work.
Recently I did a mod tutorial.

Post Reply

Return to “Modding help”