Overriding unit advancements

The place to post your WML questions and answers.

Moderators: Forum Moderators, Developers

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Overriding unit advancements

Post by The_Gnat » January 6th, 2019, 10:38 pm

Hello,

I am planning on changing the modification I am currently using for my Reign of the Lords add-on. Currently in SP I am using [advancefrom] but that is unwieldy and bad practice so I want to change to use events instead.

But the main disadvantage that using events has is that it does not display unit upgrades in the help menu. So my first question: is there anyway to update the help menu?

Secondly I am wondering what the best implementation for would be for the events?

Currently I am considering a pre advance event that would check if the unit has any alternate advancements and if so modify them to display these alternate advancements:

Code: Select all

[event]
      name=pre advance
      first_time_only=no

      [filter]
         type={UNIT}
      [/filter]
	  
      {STORE_UNIT_VAR (id=$unit.id) advances_to unit_advances_to}

	  # check if this has already been done to this unit
      [if]
		[variable]
			name=unit_advances_to
			equals={ADVANCES_TO}
		[/variable]
      [then]
			# IF SO then don't do it again
      [/then]
      [else]
			# IF NOT than modify so the unit advances properly
		  [modify_unit]
				[filter]
					id=$unit.id
				[/filter]
				advances_to={ADVANCES_TO}
		  [/modify_unit]
      [/else]
      [/if]

      {CLEAR_VARIABLE unit_advances_to}

   [/event]
However, I thought to ask if there are any unforeseen side effects of that type of event? Also I wanted to ask if there is any better method of implementing?

A few people have mentioned using unit placed events but unfortunately if a spearman is placed and then the spearman advances to a javelineer the javelineer doesn't count as being 'placed' and therefore is not modified. :hmm: However, unit placed is more optimal because it modifies units immediately rather than after the fact which allows the player to see that they can advance (through the blue XP bar).

I also considered a combination of unit placed,post advance event that would then account for all units which are either placed or advanced into. However, this is twice as many event conditions that need to be processed for every unit (and there are about 100).

Would this number of events be a problem or negatively effect campaigns?

Thank you for your thoughts! Any ideas or suggestions would be welcome as I work through this idea and hopefully reach a better solution than [advancefrom]. :D

User avatar
Ravana
Moderator
Posts: 1929
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Overriding unit advancements

Post by Ravana » January 6th, 2019, 10:49 pm

I think it would make sense to fire unit_placed after advancement.

It might be best solution to generate base_unit for everything, and on unit placed replace types.

If you are worried about number of events, can use single event for all of them. That would be easier with Lua mapping.

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 6th, 2019, 11:14 pm

Ravana wrote:
January 6th, 2019, 10:49 pm
I think it would make sense to fire unit_placed after advancement.
So are you saying that unit_placed is currently fired after advancement?
It might be best solution to generate base_unit for everything, and on unit placed replace types.
Okay yes I can do that, I currently am only generating events to override the advancements but I have base units for all of the units that have been modified so I can easily implement that instead. :)
If you are worried about number of events, can use single event for all of them. That would be easier with Lua mapping.
Okay thank you I will give that a try. :D

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 7th, 2019, 3:25 am

The only disadvantage of the above method is that whenever you place a unit (for example when you recruit) it looks odd because it creates him and then reloads him.

Is there a way not to animate the [modify_unit] ?

gfgtdf
Developer
Posts: 1126
Joined: February 10th, 2013, 2:25 pm

Re: Overriding unit advancements

Post by gfgtdf » January 7th, 2019, 4:30 am

If you use lua you can modify the units stats directly by settign arributes instead of [midify_unit]. modify_unit also has the disadvantage that the effect will be lost when the unit is rebuild, for example when remove_object is called, this again can be fiuxed with a custom lua effect, then you also won't need the post_advance event anymore, untested code:

Code: Select all

[lua]
code = <<
local on_event = wesnoth.require("on_event")
--makes Spearman advance to bowman.
local unittable = {
  ["Spearman"] = { "Bowman"},
  ["Bowman"] =  {"Knight"},
}
function wesnoth.effects.osd_fix_advancements(u)
  local advances_to = unittable[u.type]
  if advances_to then
    u.advances_to= advances_to
  end
end
on_event("unit_placed", function(cx)
  local u = wesnoth.get_unit(cx.x1, cx.y1)
  if u and not u.variables.has_osd_fix_advancements then
    u.variables.has_osd_fix_advancements = true
    u:add_modification("object", { wml.tag.effect { apply_to = "osd_fix_advancements" } } )
  end
end)
>>
[/lua]

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.

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 7th, 2019, 6:43 am

That is a good idea. I think lua be better in general but I never got around to learning the lua's syntax so I don't know if I could implement the events. ;)

Basically I would like an event that modifies the advancements of a number of units. So if I wanted to make the code work for more units would I just add more strings to the unittable?

EDIT: Btw your code works well thank you! But I wonder, can I add any number of units like this?

Code: Select all

[lua]
			code = <<
			local on_event = wesnoth.require("on_event")
			
			-- table --
			-- ALL THE UNITS ON THE LEFT NOW ADVANCE TO THE UNITS ON THE RIGHT
			-- table --
			
			local unittable = {
			  ["Elder Wose"] = { "ROLAncient Wose,ROLAncient Wose Shaman"},
			  ["Ancient Wose"] =  {"ROLArch Wose"},
			  ["Wose"] =  {"ROLElder Wose"},
			  ["Elvish Sylph"] = { "ROLElvish Hierophant"},
			  ["Elvish Sorceress"] =  {"ROLElvish Enchantress,ROLElvish Battle Druid"},
			  ["Elvish Hero"] = { "ROLElvish Prowler,ROLElvish Champion"},
			  ["Elvish Druid"] =  {"ROLElvish Shyde,ROLElvish Mystic"},
			  ["Elvish Archer"] = { "ROLElvish Ranger,ROLElvish Marksman"},
			  ["Elvish Avenger"] = { "ROLElvish Vendicator"},
			  ["Elvish Champion"] =  {"ROLElvish Halberdier,ROLElvish Legend"},
			  ["Elvish High Lord"] = { "ROLElvish Majestic"},
			  ["Elvish Marshal"] =  {"ROLElvish Grand Master"},
			  ["Elvish Sharpshooter"] = { "ROLElvish Deadeye"},
			  ["Elvish Shyde"] =  {"ROLElvish Star"},
			  ["Elvish Outrider"] = { "ROLElvish Swift,ROLElvish Gryphonier"},
			}
			function wesnoth.effects.osd_fix_advancements(u)
			  local advances_to = unittable[u.type]
			  if advances_to then
				u.advances_to= advances_to
			  end
			end
			on_event("unit_placed", function(cx)
			  local u = wesnoth.get_unit(cx.x1, cx.y1)
			  if u and not u.variables.has_osd_fix_advancements then
				u.variables.has_osd_fix_advancements = true
				u:add_modification("object", { wml.tag.effect { apply_to = "osd_fix_advancements" } } )
			  end
			end)
			>>
[/lua]
EDIT 2: Error "unkown unit type: ROLElvish Ranger,ROLElvish Marksman"

I got this error when trying to assign the unit to advance to 2 different units. Is this not allowed in lua?

User avatar
Ravana
Moderator
Posts: 1929
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Overriding unit advancements

Post by Ravana » January 7th, 2019, 7:18 am

Most likely u.advances_to expects array {"a","b"}.

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 7th, 2019, 7:22 am

Okay thank you I will try that :)

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 7th, 2019, 8:17 am

Unfortunately the code doesn't seem to work on leaders. Or other units who are placed at the start. :hmm: Is that expected behavior or have I messed up something?

EDIT: No not all units that are placed at the start of the scenario don't work so it must be a mistake I have made. It is seemingly unpredictable behavior but it appears units that are placed at the beginning when the map is created often do not advance properly. I will look into it further and post.

gfgtdf
Developer
Posts: 1126
Joined: February 10th, 2013, 2:25 pm

Re: Overriding unit advancements

Post by gfgtdf » January 7th, 2019, 3:54 pm

You coudl just also add the osd_fix_advancements object in a prestart event to cover these aswell. like adding

Code: Select all

on_event("prestart", function()
 for i, u in ipairs(wesnoth.get_units({})) do
  if not u.variables.has_osd_fix_advancements then
    u.variables.has_osd_fix_advancements = true
    u:add_modification("object", { wml.tag.effect { apply_to = "osd_fix_advancements" } } )
  end
 end
end)
to my code above.

Also note that this [lua] tag should not go into an [event] but instead should be directly placed under [era]/[scenario] etc. basicially where you'd also place events.
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.

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 7th, 2019, 7:01 pm

Okay thank you! I actually am not using an era or scenario but instead a modification. Can I put it into the modification tag? Currently it is in an event inside a modification which may be the cause if the error.

josteph
Developer
Posts: 242
Joined: August 19th, 2017, 6:58 pm

Re: Overriding unit advancements

Post by josteph » January 7th, 2019, 7:25 pm


User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 7th, 2019, 7:46 pm

josteph wrote:
January 7th, 2019, 7:25 pm
Yes. See https://wiki.wesnoth.org/ModificationWML
Great thank you!

User avatar
The_Gnat
Posts: 1833
Joined: October 10th, 2016, 3:06 am
Contact:

Re: Overriding unit advancements

Post by The_Gnat » January 8th, 2019, 7:52 pm

The code worked perfectly now that I put it directly into the modification! Also I was wondering are #ifdef 's supported within lua code?

EDIT: Apparently not

The reason I ask is because I was wondering if it is possible to define some of my advancements only if a certain campaign is running. But if that is not possible then I won't worry about it because it is not too critical.

gfgtdf
Developer
Posts: 1126
Joined: February 10th, 2013, 2:25 pm

Re: Overriding unit advancements

Post by gfgtdf » January 8th, 2019, 8:07 pm

It's possible to do the samewith luas 'if'. but it requires some knowledge about the lua programming language. (variabe scope, how to add element to tables etc)
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.

Post Reply