Ravana's Lua thread
Moderator: Forum Moderators
Ravana's Lua thread
I have been rewriting Orocia logic in Lua. When designing format for bonuses for enemy units, I reached solution that I think should be possible to do in more elegant way.
I want to hold bonus definitions in table, where combination of turn number and difficulty setting returns what modifications to apply that turn. However, those bonuses can refer to WML variables, which should be retrieved only once it is correct turn (local adaptive_multiplier = V.ORM_difficulty_setting). I solved it by having all effects return function which when called retrieves variable and returns function.
Any suggestions how to improve this?
Relevant code parts
I want to hold bonus definitions in table, where combination of turn number and difficulty setting returns what modifications to apply that turn. However, those bonuses can refer to WML variables, which should be retrieved only once it is correct turn (local adaptive_multiplier = V.ORM_difficulty_setting). I solved it by having all effects return function which when called retrieves variable and returns function.
Any suggestions how to improve this?
Relevant code parts
Code: Select all
-- each turn bonus of current turn is applied
function ORM.fun.apply_wave_modifications()
if ORM.unit_bonuses["t"..wesnoth.current.turn] == nil then return end
local difficulty = V.ORM_difficulty_mode
local units = wesnoth.get_units { side = 1 }
local bonus = ORM.unit_bonuses["t"..wesnoth.current.turn][difficulty]
for i,u in ipairs(units) do
wesnoth.add_modification(u, "trait", ORM.bonus.evaluate(bonus))
end
end
-- functions to initialize and evaluate bonuses
function ORM.bonus.evaluate(bonus)
local name = bonus.name
bonus = ORM.fun.map(function(e) return e() end, bonus)
bonus.name = name
return bonus
end
-- Usable for building trait that includes multiple bonuses
function ORM.bonus.build(name, effects)
effects.name = name
return effects
end
-- bonus definition
function ORM.bonus.swift(movement_modifier, strike_modifier)
return ORM.bonus.build("swift", {ORM.effect.increase_movement(movement_modifier), ORM.effect.increase_strikes(strike_modifier)})
end
function ORM.effect.increase_movement(movement_modifier)
return function()
local adaptive_multiplier = V.ORM_difficulty_setting
return T.effect{
apply_to = "movement",
increase=tostring(movement_modifier*adaptive_multiplier).."%"
}
end
end
function ORM.effect.increase_strikes(strike_modifier)
return function()
local adaptive_multiplier = V.ORM_difficulty_setting
return T.effect{
apply_to = "attack",
increase_attacks=tostring(strike_modifier*adaptive_multiplier).."%"
}
end
end
-- data file, defines initial wave bonuses
ORM.unit_bonuses = {
t2 = {
ultrahardcore=ORM.bonus.swift(50, 0)
}
}
-- https://en.wikibooks.org/wiki/Lua_Functional_Programming/Functions
function ORM.fun.map(func, array)
local new_array = {}
for i,v in ipairs(array) do
new_array[i] = func(v)
end
return new_array
end
Re: Ravana's Lua thread
Spent an hour finding that this results in each further call of g having changed x available.
Adding local keyword before assignment solved it.
Code: Select all
y=2
function f(x)
return function()
x=2*x
wesnoth.message(tostring(x))
end
end
g = f(y)
g()
g()
Re: Ravana's Lua thread
Is there any easy way to call modify_unit including $this_unit from Lua?
Re: Ravana's Lua thread
Trying to find out why having this function active(with rush mod on) results in OOS. It is called on side 1 turn refresh.
Is it safe to add object and change writable field of same unit reference?
Likely related
Code: Select all
function ORM.fun.apply_rush_mod()
if wesnoth.game_config.mp_settings.active_mods:find("EXI_Rush_Mod") then
local movement_modifier
if V.ORM_castledestruction_setting then
movement_modifier = 1.3
else
movement_modifier = 1.8
end
if wesnoth.current.turn <= 1 then
movement_modifier = 1
end
local units = wesnoth.get_units{
side = 1,
T["not"]{
T.filter_wml{
T.status{
ORM_rush_mod="yes"
}
}
}
}
for i,u in ipairs(units) do
wesnoth.add_modification(u, "object", {
ORM.effect.get(ORM.effect.add_status("ORM_rush_mod"))
})
u.moves = u.moves * movement_modifier
end
end
end
Likely related
Code: Select all
20180116 09:27:55< vn971> UPD: was able to solve my task "+2 movement on turn 1" on wesnoth-1.12.
20180116 09:27:55< vn971> It consists of these steps: 1. give an object with duration="turn" with a text-only ability/description 2. Add a object with duration="forever" to increase movement. 3. At start of turn 1 for each side (event), for each unit, set unit.moves = unit.max_moves 4. At start of turn 2, add an object with duration="forever" to decrease movement.
20180116 09:31:35< vn971> step 2 is needed because replays will break if I just set movement+2 from Lua. Somewhy, when I play a game, Lua works, but when a replay is happening, such changes are not respected, wesnoth says OOS. Step 3 is needed because wesnoth apparently has a bug of not really applying movement increase on turn 1. BUT, contrary to that, replays will _accept_ the movement then. So if you modify from Lua, then game works, replays don't. If you
20180116 09:31:35< vn971> use duration="turn" then replays work, but the game itself won't. OK, and step 4 is needed to decrease the movement back, because it was previously set with duration="forever", as I already explained why.
20180116 09:45:10< vn971> I wonder if some of those steps reveal actual wesnoth bugs ^
20180116 09:46:35< vn971> For example, allowing writing legit Lua code that will work in game but will not work in replays feels like a bug. Object with duration=turn that increases movement and does not work feels like a bug too.
20180116 09:55:17< Ravana_> that should be the cause of my current oos then
Re: Ravana's Lua thread
What is most sensible way to convert data between wml tables and normal tables?
Re: Ravana's Lua thread
it's unclear what you want here exactly, your do you wantRavana wrote:What is most sensible way to convert data between wml tables and normal tables?
a) an 'external' tool to convert your wml table to lua when porting your mod into lua
b) a lua code that cleans up your wml table code before processing them by lua
c) a lua code to write your lua tables into wml data when saving/loading savefiles?
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
Re: Ravana's Lua thread
c), I asked that for returning table from wesnoth.synchronise_choice. I have normal table that should be synced, so must be converted to wml table. And after it is synced, it is better to work with normal table again.
Re: Ravana's Lua thread
for that id' use a serialize function that basicially converts lua table into strings, i do the same in my addo. https://github.com/gfgtdf/PYR_No_Preper ... er.lua#L49 , note that that function i use in my addon onyl works for simple tables, that is, no userdata, and no tables that contian themselves recursively.
EDIT: the code linked above no loner uses serialisation since the deseialize methoid i used had security issues.
EDIT: the code linked above no loner uses serialisation since the deseialize methoid i used had security issues.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
- Celtic_Minstrel
- Developer
- Posts: 2211
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Ravana's Lua thread
Well, you can call any WML tag from Lua, so there's that. (ie, usingRavana wrote:Is there any easy way to call modify_unit including $this_unit from Lua?
wesnoth.fire
or wesnoth.wml_actions.tagname
) I wouldn't really recommend this though. In the case of modify_unit, you can get the list of from the filter (with wesnoth.get_units
) and loop over them in Lua to make whatever changes you need using the various accessors and mutators the API provides on the unit userdata.Personally, I think that using a table-to-string serializer as gfgtdf suggests is overkill. My recommendation for adding data to the save file would be to keep the Lua tables representing that data in a WML-compatible format (that is, use only non-integer keys that are valid identifiers, with values that are simple scalar values or simple arrays of scalar values).Ravana wrote:c), I asked that for returning table from wesnoth.synchronise_choice. I have normal table that should be synced, so must be converted to wml table. And after it is synced, it is better to work with normal table again.
Then you can simply use the
on_load
and on_save
events to inject your data into the save file (under some custom tag name) and retrieve it, respectively. (Incidentally, I couldn't find the documentation for these events or even on_mouse_action
via LuaWML...)