EarthCake's problems

The place to post your WML questions and answers.

Moderator: Forum Moderators

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.
Post Reply
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

Since this is a custom event I am not sure that side_number variable is available. Since you are creating a SP campaign and the event can't be triggered by AI side, you can remove the side_for=$side_number.

Update. As I can see side_number should be still available, so side_for=$side_number should not cause your problem.

Update 2. I just tested your code and it works. Check that you added all the events you posted in this thread to your scenario file.
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
User avatar
octalot
General Code Maintainer
Posts: 786
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: EarthCake's problems

Post by octalot »

Are you clicking on the menu item?
User avatar
EarthCake
Posts: 377
Joined: March 29th, 2019, 1:57 pm
Location: The Wall

Re: EarthCake's problems

Post by EarthCake »

@octalot, yes you are. Right click leads to walkthrough.
@sergey, can you tell me how it worked? Whatever I do, it only sets up in menu, and when I click on "walkthroughs", it does nothing, just closes the menu, and it should open scenario walkthrough choice.
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

I copied your events under [scenario] tag of one of add-ons. I will paste your code here.

Code: Select all

	[event]
		name=start
        	[set_menu_item]
			# Please don't ask what is this for.
            		id=9help
            		description=_"Walkthroughs"
            		[command]
                            	[fire_event]
                                	name=help_walkthroughs_check
                            	[/fire_event]
			[/command]
		[/set_menu_item]
	[/event]
    	[event]
        	name=help_walkthroughs_check
        	first_time_only=no
        	[message]
            		speaker=narrator
            		message=_"<span color='red'>SPOILER WARNING: Better read this only if you get stuck.</span>
Do you want to read this anyway?"
            		side_for=$side_number
            		image="wesnoth-icon.png"
            		[option]
                		label=_"No."
                		[command]
                		[/command]
            		[/option]
            		[option]
                		label=_"Yes."
                		[command]
                    			[fire_event]
                        			name=help_walkthroughs
                    			[/fire_event]
                		[/command]
            		[/option]
        	[/message]
    	[/event]
    	[event]
        	name=help_walkthroughs
        	first_time_only=no
        	[message]
            		speaker=narrator
            		message= _ "For which scenario do you need help?"
            		side_for=$side_number
            		image="wesnoth-icon.png"
            		[option]
                		label=_"Prologue"
                		[command]
                    			[message]
                        			speaker=narrator
                        			message= _ "This is just a prologue scenario. The only thing you need to do is to reach the signpost in south. The undead will try to catch you, but if you move the hero all the time towards the village in south, the undead will not be able to catch you."
                        			side_for=$side_number
                        			image="wesnoth-icon.png"
                    			[/message]
                    			[fire_event]
                        			name=help_walkthroughs
                    			[/fire_event]
                		[/command]
            		[/option]
            		[option]
                		label= _ "Scenario 1 (Defense of Elensefar)"
                		[command]
                    			[message]
                        			speaker=narrator
                        			message= _ "This isn't implemented yet."
                        			side_for=$side_number
                        			image="wesnoth-icon.png"
                    			[/message]
                    			[fire_event]
                        			name=help_walkthroughs
                    			[/fire_event]
                		[/command]
            		[/option]
			[option]
				label= _ "Exit"
				[command]
				[/command]
			[/option]
		[/message]
	[/event]
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
User avatar
EarthCake
Posts: 377
Joined: March 29th, 2019, 1:57 pm
Location: The Wall

Re: EarthCake's problems

Post by EarthCake »

Yes, sergey, it works now! Thanks.

I don't get why it didn't work when I put {GLOBAL_EVENTS} in scenario code.

EDIT: I figured out why it didn't work when I put global_events
User avatar
EarthCake
Posts: 377
Joined: March 29th, 2019, 1:57 pm
Location: The Wall

Re: EarthCake's problems

Post by EarthCake »

About question before: @octalot, I have only managed to make one leader to be able to only recruit and not recall, and another one to not recall nor recruit.
Also, @sergey: thanks for help.

So: My main question is: Is there any special command or tag that makes a unit able to recall units from previous scenarios?
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

EarthCake wrote: May 31st, 2019, 12:45 pm So: My main question is: Is there any special command or tag that makes a unit able to recall units from previous scenarios?
Any leader should be able to recall units of its side from previous scenarios by default. Can you show your code "to make one leader to be able to only recruit and not recall". I think that code disabled recall functionality for the both leaders.
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
User avatar
EarthCake
Posts: 377
Joined: March 29th, 2019, 1:57 pm
Location: The Wall

Re: EarthCake's problems

Post by EarthCake »

Here is code for whole scenario:
06_The_Elvish_Capital.cfg
(13.34 KiB) Downloaded 155 times
User avatar
octalot
General Code Maintainer
Posts: 786
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: EarthCake's problems

Post by octalot »

To make a unit able to recall units, it needs canrecruit=yes. To stop that unit from recruiting, the side's recruit list must be empty.

Example code assuming that, in the previous scenario, Konrad could both recruit and recall, and Delfador could neither recruit nor recall:

Code: Select all

    [event]
        name=prestart

        # Konrad can recruit but can't recall
        # Delfador can recall but can't recruit

        # Make the side's recruit list empty, instead add the units that Konrad
        # can recall directly to his extra_recruit
        [disallow_recruit]
            side=1
        [/disallow_recruit]
        # This has to be done with modify_unit instead of putting the
        # [filter_recall] directly in the [side] tag. Probably because we
        # already have Konrad from the previous scenario, so the existing unit
        # will be used instead of creating him from the data in the [side] tag.
        [modify_unit]
            [filter]
                id=Konrad
            [/filter]
            [filter_recall]
                type=
            [/filter_recall]
            extra_recruit=Elvish Archer, Elvish Fighter, Elvish Shaman
        [/modify_unit]
        [modify_unit]
            [filter]
                id=Delfador
            [/filter]
            canrecruit=yes
        [/modify_unit]

        ....
Last edited by octalot on May 31st, 2019, 4:17 pm, edited 1 time in total.
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

EarthCake there are several sides in the file you attached. Could you please specify which leader is supposed to recruit and which is supposed to recall? They are on different sides? For what side the recall list belongs? There is a single or several recall lists? Leaders where separated only in this scenario, in previous scenarios they were fighting on the same side?
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
User avatar
EarthCake
Posts: 377
Joined: March 29th, 2019, 1:57 pm
Location: The Wall

Re: EarthCake's problems

Post by EarthCake »

Aenic should just recruit and Soranic only recall.
No, they are not. I just put them into separate units tag because it is the way I code, and to be easier to make the upper mentioned thing.
For side 1, Soranic and Aenic belong to that side.
Single recall list.
Yes, they are fighting on the same side, and in previous scenario only Soranic could recruit and recall.

EDIT: I have managed to do this! :D
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

I have several comments.

1) disallow_recruit=yes under the side tag is just ignored. There is no such key for the side tag, see https://wiki.wesnoth.org/SideWML . disallow_recruit is a command that should be placed inside an event, see https://wiki.wesnoth.org/DirectActionsW ... recruit.5D

2) You have not specified leaders under side 1 and this is wrong. That is the reason why there is no recall list. Recall list is carried over scenarios using the save_id key (https://wiki.wesnoth.org/SideWML). You can omit the save_id key, in that case it defaults to the leader id. Since there is no leaders under the side and you have not specified the save_id manually the engine doesn't know that it should move the recall list from the previous scenarios to the side 1. Moreover, you may change the side number, but make sure that save_id is the same (either set it manually or make sure that the leader is the same).

More info why leader must be placed directly under the side tag. In your case you actually created another units (since you used the unit command), even if they have the same id, name, etc. But they are different units, not your leaders from previous scenarios. Your leaders are placed in the recall list with the other units. If you specify your leaders under the side tag, they are retrieved by the game engine from the recall list and placed on the map. That is how they will keep their XP, items, etc. Have you noticed that usually the same level 1 leader is declared under the side tag of all scenarios? But the leader levels up during the game and his progress is not lost. When you specify a leader under the side the engine first checks if there is that leader in the recall list carried from previous scenarios (it searches by unit id I think), after that it auto-recalls the leader and applies its coordinates. If leader is found in the recall list all other unit keys under the side are ignored (at least most of them are ignored). That's why I modified Aenic in the prestart event.

It is allowed to specify leader keys directly under the side tag, but that is messy. I suggest you to place your leaders under the unit tag that goes directly under the side tag. Here is the correct code. There are 2 leaders under the side, so I manually set the save_id just in case, since it is not obvious which leader's id will be used. Sides with controller=human use persistent=yes by default, it can be omitted.

Code: Select all

[side]
  side=1
  save_id=Soranic
  controller=human
  {GOLD 200 180 150}
  team_name=good_guys
  user_team_name= _ "Humans"  
  defeat_condition=no_leader_left

  [unit]
    type=Warrior Lord
    id=Soranic
    name= _ "Soranic"
    profile=portraits/soranic.png
    [modifications]
      {TRAIT_RESILIENT}
      {TRAIT_QUICK}
    [/modifications]
    unrenamable=yes
    canrecruit=yes
    x,y=52,43
  [/unit]

  [unit]
    type=White Mage
    id=Aenic
    name="Aenic"
    profile=portraits/aenic.png
    {IS_LOYAL}
    [modifications]
      {TRAIT_LOYAL}
      {TRAIT_QUICK}
   [/modifications]
   unrenamable=yes
   max_hitpoints=45
   x,y=46,7
  [/unit]
[/side]

# Soranic won't be able to recruit because of disallow_recruit for the side 1
# Aenic will able to recruit because of extra_recruit, but not recall because of filter_recall
[event]
  name=prestart
  [disallow_recruit]
    side=1
  [/disallow_recruit]

  # can't use modify_unit since it doesn't change filter_recall
  [store_unit]
    [filter]
      id=Aenic
    [/filter]
    variable=aenic_stored
  [/store_unit]

  # Aenic will be able to recruit, but not recall
  {VARIABLE aenic_stored.canrecruit "yes"}
  {VARIABLE aenic_stored.extra_recruit "Heavy Infantryman,Spearman,Mage,Bowman,Fencer"}
  {VARIABLE aenic_stored.filter_recall.race "nonexistent"}

  # need to clear his ellipse and overlay since he is a leader now
  {CLEAR_VARIABLE aenic_stored.ellipse}
  {CLEAR_VARIABLE aenic_stored.overlay}

  [unstore_unit]
    variable=aenic_stored
    x=$aenic_stored.x
    y=$aenic_stored.y
   [/unstore_unit]
   {CLEAR_VARIABLE aenic_stored}
[/event]
Ideally I would use

Code: Select all

[filter_recall]
  [not]
  [/not]
[/filter_recall]
for Aenic. This code means no unit will match. However, I don't know how to achieve that result with a stored unit. So, I made it this way:

Code: Select all

[filter_recall]
  race=nonexistent
[/filter_recall]
Update. https://wiki.wesnoth.org/InternalAction ... riables.5D may be used, anyway code in my example also works.
Last edited by sergey on May 31st, 2019, 9:25 pm, edited 2 times in total.
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

EarthCake wrote: May 31st, 2019, 3:58 pm EDIT: I have managed to do this! :D
Cool! Anyway I hope the information I provided is useful.
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
User avatar
EarthCake
Posts: 377
Joined: March 29th, 2019, 1:57 pm
Location: The Wall

Re: EarthCake's problems

Post by EarthCake »

sergey wrote: May 31st, 2019, 9:13 pm I have several comments.

1) disallow_recruit=yes under the side tag is just ignored. There is no such key for the side tag, see https://wiki.wesnoth.org/SideWML . disallow_recruit is a command that should be placed inside an event, see https://wiki.wesnoth.org/DirectActionsW ... recruit.5D
Yes, you are right, I needed to put disallow_recruit into prestart.
sergey wrote: May 31st, 2019, 9:13 pm 2) You have not specified leaders under side 1 and this is wrong. That is the reason why there is no recall list. Recall list is carried over scenarios using the save_id key (https://wiki.wesnoth.org/SideWML). You can omit the save_id key, in that case it defaults to the leader id. Since there is no leaders under the side and you have not specified the save_id manually the engine doesn't know that it should move the recall list from the previous scenarios to the side 1. Moreover, you may change the side number, but make sure that save_id is the same (either set it manually or make sure that the leader is the same).
I never paid much attention to save_id key, but for recall list save_id isn't needed. If you use persistent key, recall list is carried. Anyway, I will use save_id from now.
sergey wrote: May 31st, 2019, 9:13 pm More info why leader must be placed directly under the side tag. In your case you actually created another units (since you used the unit command), even if they have the same id, name, etc. But they are different units, not your leaders from previous scenarios. Your leaders are placed in the recall list with the other units. If you specify your leaders under the side tag, they are retrieved by the game engine from the recall list and placed on the map. That is how they will keep their XP, items, etc. Have you noticed that usually the same level 1 leader is declared under the side tag of all scenarios? But the leader levels up during the game and his progress is not lost. When you specify a leader under the side the engine first checks if there is that leader in the recall list carried from previous scenarios (it searches by unit id I think), after that it auto-recalls the leader and applies its coordinates. If leader is found in the recall list all other unit keys under the side are ignored (at least most of them are ignored). That's why I modified Aenic in the prestart event.
I think that is not true, and that id is saved. Otherwise, recall could work. Anyway, XP is kept and carried with alone unit tag.
sergey wrote: May 31st, 2019, 9:13 pm It is allowed to specify leader keys directly under the side tag, but that is messy. I suggest you to place your leaders under the unit tag that goes directly under the side tag. Here is the correct code. There are 2 leaders under the side, so I manually set the save_id just in case, since it is not obvious which leader's id will be used. Sides with controller=human use persistent=yes by default, it can be omitted.

Code: Select all

[side]
  side=1
  save_id=Soranic
  controller=human
  {GOLD 200 180 150}
  team_name=good_guys
  user_team_name= _ "Humans"  
  defeat_condition=no_leader_left

  [unit]
    type=Warrior Lord
    id=Soranic
    name= _ "Soranic"
    profile=portraits/soranic.png
    [modifications]
      {TRAIT_RESILIENT}
      {TRAIT_QUICK}
    [/modifications]
    unrenamable=yes
    canrecruit=yes
    x,y=52,43
  [/unit]

  [unit]
    type=White Mage
    id=Aenic
    name="Aenic"
    profile=portraits/aenic.png
    {IS_LOYAL}
    [modifications]
      {TRAIT_LOYAL}
      {TRAIT_QUICK}
   [/modifications]
   unrenamable=yes
   max_hitpoints=45
   x,y=46,7
  [/unit]
[/side]

# Soranic won't be able to recruit because of disallow_recruit for the side 1
# Aenic will able to recruit because of extra_recruit, but not recall because of filter_recall
[event]
  name=prestart
  [disallow_recruit]
    side=1
  [/disallow_recruit]

  # can't use modify_unit since it doesn't change filter_recall
  [store_unit]
    [filter]
      id=Aenic
    [/filter]
    variable=aenic_stored
  [/store_unit]

  # Aenic will be able to recruit, but not recall
  {VARIABLE aenic_stored.canrecruit "yes"}
  {VARIABLE aenic_stored.extra_recruit "Heavy Infantryman,Spearman,Mage,Bowman,Fencer"}
  {VARIABLE aenic_stored.filter_recall.race "nonexistent"}

  # need to clear his ellipse and overlay since he is a leader now
  {CLEAR_VARIABLE aenic_stored.ellipse}
  {CLEAR_VARIABLE aenic_stored.overlay}

  [unstore_unit]
    variable=aenic_stored
    x=$aenic_stored.x
    y=$aenic_stored.y
   [/unstore_unit]
   {CLEAR_VARIABLE aenic_stored}
[/event]
Thank you for the code, I did it in similar way:

Code: Select all

	[side]
		# This was before you told me about save_id key
		side=1
		controller=human
		type=Young Lord
		id=Soranic
		name= _ "Soranic"
		profile=portraits/soranic.png
     		[modifications]
       			{TRAIT_RESILIENT}
        		{TRAIT_QUICK}
      		[/modifications]
		unrenamable=yes
		canrecruit=yes
		{GOLD 200 180 150}
		fog=no
		recruit=Heavy Infantryman, Spearman, Mage, Bowman, Fencer
		persistent=yes
		team_name=good_guys
		user_team_name= _ "Humans"
		defeat_condition=no_leader_left
		x,y=45,7
	[/side]
	
	[event]
		name=prestart
		[modify_unit]
			[filter]
				id=Soranic
			[/filter]
            		[filter_recall]
                		race=human
            		[/filter_recall]
		[/modify_unit]
		[disallow_recruit]
			side=1
		[/disallow_recruit]
	        [store_unit]
            		[filter]
                		id=Soranic
            		[/filter]
            		kill=yes
            		variable=stored_soranic
        	[/store_unit]
        [/event]
        
        [event]
        	name=start
		[unit]
			side=1
			type=White Mage
			id=Aenic
			name="Aenic"
			profile=portraits/aenic.png
			{IS_LOYAL}
     			[modifications]
				{TRAIT_LOYAL}
				{TRAIT_QUICK}
	      		[/modifications]
			unrenamable=yes
			max_hitpoints=45
			x,y=46,7
		[/unit]
		[modify_unit]
			[filter]
				id=Aenic
			[/filter]
			canrecruit=yes
			extra_recruit=Heavy Infantryman, Spearman, Mage, Bowman, Fencer
			[filter_recall]
				type=
			[/filter_recall]
		[/modify_unit]
sergey wrote: May 31st, 2019, 9:13 pm Ideally I would use

Code: Select all

[filter_recall]
  [not]
  [/not]
[/filter_recall]
for Aenic. This code means no unit will match. However, I don't know how to achieve that result with a stored unit. So, I made it this way:

Code: Select all

[filter_recall]
  race=nonexistent
[/filter_recall]
Update. https://wiki.wesnoth.org/InternalAction ... riables.5D may be used, anyway code in my example also works.
Yes, that works, but this also works:

Code: Select all

		[modify_unit]
			[filter_recall]
				type=
			[/filter_recall]
		[/modify_unit]
That makes type to recall to null.


Yes, your informations are useful, thank you.
User avatar
sergey
Posts: 475
Joined: January 9th, 2015, 9:25 pm

Re: EarthCake's problems

Post by sergey »

EarthCake wrote: June 1st, 2019, 6:26 am I never paid much attention to save_id key, but for recall list save_id isn't needed. If you use persistent key, recall list is carried. Anyway, I will use save_id from now.
You can omit save_id as long as you have the same leader (save_id value is set to leader id by default).
EarthCake wrote: June 1st, 2019, 6:26 am I think that is not true, and that id is saved. Otherwise, recall could work. Anyway, XP is kept and carried with alone unit tag.
Interesting, I didn't know that. It means that unit command first checks for that unit on the recall list. If the unit is found then it is auto-recalled, otherwise new unit is created. That is not documented.
EarthCake wrote: June 1st, 2019, 6:26 am Thank you for the code, I did it in similar way:

Code: Select all

	[side]
		# This was before you told me about save_id key
		side=1
		controller=human
		type=Young Lord
		id=Soranic
		name= _ "Soranic"
		profile=portraits/soranic.png
     		[modifications]
       			{TRAIT_RESILIENT}
        		{TRAIT_QUICK}
      		[/modifications]
		unrenamable=yes
		canrecruit=yes
		{GOLD 200 180 150}
		fog=no
		recruit=Heavy Infantryman, Spearman, Mage, Bowman, Fencer
		persistent=yes
		team_name=good_guys
		user_team_name= _ "Humans"
		defeat_condition=no_leader_left
		x,y=45,7
	[/side]
	
	[event]
		name=prestart
		[modify_unit]
			[filter]
				id=Soranic
			[/filter]
            		[filter_recall]
                		race=human
            		[/filter_recall]
		[/modify_unit]
		[disallow_recruit]
			side=1
		[/disallow_recruit]
	        [store_unit]
            		[filter]
                		id=Soranic
            		[/filter]
            		kill=yes
            		variable=stored_soranic
        	[/store_unit]
        [/event]
        
        [event]
        	name=start
		[unit]
			side=1
			type=White Mage
			id=Aenic
			name="Aenic"
			profile=portraits/aenic.png
			{IS_LOYAL}
     			[modifications]
				{TRAIT_LOYAL}
				{TRAIT_QUICK}
	      		[/modifications]
			unrenamable=yes
			max_hitpoints=45
			x,y=46,7
		[/unit]
		[modify_unit]
			[filter]
				id=Aenic
			[/filter]
			canrecruit=yes
			extra_recruit=Heavy Infantryman, Spearman, Mage, Bowman, Fencer
			[filter_recall]
				type=
			[/filter_recall]
		[/modify_unit]
So I was wrong and modify_unit works with filter_recall. That is good. I was also clearing Aenic's ellipse and overlay. I was testing my assumptions on a hero unit {IS_HERO} and there was an "image not found" text under him. Perhaps it is not required for {IS_LOYAL} unit.
Author of SP scenario Dragon Fight and SP campaign Captured by a Nightmare.
Created The Rise of Wesnoth (alternative mechanics) version of the mainline campaign.
Post Reply