Elvish_Hunter's Lua thread
Moderator: Forum Moderators
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Elvish_Hunter's Lua thread
Yesterday I finished writing my second Lua tag. I took inspiration from the FutureWML page, and so we have an [harm_unit] tag.
How it works:
This tag should harm selected units in a similar way to what happens in combat, and if their HP goes to 0 or less, kill them.
It requires the following:
- StandardUnitFilter, to select the units to harm
- amount, the amount of damage to apply on units; if missing, this gives an error
- damage_type, if present the final damage will be altered by unit resistance
It also sets the damage applied to variable harm_amount.
Now, I have three questions:
- FutureWML says that it should have also a "alignment" key. There is any way to implement this, that should be getting a particular location's ToD and check it against cfg.alignment? Please keep in mind that I'm still a Lua beginner.
- I placed ipairs(wesnoth.get_units) directly in the cycle for. Should I have used this instead?- If a leader is killed by wesnoth.fire{"kill"}, if no last breath/death event for this unit is defined, or if such event doesn't contain [endlevel] result=defeat, defeat isn't immediate, but happens on the next turn start. Is it an error of mine that I didn't noticed? If yes, how to fix this?
I already tested it, and seems to work. Can you kindly tell me if there is something else to correct, or is it ready for core?
Code: Select all
local helper = wesnoth.require "lua/helper.lua"
function wesnoth.wml_actions.harm_unit(cfg)
local amount = tonumber(cfg.amount) or helper.wml_error("[harm_unit] missing required amount= attribute")
local damage_type = (cfg.damage_type)
local damage
for index, unit_to_harm in ipairs(wesnoth.get_units(cfg)) do
if damage_type then
damage = (amount / 100) * wesnoth.unit_resistance(unit_to_harm, tostring(damage_type))
else
damage = amount
end
damage = math.floor(damage)
unit_to_harm.hitpoints = unit_to_harm.hitpoints - damage
wesnoth.float_label(unit_to_harm.x,unit_to_harm.y,string.format("<span foreground='red'>%d</span>",damage))
if unit_to_harm.hitpoints <= 0 then
wesnoth.fire("kill", {id=unit_to_harm.id, animate="yes", fire_event="yes"})
end
wesnoth.set_variable("harm_amount", damage)
end
wesnoth.wml_actions.redraw {}
end
This tag should harm selected units in a similar way to what happens in combat, and if their HP goes to 0 or less, kill them.
It requires the following:
- StandardUnitFilter, to select the units to harm
- amount, the amount of damage to apply on units; if missing, this gives an error
- damage_type, if present the final damage will be altered by unit resistance
It also sets the damage applied to variable harm_amount.
Now, I have three questions:
- FutureWML says that it should have also a "alignment" key. There is any way to implement this, that should be getting a particular location's ToD and check it against cfg.alignment? Please keep in mind that I'm still a Lua beginner.
- I placed ipairs(wesnoth.get_units) directly in the cycle for. Should I have used this instead?
Code: Select all
local units_to_harm=wesnoth.get_units(cfg)
for index, unit_to_harm in ipairs(units_to_harm) do
I already tested it, and seems to work. Can you kindly tell me if there is something else to correct, or is it ready for core?
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: Elvish_Hunter's Lua thread
Maybe you should post the stuff as patches then (if you want to get write access like me )
http://gna.org/patch/?group=wesnoth
2 problems:
-The fired events can invalidate unit references which are still to be iterated on (kill one of the remaining units) - look how it's done in move_unit (it's the same problem there).
-harm_amount is never cleared. Don't think there's a functionality for this yet... it should be auto-cleared when leaving the calling event.
http://gna.org/patch/?group=wesnoth
2 problems:
-The fired events can invalidate unit references which are still to be iterated on (kill one of the remaining units) - look how it's done in move_unit (it's the same problem there).
-harm_amount is never cleared. Don't think there's a functionality for this yet... it should be auto-cleared when leaving the calling event.
If you've found no suitable wesnoth.something function then there's no way yet apparently...Elvish_Hunter wrote:There is any way to implement this, that should be getting a particular location's ToD and check it against cfg.alignment?
If you need units_to_harm later on make a variable, else call it directly.Elvish_Hunter wrote: - I placed ipairs(wesnoth.get_units) directly in the cycle for. Should I have used this instead?Code: Select all
local units_to_harm=wesnoth.get_units(cfg) for index, unit_to_harm in ipairs(units_to_harm) do
I has always been this way afaik. (idependently from your lua code here)Elvish_Hunter wrote:- If a leader is killed by wesnoth.fire{"kill"}, if no last breath/death event for this unit is defined, or if such event doesn't contain [endlevel] result=defeat, defeat isn't immediate, but happens on the next turn start. Is it an error of mine that I didn't noticed? If yes, how to fix this?
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
I'd be honoured to gain a Code and WML Contributor title, of course, but I don't know how to make patches on Windows...Anonymissimus wrote:Maybe you should post the stuff as patches then (if you want to get write access like me )
EDIT: this mean that I'll have to install SVN, right?
I'll look. Anyway, when I tested, this code really killed only those units that needed to be killed, that is those with 0 or less HP.Anonymissimus wrote:-The fired events can invalidate unit references which are still to be iterated on (kill one of the remaining units) - look how it's done in move_unit (it's the same problem there).
EDIT: Looked, apparently it's done in the same way:
Code: Select all
if fire_event then
wesnoth.fire_event("moveto", x, y, x2, y2)
end
harm_amount is not supposed to be cleared, but instead stored as WML variable. Not a bug, a feature.Anonymissimus wrote:-harm_amount is never cleared.
http://wiki.wesnoth.org/FutureWML wrote:Ideas that are fairly sound
New Actions
* [harm_unit] - harms a unit(s) then saves the amount as $harm_amount
o [filter]
o amount
o damage_type
o alignment
Then I can't add alignment key. I hoped that I simply overlooked it, but this time it wasn't my mistake (once in a lifetime )Anonymissimus wrote:If you've found no suitable wesnoth.something function then there's no way yet apparently...
No, it's needed only in the cycle for.Anonymissimus wrote:If you need units_to_harm later on make a variable
Ah, OK. Thanks for all your clarifications!Anonymissimus wrote:I has always been this way afaik.
If I'll have some other questions, or make some other stuff, I'll post here, of course.
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: Elvish_Hunter's Lua thread
yesElvish_Hunter wrote: EDIT: this mean that I'll have to install SVN, right?
It's not a variable specifically requested by the wml coder as opposed to the other variable-storing tags. It should behave like e.g. second_unit (in moveto events) and such, which are only valid until the end of the event. harm_amount however remains until teh end of the campaign unless cleared by the wml coder.harm_amount is not supposed to be cleared, but instead stored as WML variable. Not a bug, a feature.
You could do wesnoth.get_locations for all locs matching the alignment= key and then look in the obtained array for the unit's hex but it'd be very inefficient. I guess I could make a function available in the lua interface but you need to wait until next 1.9 release unless you compile yourself.Then I can't add alignment key. I hoped that I simply overlooked it, but this time it wasn't my mistake (once in a lifetime )
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
It should. But by looking to mainline wml-tags and helper (not so easy, for a beginner like me) I wasn't able to find any reference to second_unit. I tried also adding the value to wesnoth.current.event_context, either by using table.insert or directly, obtaining an error "table expected, got userdata". So, I suppose that such auto-storing (unit, second_unit, x1, x2...) are still managed by C++, that means: I have no idea, for now at least, on how to make harm_amount behave like second_unit.Anonymissimus wrote:It's not a variable specifically requested by the wml coder as opposed to the other variable-storing tags. It should behave like e.g. second_unit (in moveto events) and such, which are only valid until the end of the event. harm_amount however remains until teh end of the campaign unless cleared by the wml coder.
I imagined this alignment to, in fact, assign alignment to the damage itself, that is if [harm_unit] has alignment=chaotic, and happens during daytime, damage will be reduced by 25%, like if done by a chaotic unit. I wonder, however, like this key will work with liminal alignment, or with 24-hour ToD...Anonymissimus wrote:You could do wesnoth.get_locations for all locs matching the alignment= key and then look in the obtained array for the unit's hex but it'd be very inefficient.
I guess that I'll wait for your function, or for me to have a good idea on this.
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
Re: Elvish_Hunter's Lua thread
Concerning alignment (and it would also subsume resistance computation), you could perhaps create a dummy unit with a given alignment and a given damage type, and then throw it at the to-be-damaged unit (LuaWML:Units#wesnoth.simulate_combat.) I guess the easiest way to interpret the result of the simulation would be to give the dummy unit 100% cth, a dummy range, and a single attack.Elvish_Hunter wrote:I imagined this alignment to, in fact, assign alignment to the damage itself, that is if [harm_unit] has alignment=chaotic, and happens during daytime, damage will be reduced by 25%, like if done by a chaotic unit. I wonder, however, like this key will work with liminal alignment, or with 24-hour ToD...
I guess that I'll wait for your function, or for me to have a good idea on this.
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
Thanks silene. For what I understood, at this point, is better to remove the alignment= key idea, to make this code simpler to maintain.
There is still one question, however: there is any way to make harm_amount automatically cleared at the end of the event in which [harm_unit] is used? If not, I think that I'll add a key "output=yes/no", with default no (that is, if no key given it will be nil), so it will be up to the campaign/UMC/whatever author to decide if have the damage stored in variable harm_amount or not.
Thanks again, to you and Anonymissimus, for your support!
There is still one question, however: there is any way to make harm_amount automatically cleared at the end of the event in which [harm_unit] is used? If not, I think that I'll add a key "output=yes/no", with default no (that is, if no key given it will be nil), so it will be up to the campaign/UMC/whatever author to decide if have the damage stored in variable harm_amount or not.
Thanks again, to you and Anonymissimus, for your support!
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: Elvish_Hunter's Lua thread
I'd just do
if cfg.variable then wesnoth.set_variable(cfg.variable, ...) else ...
No, there's not (yet) any way.
if cfg.variable then wesnoth.set_variable(cfg.variable, ...) else ...
No, there's not (yet) any way.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
Yes, I thought about this possibility. I'll do this way.Anonymissimus wrote:if cfg.variable then wesnoth.set_variable(cfg.variable, ...) else ...
Good to know.Anonymissimus wrote:No, there's not (yet) any way.
Now, I'll correct this tag to add the variable= key, test it and try to make a patch.
EDIT: tag corrected, here there is the new code.
Spoiler:
Code: Select all
damage=( (amount / 100) * wesnoth.unit_resistance(unit_to_harm, tostring(damage_type))) or 1 --untested
After that, I think that it will be ready for the patch.
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: Elvish_Hunter's Lua thread
Here's a patch, making
local time = wesnoth.get_time_of_day(10, 10)
available. time is the time's id string then. When I find out more about the secrets of returning a table there may be mroe info.
For compiling I suggest Crab's cmake+MSVC 9 strategy, that's the easiest one, especially since you know how .bat files work.
local time = wesnoth.get_time_of_day(10, 10)
available. time is the time's id string then. When I find out more about the secrets of returning a table there may be mroe info.
For compiling I suggest Crab's cmake+MSVC 9 strategy, that's the easiest one, especially since you know how .bat files work.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
Thanks for your patch, but I decided to not add the alignment key, at least for now, mainly because we have at least three different ToD tables around (default, two suns, 24 hour, and users can define new ToD in WML). So, to add it, the best solution will be having a function that gets not only the ToD ID, but also its liminal_bonus and lawful_bonus keys.
Anyway, here there is my patch and my wiki description (feel free to correct it), I'll upload the patch also on Gna.
EDIT: patch uploaded on Gna as #2230.
I decided to go for the even easier way: Ubuntu 10.04 LTS, secondary Linux machine, svn diff>harm_unit.patch to the Terminal. For now, my main machine will remain Windows, also because I have still a lot of things to learn in Linux, but at least I have a secondary system just in case.Anonymissimus wrote:For compiling I suggest Crab's cmake+MSVC 9 strategy, that's the easiest one, especially since you know how .bat files work.
Anyway, here there is my patch and my wiki description (feel free to correct it), I'll upload the patch also on Gna.
EDIT: patch uploaded on Gna as #2230.
Spoiler:
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: Elvish_Hunter's Lua thread
-you don't need () around cfg.something
-tonumber(args) returns nil in case args is there but can't be converted so change the error message to something more general
-the filter tag should be left away as in your previous versions I think, that extra key's don't harm
-the line
if not units_to_harm then return end
does nothing, you already check whether it is nil
-d in string.format stands for digit iirc, that is, damage >= 10 is not correctly handled
-use wml_actions.tag(...), not wesnoth.fire("tag", ...); the ladder is deprecated
-there's a wesnoth.delay function; I'd prefer wesnoth.tag over wml_actions.tag if there is a suitable function
-if you do the cfg.scroll option I'd make the delay time an argument too (magic numbers are bad)
-use unit_to_harm.valid, see this:
-tonumber(args) returns nil in case args is there but can't be converted so change the error message to something more general
-the filter tag should be left away as in your previous versions I think, that extra key's don't harm
-the line
if not units_to_harm then return end
does nothing, you already check whether it is nil
-d in string.format stands for digit iirc, that is, damage >= 10 is not correctly handled
-use wml_actions.tag(...), not wesnoth.fire("tag", ...); the ladder is deprecated
-there's a wesnoth.delay function; I'd prefer wesnoth.tag over wml_actions.tag if there is a suitable function
-if you do the cfg.scroll option I'd make the delay time an argument too (magic numbers are bad)
-use unit_to_harm.valid, see this:
Code: Select all
wesnoth.put_unit({ type = "Troll", x = 20, y = 10 })
local troll = wesnoth.get_units({ x = 20, y = 10 })[1]
wml_actions.kill({ x = 20, y = 10 }) -- this may be done by a fired event for a unit which is still to be iterated on
local x = troll.x -- error since the reference "troll" is no longer valid
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
I made it this way to match the behaviour of [heal_unit], that requires a [filter] tag.Anonymissimus wrote:-the filter tag should be left away as in your previous versions I think, that extra key's don't harm
Copying from my Lua reference:Anonymissimus wrote:-d in string.format stands for digit iirc, that is, damage >= 10 is not correctly handled
Formatting field types
%d decimal integer
Am I wrong, or wml_actions.kill and wesnoth.delay are completely undocumented in LuaWML? And here, there isn't written that wesnoth.fire is deprecated.Thanks for warning me.Anonymissimus wrote:-use wml_actions.tag(...), not wesnoth.fire("tag", ...); the ladder is deprecated
-there's a wesnoth.delay function; I'd prefer wesnoth.tag over wml_actions.tag if there is a suitable function
OK, but 500 will remain as default value.Anonymissimus wrote:-if you do the cfg.scroll option I'd make the delay time an argument too (magic numbers are bad)
I don't (yet) understand how this may happen, considering that I check for unit ID to kill, but fixed anyway.Anonymissimus wrote:-use unit_to_harm.valid, see this:
Here there is a corrected version, it seems to work, if it's fine I'll upload it again on Gna.
Spoiler:
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
-
- Inactive Developer
- Posts: 2461
- Joined: August 15th, 2008, 8:46 pm
- Location: Germany
Re: Elvish_Hunter's Lua thread
All action tags (C++ ones and lua ones) are available as wml_actions.tag().
It's not quite deprecated yet - look in compatibility-1.8.lua.
This breaks your current code:
Code: Select all
[event]
name=start
{GENERIC_UNIT 1 Troll 1 1}
{GENERIC_UNIT 1 Troll 2 2}
[harm_unit]
[filter]
[/filter]
amount=200
[/harm_unit]
[/event]
[event]
name=die
[kill]
[/kill]
[/event]
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
A Simple Campaign: campaign draft for wml starters • Plan Your Advancements: mp mod
The Earth's Gut: sp campaign • Settlers of Wesnoth: mp scenario • Wesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign
- Elvish_Hunter
- Posts: 1575
- Joined: September 4th, 2009, 2:39 pm
- Location: Lintanir Forest...
Re: Elvish_Hunter's Lua thread
Thanks for the information.Anonymissimus wrote:All action tags (C++ ones and lua ones) are available as wml_actions.tag().
So, I did some experiments, and this happens because after killing the unit with [kill], [harm_unit] cannot longer find it.Anonymissimus wrote:This breaks your current code:
I have no good ideas on how to fix it, at the moment (and this can be understandable, considering that until two weeks ago I never wrote custom tags); if you have an idea, can you kindly suggest me how to fix it?
Current maintainer of these add-ons, all on 1.16:
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)
The Sojournings of Grog, Children of Dragons, A Rough Life, Wesnoth Lua Pack, The White Troll (co-author)