Skip to content

Commit

Permalink
move [unstore_unit] definition to lua
Browse files Browse the repository at this point in the history
This also adds a 'color' parameter to wesnoth.float_label. It was already
previously possible to set a labels color using pango markup, but to
implement [unstore_unit] i need to support the color= syntax as given
by [unstore_unit]

This also adds a 'fire_event' parameter to wesnoth.put_unit to specify
whether the 'unit_placed' event is fired, this is needed to implement
fire_events=yes/no in [unstore_unit] but its also generally useful
for the same reason why [unstore_unit] has this parameter.
  • Loading branch information
gfgtdf committed Mar 14, 2016
1 parent e13cf1e commit 50a9a25
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 117 deletions.
43 changes: 43 additions & 0 deletions data/lua/wml-tags.lua
Expand Up @@ -1709,3 +1709,46 @@ wesnoth.wml_actions.random_placement = function(cfg)
utils.end_var_scope(variable, variable_previous)

end

local function on_board(x, y)
if type(x) ~= "number" or type(y) ~= "number" then
return false
end
local w, h = wesnoth.get_map_size()
return x >= 1 and y >= 1 and x <= w and y <= h
end

wml_actions.unstore_unit = function(cfg)
local variable = cfg.variable or helper.wml_error("[unstore_unit] missing required 'variable' attribute")
local unit_cfg = wesnoth.get_variable(variable)
local unit = wesnoth.create_unit(unit_cfg)
local advance = cfg.advance ~= false
local animate = cfg.animate ~= false
local x = cfg.x or unit.x or -1
local y = cfg.y or unit.y or -1
wesnoth.add_known_unit(unit.type)
if on_board(x, y) then
if cfg.find_vacant then
x,y = wesnoth.find_vacant_tile(x, y, cfg.check_passability ~= false and unit)
end
unit:to_map(x, y, cfg.fire_event)
local text = nil
if unit_cfg.gender == "female" then
text = cfg.female_text or cfg.text
else
text = cfg.male_text or cfg.text
end
local color = cfg.color
if color == nil and cfg.red and cfg.blue and cfg.green then
color = cfg.red .. "," .. cfg.green .. "," .. cfg.blue
end
if text ~= nil and not wesnoth.is_skipping_messages() then
wesnoth.float_label(x, y, text, color)
end
if advance then
wesnoth.advance_unit(unit, animate, cfg.fire_event)
end
else
unit:to_recall()
end
end
113 changes: 0 additions & 113 deletions src/game_events/action_wml.cpp
Expand Up @@ -1309,119 +1309,6 @@ WML_HANDLER_FUNCTION(unit, /*event_info*/, cfg)

}

/// Unit serialization from variables
WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
{
try {
const config &var = resources::gamedata->get_variable_cfg(cfg["variable"]);

config tmp_cfg(var);
const unit_ptr u = unit_ptr( new unit(tmp_cfg, false));

preferences::encountered_units().insert(u->type_id());
map_location loc = cfg_to_loc(
(cfg.has_attribute("x") && cfg.has_attribute("y")) ? cfg : vconfig(var));
const bool advance = cfg["advance"].to_bool(true);
if(resources::gameboard->map().on_board(loc)) {
if (cfg["find_vacant"].to_bool()) {
const unit* pass_check = NULL;
if (cfg["check_passability"].to_bool(true)) pass_check = u.get();
loc = pathfind::find_vacant_tile(
loc,
pathfind::VACANT_ANY,
pass_check);
}

resources::units->erase(loc);
resources::units->add(loc, *u);

if (cfg["fire_event"].to_bool(false)) {
resources::game_events->pump().fire("unit placed", loc);
}

config::attribute_value text = var["gender"].str() == "female" ? cfg["female_text"] : cfg["male_text"];
if(text.blank()) {
text = cfg["text"];
}
play_controller *controller = resources::controller;
if(!text.empty() && !controller->is_skipping_replay())
{
// Print floating label
SDL_Color color = font::LABEL_COLOR;

if(!cfg["color"].empty()) {
color = string_to_color(cfg["color"]);
} else if(cfg.has_attribute("red") || cfg.has_attribute("green") || cfg.has_attribute("blue")) {
color = create_color(cfg["red"], cfg["green"], cfg["blue"]);
}

resources::screen->float_label(loc, text, color);
}
if(advance) {
advance_unit_at(advance_unit_params(loc)
.fire_events(cfg["fire_event"].to_bool(false))
.animate(cfg["animate"].to_bool(true)));
}
} else {
if(advance && u->advances()) {
WRN_NG << "Cannot advance units when unstoring to the recall list." << std::endl;
}

team& t = (*resources::teams)[u->side()-1];

// Test whether the recall list has duplicates if so warn.
// This might be removed at some point but the uniqueness of
// the description is needed to avoid the recall duplication
// bugs. Duplicates here might cause the wrong unit being
// replaced by the wrong unit.
if(t.recall_list().size() > 1) {
std::vector<size_t> desciptions;
BOOST_FOREACH ( const unit_const_ptr & pt, t.recall_list() ) {

const size_t desciption =
pt->underlying_id();
if(std::find(desciptions.begin(), desciptions.end(),
desciption) != desciptions.end()) {

lg::wml_error << "Recall list has duplicate unit "
"underlying_ids '" << desciption
<< "' unstore_unit may not work as expected.\n";
} else {
desciptions.push_back(desciption);
}
}
}

// Avoid duplicates in the list.
/**
* @todo it would be better to change recall_list() from
* a vector to a map and use the underlying_id as key.
*/
size_t old_size = t.recall_list().size();
t.recall_list().erase_by_underlying_id(u->underlying_id());
if (t.recall_list().size() != old_size) {
LOG_NG << "Replaced unit '"
<< u->underlying_id() << "' on the recall list\n";
}
t.recall_list().add(u);
}

// If we unstore a leader make sure the team gets a leader if not the loading
// in MP might abort since a side without a leader has a recall list.
if(u->can_recruit()) {
(*resources::teams)[u->side() - 1].have_leader();
}

}
catch (const invalid_variablename_exception&)
{
ERR_NG << "invlid variable name in unstore_unit" << std::endl;
}
catch (game::game_error &e) {
ERR_NG << "could not de-serialize unit: '" << e.message << "'" << std::endl;
}
}

WML_HANDLER_FUNCTION(volume, /*event_info*/, cfg)
{

Expand Down
17 changes: 13 additions & 4 deletions src/scripting/game_lua_kernel.cpp
Expand Up @@ -2275,13 +2275,16 @@ int game_lua_kernel::intf_print(lua_State *L) {
* Places a unit on the map.
* - Args 1,2: (optional) location.
* - Arg 3: Unit (WML table or proxy), or nothing/nil to delete.
* - Args 4: (optional) boolean
* OR
* - Arg 1: Unit (WML table or proxy)
* - Args 2,3: (optional) location
* - Args 4: (optional) boolean
*/
int game_lua_kernel::intf_put_unit(lua_State *L)
{
int unit_arg = 1;
int fire_event_arg = 4;

lua_unit *lu = NULL;
unit_ptr u = unit_ptr();
Expand All @@ -2299,6 +2302,8 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
if (!map().on_board(loc)) {
return luaL_argerror(L, 1, "invalid location");
}
} else {
fire_event_arg = 2;
}

if (luaW_hasmetatable(L, unit_arg, getunitKey))
Expand Down Expand Up @@ -2351,9 +2356,9 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
u->set_location(loc);
units().insert(u);
}

play_controller_.pump().fire("unit placed", loc);

if(luaW_toboolean(L, fire_event_arg)) {
play_controller_.pump().fire("unit placed", loc);
}
return 0;
}

Expand Down Expand Up @@ -2516,10 +2521,14 @@ int game_lua_kernel::intf_float_label(lua_State *L)
map_location loc;
loc.x = luaL_checkinteger(L, 1) - 1;
loc.y = luaL_checkinteger(L, 2) - 1;
SDL_Color color = font::LABEL_COLOR;

t_string text = luaW_checktstring(L, 3);
if (!lua_isnoneornil(L, 4)) {
color = string_to_color(luaW_checktstring(L, 4));
}
if (game_display_) {
game_display_->float_label(loc, text, font::LABEL_COLOR);
game_display_->float_label(loc, text, color);
}
return 0;
}
Expand Down

0 comments on commit 50a9a25

Please sign in to comment.