Control Code
Control Code
After finishing a 60 hour freeplay game I wanted to try my hand at modding. I saw that windmills have been somewhat debated already on the fourm but decided to try and make one myself.
So far ive got the research, item, and placeable working. the windmill at present works like a small solar panel, increasing and decreasing power with day/night. Id like to modify this to work with the wind speed/direction.
I saw that I can get access to game.windspeed/game.windorientation but im not sure how to get the placed item to react to the changes. Ive been looking for the code that controls the solar panels and steam engines to model it after but no luck.
I imagine i need to create a control.lua but all the examples ive found are for driving around vehicles.
So far ive got the research, item, and placeable working. the windmill at present works like a small solar panel, increasing and decreasing power with day/night. Id like to modify this to work with the wind speed/direction.
I saw that I can get access to game.windspeed/game.windorientation but im not sure how to get the placed item to react to the changes. Ive been looking for the code that controls the solar panels and steam engines to model it after but no luck.
I imagine i need to create a control.lua but all the examples ive found are for driving around vehicles.
Re: Control Code
Yes, you need a control.lua file. First, read up on the lua programming language if you haven't already (and especially if you haven't used a programming language before), I recommend PIL but you could watch some Youtube videos or whatever you prefer. Second, because of the way that Factorio is right now, very little of the energy code is viewable/usable from lua (it's mostly coded in c++). Third (following from 2), to do this you'd need an entity that can provide power (meaning, steam engine, accumulator, or solar panel) and to increase it's 'energy' (the value is actually the buffer for the entity) based on the wind speed/orientation as you desired. SO what you'd do is something likeNarinik wrote:I imagine i need to create a control.lua but all the examples ive found are for driving around vehicles.
Code: Select all
require "defines" -- added in edit, no idea why I forgot it :)
function init()
if not glob.windmills then glob.windmills = {} end -- create a table to store built windmills, only data in the glob table will the loaded with saves
end
game.oninit(function() init() end) -- call the init function when the mod is added to a game
game.onload(function() init() end) -- call the init function when a save is loaded
game.onevent(defines.events.onbuiltentity, function() -- get notifications for player-built entities
if event.createdentity.name == "wind_mill" then -- if the entity is the windmill
table.insert(glob.windmills, event.createdentity) -- place the new windmill entity into the windmill table
end
end)
game.onevent(defines.events.ontick, function()
if event.tick%60 == 4 then -- every 60 ticks / 1 second
for index, windmill in ipairs(glob.windmills) do
if windmill.valid then
GeneratePower(windmill)
else
table.remove(glob.windmills, index) -- remove the invalid windmill
end
end
end
end)
function GeneratePower(windmill)
windmill.energy = windmill.energy + (game.windspeed * 1000) * directionModifier(windmill)
end
function directionModifier(windmill)
if windmill.direction/8 ~= game.windorientation or 1-windmill.direction/8 ~= game.windorientation then
return 0.5 -- half generated power if the windmill is not facing in either the same direction or the opposite direction of the wind
else
return 1 -- do not reduce power if windmill IS facing in the same direction, or the opposite direction
end
end

A possible issue is that the energy (buffer) is pretty much set by Factorio and there isn't much you can do to change it's max size, nor can you give it more energy than Factorio decides it's buffer size is (if you set the energy property higher than the buffer it's simply set to be the size of the buffer...). There is a buffer property in the prototypes, but the last I knew Factorio pretty much ignores it, by which I mean it starts off with that value but if Factorio thinks it should be lower based on how much the prototype says it produces it'll do so without caring that you specifically told it to be larger...
There is one other thing to note: I'm not sure how much the wind may change in a normal game...I'm not sure if it's existence is even used right now in the base game. So it's possible you'd need some extra code to make the wind actually change yourself...
I hope that was at least a little helpful

<I'm really not active any more so these may not be up to date>
~FreeER=Factorio Modding
- Factorio Wiki
- My Factorio Modding Guide
- Wiki Modding Guide
Feel free to pm me
Or drop into #factorio on irc.esper.net
~FreeER=Factorio Modding
- Factorio Wiki
- My Factorio Modding Guide
- Wiki Modding Guide
Feel free to pm me

Or drop into #factorio on irc.esper.net
Re: Control Code
FreeEr: Thank you, you should post this on wiki, this is really good tutorial that explain how to do the magic lua work.
Re: Control Code
Well a lot of it is basic lua coding (for which you need to be at least slightly familiar with the language) and simply knowing which properties and methods are available for entities, which can be seen on the wiki here, and the events which are on the wiki here.Colombo wrote:FreeEr: Thank you, you should post this on wiki, this is really good tutorial that explain how to do the magic lua work.
I do have a tutorial on the wiki about making a simple bomber aircraft, here, which covers some of the essentials (though it's a bit outdated it's mostly still accurate I believe). The problem with making a fantastic tutorial is that it'd have to be very long or fairly vague to cover everything...The code I provided is somewhat exclusive to energy and a lot of people might not understand how it would apply to them without already knowing the lua language. A lot of the issues that modders (especially new modders, but also the more experienced ones) encounter are just the little quirks of Factorio's modding API (like the energy property being the buffer of the entity, and that some entities only accept electrical energy sources and not burner power sources, etc.) which can really only be learned (sometimes) by looking at the wiki, figuring it out yourself or asking someone who's already discovered the quirk


I'm glad you found it helpful however

Re: Control Code
Sure, I know your tutorial, but it covers only basic stuff, not that advanced properties that could be achieved by this.
Eg. I wanted to make "dust collectors", various tools that would lower pollution. As from 10.1, assembling machines and labs could run on burners, this will be usefull for my "burner aditions" mod, that will add those things and enable more coal-powered alternative.
But, I didn't know how to create those advanced behavior. The first, passive, dust collector would basically do:
lower pollution -> create dust -> if there is dust, stop working (forcing player to manage waste)
But how could I do it? I tried to read through Treefarm and Dytech, that have similar behavior, but those have quite complicated stuff and that behavior was a bit lost. Your example provided me with clear way how to see and work with it.
Eg. I wanted to make "dust collectors", various tools that would lower pollution. As from 10.1, assembling machines and labs could run on burners, this will be usefull for my "burner aditions" mod, that will add those things and enable more coal-powered alternative.
But, I didn't know how to create those advanced behavior. The first, passive, dust collector would basically do:
lower pollution -> create dust -> if there is dust, stop working (forcing player to manage waste)
But how could I do it? I tried to read through Treefarm and Dytech, that have similar behavior, but those have quite complicated stuff and that behavior was a bit lost. Your example provided me with clear way how to see and work with it.
Re: Control Code
True, it only directly covers the basics, but it also mentions the wiki locations where the properties can be found. It should probably also mention the Prototypes wiki page, but that was created after the tutorial wasColombo wrote:Sure, I know your tutorial, but it covers only basic stuff, not that advanced properties that could be achieved by this.

Mostly because it was tailored to something specific and didn't include non-relevant code, which a long tutorial (and large mods) wouldColombo wrote:Your example provided me with clear way how to see and work with it.

Pollution control can be found under the "Lua/Game" object as pollute and getpollution, you should (I think) be able to give pollute a negative value to decrease pollution, and dust_collector.insert to add dust at the same time after using getinventory to see if there was any room (or caninsert) or getitemcount to see if there was any dust specifically (rather than any items), all of which are mentioned in the Lua/Inventory object, alternatively (what I believe DyTech does) you can give the dust_collector a negative emissions_per_tick value in the prototype (as mentioned in the Prototype/Entity page) to decrease pollution and simply insert some dust every second or so, but then you can't stop the pollution decreasing without destroying the collectors (and/or replacing them with a 'non-working' entity). Of course either way you'd need to know where the dust_collectors are which means adding to them to a glob table in onbuiltentity (and realizing that robot built entities do not raise the onbuiltentity event at this time, to find those you'd need player interaction through a script interface or guis...). The Treefarm hydroculture seems to use the emissions properties of the energy_source rather than emissions_per_tick which means pollution is only decreased when it's actually working, however the trees all use the emissions_per_tick (like the regular base game trees do, and I think DyTech as well). So if you went with the first you'd use code like (most numbers are arbitrary)
Code: Select all
game.onevent(defines.events.onbuiltentity, function()
if event.createdentity.name == "dust_collector" then table.insert(glob.collectors, event.createdentity) end
end)
game.onevent(defines.events.ontick, function()
if event.tick%60 == 20 then
for index, collector in ipairs(glob.collectors) do
if collector.valid then
if collector.caninsert{name="dust", count=10} and collector.getitemcount("dust") < 20 then -- if 10 dust can be inserted and it currently has less than 20
collector.insert{name="dust", count=10}
game.pollute(collector.position, -10) -- game.pollute, according to the wiki, takes a position to pollute and the amount of pollution to add
end
else
table.remove(glob.collectors, index)
end
end
end
end)

Re: Control Code
FreeER, that's pretty much exactly what I was looking for. Thanks! Sorry for the delayed reply, I was away for the weekend

I actually have a degree in computer science and am working on a masters. I didn't want to be too specific in my question,(asking for entry points, event handlers ect) since im completely unfamiliar with the framework that was implemented.FreeER wrote:(and especially if you haven't used a programming language before)
Re: Control Code
Glad it was helpful...hm, I seem to have forgotten require "defines" at the top (that would cause an error..., it's located in data\core\lualib by the way).Narinik wrote:FreeER, that's pretty much exactly what I was looking for. Thanks!
No problem, just left me wondering if you'd managed to see itNarinik wrote:Sorry for the delayed reply, I was away for the weekend![]()

Ah, you're where I wish I wasNarinik wrote:I actually have a degree in computer science and am working on a masters.


Re: Control Code
Im not sure why my post isnt showing up, so if this is a repost ill delete.
How do I define a new type? So I imagine i can access windmill.production and do something like
as is, the 'windmill' is just a solar panel that reacts to the sun.
How do I define a new type? So I imagine i can access windmill.production and do something like
Code: Select all
windmill.production = (generate number) +"W"
as is, the 'windmill' is just a solar panel that reacts to the sun.
Code: Select all
type = "solar-panel",
name = "simple-windmill",
icon = "__windmill__/graphics/windmill_icon.png",
flags = {"placeable-neutral", "player-creation"},
minable = {hardness = 0.2, mining_time = 0.5, result = "simple-windmill"},
max_health = 100,
corpse = "big-remnants",
collision_box = {{-0.7, -1.4}, {0.7, 1.4}},
selection_box = {{-0.8, -1.5}, {0.8, 1.5}},
energy_source =
{
type = "electric",
usage_priority = "primary-output"
},
picture =
{
filename = "__windmill__/graphics/windmill.png",
priority = "high",
width = 52,
height = 96
},
production = "500W"
}
Re: Control Code
Not a repost as far as I can tell.Narinik wrote:Im not sure why my post isnt showing up, so if this is a repost ill delete.
This is currently not possible. Neither actual types (like type="windmill") nor adding a new property to the type (Factorio simply ignores it), nor can you dynamically change the prototype once it's loaded (you can of course use regular lua functions in the prototype file, but you can't access and change those values during runtime). Which means you can not simply change the production value of a solar panel in game based on the wind nor make a new type that works like the solar panel but using wind instead of day light as a production modifier.Narinik wrote:How do I define a new type?
In this case you could probably use a type accumulator (or generator) to prevent it being affected by the sun and keep it's buffer filled in ontick (based on the wind of course). What's done to work around this with more complicated issues is to store as a variable in the control.lua any additional information that's needed (and maybe store the lua entity in a table that also includes that info, if each entity will be different), and (if necessary) use createentity to spawn another entity (usually with an invisible image and no collision) in the same position in order to use the features of other types (a train wagon with a roboport for example, see the Wagon mod). You can of course make a post in the interface requests and encourage the devs to create a type that works based on the wind, or simply being able to specify the production modifier for solar-panels, or anything else you believe would be helpful.
Re: Control Code
So here you can see my awesome gfx. but the question being, why do i get unknown key ect?
in my data.lua
in my data.lua
Code: Select all
{
type = "technology",
name = "WindPower",
- Attachments
-
- untitled.PNG (225.21 KiB) Viewed 7338 times
Re: Control Code
Unkown key:"type-name.name" is the default name for prototypes that do not have a locale translation, which are added by creating a 'locale' folder and inside that a folder with the two letter language code ('en' for english), and then a cfg file for the actual locale data (there can be multiple files as in the base game or a single file), inside the cfg(s) you use the headers And then beneath the proper header add the translations in the format: the-code-name=Name/Description shown in game
The cfg(s) must have an encoding of "UTF-8 without BOM", I find it easiest to copy an existing locale file to avoid issues with the encoding.
Mod control.lua text (ie, game.player.print, game.showmessagedialog, etc.) can be translated by using a 'script-locale' folder with a single cfg named using the two letter code (instead of nested folders), and then using game.gettext(text-code-name-in-cfg) in the control.lua instead of hard coding the string (which will pull the proper translation based on the language settings from the locales). Mod campaigns and scenarios use a folder 'locale' like the prototype locales but the same file setup as stated for the control.lua locales.
I think that covers all of the locale information
edit: forgot some (copied from wiki):
game.localise is the same as game.gettext but allows accessing base game localisations as well.
game.getlocaliseditemname takes an item's code-name and returns the localised name
getlocalisedentityname and getlocalisedtechnologyname, see above but for entities and technologies.
Code: Select all
[autoplace-control-names]
[entity-name]
[entity-description]
[technology-name]
[technology-description]
[item-group-name]
[item-name]
[item-description]
[item-limitation] (note: only used for production-module-usable-only-on-intermeidates in the base game, not sure how this header actually works to be honest)
[equipment-name]
[modifier-description] (note: tech modifiers can not be created with lua so...until that's possible this one is practically useless to modders)
[damage-type-name]
[tile-name]
[recipe-name]
[fluid-name]
The cfg(s) must have an encoding of "UTF-8 without BOM", I find it easiest to copy an existing locale file to avoid issues with the encoding.
Mod control.lua text (ie, game.player.print, game.showmessagedialog, etc.) can be translated by using a 'script-locale' folder with a single cfg named using the two letter code (instead of nested folders), and then using game.gettext(text-code-name-in-cfg) in the control.lua instead of hard coding the string (which will pull the proper translation based on the language settings from the locales). Mod campaigns and scenarios use a folder 'locale' like the prototype locales but the same file setup as stated for the control.lua locales.
I think that covers all of the locale information

edit: forgot some (copied from wiki):
game.localise is the same as game.gettext but allows accessing base game localisations as well.
game.getlocaliseditemname takes an item's code-name and returns the localised name
getlocalisedentityname and getlocalisedtechnologyname, see above but for entities and technologies.
Re: Control Code
Sweet, got it working as a generator type. but it acts kind of funny. It only updates once a second(event.tick%60) so i get this as a power graph:
- Attachments
-
- untitled.PNG (406.24 KiB) Viewed 7337 times
Re: Control Code
yeah...not much can be done about that, other than doing it every tick (in which case you'd probably want extra code to prevent a loop over 100+ wind mills freezing the game...). Or maybe staggering when each windmill is filled, I've never tried that to be honest. Of course, while it looks funny every second, it's fairly easy to pretend that it's filling a capacitor that gets drained every second instead of feeding the power into the grid immediately...Narinik wrote:Sweet, got it working as a generator type. but it acts kind of funny. It only updates once a second(event.tick%60) so i get this as a power graph:
Re: Control Code
I think ive got it working as a generator. set the ontick to fire every tick to smooth out the graph.
also put together a quick model, that is most likely at the wrong angle.
also put together a quick model, that is most likely at the wrong angle.
- Attachments
-
- untitled.PNG (12.31 KiB) Viewed 7326 times
Re: Control Code
nice 

Re: Control Code
windmill ingame, angle is a little off. got the animation working but it only plays once for some reason. is it possible to just have it play and set the animation speed?
- Attachments
-
- untitled.PNG (191.81 KiB) Viewed 7325 times
Re: Control Code
I don't think I've had that issue before, but then I rarely work with graphics... I know there is an animation_speed property so you can try that if you're sure you've got the other properties (frame_count, line_length, etc.) right.Narinik wrote:got the animation working but it only plays once for some reason. is it possible to just have it play and set the animation speed?
edit: there's also animation_speed_coefficient, structure_animation_speed_coefficient, structure_animation_movement_cooldown, used on some entities in the base game...I can't guarantee they are used for all animations however.
edit2: From looking at the source those last three are for only certain entities not all entities, but animation_speed should work for any entity with an animation.
Re: Control Code
Switched over to being a generator, not sure why this is happening:
- Attachments
-
- untitled.PNG (297.87 KiB) Viewed 7305 times
Re: Control Code
hm, no idea unless it is somehow producing a negative amount of energy (or using power instead of generating it)...Narinik wrote:Switched over to being a generator, not sure why this is happening: