[engine] Design of [query_location]

Brainstorm ideas of possible additions to the game. Read this before posting!

Moderators: Forum Moderators, Developers

Forum rules
Before posting a new idea, you must read the following:
User avatar
Ravana
Moderator
Posts: 1831
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: [engine] Design of [query_location]

Post by Ravana » February 10th, 2018, 8:57 pm

I could try it again with the code you changed. Been testing on 1.13.10 release.

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

Re: [engine] Design of [query_location]

Post by gfgtdf » February 10th, 2018, 9:07 pm

this is the code i used for testing:

[multiplayer] file:

Code: Select all

....
	[event]
		name = "start"
		[set_menu_item]
			id = "menu_1"
			description = "menu 1"
			[command]
				[lua]
					code = "wesnoth.dofile('{CURRENT_DIRECTORY}/lua/testql.lua')"
				[/lua]
			[/command]
		[/set_menu_item]
	[/event]
....
testql.lua:

Code: Select all

-- Parameters
-- [filter_location] location filter - error if matches no location, if missing matches all locations
-- max_count - optional default 1, how many locations player may select, not allowed to be 0, not allowed to be less than min_count
-- min_count - optional default 1, how many locations player needs to select
-- allow_fog - optional default false
-- allow_shroud - optional default false. If you allow both shroud and fog here, you can include custom vision location filter
-- variable - WML variable for result - optional default location
-- confirm_message - optional, if used then there is dialog to finish selection, with min_count=0 cancel, reseting selection
-- overlay_selected, overlay_selectable, overlay_unselectable - custom overlay - optional, use "" to not display
-- overlay_message - optional printed while selecting
function wesnoth.wml_actions.query_location3(cfg)
	local helper = wesnoth.require "lua/helper.lua"
	local T = helper.set_wml_tag_metatable {}
	local location_set = wesnoth.require "lua/location_set.lua"
	-- local overlay_choosable = cfg.overlay_selectable or "terrain/alphamask.png~O(0.2)~CS(255,255,0)"
	local overlay_choosable = cfg.overlay_selectable or "misc/hover-hex.png"
	-- local overlay_chosen = cfg.overlay_selected or "terrain/alphamask.png~O(0.2)~CS(0,255,0)"
	local overlay_chosen = cfg.overlay_selected or "misc/blank-hex.png~BLIT(misc/hover-hex-enemy-bottom.png)~BLIT(misc/hover-hex-enemy-top.png)"
	local overlay_unselectable = cfg.overlay_unselectable or "terrain/alphamask.png~O(0.4)~CS(127,127,127)"
	local variable = cfg.variable or "location"
	local allow_fog = cfg.allow_fog or false
	local allow_shroud = cfg.allow_shroud or false
	local max_count = cfg.max_count or 1
	local min_count = cfg.min_count or 1
	local confirm_message = cfg.confirm_message
	local overlay_message = cfg.overlay_message or "Click on location to choose."
	local filter = helper.literal(helper.get_child(cfg, "filter_location")) or {}
	
	filter.include_borders = false -- prevent getting stuck when only way to get required amount of locations would be with borders, which are not selectable
	if allow_fog and not allow_shroud then
		table.insert(filter, T.filter_vision{side=wesnoth.current.side,respect_fog=false})
	elseif not allow_fog and not allow_shroud then
		table.insert(filter, T.filter_vision{side=wesnoth.current.side})
	end
	
	local allowed_locations = wesnoth.get_locations(filter)
	if #allowed_locations < min_count then helper.wml_error("query_location matches less locations than min_count "..#allowed_locations.."<"..min_count) end
	if min_count > max_count then helper.wml_error("query_location min_count is higher than max_count "..min_count..">"..max_count) end
	if max_count == 0 then helper.wml_error("query_location called with max_count=0") end
	if #allowed_locations == 0 and min_count == 0 then return end
	
	local res = wesnoth.synchronize_choice("location", function()
		
		
		local disabled_locations = location_set.create()
		if overlay_unselectable then
			for _, loc in ipairs(wesnoth.get_locations({{[1]="not",[2]=filter}})) do
				x = loc[1]
				y = loc[2]
				disabled_locations:insert(x, y)
				wesnoth.add_tile_overlay(x, y, { image = overlay_unselectable })
			end
		end
		
		wesnoth.wml_actions.disallow_end_turn()
		
		local old_callback = wesnoth.game_events.on_mouse_action
		local finished = false
		local adding = true
		
		local candidates = location_set.create()
		local chosen_locations = location_set.create()
		for _, loc in ipairs(allowed_locations) do
			x = loc[1]
			y = loc[2]
			candidates:insert(x, y)
			wesnoth.add_tile_overlay(x, y, { image = overlay_choosable })
		end
		wesnoth.redraw{}
		
		function wesnoth.game_events.on_mouse_action(x,y)         
			if adding and candidates:get(x,y) then
                if chosen_locations:size() < max_count then
					chosen_locations:insert(x,y)
					candidates:remove(x,y)
					wesnoth.remove_tile_overlay(x, y, { image = overlay_choosable })
					wesnoth.add_tile_overlay(x, y, { image = overlay_chosen })
				end
			elseif adding and chosen_locations:get(x,y) then
                if chosen_locations:size() >= min_count then
					finished = true
				end
			elseif not adding and candidates:get(x,y) then
                finished = true
			elseif not adding and chosen_locations:get(x,y) then
                if chosen_locations:size() > min_count then
					candidates:insert(x,y)
					chosen_locations:remove(x,y)
					wesnoth.remove_tile_overlay(x, y, { image = overlay_chosen })
					wesnoth.add_tile_overlay(x, y, { image = overlay_choosable })
				else
					finished=true
				end
			elseif not candidates:get(x,y) and not chosen_locations:get(x,y) then
                if chosen_locations:size() >= min_count then
					finished = true
				end
			end
			
			if chosen_locations:size() == max_count then
                finished = true
			end
		end
		
		local function print_current_count()
			wesnoth.print{text=overlay_message .. " Selected "..chosen_locations:size().."/ ("..min_count..".."..max_count..")",size=24}
		end
		
		local function clear_selection()
			chosen_locations:iter(function(x,y,data)
                wesnoth.remove_tile_overlay(x, y, { image = overlay_chosen })
			end)
			chosen_locations:clear()
		end
		
		local function reset_selection()
			chosen_locations:iter(function(x,y,data)
                wesnoth.remove_tile_overlay(x, y, { image = overlay_chosen })
                wesnoth.add_tile_overlay(x, y, { image = overlay_choosable })
                candidates:insert(x,y)
			end)
			chosen_locations:clear()
			finished = false
		end
		
		while not finished do
			while not finished do
                print_current_count()
                wesnoth.delay(10)
			end
			
			print_current_count()
			
			if confirm_message then
                local options = {"Finish", "Choose again", "Quit"}
                if min_count ~= 0 then
					table.remove(options, 3)
				end
                local result = helper.get_user_choice({ speaker = "narrator", message = confirm_message }, options)
                if result == 1 then
				elseif result == 2 then
					reset_selection()
				elseif result == 3 then
					clear_selection()
				end
			end
		end
		
		wesnoth.game_events.on_mouse_action = old_callback
		
		candidates:iter(function(x,y,data)
			wesnoth.remove_tile_overlay(x, y, { image = overlay_choosable })
		end)
		chosen_locations:iter(function(x,y,data)
			wesnoth.remove_tile_overlay(x, y, { image = overlay_chosen })
		end)
		
		disabled_locations:iter(function(x,y,data)
			wesnoth.remove_tile_overlay(x, y, { image = overlay_unselectable })
		end)
		disabled_locations:clear()
		
		local wml_object = {}
		for i,v in ipairs(chosen_locations:to_pairs()) do
			wml_object[i] = {"value",{x=v[1],y=v[2]}}
		end
		wesnoth.redraw{}
		
		return wml_object
	end)
	
	local normal_object = {}
	for i=1,#res do
		normal_object[i] = res[i][2]
	end
	wesnoth.wml_actions.allow_end_turn()
	helper.set_variable_array(variable, normal_object)
	return normal_object
end

wesnoth.random()
wesnoth.wml_actions.query_location3({})
wesnoth.wml_actions.query_location3({})


EDIT: did the forum always convert tabs to 3 spaces, feeld alien to me.
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
Ravana
Moderator
Posts: 1831
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: [engine] Design of [query_location]

Post by Ravana » February 10th, 2018, 9:15 pm

Same symptoms with that, https://i.imgur.com/7AfjBFf.jpg.

While it is possible to accidentally make selection still, overlays arent applied and control change dialog stays visible. And not possible to scroll around or anything.

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

Re: [engine] Design of [query_location]

Post by gfgtdf » February 10th, 2018, 9:47 pm

i just installed and tested on 1.13.10 release, and couldn't reprporudce this, although it somehow felt slower then when i tested on 1.13.10+dev (mid november)
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
Sapient
Inactive Developer
Posts: 4448
Joined: November 26th, 2005, 7:41 am
Contact:

Re: [engine] Design of [query_location]

Post by Sapient » February 11th, 2018, 12:08 am

Isn’t this query a separate UI mode? Trying to code it entirely in Lua seems like a troublesome approach.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."

User avatar
Celtic_Minstrel
Developer
Posts: 1199
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: [engine] Design of [query_location]

Post by Celtic_Minstrel » February 11th, 2018, 12:43 am

I'd say the proper solution for errors caused by leaving while a query is in progress is... don't allow leaving while a query is in progress.

Not sure if that's possible with this approach, though.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

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

Re: [engine] Design of [query_location]

Post by gfgtdf » February 11th, 2018, 12:52 am

Sapient wrote:Isn’t this query a separate UI mode? Trying to code it entirely in Lua seems like a troublesome approach.
well it's quite possible that add_tile_overlay in it's current form turns out to be insufficient for this task but i do think that providing just the 'ingredients' and one mainline lua implementation does give the umc devs more flexibility, which is a nice thing in cases like this.
Celtic_Minstrel wrote:I'd say the proper solution for errors caused by leaving while a query is in progress is... don't allow leaving while a query is in progress.

Not sure if that's possible with this approach, though.
you obviously cannot stop people from leaving, people can just close the game, cut their network connection cable 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.

User avatar
Celtic_Minstrel
Developer
Posts: 1199
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: [engine] Design of [query_location]

Post by Celtic_Minstrel » February 11th, 2018, 1:16 am

Oh yeah, that's a good point... then what's needed is some way to react to someone leaving, so that the query can be cancelled.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

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

Re: [engine] Design of [query_location]

Post by Ravana » February 11th, 2018, 1:28 am

Current query change can be detected at least, wesnoth.message("synchronize_choice function fired for nonlocal side"). Those in queue however happen before they should.

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

Re: [engine] Design of [query_location]

Post by gfgtdf » February 11th, 2018, 1:31 am

hmm well i don't think this is needed, what currently (the code i tested) happens is that the choice is shown to the side that takes the control over the side just like it's done with all other choiches (advancement choice/message with options etc.) in this case it woudl probably not be posible to cancel the action in a good way always (like advancement choices it usualyl don't make sense to cancel them), it depends in the concreate usecase though.

This happens unless the action was not yet sended to the other players (because it is was undoable) in that case no abort code is needed since the action was not sended to the other players. Actuall i am not 100% sure whether this is what happens currently, but iirc this is how this stuff is supposed to work.

Our current problem is that

1) Mp relates issues that onyl happen when revanna tests and i coudl not reproduce, i'd be nice if some more people could test it

2) ui issues unrelates to mp, that is the overlay somwhow looking bad in comination with wall terrain & fog. Image
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