diff --git a/data/lua/wml-tags.lua b/data/lua/wml-tags.lua index edc1ab51893..bf882a88f07 100644 --- a/data/lua/wml-tags.lua +++ b/data/lua/wml-tags.lua @@ -1041,6 +1041,10 @@ function wml_actions.harm_unit(cfg) end_var_scope("this_unit", this_unit) end +function wml_actions.heal_unit(cfg) + wesnoth.heal_unit(cfg) +end + function wml_actions.transform_unit(cfg) local transform_to = cfg.transform_to diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ef49229dada..8d80bac2aa9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -970,6 +970,7 @@ set(wesnoth-main_SRC scripting/lua_gui2.cpp scripting/lua_kernel_base.cpp scripting/lua_map_location_ops.cpp + scripting/lua_race.cpp scripting/lua_rng.cpp scripting/lua_team.cpp scripting/lua_types.cpp diff --git a/src/SConscript b/src/SConscript index 21fe502ab4d..4b6f8e6d595 100644 --- a/src/SConscript +++ b/src/SConscript @@ -543,6 +543,7 @@ wesnoth_sources = Split(""" scripting/lua_gui2.cpp scripting/lua_kernel_base.cpp scripting/lua_map_location_ops.cpp + scripting/lua_race.cpp scripting/lua_rng.cpp scripting/lua_team.cpp scripting/lua_types.cpp diff --git a/src/game_events/action_wml.cpp b/src/game_events/action_wml.cpp index cd5b96047fb..aa5e8f5591d 100644 --- a/src/game_events/action_wml.cpp +++ b/src/game_events/action_wml.cpp @@ -547,82 +547,6 @@ WML_HANDLER_FUNCTION(get_global_variable,/**/,pcfg) verify_and_get_global_variable(pcfg); } -WML_HANDLER_FUNCTION(heal_unit, event_info, cfg) -{ - unit_map* units = resources::units; - - const vconfig & healers_filter = cfg.child("filter_second"); - std::vector healers; - if (!healers_filter.null()) { - const unit_filter ufilt(healers_filter, resources::filter_con); - BOOST_FOREACH(unit& u, *units) { - if ( ufilt(u) && u.has_ability_type("heals") ) { - healers.push_back(&u); - } - } - } - - const config::attribute_value amount = cfg["amount"]; - const config::attribute_value moves = cfg["moves"]; - const bool restore_attacks = cfg["restore_attacks"].to_bool(false); - const bool restore_statuses = cfg["restore_statuses"].to_bool(true); - const bool animate = cfg["animate"].to_bool(false); - - const vconfig & healed_filter = cfg.child("filter"); - bool only_unit_at_loc1 = healed_filter.null(); - bool heal_amount_to_set = true; - - const unit_filter ufilt(healed_filter, resources::filter_con); - for(unit_map::unit_iterator u = units->begin(); u != units->end(); ++u) { - if (only_unit_at_loc1) - { - u = units->find(event_info.loc1); - if(!u.valid()) return; - } - else if ( !ufilt(*u) ) continue; - - int heal_amount = u->max_hitpoints() - u->hitpoints(); - if(amount.blank() || amount == "full") u->set_hitpoints(u->max_hitpoints()); - else { - heal_amount = lexical_cast_default (amount, heal_amount); - const int new_hitpoints = std::max(1, std::min(u->max_hitpoints(), u->hitpoints() + heal_amount)); - heal_amount = new_hitpoints - u->hitpoints(); - u->set_hitpoints(new_hitpoints); - } - - if(!moves.blank()) { - if(moves == "full") u->set_movement(u->total_movement()); - else { - // set_movement doesn't set below 0 - u->set_movement(std::min( - u->total_movement(), - u->movement_left() + lexical_cast_default (moves, 0) - )); - } - } - - if(restore_attacks) u->set_attacks(u->max_attacks()); - - if(restore_statuses) - { - u->set_state(unit::STATE_POISONED, false); - u->set_state(unit::STATE_SLOWED, false); - u->set_state(unit::STATE_PETRIFIED, false); - u->set_state(unit::STATE_UNHEALABLE, false); - u->anim_comp().set_standing(); - } - - if (heal_amount_to_set) - { - heal_amount_to_set = false; - resources::gamedata->get_variable("heal_amount") = heal_amount; - } - - if(animate) unit_display::unit_healing(*u, healers, heal_amount); - if(only_unit_at_loc1) return; - } -} - WML_HANDLER_FUNCTION(lift_fog, /*event_info*/, cfg) { toggle_fog(true, cfg, !cfg["multiturn"].to_bool(false)); diff --git a/src/scripting/game_lua_kernel.cpp b/src/scripting/game_lua_kernel.cpp index ecc0b1f4ef9..f533a6a4317 100644 --- a/src/scripting/game_lua_kernel.cpp +++ b/src/scripting/game_lua_kernel.cpp @@ -69,7 +69,6 @@ #include "pathfind/pathfind.hpp" // for full_cost_map, plain_route, etc #include "pathfind/teleport.hpp" // for get_teleport_locations, etc #include "play_controller.hpp" // for play_controller -#include "race.hpp" // for unit_race, race_map #include "recall_list_manager.hpp" // for recall_list_manager #include "replay.hpp" // for get_user_choice, etc #include "reports.hpp" // for register_generator, etc @@ -77,6 +76,7 @@ #include "scripting/lua_common.hpp" #include "scripting/lua_cpp_function.hpp" #include "scripting/lua_gui2.hpp" // for show_gamestate_inspector +#include "scripting/lua_race.hpp" #include "scripting/lua_team.hpp" #include "scripting/lua_types.hpp" // for getunitKey, dlgclbkKey, etc #include "scripting/lua_unit_type.hpp" @@ -200,32 +200,6 @@ namespace { }; }//unnamed namespace for queued_event_context -/** - * Gets some data on a race (__index metamethod). - * - Arg 1: table containing an "id" field. - * - Arg 2: string containing the name of the property. - * - Ret 1: something containing the attribute. - */ -static int impl_race_get(lua_State* L) -{ - char const* m = luaL_checkstring(L, 2); - lua_pushstring(L, "id"); - lua_rawget(L, 1); - const unit_race* raceptr = unit_types.find_race(lua_tostring(L, -1)); - if(!raceptr) return luaL_argerror(L, 1, "unknown race"); - unit_race const &race = *raceptr; - - return_tstring_attrib("description", race.description()); - return_tstring_attrib("name", race.name()); - return_int_attrib("num_traits", race.num_traits()); - return_tstring_attrib("plural_name", race.plural_name()); - return_bool_attrib("ignore_global_traits", !race.uses_global_traits()); - return_string_attrib("undead_variation", race.undead_variation()); - return_cfgref_attrib("__cfg", race.get_cfg()); - - return 0; -} - /** * Destroys a unit object before it is collected (__gc metamethod). */ @@ -1906,6 +1880,88 @@ int game_lua_kernel::intf_find_cost_map(lua_State *L) return 1; } +int game_lua_kernel::intf_heal_unit(lua_State *L) +{ + vconfig cfg(luaW_checkvconfig(L, 1)); + + const game_events::queued_event &event_info = get_event_info(); + + unit_map & temp = units(); + unit_map* units = & temp; + + const vconfig & healers_filter = cfg.child("filter_second"); + std::vector healers; + if (!healers_filter.null()) { + const unit_filter ufilt(healers_filter, &game_state_); + BOOST_FOREACH(unit& u, *units) { + if ( ufilt(u) && u.has_ability_type("heals") ) { + healers.push_back(&u); + } + } + } + + const config::attribute_value amount = cfg["amount"]; + const config::attribute_value moves = cfg["moves"]; + const bool restore_attacks = cfg["restore_attacks"].to_bool(false); + const bool restore_statuses = cfg["restore_statuses"].to_bool(true); + const bool animate = cfg["animate"].to_bool(false); + + const vconfig & healed_filter = cfg.child("filter"); + bool only_unit_at_loc1 = healed_filter.null(); + bool heal_amount_to_set = true; + + const unit_filter ufilt(healed_filter, &game_state_); + for(unit_map::unit_iterator u = units->begin(); u != units->end(); ++u) { + if (only_unit_at_loc1) + { + u = units->find(event_info.loc1); + if(!u.valid()) return 0; + } + else if ( !ufilt(*u) ) continue; + + int heal_amount = u->max_hitpoints() - u->hitpoints(); + if(amount.blank() || amount == "full") u->set_hitpoints(u->max_hitpoints()); + else { + heal_amount = lexical_cast_default (amount, heal_amount); + const int new_hitpoints = std::max(1, std::min(u->max_hitpoints(), u->hitpoints() + heal_amount)); + heal_amount = new_hitpoints - u->hitpoints(); + u->set_hitpoints(new_hitpoints); + } + + if(!moves.blank()) { + if(moves == "full") u->set_movement(u->total_movement()); + else { + // set_movement doesn't set below 0 + u->set_movement(std::min( + u->total_movement(), + u->movement_left() + lexical_cast_default (moves, 0) + )); + } + } + + if(restore_attacks) u->set_attacks(u->max_attacks()); + + if(restore_statuses) + { + u->set_state(unit::STATE_POISONED, false); + u->set_state(unit::STATE_SLOWED, false); + u->set_state(unit::STATE_PETRIFIED, false); + u->set_state(unit::STATE_UNHEALABLE, false); + u->anim_comp().set_standing(); + } + + if (heal_amount_to_set) + { + heal_amount_to_set = false; + gamedata().get_variable("heal_amount") = heal_amount; + } + + if(animate) unit_display::unit_healing(*u, healers, heal_amount); + if(only_unit_at_loc1) return 0; + } + return 0; +} + /** * Places a unit on the map. * - Args 1,2: (optional) location. @@ -3600,6 +3656,7 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state & { "get_villages", boost::bind(&game_lua_kernel::intf_get_villages, this, _1) }, { "get_village_owner", boost::bind(&game_lua_kernel::intf_get_village_owner, this, _1) }, { "get_displayed_unit", boost::bind(&game_lua_kernel::intf_get_displayed_unit, this, _1) }, + { "heal_unit", boost::bind(&game_lua_kernel::intf_heal_unit, this, _1) }, { "highlight_hex", boost::bind(&game_lua_kernel::intf_highlight_hex, this, _1) }, { "is_enemy", boost::bind(&game_lua_kernel::intf_is_enemy, this, _1) }, { "kill", boost::bind(&game_lua_kernel::intf_kill, this, _1) }, @@ -3650,16 +3707,7 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state & cmd_log_ << lua_unit_type::register_metatable(L); //Create the getrace metatable - cmd_log_ << "Adding getrace metatable...\n"; - - lua_pushlightuserdata(L - , getraceKey); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, impl_race_get); - lua_setfield(L, -2, "__index"); - lua_pushstring(L, "race"); - lua_setfield(L, -2, "__metatable"); - lua_rawset(L, LUA_REGISTRYINDEX); + cmd_log_ << lua_race::register_metatable(L); // Create the getunit metatable. cmd_log_ << "Adding getunit metatable...\n"; @@ -3817,23 +3865,9 @@ void game_lua_kernel::initialize() lua_settop(L, 0); lua_getglobal(L, "wesnoth"); - lua_pushlightuserdata(L - , getraceKey); - lua_rawget(L, LUA_REGISTRYINDEX); - const race_map& races = unit_types.races(); - lua_createtable(L, 0, races.size()); - BOOST_FOREACH(const race_map::value_type &race, races) - { - lua_createtable(L, 0, 1); - char const* id = race.first.c_str(); - lua_pushstring(L, id); - lua_setfield(L, -2, "id"); - lua_pushvalue(L, -3); - lua_setmetatable(L, -2); - lua_setfield(L, -2, id); - } - lua_setfield(L, -3, "races"); - lua_pop(L, 2); + luaW_pushracetable(L); + lua_setfield(L, -2, "races"); + lua_pop(L, 1); // Execute the preload scripts. cmd_log_ << "Running preload scripts...\n"; diff --git a/src/scripting/game_lua_kernel.hpp b/src/scripting/game_lua_kernel.hpp index 7ff1d9ec002..369d0137d3d 100644 --- a/src/scripting/game_lua_kernel.hpp +++ b/src/scripting/game_lua_kernel.hpp @@ -109,6 +109,7 @@ class game_lua_kernel : public lua_kernel_base int intf_find_path(lua_State *L); int intf_find_reach(lua_State *L); int intf_find_cost_map(lua_State *L); + int intf_heal_unit(lua_State *L); int intf_message(lua_State *L); int intf_open_help(lua_State *L); int intf_play_sound(lua_State *L); diff --git a/src/scripting/lua_race.cpp b/src/scripting/lua_race.cpp new file mode 100644 index 00000000000..4ddff72b660 --- /dev/null +++ b/src/scripting/lua_race.cpp @@ -0,0 +1,98 @@ +/* + Copyright (C) 2014 by Chris Beck + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#include "scripting/lua_race.hpp" + +#include "lua/lua.h" +#include "lua/lauxlib.h" +#include "race.hpp" +#include "scripting/lua_common.hpp" +#include "unit_types.hpp" + +#include +#include + +/** + * Implementation for a lua reference to a race, + * used by the wesnoth in-game races table. + */ + +// Registry key +static const char * Race = "race"; + +/** + * Gets some data on a race (__index metamethod). + * - Arg 1: table containing an "id" field. + * - Arg 2: string containing the name of the property. + * - Ret 1: something containing the attribute. + */ +static int impl_race_get(lua_State* L) +{ + char const* m = luaL_checkstring(L, 2); + lua_pushstring(L, "id"); + lua_rawget(L, 1); + const unit_race* raceptr = unit_types.find_race(lua_tostring(L, -1)); + if(!raceptr) return luaL_argerror(L, 1, "unknown race"); + unit_race const &race = *raceptr; + + return_tstring_attrib("description", race.description()); + return_tstring_attrib("name", race.name()); + return_int_attrib("num_traits", race.num_traits()); + return_tstring_attrib("plural_name", race.plural_name()); + return_bool_attrib("ignore_global_traits", !race.uses_global_traits()); + return_string_attrib("undead_variation", race.undead_variation()); + return_cfgref_attrib("__cfg", race.get_cfg()); + + return 0; +} + +namespace lua_race { + + std::string register_metatable(lua_State * L) + { + luaL_newmetatable(L, Race); + + static luaL_Reg const callbacks[] = { + { "__index", &impl_race_get}, + { NULL, NULL } + }; + luaL_setfuncs(L, callbacks, 0); + + lua_pushstring(L, "race"); + lua_setfield(L, -2, "__metatable"); + + return "Adding getrace metatable...\n"; + } +} + +void luaW_pushrace(lua_State *L, const unit_race & race) +{ + lua_createtable(L, 0, 1); + lua_pushstring(L, race.id().c_str()); + lua_setfield(L, -2, "id"); + luaL_setmetatable(L, Race); +} + +void luaW_pushracetable(lua_State *L) +{ + const race_map& races = unit_types.races(); + lua_createtable(L, 0, races.size()); + + BOOST_FOREACH(const race_map::value_type &race, races) + { + assert(race.first == race.second.id()); + luaW_pushrace(L, race.second); + lua_setfield(L, -2, race.first.c_str()); + } +} diff --git a/src/scripting/lua_race.hpp b/src/scripting/lua_race.hpp new file mode 100644 index 00000000000..a1b64d777fe --- /dev/null +++ b/src/scripting/lua_race.hpp @@ -0,0 +1,35 @@ +/* + Copyright (C) 2014 by Chris Beck + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#ifndef LUA_RACE_HPP_INCLUDED +#define LUA_RACE_HPP_INCLUDED + +class unit_race; +struct lua_State; + +#include + +/** + * This namespace contains bindings for lua to hold a pointer to a race, + * and to access and modify it. + */ +namespace lua_race { + std::string register_metatable(lua_State *); +} //end namespace lua_team + +// Create a lua reference to the race. +void luaW_pushrace(lua_State *, const unit_race &); +void luaW_pushracetable(lua_State *); + +#endif diff --git a/src/scripting/lua_types.cpp b/src/scripting/lua_types.cpp index dbb1f0ff9d5..03a0a3d8187 100644 --- a/src/scripting/lua_types.cpp +++ b/src/scripting/lua_types.cpp @@ -16,14 +16,12 @@ /* Dummy pointer for getting unique keys for Lua's registry. */ static char const v_executeKey = 0; -static char const v_getraceKey = 0; static char const v_getunitKey = 0; static char const v_unitvarKey = 0; static char const v_ustatusKey = 0; luatypekey const executeKey = static_cast(const_cast(&v_executeKey)); -luatypekey const getraceKey = static_cast(const_cast(&v_getraceKey)); luatypekey const getunitKey = static_cast(const_cast(&v_getunitKey)); luatypekey const unitvarKey = static_cast(const_cast(&v_unitvarKey)); luatypekey const ustatusKey = static_cast(const_cast(&v_ustatusKey)); diff --git a/src/scripting/lua_types.hpp b/src/scripting/lua_types.hpp index 0f071c37843..4254be700f8 100644 --- a/src/scripting/lua_types.hpp +++ b/src/scripting/lua_types.hpp @@ -20,7 +20,6 @@ typedef void* luatypekey; // i dont want to cast to void* each time .... // a drawback is, that these are now normal static variables wich are initialised at initialisation time (so you shoudn't use these at/before initialisation time). extern luatypekey const executeKey; -extern luatypekey const getraceKey; extern luatypekey const getunitKey; extern luatypekey const unitvarKey; extern luatypekey const ustatusKey; diff --git a/src/seed_rng.cpp b/src/seed_rng.cpp index 1bf6fcd4786..65bba84dfc2 100644 --- a/src/seed_rng.cpp +++ b/src/seed_rng.cpp @@ -49,16 +49,14 @@ namespace seed_rng { - #ifdef SEED_RNG_USE_BOOST_RANDOM_DEVICE uint32_t next_seed() { + #ifdef SEED_RNG_USE_BOOST_RANDOM_DEVICE static boost::random_device rnd_; return rnd_(); - } #else - uint32_t next_seed() { return static_cast (std::time(0)); - } #endif + } std::string next_seed_str() { uint32_t random_seed_ = next_seed();