Merge pull request #744 from lua_refactor
Refactor some Lua stuff and reduce const_cast usage Conflicts: src/scripting/game_lua_kernel.cpp src/scripting/lua_unit.cpp
This commit is contained in:
commit
e821e508c3
36 changed files with 1157 additions and 1153 deletions
|
@ -164,6 +164,10 @@
|
|||
9193FC7B1D5AE5B2004F6C07 /* name_generator_factory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 913D26751D3C9697002FF3AB /* name_generator_factory.cpp */; };
|
||||
9193FC7E1D5BB64F004F6C07 /* advancement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9193FC7C1D5BB64E004F6C07 /* advancement.cpp */; };
|
||||
9193FC7F1D5BB64F004F6C07 /* advancement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9193FC7C1D5BB64E004F6C07 /* advancement.cpp */; };
|
||||
9193FC821D5C2CF8004F6C07 /* lua_unit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9193FC801D5C2CF7004F6C07 /* lua_unit.cpp */; };
|
||||
9193FC831D5C2D00004F6C07 /* lua_unit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9193FC801D5C2CF7004F6C07 /* lua_unit.cpp */; };
|
||||
9193FC861D5D7461004F6C07 /* lua_unit_attacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9193FC841D5D7452004F6C07 /* lua_unit_attacks.cpp */; };
|
||||
9193FC871D5D7461004F6C07 /* lua_unit_attacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9193FC841D5D7452004F6C07 /* lua_unit_attacks.cpp */; };
|
||||
919B37F81BAF789E00E0094C /* synced_user_choice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B37F71BAF789D00E0094C /* synced_user_choice.cpp */; };
|
||||
919B37FC1BAF7A9D00E0094C /* synced_choice_wait.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B37FA1BAF7A9D00E0094C /* synced_choice_wait.cpp */; };
|
||||
91A214E51CAD666B00927AEA /* arrow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B52EE8A1121359A600CFBDAB /* arrow.cpp */; };
|
||||
|
@ -268,7 +272,6 @@
|
|||
91A215601CAD6A8B00927AEA /* lzio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC89A1281879D17D00A3B0B1 /* lzio.cpp */; };
|
||||
91A215621CAD6DA400927AEA /* application_lua_kernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC218E9A1A1064F4007C910C /* application_lua_kernel.cpp */; };
|
||||
91A215631CAD6DA400927AEA /* game_lua_kernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC218EA21A106673007C910C /* game_lua_kernel.cpp */; };
|
||||
91A215641CAD6DA400927AEA /* lua_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C02A0D182F1F64008525C6 /* lua_api.cpp */; };
|
||||
91A215651CAD6DA400927AEA /* lua_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC218E9E1A106648007C910C /* lua_common.cpp */; };
|
||||
91A215661CAD6DA400927AEA /* lua_cpp_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECD5D7BE1A22DC8600114175 /* lua_cpp_function.cpp */; };
|
||||
91A215671CAD6DA400927AEA /* lua_fileops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECA4A6781A1EC319006BCCF2 /* lua_fileops.cpp */; };
|
||||
|
@ -278,7 +281,6 @@
|
|||
91A2156B1CAD6DA400927AEA /* lua_race.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECC2FFF91A51A00900023AF4 /* lua_race.cpp */; };
|
||||
91A2156C1CAD6DA500927AEA /* lua_rng.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECA4A67A1A1EC319006BCCF2 /* lua_rng.cpp */; };
|
||||
91A2156D1CAD6DA500927AEA /* lua_team.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC5430211A4E6024006D206C /* lua_team.cpp */; };
|
||||
91A2156E1CAD6DA500927AEA /* lua_types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C02A0E182F1F64008525C6 /* lua_types.cpp */; };
|
||||
91A2156F1CAD6DA500927AEA /* lua_unit_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC5430221A4E6024006D206C /* lua_unit_type.cpp */; };
|
||||
91A215701CAD6E7500927AEA /* context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC59F25F1A4529D2001910CB /* context.cpp */; };
|
||||
91A215711CAD6E7500927AEA /* manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EC59F2601A4529D2001910CB /* manager.cpp */; };
|
||||
|
@ -1259,8 +1261,6 @@
|
|||
F480CD4B14035038007175D6 /* sourceparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F480CD3C14035038007175D6 /* sourceparser.cpp */; };
|
||||
F480CD4C14035038007175D6 /* tag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F480CD3E14035038007175D6 /* tag.cpp */; };
|
||||
F49F134A15BC627C00B64B0B /* edit_label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F49F134815BC627C00B64B0B /* edit_label.cpp */; };
|
||||
F4C02A10182F1F64008525C6 /* lua_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C02A0D182F1F64008525C6 /* lua_api.cpp */; };
|
||||
F4C02A11182F1F64008525C6 /* lua_types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C02A0E182F1F64008525C6 /* lua_types.cpp */; };
|
||||
F4C5DD68158CFD5E0044F754 /* point.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4C5DD66158CFD5E0044F754 /* point.cpp */; };
|
||||
F4D2A99614DAED0E00CAFF31 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2A99514DAED0E00CAFF31 /* CoreFoundation.framework */; };
|
||||
F4D2A9D514DAED4200CAFF31 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4D2A99514DAED0E00CAFF31 /* CoreFoundation.framework */; };
|
||||
|
@ -1594,6 +1594,10 @@
|
|||
9193FC781D5AC2D8004F6C07 /* game_stats.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = game_stats.hpp; sourceTree = "<group>"; };
|
||||
9193FC7C1D5BB64E004F6C07 /* advancement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = advancement.cpp; sourceTree = "<group>"; };
|
||||
9193FC7D1D5BB64E004F6C07 /* advancement.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = advancement.hpp; sourceTree = "<group>"; };
|
||||
9193FC801D5C2CF7004F6C07 /* lua_unit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_unit.cpp; sourceTree = "<group>"; };
|
||||
9193FC811D5C2CF8004F6C07 /* lua_unit.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = lua_unit.hpp; sourceTree = "<group>"; };
|
||||
9193FC841D5D7452004F6C07 /* lua_unit_attacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_unit_attacks.cpp; sourceTree = "<group>"; };
|
||||
9193FC851D5D745D004F6C07 /* lua_unit_attacks.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = lua_unit_attacks.hpp; sourceTree = "<group>"; };
|
||||
919B37F71BAF789D00E0094C /* synced_user_choice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_user_choice.cpp; sourceTree = "<group>"; };
|
||||
919B37F91BAF78AB00E0094C /* synced_user_choice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = synced_user_choice.hpp; sourceTree = "<group>"; };
|
||||
919B37FA1BAF7A9D00E0094C /* synced_choice_wait.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = synced_choice_wait.cpp; sourceTree = "<group>"; };
|
||||
|
@ -2245,7 +2249,6 @@
|
|||
B5A5E3E012132C790047782D /* lundump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lundump.h; sourceTree = "<group>"; };
|
||||
B5A5E3E212132C790047782D /* lvm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lvm.h; sourceTree = "<group>"; };
|
||||
B5A5E3E412132C790047782D /* lzio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lzio.h; sourceTree = "<group>"; };
|
||||
B5A5E45012132DE30047782D /* lua_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = lua_api.hpp; sourceTree = "<group>"; };
|
||||
B5A9914A0ECA4064002BE442 /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = fonts; path = ../../fonts; sourceTree = SOURCE_ROOT; };
|
||||
B5A9B0780ECA4074002BE442 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../../images; sourceTree = SOURCE_ROOT; };
|
||||
B5A9B2140ECA4074002BE442 /* sounds */ = {isa = PBXFileReference; lastKnownFileType = folder; name = sounds; path = ../../sounds; sourceTree = SOURCE_ROOT; };
|
||||
|
@ -2656,7 +2659,6 @@
|
|||
F480CD3F14035038007175D6 /* tag.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tag.hpp; sourceTree = "<group>"; };
|
||||
F49F134815BC627C00B64B0B /* edit_label.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = edit_label.cpp; sourceTree = "<group>"; };
|
||||
F49F134915BC627C00B64B0B /* edit_label.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = edit_label.hpp; sourceTree = "<group>"; };
|
||||
F4C02A0D182F1F64008525C6 /* lua_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_api.cpp; sourceTree = "<group>"; };
|
||||
F4C02A0E182F1F64008525C6 /* lua_types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lua_types.cpp; sourceTree = "<group>"; };
|
||||
F4C02A0F182F1F64008525C6 /* lua_types.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = lua_types.hpp; sourceTree = "<group>"; };
|
||||
F4C5DD66158CFD5E0044F754 /* point.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = point.cpp; sourceTree = "<group>"; };
|
||||
|
@ -4125,8 +4127,6 @@
|
|||
91B621E21B76BAF300B00E0F /* context.hpp */,
|
||||
EC218EA21A106673007C910C /* game_lua_kernel.cpp */,
|
||||
91B621E41B76BB0100B00E0F /* game_lua_kernel.hpp */,
|
||||
F4C02A0D182F1F64008525C6 /* lua_api.cpp */,
|
||||
B5A5E45012132DE30047782D /* lua_api.hpp */,
|
||||
EC218E9E1A106648007C910C /* lua_common.cpp */,
|
||||
91B621E51B76BB0700B00E0F /* lua_common.hpp */,
|
||||
ECD5D7BE1A22DC8600114175 /* lua_cpp_function.cpp */,
|
||||
|
@ -4148,8 +4148,10 @@
|
|||
91B621EC1B76BB2200B00E0F /* lua_rng.hpp */,
|
||||
EC5430211A4E6024006D206C /* lua_team.cpp */,
|
||||
91B621ED1B76BB2600B00E0F /* lua_team.hpp */,
|
||||
F4C02A0E182F1F64008525C6 /* lua_types.cpp */,
|
||||
F4C02A0F182F1F64008525C6 /* lua_types.hpp */,
|
||||
9193FC801D5C2CF7004F6C07 /* lua_unit.cpp */,
|
||||
9193FC811D5C2CF8004F6C07 /* lua_unit.hpp */,
|
||||
9193FC841D5D7452004F6C07 /* lua_unit_attacks.cpp */,
|
||||
9193FC851D5D745D004F6C07 /* lua_unit_attacks.hpp */,
|
||||
EC5430221A4E6024006D206C /* lua_unit_type.cpp */,
|
||||
91B621EE1B76BB2C00B00E0F /* lua_unit_type.hpp */,
|
||||
EC59F2601A4529D2001910CB /* manager.cpp */,
|
||||
|
@ -4940,7 +4942,6 @@
|
|||
EC89A1431879D17D00A3B0B1 /* ltable.cpp in Sources */,
|
||||
EC89A1441879D17D00A3B0B1 /* ltablib.cpp in Sources */,
|
||||
EC89A1451879D17D00A3B0B1 /* ltm.cpp in Sources */,
|
||||
F4C02A10182F1F64008525C6 /* lua_api.cpp in Sources */,
|
||||
EC218EA01A106648007C910C /* lua_common.cpp in Sources */,
|
||||
ECD5D7BF1A22DC8600114175 /* lua_cpp_function.cpp in Sources */,
|
||||
ECA4A67B1A1EC319006BCCF2 /* lua_fileops.cpp in Sources */,
|
||||
|
@ -4954,7 +4955,6 @@
|
|||
ECC2FFFA1A51A00900023AF4 /* lua_race.cpp in Sources */,
|
||||
ECA4A67D1A1EC319006BCCF2 /* lua_rng.cpp in Sources */,
|
||||
EC5430231A4E6024006D206C /* lua_team.cpp in Sources */,
|
||||
F4C02A11182F1F64008525C6 /* lua_types.cpp in Sources */,
|
||||
EC5430241A4E6024006D206C /* lua_unit_type.cpp in Sources */,
|
||||
EC89A1481879D17D00A3B0B1 /* lundump.cpp in Sources */,
|
||||
EC89A1491879D17D00A3B0B1 /* lvm.cpp in Sources */,
|
||||
|
@ -5237,6 +5237,8 @@
|
|||
9193FC791D5AC2D8004F6C07 /* game_stats.cpp in Sources */,
|
||||
9193FC7E1D5BB64F004F6C07 /* advancement.cpp in Sources */,
|
||||
917746C11D680C7C00E8689A /* walker_tree_node.cpp in Sources */,
|
||||
9193FC821D5C2CF8004F6C07 /* lua_unit.cpp in Sources */,
|
||||
9193FC861D5D7461004F6C07 /* lua_unit_attacks.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5603,7 +5605,6 @@
|
|||
91A215601CAD6A8B00927AEA /* lzio.cpp in Sources */,
|
||||
91A215621CAD6DA400927AEA /* application_lua_kernel.cpp in Sources */,
|
||||
91A215631CAD6DA400927AEA /* game_lua_kernel.cpp in Sources */,
|
||||
91A215641CAD6DA400927AEA /* lua_api.cpp in Sources */,
|
||||
91A215651CAD6DA400927AEA /* lua_common.cpp in Sources */,
|
||||
91A215661CAD6DA400927AEA /* lua_cpp_function.cpp in Sources */,
|
||||
91A215671CAD6DA400927AEA /* lua_fileops.cpp in Sources */,
|
||||
|
@ -5613,7 +5614,6 @@
|
|||
91A2156B1CAD6DA400927AEA /* lua_race.cpp in Sources */,
|
||||
91A2156C1CAD6DA500927AEA /* lua_rng.cpp in Sources */,
|
||||
91A2156D1CAD6DA500927AEA /* lua_team.cpp in Sources */,
|
||||
91A2156E1CAD6DA500927AEA /* lua_types.cpp in Sources */,
|
||||
91A2156F1CAD6DA500927AEA /* lua_unit_type.cpp in Sources */,
|
||||
91A215701CAD6E7500927AEA /* context.cpp in Sources */,
|
||||
91A215711CAD6E7500927AEA /* manager.cpp in Sources */,
|
||||
|
@ -5809,6 +5809,8 @@
|
|||
9193FC7B1D5AE5B2004F6C07 /* name_generator_factory.cpp in Sources */,
|
||||
9193FC7F1D5BB64F004F6C07 /* advancement.cpp in Sources */,
|
||||
917746C21D680C7C00E8689A /* walker_tree_node.cpp in Sources */,
|
||||
9193FC831D5C2D00004F6C07 /* lua_unit.cpp in Sources */,
|
||||
9193FC871D5D7461004F6C07 /* lua_unit_attacks.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -383,8 +383,7 @@ void readonly_context_impl::calculate_moves(const unit_map& units, std::map<map_
|
|||
continue;
|
||||
}
|
||||
// If it's an enemy unit, reset its moves while we do the calculations.
|
||||
unit* held_unit = const_cast<unit *>(&*un_it);
|
||||
const unit_movement_resetter move_resetter(*held_unit,enemy || assume_full_movement);
|
||||
const unit_movement_resetter move_resetter(*un_it,enemy || assume_full_movement);
|
||||
|
||||
// Insert the trivial moves of staying on the same map location.
|
||||
if (un_it->movement_left() > 0) {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "units/unit.hpp"
|
||||
#include "pathfind/pathfind.hpp"
|
||||
#include "units/filter.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "lua/lauxlib.h"
|
||||
|
||||
namespace ai {
|
||||
|
@ -479,10 +479,7 @@ config aspect_attacks_lua::to_config() const
|
|||
static bool call_lua_filter_fcn(lua_State* L, const unit& u, int idx)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, idx);
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u.underlying_id());
|
||||
lua_pushlightuserdata(L, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, u.underlying_id());
|
||||
luaW_pcall(L, 1, 1);
|
||||
bool result = luaW_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "ai/lua/core.hpp"
|
||||
#include "ai/composite/aspect.hpp"
|
||||
#include "scripting/game_lua_kernel.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "scripting/push_check.hpp"
|
||||
#include "lua_object.hpp" // (Nephro)
|
||||
|
||||
|
@ -50,7 +50,7 @@ static lg::log_domain log_ai_engine_lua("ai/engine/lua");
|
|||
#define LOG_LUA LOG_STREAM(info, log_ai_engine_lua)
|
||||
#define ERR_LUA LOG_STREAM(err, log_ai_engine_lua)
|
||||
|
||||
static char const aisKey = 0;
|
||||
static char const aisKey[] = "ai contexts";
|
||||
|
||||
namespace ai {
|
||||
|
||||
|
@ -59,17 +59,15 @@ static void push_attack_analysis(lua_State *L, const attack_analysis&);
|
|||
void lua_ai_context::init(lua_State *L)
|
||||
{
|
||||
// Create the ai elements table.
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_newtable(L);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
}
|
||||
|
||||
void lua_ai_context::get_arguments(config &cfg) const
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
lua_rawgeti(L, -1, num_);
|
||||
|
||||
lua_getfield(L, -1, "params");
|
||||
|
@ -82,8 +80,7 @@ void lua_ai_context::set_arguments(const config &cfg)
|
|||
{
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
lua_rawgeti(L, -1, num_);
|
||||
|
||||
luaW_pushconfig(L, cfg);
|
||||
|
@ -96,8 +93,7 @@ void lua_ai_context::get_persistent_data(config &cfg) const
|
|||
{
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
lua_rawgeti(L, -1, num_);
|
||||
|
||||
lua_getfield(L, -1, "data");
|
||||
|
@ -110,8 +106,7 @@ void lua_ai_context::set_persistent_data(const config &cfg)
|
|||
{
|
||||
int top = lua_gettop(L);
|
||||
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
lua_rawgeti(L, -1, num_);
|
||||
|
||||
luaW_pushconfig(L, cfg);
|
||||
|
@ -955,8 +950,7 @@ static void generate_and_push_ai_table(lua_State* L, ai::engine_lua* engine) {
|
|||
static size_t generate_and_push_ai_state(lua_State* L, ai::engine_lua* engine)
|
||||
{
|
||||
// Retrieve the ai elements table from the registry.
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // [-1: AIs registry table]
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AIs registry table]
|
||||
size_t length_ai = lua_rawlen(L, -1); // length of table
|
||||
lua_newtable(L); // [-1: AI state table -2: AIs registry table]
|
||||
generate_and_push_ai_table(L, engine); // [-1: AI routines -2: AI state -3: AIs registry]
|
||||
|
@ -1022,8 +1016,7 @@ lua_ai_action_handler* lua_ai_action_handler::create(lua_State *L, char const *c
|
|||
}
|
||||
|
||||
// Retrieve the ai elements table from the registry.
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); //stack size is now 2 [-1: ais_table -2: f]
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey); //stack size is now 2 [-1: ais_table -2: f]
|
||||
// Push the function in the table so that it is not collected.
|
||||
size_t length = lua_rawlen(L, -1);//length of ais_table
|
||||
lua_pushvalue(L, -2); //stack size is now 3: [-1: f -2: ais_table -3: f]
|
||||
|
@ -1054,8 +1047,7 @@ lua_ai_load::lua_ai_load(lua_ai_context& ctx, bool read_only) : L(ctx.L), was_re
|
|||
return; // Leave the AI table on the stack, as requested
|
||||
}
|
||||
lua_pop(L, 1); // Pop the nil value off the stack
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey))); // [-1: key]
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // [-1: AI registry]
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry]
|
||||
lua_rawgeti(L, -1, ctx.num_); // [-1: AI state -2: AI registry]
|
||||
lua_remove(L,-2); // [-1: AI state]
|
||||
|
||||
|
@ -1087,8 +1079,7 @@ lua_ai_load::~lua_ai_load()
|
|||
lua_ai_context::~lua_ai_context()
|
||||
{
|
||||
// Remove the ai context from the registry, so that it can be collected.
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
lua_pushnil(L);
|
||||
lua_rawseti(L, -2, num_);
|
||||
lua_pop(L, 1);
|
||||
|
@ -1102,8 +1093,7 @@ void lua_ai_action_handler::handle(const config &cfg, bool read_only, lua_object
|
|||
lua_ai_load ctx(context_, read_only); // [-1: AI state table]
|
||||
|
||||
// Load the user function from the registry.
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey))); // [-1: key -2: AI state]
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); // [-1: AI registry -2: AI state]
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey); // [-1: AI registry -2: AI state]
|
||||
lua_rawgeti(L, -1, num_); // [-1: AI action -2: AI registry -3: AI state]
|
||||
lua_remove(L, -2); // [-1: AI action -2: AI state]
|
||||
|
||||
|
@ -1125,8 +1115,7 @@ void lua_ai_action_handler::handle(const config &cfg, bool read_only, lua_object
|
|||
lua_ai_action_handler::~lua_ai_action_handler()
|
||||
{
|
||||
// Remove the function from the registry, so that it can be collected.
|
||||
lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, aisKey);
|
||||
lua_pushnil(L);
|
||||
lua_rawseti(L, -2, num_);
|
||||
lua_pop(L, 1);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "ai/lua/lua_object.hpp"
|
||||
#include "ai/lua/engine_lua.hpp"
|
||||
#include "ai/default/aspect_attacks.hpp"
|
||||
#include "scripting/lua_types.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "resources.hpp"
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "lua/lua.h"
|
||||
#include "map/location.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "terrain/filter.hpp"
|
||||
#include "variable.hpp"
|
||||
|
|
|
@ -863,8 +863,10 @@ void config::recursive_clear_value(const std::string& key)
|
|||
|
||||
values.erase(key);
|
||||
|
||||
for (const any_child &value : all_children_range()) {
|
||||
const_cast<config *>(&value.cfg)->recursive_clear_value(key);
|
||||
for(std::pair<const std::string, child_list>& p : children) {
|
||||
for(config* cfg : p.second) {
|
||||
cfg->recursive_clear_value(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1339,8 +1341,10 @@ void config::clear_diff_track(const config& diff)
|
|||
itor->second[index]->clear_diff_track(item.cfg);
|
||||
}
|
||||
}
|
||||
for (const any_child &value : all_children_range()) {
|
||||
const_cast<config *>(&value.cfg)->remove_attribute(diff_track_attribute);
|
||||
for(std::pair<const std::string, child_list>& p : children) {
|
||||
for(config* cfg : p.second) {
|
||||
cfg->remove_attribute(diff_track_attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -213,9 +213,9 @@ const config &manager::get_values()
|
|||
config& manager::get_value_cfg(const std::string& id)
|
||||
{
|
||||
{
|
||||
const config& value_cfg = get_value_cfg_or_empty(id);
|
||||
if (!value_cfg.empty()) {
|
||||
return const_cast<config&>(value_cfg);
|
||||
config& value_cfg = values_.find_child("option", "id", id);
|
||||
if(value_cfg) {
|
||||
return value_cfg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,16 +237,8 @@ config& manager::get_value_cfg(const std::string& id)
|
|||
const config& manager::get_value_cfg_or_empty(const std::string& id) const
|
||||
{
|
||||
static const config empty;
|
||||
|
||||
for (const config::any_child& i : values_.all_children_range()) {
|
||||
for (const config& j : i.cfg.child_range("option")) {
|
||||
if (j["id"] == id) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return empty;
|
||||
const config& cfg = values_.find_child("option", "id", id);
|
||||
return cfg ? cfg : empty;
|
||||
}
|
||||
|
||||
config::any_child manager::get_option_parent(const std::string& id) const
|
||||
|
|
|
@ -94,7 +94,7 @@ void map_labels::read(const config &cfg)
|
|||
recalculate_labels();
|
||||
}
|
||||
|
||||
const terrain_label* map_labels::get_label(const map_location& loc, const std::string& team_name) const
|
||||
terrain_label* map_labels::get_label_private(const map_location& loc, const std::string& team_name)
|
||||
{
|
||||
team_label_map::const_iterator label_map = labels_.find(team_name);
|
||||
if (label_map != labels_.end()) {
|
||||
|
|
|
@ -41,7 +41,9 @@ public:
|
|||
void write(config& res) const;
|
||||
void read(const config &cfg);
|
||||
|
||||
const terrain_label* get_label(const map_location& loc, const std::string& team_name) const;
|
||||
const terrain_label* get_label(const map_location& loc, const std::string& team_name) const {
|
||||
return const_cast<map_labels*>(this)->get_label_private(loc, team_name);
|
||||
}
|
||||
// search a team-only label, if fails then try public labels
|
||||
const terrain_label* get_label(const map_location& loc) const;
|
||||
const terrain_label* set_label(const map_location& loc,
|
||||
|
@ -81,10 +83,7 @@ private:
|
|||
void add_label(const map_location &, terrain_label *);
|
||||
|
||||
void clear_map(label_map &, bool);
|
||||
/// For our private use, a wrapper for get_label() that can return a pointer
|
||||
/// to a non-const terrain_label.
|
||||
terrain_label* get_label_private(const map_location& loc, const std::string& team_name)
|
||||
{ return const_cast<terrain_label*>(get_label(loc, team_name)); }
|
||||
terrain_label* get_label_private(const map_location& loc, const std::string& team_name);
|
||||
// Note: this is not an overload of get_label() so that we do not block
|
||||
// outsiders from calling get_label for a non-const map_labels object.
|
||||
|
||||
|
|
|
@ -458,7 +458,7 @@ static void find_routes(
|
|||
}
|
||||
|
||||
|
||||
static paths::dest_vect::iterator lower_bound(paths::dest_vect &v, const map_location &loc)
|
||||
static paths::dest_vect::const_iterator lower_bound(const paths::dest_vect &v, const map_location &loc)
|
||||
{
|
||||
size_t sz = v.size(), pos = 0;
|
||||
while (sz)
|
||||
|
@ -473,14 +473,14 @@ static paths::dest_vect::iterator lower_bound(paths::dest_vect &v, const map_loc
|
|||
|
||||
paths::dest_vect::const_iterator paths::dest_vect::find(const map_location &loc) const
|
||||
{
|
||||
const_iterator i = lower_bound(const_cast<dest_vect &>(*this), loc), i_end = end();
|
||||
const_iterator i = lower_bound(*this, loc), i_end = end();
|
||||
if (i != i_end && i->curr != loc) i = i_end;
|
||||
return i;
|
||||
}
|
||||
|
||||
void paths::dest_vect::insert(const map_location &loc)
|
||||
{
|
||||
iterator i = lower_bound(*this, loc), i_end = end();
|
||||
const_iterator i = lower_bound(*this, loc), i_end = end();
|
||||
if (i != i_end && i->curr == loc) return;
|
||||
paths::step s = { loc, map_location(), 0 };
|
||||
std::vector<step>::insert(i, s);
|
||||
|
|
|
@ -739,7 +739,7 @@ const mp_game_settings& play_controller::get_mp_settings()
|
|||
return saved_game_.mp_settings();
|
||||
}
|
||||
|
||||
const game_classification& play_controller::get_classification()
|
||||
game_classification& play_controller::get_classification()
|
||||
{
|
||||
return saved_game_.classification();
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@ public:
|
|||
|
||||
std::shared_ptr<wb::manager> get_whiteboard();
|
||||
const mp_game_settings& get_mp_settings();
|
||||
const game_classification& get_classification();
|
||||
game_classification& get_classification();
|
||||
int get_server_request_number() const { return gamestate().server_request_number_; }
|
||||
void increase_server_request_number() { ++gamestate().server_request_number_; }
|
||||
|
||||
|
|
|
@ -30,12 +30,10 @@
|
|||
#include "config.hpp"
|
||||
#include "game_errors.hpp"
|
||||
#include "log.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_cpp_function.hpp"
|
||||
#include "scripting/lua_fileops.hpp"
|
||||
#include "scripting/lua_kernel_base.hpp"
|
||||
#include "scripting/lua_types.hpp"
|
||||
#include "scripting/plugins/context.hpp"
|
||||
#include "scripting/plugins/manager.hpp"
|
||||
|
||||
|
|
|
@ -72,14 +72,14 @@
|
|||
#include "recall_list_manager.hpp" // for recall_list_manager
|
||||
#include "replay.hpp" // for get_user_choice, etc
|
||||
#include "reports.hpp" // for register_generator, etc
|
||||
#include "scripting/lua_api.hpp" // for luaW_toboolean, etc
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "scripting/lua_unit_attacks.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_cpp_function.hpp"
|
||||
#include "scripting/lua_gui2.hpp" // for show_gamestate_inspector
|
||||
#include "scripting/lua_pathfind_cost_calculator.hpp"
|
||||
#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"
|
||||
#include "scripting/push_check.hpp"
|
||||
#include "sdl/utils.hpp" // for surface
|
||||
|
@ -327,497 +327,6 @@ namespace {
|
|||
};
|
||||
}//unnamed namespace for queued_event_context
|
||||
|
||||
/**
|
||||
* Destroys a unit object before it is collected (__gc metamethod).
|
||||
*/
|
||||
static int impl_unit_collect(lua_State *L)
|
||||
{
|
||||
lua_unit *u = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
u->lua_unit::~lua_unit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks two lua proxy units for equality. (__eq metamethod)
|
||||
*/
|
||||
static int impl_unit_equality(lua_State* L)
|
||||
{
|
||||
unit& left = luaW_checkunit(L, 1);
|
||||
unit& right = luaW_checkunit(L, 2);
|
||||
const bool equal = left.underlying_id() == right.underlying_id();
|
||||
lua_pushboolean(L, equal);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets some data on a unit (__index metamethod).
|
||||
* - Arg 1: full userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the property.
|
||||
* - Ret 1: something containing the attribute.
|
||||
*/
|
||||
static int impl_unit_get(lua_State *L)
|
||||
{
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
const unit* pu = lu->get();
|
||||
|
||||
if (strcmp(m, "valid") == 0)
|
||||
{
|
||||
if (!pu) return 0;
|
||||
if (lu->on_map())
|
||||
lua_pushstring(L, "map");
|
||||
else if (lu->on_recall_list())
|
||||
lua_pushstring(L, "recall");
|
||||
else
|
||||
lua_pushstring(L, "private");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!pu) return luaL_argerror(L, 1, "unknown unit");
|
||||
unit const &u = *pu;
|
||||
|
||||
// Find the corresponding attribute.
|
||||
return_int_attrib("x", u.get_location().x + 1);
|
||||
return_int_attrib("y", u.get_location().y + 1);
|
||||
if (strcmp(m, "loc") == 0) {
|
||||
lua_pushinteger(L, u.get_location().x + 1);
|
||||
lua_pushinteger(L, u.get_location().y + 1);
|
||||
return 2;
|
||||
}
|
||||
return_int_attrib("side", u.side());
|
||||
return_string_attrib("id", u.id());
|
||||
return_string_attrib("type", u.type_id());
|
||||
return_string_attrib("image_mods", u.effect_image_mods());
|
||||
return_string_attrib("usage", u.usage());
|
||||
return_int_attrib("hitpoints", u.hitpoints());
|
||||
return_int_attrib("max_hitpoints", u.max_hitpoints());
|
||||
return_int_attrib("experience", u.experience());
|
||||
return_int_attrib("max_experience", u.max_experience());
|
||||
return_int_attrib("recall_cost", u.recall_cost());
|
||||
return_int_attrib("moves", u.movement_left());
|
||||
return_int_attrib("max_moves", u.total_movement());
|
||||
return_int_attrib("max_attacks", u.max_attacks());
|
||||
return_int_attrib("attacks_left", u.attacks_left());
|
||||
return_tstring_attrib("name", u.name());
|
||||
return_bool_attrib("canrecruit", u.can_recruit());
|
||||
return_int_attrib("level", u.level());
|
||||
return_int_attrib("cost", u.cost());
|
||||
|
||||
return_vector_string_attrib("extra_recruit", u.recruits());
|
||||
return_vector_string_attrib("advances_to", u.advances_to());
|
||||
|
||||
if (strcmp(m, "alignment") == 0) {
|
||||
lua_push(L, u.alignment());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(m, "upkeep") == 0) {
|
||||
unit::t_upkeep upkeep = u.upkeep_raw();
|
||||
if(boost::get<unit::upkeep_full>(&upkeep) != nullptr){
|
||||
lua_pushstring(L, "full");
|
||||
}
|
||||
else if(boost::get<unit::upkeep_loyal>(&upkeep) != nullptr){
|
||||
lua_pushstring(L, "loyal");
|
||||
}
|
||||
else {
|
||||
lua_push(L, boost::get<int>(upkeep));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "advancements") == 0) {
|
||||
lua_push(L, u.modification_advancements());
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "overlays") == 0) {
|
||||
lua_push(L, u.overlays());
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "traits") == 0) {
|
||||
lua_push(L, u.get_traits_list());
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "abilities") == 0) {
|
||||
lua_push(L, u.get_ability_list());
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "status") == 0) {
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawseti(L, -2, 1);
|
||||
lua_pushlightuserdata(L
|
||||
, ustatusKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "variables") == 0) {
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawseti(L, -2, 1);
|
||||
lua_pushlightuserdata(L
|
||||
, unitvarKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "attacks") == 0) {
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, 1);
|
||||
// hack: store the unit at -1 becasue we want positive indexes to refers to the attacks.
|
||||
lua_rawseti(L, -2, -1);
|
||||
lua_pushlightuserdata(L, uattacksKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
return_cfg_attrib("recall_filter", cfg = u.recall_filter());
|
||||
return_bool_attrib("hidden", u.get_hidden());
|
||||
return_bool_attrib("petrified", u.incapacitated());
|
||||
return_bool_attrib("resting", u.resting());
|
||||
return_string_attrib("role", u.get_role());
|
||||
return_string_attrib("race", u.race()->id());
|
||||
return_string_attrib("gender", gender_string(u.gender()));
|
||||
return_string_attrib("variation", u.variation());
|
||||
return_bool_attrib("zoc", u.get_emit_zoc());
|
||||
return_string_attrib("facing", map_location::write_direction(u.facing()));
|
||||
return_string_attrib("portrait", u.big_profile() == u.absolute_image() ? u.absolute_image() + u.image_mods() : u.big_profile());
|
||||
return_cfg_attrib("__cfg", u.write(cfg); u.get_location().write(cfg));
|
||||
|
||||
return lua_kernel_base::get_lua_kernel<game_lua_kernel>(L).return_unit_method(L, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets some data on a unit (__newindex metamethod).
|
||||
* - Arg 1: full userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the property.
|
||||
* - Arg 3: something containing the attribute.
|
||||
*/
|
||||
static int impl_unit_set(lua_State *L)
|
||||
{
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
unit* pu = lu->get();
|
||||
if (!pu) return luaL_argerror(L, 1, "unknown unit");
|
||||
unit &u = *pu;
|
||||
|
||||
// Find the corresponding attribute.
|
||||
//modify_int_attrib_check_range("side", u.set_side(value), 1, static_cast<int>(teams().size())); TODO: Figure out if this is a good idea, to refer to teams() and make this depend on having a gamestate
|
||||
modify_int_attrib("side", u.set_side(value));
|
||||
modify_int_attrib("moves", u.set_movement(value));
|
||||
modify_int_attrib("hitpoints", u.set_hitpoints(value));
|
||||
modify_int_attrib("experience", u.set_experience(value));
|
||||
modify_int_attrib("recall_cost", u.set_recall_cost(value));
|
||||
modify_int_attrib("attacks_left", u.set_attacks(value));
|
||||
modify_int_attrib("level", u.set_level(value));
|
||||
modify_bool_attrib("resting", u.set_resting(value));
|
||||
modify_tstring_attrib("name", u.set_name(value));
|
||||
modify_string_attrib("role", u.set_role(value));
|
||||
modify_string_attrib("facing", u.set_facing(map_location::parse_direction(value)));
|
||||
modify_bool_attrib("hidden", u.set_hidden(value));
|
||||
modify_bool_attrib("zoc", u.set_emit_zoc(value));
|
||||
modify_bool_attrib("canrecruit", u.set_can_recruit(value));
|
||||
|
||||
modify_vector_string_attrib("extra_recruit", u.set_recruits(vector));
|
||||
modify_vector_string_attrib("advances_to", u.set_advances_to(vector));
|
||||
if (strcmp(m, "alignment") == 0) {
|
||||
u.set_alignment(lua_check<unit_type::ALIGNMENT>(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (strcmp(m, "advancements") == 0) {
|
||||
u.set_advancements(lua_check<std::vector<config> >(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(m, "upkeep") == 0) {
|
||||
if(lua_isnumber(L, 3)) {
|
||||
u.set_upkeep(luaL_checkint(L, 3));
|
||||
return 0;
|
||||
}
|
||||
const char* v = luaL_checkstring(L, 3);
|
||||
if(strcmp(m, "loyal") == 0) {
|
||||
u.set_upkeep(unit::upkeep_loyal());
|
||||
}
|
||||
else if(strcmp(m, "full") == 0) {
|
||||
u.set_upkeep(unit::upkeep_full());
|
||||
}
|
||||
else {
|
||||
|
||||
std::string err_msg = "unknown upkeep value of unit: ";
|
||||
err_msg += v;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (!lu->on_map()) {
|
||||
map_location loc = u.get_location();
|
||||
modify_int_attrib("x", loc.x = value - 1; u.set_location(loc));
|
||||
modify_int_attrib("y", loc.y = value - 1; u.set_location(loc));
|
||||
}
|
||||
|
||||
std::string err_msg = "unknown modifiable property of unit: ";
|
||||
err_msg += m;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a unit (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Ret 1: boolean.
|
||||
*/
|
||||
static int impl_unit_status_get(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1))
|
||||
return luaL_typerror(L, 1, "unit status");
|
||||
lua_rawgeti(L, 1, 1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
if (!u) return luaL_argerror(L, 1, "unknown unit");
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
lua_pushboolean(L, u->get_state(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of a unit (__newindex metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Arg 3: boolean.
|
||||
*/
|
||||
static int impl_unit_status_set(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1))
|
||||
return luaL_typerror(L, 1, "unit status");
|
||||
lua_rawgeti(L, 1, 1);
|
||||
unit* u = luaW_tounit(L, -1);
|
||||
if (!u) return luaL_argerror(L, 1, "unknown unit");
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
u->set_state(m, luaW_toboolean(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the variable of a unit (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Ret 1: boolean.
|
||||
*/
|
||||
static int impl_unit_variables_get(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1))
|
||||
return luaL_typerror(L, 1, "unit variables");
|
||||
lua_rawgeti(L, 1, 1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
if (!u) return luaL_argerror(L, 1, "unknown unit");
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
return_cfgref_attrib("__cfg", u->variables());
|
||||
|
||||
variable_access_const v(m, u->variables());
|
||||
return luaW_pushvariable(L, v) ? 1 : 0;
|
||||
}
|
||||
/**
|
||||
* Gets the attacks of a unit or unit type (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit or unit type.
|
||||
* - Arg 2: index (int) or id (string) identifying a particular attack.
|
||||
* - Ret 1: the unit's attacks.
|
||||
*/
|
||||
static int impl_unit_attacks_get(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attacks");
|
||||
}
|
||||
lua_rawgeti(L, 1, -1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
const unit_type* ut = static_cast<const unit_type*>(luaL_testudata(L, -1, "unit type"));
|
||||
if (!u && !ut) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
const attack_type* attack = nullptr;
|
||||
const std::vector<attack_type>& attacks = u ? u->attacks() : ut->attacks();
|
||||
if(!lua_isnumber(L,2)) {
|
||||
std::string attack_id = luaL_checkstring(L, 2);
|
||||
for (const attack_type& at : attacks) {
|
||||
if(at.id() == attack_id) {
|
||||
attack = &at;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (attack == nullptr) {
|
||||
//return nil on invalid index, just like lua tables do.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
size_t index = luaL_checkinteger(L, 2) - 1;
|
||||
if (index >= attacks.size()) {
|
||||
//return nil on invalid index, just like lua tables do.
|
||||
return 0;
|
||||
}
|
||||
attack = &attacks[index];
|
||||
}
|
||||
|
||||
// stack { lua_unit }, id/index, lua_unit
|
||||
lua_createtable(L, 2, 0);
|
||||
// stack { lua_unit }, id/index, lua_unit, table
|
||||
lua_pushvalue(L, -2);
|
||||
// stack { lua_unit }, id/index, lua_unit, table, lua_unit
|
||||
lua_rawseti(L, -2, 1);
|
||||
// stack { lua_unit }, id/index, lua_unit, table
|
||||
lua_pushstring(L, attack->id().c_str());
|
||||
// stack { lua_unit }, id/index, lua_unit, table, attack id
|
||||
lua_rawseti(L, -2, 2);
|
||||
// stack { lua_unit }, id/index, lua_unit, table
|
||||
lua_pushlightuserdata(L, uattackKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the attacks of a unit (__len metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Ret 1: size of unit attacks vector.
|
||||
*/
|
||||
static int impl_unit_attacks_len(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attacks");
|
||||
}
|
||||
lua_rawgeti(L, 1, -1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
if (!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
lua_pushinteger(L, u->attacks().size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a propoerty of a units attack (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id. and a string identyfying the attack.
|
||||
* - Arg 2: string
|
||||
* - Ret 1:
|
||||
*/
|
||||
static int impl_unit_attack_get(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attack");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
if (!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
lua_rawgeti(L, 1, 2);
|
||||
std::string attack_id = luaL_checkstring(L, -1);
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
for (const attack_type& attack : u->attacks())
|
||||
{
|
||||
if(attack.id() == attack_id)
|
||||
{
|
||||
|
||||
return_string_attrib("description", attack.name());
|
||||
return_string_attrib("name", attack.id());
|
||||
return_string_attrib("type", attack.type());
|
||||
return_string_attrib("icon", attack.icon());
|
||||
return_string_attrib("range", attack.range());
|
||||
// "min_range"
|
||||
// "max_range"
|
||||
return_int_attrib("damage", attack.damage());
|
||||
return_int_attrib("number", attack.num_attacks());
|
||||
return_int_attrib("attack_weight", attack.attack_weight());
|
||||
return_int_attrib("defense_weight", attack.defense_weight());
|
||||
return_int_attrib("accuracy", attack.accuracy());
|
||||
return_int_attrib("movement_used", attack.movement_used());
|
||||
return_int_attrib("parry", attack.parry());
|
||||
return_cfgref_attrib("specials", attack.specials());
|
||||
return_cfgref_attrib("__cfg", attack.to_config());
|
||||
std::string err_msg = "unknown property of attack: ";
|
||||
err_msg += m;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
}
|
||||
return luaL_argerror(L, 1, "invalid attack id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a propoerty of a units attack (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id. and a string identyfying the attack.
|
||||
* - Arg 2: string
|
||||
* - Ret 1:
|
||||
*/
|
||||
static int impl_unit_attack_set(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attack");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
unit* u = luaW_tounit(L, -1);
|
||||
if (!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
lua_rawgeti(L, 1, 2);
|
||||
std::string attack_id = luaL_checkstring(L, -1);
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
for (attack_type& attack : u->attacks())
|
||||
{
|
||||
if(attack.id() == attack_id)
|
||||
{
|
||||
|
||||
modify_tstring_attrib("description", attack.set_name(value));
|
||||
// modify_string_attrib("name", attack.set_id(value));
|
||||
modify_string_attrib("type", attack.set_type(value));
|
||||
modify_string_attrib("icon", attack.set_icon(value));
|
||||
modify_string_attrib("range", attack.set_range(value));
|
||||
// "min_range"
|
||||
// "max_range"
|
||||
modify_int_attrib("damage", attack.set_damage(value));
|
||||
modify_int_attrib("number", attack.set_num_attacks(value));
|
||||
modify_int_attrib("attack_weight", attack.set_attack_weight(value));
|
||||
modify_int_attrib("defense_weight", attack.set_defense_weight(value));
|
||||
modify_int_attrib("accuracy", attack.set_accuracy(value));
|
||||
modify_int_attrib("movement_used", attack.set_movement_used(value));
|
||||
modify_int_attrib("parry", attack.set_parry(value));
|
||||
|
||||
if (strcmp(m, "specials") == 0) { \
|
||||
attack.set_specials(luaW_checkconfig(L, 3));
|
||||
return 0;
|
||||
}
|
||||
return_cfgref_attrib("specials", attack.specials());
|
||||
std::string err_msg = "unknown modifyable property of attack: ";
|
||||
err_msg += m;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
}
|
||||
return luaL_argerror(L, 1, "invalid attack id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the variable of a unit (__newindex metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Arg 3: scalar.
|
||||
*/
|
||||
static int impl_unit_variables_set(lua_State *L)
|
||||
{
|
||||
if (!lua_istable(L, 1))
|
||||
return luaL_typerror(L, 1, "unit variables");
|
||||
lua_rawgeti(L, 1, 1);
|
||||
unit* u = luaW_tounit(L, -1);
|
||||
if (!u) return luaL_argerror(L, 1, "unknown unit");
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
if (strcmp(m, "__cfg") == 0) {
|
||||
u->variables() = luaW_checkconfig(L, 3);
|
||||
return 0;
|
||||
}
|
||||
variable_access_create v(m, u->variables());
|
||||
luaW_checkvariable(L, v, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets currently viewing side.
|
||||
* - Ret 1: integer specifying the currently viewing side
|
||||
|
@ -868,10 +377,7 @@ int game_lua_kernel::intf_get_unit(lua_State *L)
|
|||
std::string id = luaL_checkstring(L, 1);
|
||||
for(const unit& u : units()) {
|
||||
if(u.id() == id) {
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u.underlying_id());
|
||||
lua_pushlightuserdata(L, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, u.underlying_id());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -884,11 +390,7 @@ int game_lua_kernel::intf_get_unit(lua_State *L)
|
|||
|
||||
if (!ui.valid()) return 0;
|
||||
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(ui->underlying_id());
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, ui->underlying_id());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -909,11 +411,7 @@ int game_lua_kernel::intf_get_displayed_unit(lua_State *L)
|
|||
game_display_->show_everything());
|
||||
if (!ui.valid()) return 0;
|
||||
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(ui->underlying_id());
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, ui->underlying_id());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -928,21 +426,16 @@ int game_lua_kernel::intf_get_units(lua_State *L)
|
|||
vconfig filter = luaW_checkvconfig(L, 1, true);
|
||||
|
||||
// Go through all the units while keeping the following stack:
|
||||
// 1: metatable, 2: return table, 3: userdata, 4: metatable copy
|
||||
// 1: return table, 2: userdata
|
||||
lua_settop(L, 0);
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_newtable(L);
|
||||
int i = 1;
|
||||
|
||||
// note that if filter is null, this yields a null filter matching everything (and doing no work)
|
||||
filter_context & fc = game_state_;
|
||||
for (const unit * ui : unit_filter(filter, &fc).all_matches_on_map()) {
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(ui->underlying_id());
|
||||
lua_pushvalue(L, 1);
|
||||
lua_setmetatable(L, 3);
|
||||
lua_rawseti(L, 2, i);
|
||||
luaW_pushunit(L, ui->underlying_id());
|
||||
lua_rawseti(L, 1, i);
|
||||
++i;
|
||||
}
|
||||
return 1;
|
||||
|
@ -957,12 +450,7 @@ int game_lua_kernel::intf_get_units(lua_State *L)
|
|||
*/
|
||||
int game_lua_kernel::intf_match_unit(lua_State *L)
|
||||
{
|
||||
if (!luaW_hasmetatable(L, 1, getunitKey))
|
||||
return luaL_typerror(L, 1, "unit");
|
||||
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
unit* u = lu->get();
|
||||
if (!u) return luaL_argerror(L, 1, "unit not found");
|
||||
lua_unit& u = *luaW_checkunit_ref(L, 1);
|
||||
|
||||
vconfig filter = luaW_checkvconfig(L, 2, true);
|
||||
|
||||
|
@ -973,8 +461,8 @@ int game_lua_kernel::intf_match_unit(lua_State *L)
|
|||
|
||||
filter_context & fc = game_state_;
|
||||
|
||||
if (luaW_hasmetatable(L, 3, getunitKey)) {
|
||||
if (int side = lu->on_recall_list()) {
|
||||
if(unit* u_adj = luaW_tounit(L, 3)) {
|
||||
if(int side = u.on_recall_list()) {
|
||||
WRN_LUA << "wesnoth.match_unit called with a secondary unit (3rd argument), ";
|
||||
WRN_LUA << "but unit to match was on recall list. ";
|
||||
WRN_LUA << "Thus the 3rd argument is ignored.\n";
|
||||
|
@ -983,13 +471,11 @@ int game_lua_kernel::intf_match_unit(lua_State *L)
|
|||
lua_pushboolean(L, unit_filter(filter, &fc).matches(*u, map_location()));
|
||||
return 1;
|
||||
}
|
||||
lua_unit *lu_adj = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
unit* u_adj = lu_adj->get();
|
||||
if (!u_adj) {
|
||||
return luaL_argerror(L, 3, "unit not found");
|
||||
}
|
||||
lua_pushboolean(L, unit_filter(filter, &fc).matches(*u, *u_adj));
|
||||
} else if (int side = lu->on_recall_list()) {
|
||||
} else if(int side = u.on_recall_list()) {
|
||||
map_location loc;
|
||||
luaW_tolocation(L, 3, loc); // If argument 3 isn't a location, loc is unchanged
|
||||
team &t = (teams())[side - 1];
|
||||
|
@ -1015,11 +501,8 @@ int game_lua_kernel::intf_get_recall_units(lua_State *L)
|
|||
vconfig filter = luaW_checkvconfig(L, 1, true);
|
||||
|
||||
// Go through all the units while keeping the following stack:
|
||||
// 1: metatable, 2: return table, 3: userdata, 4: metatable copy
|
||||
// 1: return table, 2: userdata
|
||||
lua_settop(L, 0);
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_newtable(L);
|
||||
int i = 1, s = 1;
|
||||
filter_context & fc = game_state_;
|
||||
|
@ -1034,10 +517,8 @@ int game_lua_kernel::intf_get_recall_units(lua_State *L)
|
|||
if (!ufilt( *u, map_location() ))
|
||||
continue;
|
||||
}
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(s, u->underlying_id());
|
||||
lua_pushvalue(L, 1);
|
||||
lua_setmetatable(L, 3);
|
||||
lua_rawseti(L, 2, i);
|
||||
luaW_pushunit(L, s, u->underlying_id());
|
||||
lua_rawseti(L, 1, i);
|
||||
++i;
|
||||
}
|
||||
++s;
|
||||
|
@ -1232,14 +713,14 @@ int game_lua_kernel::intf_clear_menu_item(lua_State *L)
|
|||
|
||||
int game_lua_kernel::intf_set_end_campaign_credits(lua_State *L)
|
||||
{
|
||||
game_classification &classification = const_cast<game_classification &> (play_controller_.get_classification());
|
||||
game_classification &classification = play_controller_.get_classification();
|
||||
classification.end_credits = luaW_toboolean(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int game_lua_kernel::intf_set_end_campaign_text(lua_State *L)
|
||||
{
|
||||
game_classification &classification = const_cast<game_classification &> (play_controller_.get_classification());
|
||||
game_classification &classification = play_controller_.get_classification();
|
||||
classification.end_text = luaW_checktstring(L, 1);
|
||||
if (lua_isnumber(L, 2)) {
|
||||
classification.end_text_duration = static_cast<int> (lua_tonumber(L, 2));
|
||||
|
@ -1884,7 +1365,7 @@ int game_lua_kernel::intf_get_end_level_data(lua_State* L)
|
|||
return 0;
|
||||
}
|
||||
auto data = play_controller_.get_end_level_data_const();
|
||||
new(lua_newuserdata(L, sizeof(end_level_data))) end_level_data();
|
||||
new(L) end_level_data();
|
||||
if(luaL_newmetatable(L, "end level data")) {
|
||||
static luaL_Reg const callbacks[] = {
|
||||
{ "__index", &impl_end_level_data_get},
|
||||
|
@ -2463,6 +1944,15 @@ int game_lua_kernel::intf_print(lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void game_lua_kernel::put_unit_helper(const map_location& loc)
|
||||
{
|
||||
if(game_display_) {
|
||||
game_display_->invalidate(loc);
|
||||
}
|
||||
|
||||
units().erase(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places a unit on the map.
|
||||
* - Arg 1: (optional) location.
|
||||
|
@ -2479,8 +1969,6 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
|
|||
}
|
||||
int unit_arg = 1;
|
||||
|
||||
lua_unit *lu = nullptr;
|
||||
unit_ptr u = unit_ptr();
|
||||
map_location loc;
|
||||
if (lua_isnumber(L, 1)) {
|
||||
// Since this form is deprecated, I didn't bother updating it to luaW_tolocation.
|
||||
|
@ -2496,12 +1984,9 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
|
|||
}
|
||||
}
|
||||
|
||||
if (luaW_hasmetatable(L, unit_arg, getunitKey))
|
||||
{
|
||||
lu = static_cast<lua_unit *>(lua_touserdata(L, unit_arg));
|
||||
u = lu->get_shared();
|
||||
if (!u) return luaL_argerror(L, unit_arg, "unit not found");
|
||||
if (lu->on_map() && (unit_arg == 1 || u->get_location() == loc)) {
|
||||
if((luaW_isunit(L, unit_arg))) {
|
||||
lua_unit& u = *luaW_checkunit_ref(L, unit_arg);
|
||||
if(u.on_map() && u->get_location() == loc) {
|
||||
return 0;
|
||||
}
|
||||
if (!loc.valid()) {
|
||||
|
@ -2511,9 +1996,10 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
|
|||
} else if (unit_arg != 1) {
|
||||
WRN_LUA << "wesnoth.put_unit(x, y, unit) is deprecated. Use wesnoth.put_unit(unit, x, y) instead\n";
|
||||
}
|
||||
}
|
||||
else if (!lua_isnoneornil(L, unit_arg))
|
||||
{
|
||||
put_unit_helper(loc);
|
||||
u.put_map(loc);
|
||||
u.get_shared()->anim_comp().set_standing();
|
||||
} else if(!lua_isnoneornil(L, unit_arg)) {
|
||||
const vconfig* vcfg = nullptr;
|
||||
config cfg = luaW_checkconfig(L, unit_arg, vcfg);
|
||||
if (unit_arg == 1 && !map().on_board(loc)) {
|
||||
|
@ -2524,29 +2010,16 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
|
|||
} else if (unit_arg != 1) {
|
||||
WRN_LUA << "wesnoth.put_unit(x, y, unit) is deprecated. Use wesnoth.put_unit(unit, x, y) instead\n";
|
||||
}
|
||||
u = unit_ptr (new unit(cfg, true, vcfg));
|
||||
}
|
||||
|
||||
if (game_display_) {
|
||||
game_display_->invalidate(loc);
|
||||
}
|
||||
|
||||
if (!u) {
|
||||
if (unit_arg == 3) {
|
||||
WRN_LUA << "wesnoth.put_unit(x, y) is deprecated. Use wesnoth.erase_unit(x, y) instead\n";
|
||||
units().erase(loc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
units().erase(loc);
|
||||
|
||||
if (lu) {
|
||||
lu->put_map(loc);
|
||||
lu->get_shared()->anim_comp().set_standing();
|
||||
} else {
|
||||
unit_ptr u(new unit(cfg, true, vcfg));
|
||||
put_unit_helper(loc);
|
||||
u->set_location(loc);
|
||||
units().insert(u);
|
||||
} else {
|
||||
WRN_LUA << "wesnoth.put_unit(x, y) is deprecated. Use wesnoth.erase_unit(x, y) instead\n";
|
||||
put_unit_helper(loc);
|
||||
return 0; // Don't fire event when unit is only erase
|
||||
}
|
||||
|
||||
if(unit_arg != 1 || luaW_toboolean(L, 3)) {
|
||||
play_controller_.pump().fire("unit_placed", loc);
|
||||
}
|
||||
|
@ -2564,18 +2037,14 @@ int game_lua_kernel::intf_erase_unit(lua_State *L)
|
|||
}
|
||||
map_location loc;
|
||||
|
||||
if (luaW_hasmetatable(L, 1, getunitKey)) {
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
unit_ptr u = lu->get_shared();
|
||||
if (!lu->get()) {
|
||||
return luaL_argerror(L, 1, "unit not found");
|
||||
}
|
||||
if (lu->on_map()) {
|
||||
if(luaW_isunit(L, 1)) {
|
||||
lua_unit& u = *luaW_checkunit_ref(L, 1);
|
||||
if (u.on_map()) {
|
||||
loc = u->get_location();
|
||||
if (!map().on_board(loc)) {
|
||||
return luaL_argerror(L, 1, "invalid location");
|
||||
}
|
||||
} else if (int side = lu->on_recall_list()) {
|
||||
} else if (int side = u.on_recall_list()) {
|
||||
team &t = teams()[side - 1];
|
||||
// Should it use underlying ID instead?
|
||||
t.recall_list().erase_if_matches_id(u->id());
|
||||
|
@ -2616,21 +2085,23 @@ int game_lua_kernel::intf_put_recall_unit(lua_State *L)
|
|||
int side = lua_tointeger(L, 2);
|
||||
if (unsigned(side) > teams().size()) side = 0;
|
||||
|
||||
if (luaW_hasmetatable(L, 1, getunitKey))
|
||||
{
|
||||
lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
if(luaW_isunit(L, 1)) {
|
||||
lu = luaW_checkunit_ref(L, 1);
|
||||
u = lu->get_shared();
|
||||
if (!u || lu->on_recall_list())
|
||||
return luaL_argerror(L, 1, "unit not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lu->on_recall_list() == side) {
|
||||
return luaL_argerror(L, 1, "unit already on recall list");
|
||||
}
|
||||
} else {
|
||||
const vconfig* vcfg = nullptr;
|
||||
config cfg = luaW_checkconfig(L, 1, vcfg);
|
||||
u = unit_ptr(new unit(cfg, true, vcfg));
|
||||
}
|
||||
|
||||
if (!side) side = u->side();
|
||||
if (!side) {
|
||||
side = u->side();
|
||||
} else {
|
||||
u->set_side(side);
|
||||
}
|
||||
team &t = teams()[side - 1];
|
||||
// Avoid duplicates in the recall list.
|
||||
size_t uid = u->underlying_id();
|
||||
|
@ -2655,11 +2126,8 @@ int game_lua_kernel::intf_extract_unit(lua_State *L)
|
|||
if(map_locked_) {
|
||||
return luaL_error(L, "Attempted to remove a unit while the map is locked");
|
||||
}
|
||||
if (!luaW_hasmetatable(L, 1, getunitKey))
|
||||
return luaL_typerror(L, 1, "unit");
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
lua_unit* lu = luaW_checkunit_ref(L, 1);
|
||||
unit_ptr u = lu->get_shared();
|
||||
if (!u) return luaL_argerror(L, 1, "unit not found");
|
||||
|
||||
if (lu->on_map()) {
|
||||
u = units().extract(u->get_location());
|
||||
|
@ -2689,10 +2157,10 @@ int game_lua_kernel::intf_find_vacant_tile(lua_State *L)
|
|||
{
|
||||
map_location loc = luaW_checklocation(L, 1);
|
||||
|
||||
unit_ptr u = unit_ptr();
|
||||
unit_ptr u;
|
||||
if (!lua_isnoneornil(L, 2)) {
|
||||
if (luaW_hasmetatable(L, 2, getunitKey)) {
|
||||
u = static_cast<lua_unit *>(lua_touserdata(L, 2))->get_shared();
|
||||
if(luaW_isunit(L, 2)) {
|
||||
u = luaW_checkunit_ptr(L, 2, true);
|
||||
} else {
|
||||
const vconfig* vcfg = nullptr;
|
||||
config cfg = luaW_checkconfig(L, 2, vcfg);
|
||||
|
@ -2740,11 +2208,7 @@ static int intf_create_unit(lua_State *L)
|
|||
const vconfig* vcfg = nullptr;
|
||||
config cfg = luaW_checkconfig(L, 1, vcfg);
|
||||
unit_ptr u = unit_ptr(new unit(cfg, true, vcfg));
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u);
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, u);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2756,11 +2220,7 @@ static int intf_create_unit(lua_State *L)
|
|||
static int intf_copy_unit(lua_State *L)
|
||||
{
|
||||
unit& u = luaW_checkunit(L, 1);
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(unit_ptr(new unit(u)));
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, unit_ptr(new unit(u)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -4765,75 +4225,9 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
|
|||
//Create the getrace metatable
|
||||
cmd_log_ << lua_race::register_metatable(L);
|
||||
|
||||
// Create the getunit metatable.
|
||||
cmd_log_ << "Adding getunit metatable...\n";
|
||||
|
||||
lua_pushlightuserdata(L
|
||||
, getunitKey);
|
||||
lua_createtable(L, 0, 5);
|
||||
lua_pushcfunction(L, impl_unit_collect);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pushcfunction(L, impl_unit_equality);
|
||||
lua_setfield(L, -2, "__eq");
|
||||
lua_pushcfunction(L, impl_unit_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
// Create the unit status metatable.
|
||||
cmd_log_ << "Adding unit status metatable...\n";
|
||||
|
||||
lua_pushlightuserdata(L
|
||||
, ustatusKey);
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushcfunction(L, impl_unit_status_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_status_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit status");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
// Create the unit attacks metatable.
|
||||
cmd_log_ << "Adding unit attacks metatable...\n";
|
||||
|
||||
lua_pushlightuserdata(L, uattacksKey);
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushcfunction(L, impl_unit_attacks_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_attacks_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pushstring(L, "unit attacks");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
|
||||
lua_pushlightuserdata(L, uattackKey);
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushcfunction(L, impl_unit_attack_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_attack_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit attack");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
// Create the unit variables metatable.
|
||||
cmd_log_ << "Adding unit variables metatable...\n";
|
||||
|
||||
lua_pushlightuserdata(L
|
||||
, unitvarKey);
|
||||
lua_createtable(L, 0, 3);
|
||||
lua_pushcfunction(L, impl_unit_variables_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_variables_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit variables");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
//Create the unit metatables
|
||||
cmd_log_ << lua_units::register_metatables(L);
|
||||
cmd_log_ << lua_units::register_attacks_metatables(L);
|
||||
|
||||
// Create the vconfig metatable.
|
||||
cmd_log_ << lua_common::register_vconfig_metatable(L);
|
||||
|
@ -5320,10 +4714,7 @@ bool game_lua_kernel::run_filter(char const *name, unit const &u)
|
|||
unit_map::const_unit_iterator ui = units().find(u.get_location());
|
||||
if (!ui.valid()) return false;
|
||||
// Pass the unit as argument.
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(ui->underlying_id());
|
||||
lua_pushlightuserdata(L, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
luaW_pushunit(L, ui->underlying_id());
|
||||
|
||||
return run_filter(name, 1);
|
||||
}
|
||||
|
|
|
@ -117,6 +117,7 @@ class game_lua_kernel : public lua_kernel_base
|
|||
int intf_open_help(lua_State *L);
|
||||
int intf_play_sound(lua_State *L);
|
||||
int intf_print(lua_State *L);
|
||||
void put_unit_helper(const map_location& loc);
|
||||
int intf_put_unit(lua_State *L);
|
||||
int intf_erase_unit(lua_State *L);
|
||||
int intf_put_recall_unit(lua_State *L);
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 - 2016 by Guillaume Melquiond <guillaume.melquiond@gmail.com>
|
||||
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 "lua_api.hpp"
|
||||
#include "lua_types.hpp"
|
||||
|
||||
#include "lua_jailbreak_exception.hpp" // for tlua_jailbreak_exception
|
||||
|
||||
#include "chat_events.hpp" // for chat_handler, etc
|
||||
#include "config.hpp"
|
||||
#include "display_chat_manager.hpp"
|
||||
#include "game_board.hpp"
|
||||
#include "game_display.hpp"
|
||||
#include "log.hpp"
|
||||
#include "map/location.hpp" // for map_location
|
||||
#include "resources.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "tstring.hpp"
|
||||
#include "units/unit.hpp"
|
||||
#include "units/map.hpp"
|
||||
#include "variable.hpp"
|
||||
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <map> // for map<>::key_type
|
||||
#include <new> // for operator new
|
||||
#include <ostream> // for operator<<, basic_ostream, etc
|
||||
#include <utility> // for pair
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "lua/lauxlib.h"
|
||||
#include "lua/lua.h" // for lua_State, lua_settop, etc
|
||||
|
||||
static lg::log_domain log_scripting_lua("scripting/lua");
|
||||
#define LOG_LUA LOG_STREAM(info, log_scripting_lua)
|
||||
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
|
||||
|
||||
void chat_message(std::string const &caption, std::string const &msg)
|
||||
{
|
||||
if (!resources::screen) return;
|
||||
resources::screen->get_chat_manager().add_chat_message(time(nullptr), caption, 0, msg,
|
||||
events::chat_handler::MESSAGE_PUBLIC, false);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4706)
|
||||
#endif
|
||||
bool luaW_pcall(lua_State *L
|
||||
, int nArgs, int nRets, bool allow_wml_error)
|
||||
{
|
||||
// Load the error handler before the function and its arguments.
|
||||
lua_pushlightuserdata(L
|
||||
, executeKey);
|
||||
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_insert(L, -2 - nArgs);
|
||||
|
||||
int error_handler_index = lua_gettop(L) - nArgs - 1;
|
||||
|
||||
// Call the function.
|
||||
int res = lua_pcall(L, nArgs, nRets, -2 - nArgs);
|
||||
tlua_jailbreak_exception::rethrow();
|
||||
|
||||
if (res)
|
||||
{
|
||||
/*
|
||||
* When an exception is thrown which doesn't derive from
|
||||
* std::exception m will be nullptr pointer.
|
||||
*/
|
||||
char const *m = lua_tostring(L, -1);
|
||||
if(m) {
|
||||
if (allow_wml_error && strncmp(m, "~wml:", 5) == 0) {
|
||||
m += 5;
|
||||
char const *e = strstr(m, "stack traceback");
|
||||
lg::wml_error() << std::string(m, e ? e - m : strlen(m));
|
||||
} else if (allow_wml_error && strncmp(m, "~lua:", 5) == 0) {
|
||||
m += 5;
|
||||
char const *e = nullptr, *em = m;
|
||||
while (em[0] && ((em = strstr(em + 1, "stack traceback"))))
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
e = em;
|
||||
chat_message("Lua error", std::string(m, e ? e - m : strlen(m)));
|
||||
} else {
|
||||
ERR_LUA << m << '\n';
|
||||
chat_message("Lua error", m);
|
||||
}
|
||||
} else {
|
||||
chat_message("Lua caught unknown exception", "");
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the error handler.
|
||||
lua_remove(L, error_handler_index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
lua_unit::~lua_unit()
|
||||
{
|
||||
}
|
||||
|
||||
unit* lua_unit::get()
|
||||
{
|
||||
if (ptr) return ptr.get();
|
||||
if (c_ptr) return c_ptr;
|
||||
if (side) {
|
||||
return resources::gameboard->teams()[side - 1].recall_list().find_if_matches_underlying_id(uid).get();
|
||||
}
|
||||
unit_map::unit_iterator ui = resources::units->find(uid);
|
||||
if (!ui.valid()) return nullptr;
|
||||
return ui.get_shared_ptr().get(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
|
||||
}
|
||||
unit_ptr lua_unit::get_shared()
|
||||
{
|
||||
if (ptr) return ptr;
|
||||
if (side) {
|
||||
return resources::gameboard->teams()[side - 1].recall_list().find_if_matches_underlying_id(uid);
|
||||
}
|
||||
unit_map::unit_iterator ui = resources::units->find(uid);
|
||||
if (!ui.valid()) return unit_ptr();
|
||||
return ui.get_shared_ptr(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
|
||||
}
|
||||
|
||||
// Having this function here not only simplifies other code, it allows us to move
|
||||
// pointers around from one structure to another.
|
||||
// This makes bare pointer->map in particular about 2 orders of magnitude faster,
|
||||
// as benchmarked from Lua code.
|
||||
bool lua_unit::put_map(const map_location &loc)
|
||||
{
|
||||
if (ptr) {
|
||||
ptr->set_location(loc);
|
||||
resources::units->erase(loc);
|
||||
std::pair<unit_map::unit_iterator, bool> res = resources::units->insert(ptr);
|
||||
if (res.second) {
|
||||
ptr.reset();
|
||||
uid = res.first->underlying_id();
|
||||
} else {
|
||||
ERR_LUA << "Could not move unit " << ptr->underlying_id() << " onto map location " << loc << '\n';
|
||||
return false;
|
||||
}
|
||||
} else if (side) { // recall list
|
||||
unit_ptr it = resources::gameboard->teams()[side - 1].recall_list().extract_if_matches_underlying_id(uid);
|
||||
if (it) {
|
||||
side = 0;
|
||||
// uid may be changed by unit_map on insertion
|
||||
uid = resources::units->replace(loc, *it).first->underlying_id();
|
||||
} else {
|
||||
ERR_LUA << "Could not find unit " << uid << " on recall list of side " << side << '\n';
|
||||
return false;
|
||||
}
|
||||
} else { // on map
|
||||
unit_map::unit_iterator ui = resources::units->find(uid);
|
||||
if (ui != resources::units->end()) {
|
||||
map_location from = ui->get_location();
|
||||
if (from != loc) { // This check is redundant in current usage
|
||||
resources::units->erase(loc);
|
||||
resources::units->move(from, loc);
|
||||
}
|
||||
// No need to change our contents
|
||||
} else {
|
||||
ERR_LUA << "Could not find unit " << uid << " on the map" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unit* luaW_tounit(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
if (!luaW_hasmetatable(L, index, getunitKey)) return nullptr;
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, index));
|
||||
if (only_on_map && !lu->on_map()) return nullptr;
|
||||
return lu->get();
|
||||
}
|
||||
|
||||
unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
if (!luaW_hasmetatable(L, index, getunitKey)) return unit_ptr();
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, index));
|
||||
if (only_on_map && !lu->on_map()) return unit_ptr();
|
||||
return lu->get_shared();
|
||||
}
|
||||
|
||||
unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
unit_ptr u = luaW_tounit(L, index, only_on_map);
|
||||
if (!u) luaL_typerror(L, index, "unit");
|
||||
return u;
|
||||
}
|
||||
unit& luaW_checkunit(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
unit* u = luaW_tounit(L, index, only_on_map);
|
||||
if (!u) luaL_typerror(L, index, "unit");
|
||||
return *u;
|
||||
}
|
||||
|
||||
lua_unit* luaW_pushlocalunit(lua_State *L, unit& u)
|
||||
{
|
||||
lua_unit* res = new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u);
|
||||
lua_pushlightuserdata(L, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
return res;
|
||||
}
|
|
@ -26,12 +26,14 @@
|
|||
#include "global.hpp"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_types.hpp" // for gettextKey, tstringKey, etc
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "tstring.hpp" // for t_string
|
||||
#include "variable.hpp" // for vconfig
|
||||
#include "log.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "lua_jailbreak_exception.hpp"
|
||||
#include "game_display.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iterator> // for distance, advance
|
||||
|
@ -41,11 +43,12 @@
|
|||
#include "lua/lauxlib.h"
|
||||
#include "lua/lua.h"
|
||||
|
||||
static const char * gettextKey = "gettext";
|
||||
static const char * vconfigKey = "vconfig";
|
||||
static const char * vconfigpairsKey = "vconfig pairs";
|
||||
static const char * vconfigipairsKey = "vconfig ipairs";
|
||||
const char * tstringKey = "translatable string";
|
||||
static const char gettextKey[] = "gettext";
|
||||
static const char vconfigKey[] = "vconfig";
|
||||
static const char vconfigpairsKey[] = "vconfig pairs";
|
||||
static const char vconfigipairsKey[] = "vconfig ipairs";
|
||||
static const char tstringKey[] = "translatable string";
|
||||
static const char executeKey[] = "err";
|
||||
|
||||
static lg::log_domain log_scripting_lua("scripting/lua");
|
||||
#define LOG_LUA LOG_STREAM(info, log_scripting_lua)
|
||||
|
@ -118,7 +121,7 @@ static void tstring_concat_aux(lua_State *L, t_string &dst, int src)
|
|||
static int impl_tstring_concat(lua_State *L)
|
||||
{
|
||||
// Create a new t_string.
|
||||
t_string *t = new(lua_newuserdata(L, sizeof(t_string))) t_string;
|
||||
t_string *t = new(L) t_string;
|
||||
luaL_setmetatable(L, tstringKey);
|
||||
|
||||
// Append both arguments to t.
|
||||
|
@ -298,9 +301,8 @@ static int impl_vconfig_pairs_collect(lua_State *L)
|
|||
*/
|
||||
static int impl_vconfig_pairs(lua_State *L)
|
||||
{
|
||||
static const size_t sz = sizeof(config::const_attr_itors);
|
||||
vconfig vcfg = luaW_checkvconfig(L, 1);
|
||||
new(lua_newuserdata(L, sz)) config::const_attr_itors(vcfg.get_config().attribute_range());
|
||||
new(L) config::const_attr_itors(vcfg.get_config().attribute_range());
|
||||
luaL_newmetatable(L, vconfigpairsKey);
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushcclosure(L, &impl_vconfig_pairs_iter, 1);
|
||||
|
@ -348,9 +350,8 @@ static int impl_vconfig_ipairs_collect(lua_State *L)
|
|||
*/
|
||||
static int impl_vconfig_ipairs(lua_State *L)
|
||||
{
|
||||
static const size_t sz = sizeof(vconfig_child_range);
|
||||
vconfig cfg = luaW_checkvconfig(L, 1);
|
||||
new(lua_newuserdata(L, sz)) vconfig_child_range(cfg.ordered_begin(), cfg.ordered_end());
|
||||
new(L) vconfig_child_range(cfg.ordered_begin(), cfg.ordered_end());
|
||||
luaL_newmetatable(L, vconfigipairsKey);
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushcclosure(L, &impl_vconfig_ipairs_iter, 1);
|
||||
|
@ -454,15 +455,28 @@ std::string register_vconfig_metatable(lua_State *L)
|
|||
|
||||
} // end namespace lua_common
|
||||
|
||||
void* operator new(size_t sz, lua_State *L)
|
||||
{
|
||||
return lua_newuserdata(L, sz);
|
||||
}
|
||||
|
||||
void operator delete(void*, lua_State *L)
|
||||
{
|
||||
// Not sure if this is needed since it's a no-op
|
||||
// It's only called if a constructor throws while using the above operator new
|
||||
// By removing the userdata from the stack, this should ensure that Lua frees it
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void luaW_pushvconfig(lua_State *L, vconfig const &cfg)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(vconfig))) vconfig(cfg);
|
||||
new(L) vconfig(cfg);
|
||||
luaL_setmetatable(L, vconfigKey);
|
||||
}
|
||||
|
||||
void luaW_pushtstring(lua_State *L, t_string const &v)
|
||||
{
|
||||
new(lua_newuserdata(L, sizeof(t_string))) t_string(v);
|
||||
new(L) t_string(v);
|
||||
luaL_setmetatable(L, tstringKey);
|
||||
}
|
||||
|
||||
|
@ -522,19 +536,6 @@ bool luaW_toscalar(lua_State *L, int index, config::attribute_value& v)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool luaW_hasmetatable(lua_State *L
|
||||
, int index
|
||||
, luatypekey key)
|
||||
{
|
||||
if (!lua_getmetatable(L, index))
|
||||
return false;
|
||||
lua_pushlightuserdata(L, key);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
bool ok = lua_rawequal(L, -1, -2) == 1;
|
||||
lua_pop(L, 2);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool luaW_totstring(lua_State *L, int index, t_string &str)
|
||||
{
|
||||
switch (lua_type(L, index)) {
|
||||
|
@ -894,3 +895,82 @@ bool luaW_checkvariable(lua_State *L, variable_access_create& v, int n)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void chat_message(std::string const &caption, std::string const &msg)
|
||||
{
|
||||
if (!resources::screen) return;
|
||||
resources::screen->get_chat_manager().add_chat_message(time(nullptr), caption, 0, msg,
|
||||
events::chat_handler::MESSAGE_PUBLIC, false);
|
||||
}
|
||||
|
||||
// To silence "no prototype" warnings
|
||||
void push_error_handler(lua_State *L);
|
||||
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets);
|
||||
|
||||
void push_error_handler(lua_State *L)
|
||||
{
|
||||
luaW_getglobal(L, "debug", "traceback");
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, executeKey);
|
||||
}
|
||||
|
||||
int luaW_pcall_internal(lua_State *L, int nArgs, int nRets)
|
||||
{
|
||||
// Load the error handler before the function and its arguments.
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, executeKey);
|
||||
lua_insert(L, -2 - nArgs);
|
||||
|
||||
int error_handler_index = lua_gettop(L) - nArgs - 1;
|
||||
|
||||
// Call the function.
|
||||
int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
|
||||
|
||||
// Remove the error handler.
|
||||
lua_remove(L, error_handler_index);
|
||||
|
||||
tlua_jailbreak_exception::rethrow();
|
||||
|
||||
return errcode;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4706)
|
||||
#endif
|
||||
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error)
|
||||
{
|
||||
int res = luaW_pcall_internal(L, nArgs, nRets);
|
||||
|
||||
if (res)
|
||||
{
|
||||
/*
|
||||
* When an exception is thrown which doesn't derive from
|
||||
* std::exception m will be nullptr pointer.
|
||||
*/
|
||||
char const *m = lua_tostring(L, -1);
|
||||
if(m) {
|
||||
if (allow_wml_error && strncmp(m, "~wml:", 5) == 0) {
|
||||
m += 5;
|
||||
char const *e = strstr(m, "stack traceback");
|
||||
lg::wml_error() << std::string(m, e ? e - m : strlen(m));
|
||||
} else if (allow_wml_error && strncmp(m, "~lua:", 5) == 0) {
|
||||
m += 5;
|
||||
char const *e = nullptr, *em = m;
|
||||
while (em[0] && ((em = strstr(em + 1, "stack traceback"))))
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
e = em;
|
||||
chat_message("Lua error", std::string(m, e ? e - m : strlen(m)));
|
||||
} else {
|
||||
ERR_LUA << m << '\n';
|
||||
chat_message("Lua error", m);
|
||||
}
|
||||
} else {
|
||||
chat_message("Lua caught unknown exception", "");
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -25,10 +25,10 @@ class t_string;
|
|||
class vconfig;
|
||||
|
||||
#include "config.hpp"
|
||||
#include "scripting/lua_types.hpp"
|
||||
#include "variable_info.hpp"
|
||||
#include "map/location.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace lua_common {
|
||||
int intf_textdomain(lua_State *L);
|
||||
|
@ -39,7 +39,9 @@ namespace lua_common {
|
|||
std::string register_vconfig_metatable(lua_State *L);
|
||||
|
||||
}
|
||||
extern const char * tstringKey;
|
||||
|
||||
void* operator new(size_t sz, lua_State *L);
|
||||
void operator delete(void* p, lua_State *L);
|
||||
|
||||
/**
|
||||
* Pushes a vconfig on the top of the stack.
|
||||
|
@ -61,12 +63,6 @@ void luaW_pushscalar(lua_State *L, config::attribute_value const &v);
|
|||
*/
|
||||
bool luaW_toscalar(lua_State *L, int index, config::attribute_value& v);
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the metatable of the object is the one found in the registry.
|
||||
*/
|
||||
bool luaW_hasmetatable(lua_State *L, int index, luatypekey key);
|
||||
|
||||
/**
|
||||
* Converts a scalar to a translatable string.
|
||||
*/
|
||||
|
@ -165,6 +161,18 @@ bool luaW_pushvariable(lua_State *L, variable_access_const& v);
|
|||
|
||||
bool luaW_checkvariable(lua_State *L, variable_access_create& v, int n);
|
||||
|
||||
/**
|
||||
* Displays a message in the chat window.
|
||||
*/
|
||||
void chat_message(std::string const &caption, std::string const &msg);
|
||||
|
||||
/**
|
||||
* Calls a Lua function stored below its @a nArgs arguments at the top of the stack.
|
||||
* @param nRets LUA_MULTRET for unbounded return values.
|
||||
* @return true if the call was successful and @a nRets return values are available.
|
||||
*/
|
||||
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error = false);
|
||||
|
||||
|
||||
#define return_tstring_attrib(name, accessor) \
|
||||
if (strcmp(m, name) == 0) { \
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "game_config.hpp" //for game_config::debug_lua
|
||||
#include "game_errors.hpp"
|
||||
#include "log.hpp"
|
||||
#include "scripting/lua_api.hpp" // for chat_message, luaW_pcall
|
||||
#include "scripting/lua_common.hpp" // for chat_message, luaW_pcall
|
||||
|
||||
#include <exception>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "boost/variant/static_visitor.hpp"
|
||||
|
||||
#include "scripting/game_lua_kernel.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "lua/lauxlib.h"
|
||||
#include "lua/lua.h"
|
||||
|
@ -27,6 +27,8 @@
|
|||
#include "resources.hpp"
|
||||
#include "units/map.hpp"
|
||||
|
||||
static const char formulaKey[] = "formula";
|
||||
|
||||
void luaW_pushfaivariant(lua_State* L, variant val);
|
||||
variant luaW_tofaivariant(lua_State* L, int i);
|
||||
|
||||
|
@ -141,13 +143,10 @@ void luaW_pushfaivariant(lua_State* L, variant val) {
|
|||
const unit& u = u_ref->get_unit();
|
||||
unit_map::iterator un_it = resources::units->find(u.get_location());
|
||||
if(&*un_it == &u) {
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u.underlying_id());
|
||||
luaW_pushunit(L, u.underlying_id());
|
||||
} else {
|
||||
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(u.side(), u.underlying_id());
|
||||
luaW_pushunit(L, u.side(), u.underlying_id());
|
||||
}
|
||||
lua_pushlightuserdata(L, getunitKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
} else if(location_callable* loc_ref = val.try_convert<location_callable>()) {
|
||||
luaW_pushlocation(L, loc_ref->loc());
|
||||
} else {
|
||||
|
@ -208,8 +207,8 @@ int lua_formula_bridge::intf_eval_formula(lua_State *L)
|
|||
{
|
||||
bool need_delete = false;
|
||||
fwrapper* form;
|
||||
if(luaW_hasmetatable(L, 1, formulaKey)) {
|
||||
form = static_cast<fwrapper*>(lua_touserdata(L, 1));
|
||||
if(void* ud = luaL_testudata(L, 1, formulaKey)) {
|
||||
form = static_cast<fwrapper*>(ud);
|
||||
} else {
|
||||
need_delete = true;
|
||||
form = new fwrapper(luaL_checkstring(L, 1));
|
||||
|
@ -235,10 +234,8 @@ int lua_formula_bridge::intf_compile_formula(lua_State* L)
|
|||
if(!lua_isstring(L, 1)) {
|
||||
luaL_typerror(L, 1, "string");
|
||||
}
|
||||
new(lua_newuserdata(L, sizeof(fwrapper))) fwrapper(lua_tostring(L, 1));
|
||||
lua_pushlightuserdata(L, formulaKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
new(L) fwrapper(lua_tostring(L, 1));
|
||||
luaL_setmetatable(L, formulaKey);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -280,8 +277,7 @@ static int impl_formula_tostring(lua_State* L)
|
|||
|
||||
std::string lua_formula_bridge::register_metatables(lua_State* L)
|
||||
{
|
||||
lua_pushlightuserdata(L, formulaKey);
|
||||
lua_createtable(L, 0, 4);
|
||||
luaL_newmetatable(L, formulaKey);
|
||||
lua_pushcfunction(L, impl_formula_collect);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pushcfunction(L, impl_formula_tostring);
|
||||
|
@ -290,7 +286,6 @@ std::string lua_formula_bridge::register_metatables(lua_State* L)
|
|||
lua_setfield(L, -2, "__call");
|
||||
lua_pushstring(L, "formula");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
return "Adding formula metatable...\n";
|
||||
}
|
||||
|
|
|
@ -41,9 +41,7 @@
|
|||
|
||||
#include "config.hpp"
|
||||
#include "log.hpp"
|
||||
#include "scripting/lua_api.hpp" // for luaW_toboolean, etc
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_types.hpp" // for getunitKey, dlgclbkKey, etc
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "tstring.hpp"
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "scripting/lua_gui2.hpp"
|
||||
#include "scripting/lua_map_location_ops.hpp"
|
||||
#include "scripting/lua_rng.hpp"
|
||||
#include "scripting/lua_types.hpp"
|
||||
#include "scripting/push_check.hpp"
|
||||
|
||||
#include "version.hpp" // for do_version_check, etc
|
||||
|
@ -196,11 +195,10 @@ static int intf_name_generator(lua_State *L)
|
|||
}
|
||||
int chain_sz = luaL_optinteger(L, 3, 2);
|
||||
int max_len = luaL_optinteger(L, 4, 12);
|
||||
gen = new(lua_newuserdata(L, sizeof(markov_generator))) markov_generator(input, chain_sz, max_len);
|
||||
gen = new(L) markov_generator(input, chain_sz, max_len);
|
||||
// Ensure the pointer didn't change when cast
|
||||
assert(static_cast<void*>(gen) == dynamic_cast<markov_generator*>(gen));
|
||||
} else if(type == "context_free" || type == "cfg" || type == "CFG") {
|
||||
void* buf = lua_newuserdata(L, sizeof(context_free_grammar_generator));
|
||||
if(lua_istable(L, 2)) {
|
||||
std::map<std::string, std::vector<std::string>> data;
|
||||
for(lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) {
|
||||
|
@ -218,10 +216,10 @@ static int intf_name_generator(lua_State *L)
|
|||
}
|
||||
}
|
||||
if(!data.empty()) {
|
||||
gen = new(buf) context_free_grammar_generator(data);
|
||||
gen = new(L) context_free_grammar_generator(data);
|
||||
}
|
||||
} else {
|
||||
gen = new(buf) context_free_grammar_generator(luaL_checkstring(L, 2));
|
||||
gen = new(L) context_free_grammar_generator(luaL_checkstring(L, 2));
|
||||
}
|
||||
if(gen) {
|
||||
assert(static_cast<void*>(gen) == dynamic_cast<context_free_grammar_generator*>(gen));
|
||||
|
@ -253,6 +251,8 @@ int dispatch(lua_State *L) {
|
|||
return ((lua_kernel_base::get_lua_kernel<lua_kernel_base>(L)).*method)(L);
|
||||
}
|
||||
|
||||
extern void push_error_handler(lua_State *L);
|
||||
|
||||
// Ctor, initialization
|
||||
lua_kernel_base::lua_kernel_base(CVideo * video)
|
||||
: mState(luaL_newstate())
|
||||
|
@ -318,14 +318,7 @@ lua_kernel_base::lua_kernel_base(CVideo * video)
|
|||
|
||||
// Store the error handler.
|
||||
cmd_log_ << "Adding error handler...\n";
|
||||
|
||||
lua_pushlightuserdata(L
|
||||
, executeKey);
|
||||
lua_getglobal(L, "debug");
|
||||
lua_getfield(L, -1, "traceback");
|
||||
lua_remove(L, -2);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
lua_pop(L, 1);
|
||||
push_error_handler(L);
|
||||
|
||||
// Create the gettext metatable.
|
||||
cmd_log_ << lua_common::register_gettext_metatable(L);
|
||||
|
@ -493,23 +486,11 @@ bool lua_kernel_base::protected_call(int nArgs, int nRets, error_handler e_h)
|
|||
return protected_call(mState, nArgs, nRets, e_h);
|
||||
}
|
||||
|
||||
extern int luaW_pcall_internal(lua_State *L, int nArgs, int nRets);
|
||||
|
||||
bool lua_kernel_base::protected_call(lua_State * L, int nArgs, int nRets, error_handler e_h)
|
||||
{
|
||||
// Load the error handler before the function and its arguments.
|
||||
lua_pushlightuserdata(L
|
||||
, executeKey);
|
||||
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_insert(L, -2 - nArgs);
|
||||
|
||||
int error_handler_index = lua_gettop(L) - nArgs - 1;
|
||||
|
||||
// Call the function.
|
||||
int errcode = lua_pcall(L, nArgs, nRets, -2 - nArgs);
|
||||
tlua_jailbreak_exception::rethrow();
|
||||
|
||||
// Remove the error handler.
|
||||
lua_remove(L, error_handler_index);
|
||||
int errcode = luaW_pcall_internal(L, nArgs, nRets);
|
||||
|
||||
if (errcode != LUA_OK) {
|
||||
char const * msg = lua_tostring(L, -1);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
#include "lua/lua.h"
|
||||
#include "map/location.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "pathfind/pathfind.hpp"
|
||||
|
||||
/**
|
||||
|
|
|
@ -74,15 +74,13 @@ static int impl_race_get(lua_State* L)
|
|||
return 1;
|
||||
}
|
||||
if (strcmp(m, "male_name_gen") == 0) {
|
||||
new(lua_newuserdata(L, sizeof(proxy_name_generator)))
|
||||
proxy_name_generator(race.generator(unit_race::MALE));
|
||||
new(L) proxy_name_generator(race.generator(unit_race::MALE));
|
||||
luaL_getmetatable(L, Gen);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(m, "female_name_gen") == 0) {
|
||||
new(lua_newuserdata(L, sizeof(proxy_name_generator)))
|
||||
proxy_name_generator(race.generator(unit_race::FEMALE));
|
||||
new(L) proxy_name_generator(race.generator(unit_race::FEMALE));
|
||||
luaL_getmetatable(L, Gen);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
|
|
|
@ -37,7 +37,7 @@ static const char * Rng = "Rng";
|
|||
int impl_rng_create(lua_State* L)
|
||||
{
|
||||
uint32_t seed = lua_kernel_base::get_lua_kernel<lua_kernel_base>(L).get_random_seed();
|
||||
new ( lua_newuserdata(L, sizeof(mt_rng)) ) mt_rng(seed);
|
||||
new(L) mt_rng(seed);
|
||||
luaL_setmetatable(L, Rng);
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2014 - 2016 by David White <dave@whitevine.net>
|
||||
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 "lua_types.hpp"
|
||||
|
||||
/* Dummy pointer for getting unique keys for Lua's registry. */
|
||||
static char const v_executeKey = 0;
|
||||
static char const v_getunitKey = 0;
|
||||
static char const v_unitvarKey = 0;
|
||||
static char const v_ustatusKey = 0;
|
||||
static char const v_uattacksKey = 0;
|
||||
static char const v_uattackKey = 0;
|
||||
static char const v_formulaKey = 0;
|
||||
|
||||
|
||||
luatypekey const executeKey = static_cast<void *>(const_cast<char *>(&v_executeKey));
|
||||
luatypekey const getunitKey = static_cast<void *>(const_cast<char *>(&v_getunitKey));
|
||||
luatypekey const unitvarKey = static_cast<void *>(const_cast<char *>(&v_unitvarKey));
|
||||
luatypekey const ustatusKey = static_cast<void *>(const_cast<char *>(&v_ustatusKey));
|
||||
luatypekey const uattacksKey = static_cast<void *>(const_cast<char *>(&v_uattacksKey));
|
||||
luatypekey const uattackKey = static_cast<void *>(const_cast<char *>(&v_uattackKey));
|
||||
luatypekey const formulaKey = static_cast<void *>(const_cast<char *>(&v_formulaKey));
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2014 - 2016 by David White <dave@whitevine.net>
|
||||
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 SCRIPTING_LUA_TYPES_HPP
|
||||
#define SCRIPTING_LUA_TYPES_HPP
|
||||
|
||||
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 getunitKey;
|
||||
extern luatypekey const unitvarKey;
|
||||
extern luatypekey const ustatusKey;
|
||||
extern luatypekey const uattacksKey;
|
||||
extern luatypekey const uattackKey;
|
||||
extern luatypekey const formulaKey;
|
||||
|
||||
#endif
|
568
src/scripting/lua_unit.cpp
Normal file
568
src/scripting/lua_unit.cpp
Normal file
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
Copyright (C) 2009 - 2016 by Guillaume Melquiond <guillaume.melquiond@gmail.com>
|
||||
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 "lua_unit.hpp"
|
||||
|
||||
#include "game_board.hpp"
|
||||
#include "log.hpp"
|
||||
#include "map/location.hpp" // for map_location
|
||||
#include "resources.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_unit_attacks.hpp"
|
||||
#include "scripting/push_check.hpp"
|
||||
#include "scripting/game_lua_kernel.hpp"
|
||||
#include "units/unit.hpp"
|
||||
#include "units/map.hpp"
|
||||
|
||||
#include "lua/lauxlib.h"
|
||||
#include "lua/lua.h" // for lua_State, lua_settop, etc
|
||||
|
||||
static lg::log_domain log_scripting_lua("scripting/lua");
|
||||
#define LOG_LUA LOG_STREAM(info, log_scripting_lua)
|
||||
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)
|
||||
|
||||
static const char getunitKey[] = "unit";
|
||||
static const char ustatusKey[] = "unit status";
|
||||
static const char unitvarKey[] = "unit variables";
|
||||
|
||||
lua_unit::~lua_unit()
|
||||
{
|
||||
}
|
||||
|
||||
unit* lua_unit::get()
|
||||
{
|
||||
if (ptr) return ptr.get();
|
||||
if (c_ptr) return c_ptr;
|
||||
if (side) {
|
||||
return resources::gameboard->teams()[side - 1].recall_list().find_if_matches_underlying_id(uid).get();
|
||||
}
|
||||
unit_map::unit_iterator ui = resources::units->find(uid);
|
||||
if (!ui.valid()) return nullptr;
|
||||
return ui.get_shared_ptr().get(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
|
||||
}
|
||||
unit_ptr lua_unit::get_shared()
|
||||
{
|
||||
if (ptr) return ptr;
|
||||
if (side) {
|
||||
return resources::gameboard->teams()[side - 1].recall_list().find_if_matches_underlying_id(uid);
|
||||
}
|
||||
unit_map::unit_iterator ui = resources::units->find(uid);
|
||||
if (!ui.valid()) return unit_ptr();
|
||||
return ui.get_shared_ptr(); //&*ui would not be legal, must get new shared_ptr by copy ctor because the unit_map itself is holding a boost shared pointer.
|
||||
}
|
||||
|
||||
// Having this function here not only simplifies other code, it allows us to move
|
||||
// pointers around from one structure to another.
|
||||
// This makes bare pointer->map in particular about 2 orders of magnitude faster,
|
||||
// as benchmarked from Lua code.
|
||||
bool lua_unit::put_map(const map_location &loc)
|
||||
{
|
||||
if (ptr) {
|
||||
ptr->set_location(loc);
|
||||
resources::units->erase(loc);
|
||||
std::pair<unit_map::unit_iterator, bool> res = resources::units->insert(ptr);
|
||||
if (res.second) {
|
||||
ptr.reset();
|
||||
uid = res.first->underlying_id();
|
||||
} else {
|
||||
ERR_LUA << "Could not move unit " << ptr->underlying_id() << " onto map location " << loc << '\n';
|
||||
return false;
|
||||
}
|
||||
} else if (side) { // recall list
|
||||
unit_ptr it = resources::gameboard->teams()[side - 1].recall_list().extract_if_matches_underlying_id(uid);
|
||||
if (it) {
|
||||
side = 0;
|
||||
// uid may be changed by unit_map on insertion
|
||||
uid = resources::units->replace(loc, *it).first->underlying_id();
|
||||
} else {
|
||||
ERR_LUA << "Could not find unit " << uid << " on recall list of side " << side << '\n';
|
||||
return false;
|
||||
}
|
||||
} else { // on map
|
||||
unit_map::unit_iterator ui = resources::units->find(uid);
|
||||
if (ui != resources::units->end()) {
|
||||
map_location from = ui->get_location();
|
||||
if (from != loc) { // This check is redundant in current usage
|
||||
resources::units->erase(loc);
|
||||
resources::units->move(from, loc);
|
||||
}
|
||||
// No need to change our contents
|
||||
} else {
|
||||
ERR_LUA << "Could not find unit " << uid << " on the map" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool luaW_isunit(lua_State* L, int index)
|
||||
{
|
||||
return luaL_testudata(L, index,getunitKey);
|
||||
}
|
||||
|
||||
enum {
|
||||
LU_OK,
|
||||
LU_NOT_UNIT,
|
||||
LU_NOT_ON_MAP,
|
||||
LU_NOT_VALID,
|
||||
};
|
||||
|
||||
static lua_unit* internal_get_unit(lua_State *L, int index, bool only_on_map, int& error)
|
||||
{
|
||||
error = LU_OK;
|
||||
if(!luaW_isunit(L, index)) {
|
||||
error = LU_NOT_UNIT;
|
||||
return nullptr;
|
||||
}
|
||||
lua_unit* lu = static_cast<lua_unit*>(lua_touserdata(L, index));
|
||||
if(only_on_map && !lu->on_map()) {
|
||||
error = LU_NOT_ON_MAP;
|
||||
}
|
||||
if(!lu->get()) {
|
||||
error = LU_NOT_VALID;
|
||||
}
|
||||
return lu;
|
||||
}
|
||||
|
||||
unit* luaW_tounit(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
int error;
|
||||
lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
|
||||
if(error != LU_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
return lu->get();
|
||||
}
|
||||
|
||||
unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
int error;
|
||||
lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
|
||||
if(error != LU_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
return lu->get_shared();
|
||||
}
|
||||
|
||||
lua_unit* luaW_tounit_ref(lua_State *L, int index)
|
||||
{
|
||||
int error;
|
||||
return internal_get_unit(L, index, false, error);
|
||||
}
|
||||
|
||||
static void unit_show_error(lua_State *L, int index, int error)
|
||||
{
|
||||
switch(error) {
|
||||
case LU_NOT_UNIT:
|
||||
luaL_typerror(L, index, "unit");
|
||||
case LU_NOT_VALID:
|
||||
luaL_argerror(L, index, "unit not found");
|
||||
case LU_NOT_ON_MAP:
|
||||
luaL_argerror(L, index, "unit not found on map");
|
||||
}
|
||||
}
|
||||
|
||||
unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
int error;
|
||||
lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
|
||||
unit_show_error(L, index, error);
|
||||
return lu->get_shared();
|
||||
}
|
||||
|
||||
unit& luaW_checkunit(lua_State *L, int index, bool only_on_map)
|
||||
{
|
||||
int error;
|
||||
lua_unit* lu = internal_get_unit(L, index, only_on_map, error);
|
||||
unit_show_error(L, index, error);
|
||||
return *lu->get();
|
||||
}
|
||||
|
||||
lua_unit* luaW_checkunit_ref(lua_State *L, int index)
|
||||
{
|
||||
int error;
|
||||
lua_unit* lu = internal_get_unit(L, index, false, error);
|
||||
unit_show_error(L, index, error);
|
||||
return lu;
|
||||
}
|
||||
|
||||
void lua_unit::setmetatable(lua_State *L)
|
||||
{
|
||||
luaL_setmetatable(L, getunitKey);
|
||||
}
|
||||
|
||||
lua_unit* luaW_pushlocalunit(lua_State *L, unit& u)
|
||||
{
|
||||
lua_unit* res = new(L) lua_unit(u);
|
||||
lua_unit::setmetatable(L);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a unit object before it is collected (__gc metamethod).
|
||||
*/
|
||||
static int impl_unit_collect(lua_State *L)
|
||||
{
|
||||
lua_unit *u = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
u->lua_unit::~lua_unit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks two lua proxy units for equality. (__eq metamethod)
|
||||
*/
|
||||
static int impl_unit_equality(lua_State* L)
|
||||
{
|
||||
unit& left = luaW_checkunit(L, 1);
|
||||
unit& right = luaW_checkunit(L, 2);
|
||||
const bool equal = left.underlying_id() == right.underlying_id();
|
||||
lua_pushboolean(L, equal);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets some data on a unit (__index metamethod).
|
||||
* - Arg 1: full userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the property.
|
||||
* - Ret 1: something containing the attribute.
|
||||
*/
|
||||
static int impl_unit_get(lua_State *L)
|
||||
{
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
const unit* pu = lu->get();
|
||||
|
||||
if(strcmp(m, "valid") == 0) {
|
||||
if(!pu) {
|
||||
return 0;
|
||||
}
|
||||
if(lu->on_map()) {
|
||||
lua_pushstring(L, "map");
|
||||
} else if(lu->on_recall_list()) {
|
||||
lua_pushstring(L, "recall");
|
||||
} else {
|
||||
lua_pushstring(L, "private");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!pu) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
|
||||
unit const &u = *pu;
|
||||
|
||||
// Find the corresponding attribute.
|
||||
return_int_attrib("x", u.get_location().x + 1);
|
||||
return_int_attrib("y", u.get_location().y + 1);
|
||||
if(strcmp(m, "loc") == 0) {
|
||||
lua_pushinteger(L, u.get_location().x + 1);
|
||||
lua_pushinteger(L, u.get_location().y + 1);
|
||||
return 2;
|
||||
}
|
||||
return_int_attrib("side", u.side());
|
||||
return_string_attrib("id", u.id());
|
||||
return_string_attrib("type", u.type_id());
|
||||
return_string_attrib("image_mods", u.effect_image_mods());
|
||||
return_string_attrib("usage", u.usage());
|
||||
return_int_attrib("hitpoints", u.hitpoints());
|
||||
return_int_attrib("max_hitpoints", u.max_hitpoints());
|
||||
return_int_attrib("experience", u.experience());
|
||||
return_int_attrib("max_experience", u.max_experience());
|
||||
return_int_attrib("recall_cost", u.recall_cost());
|
||||
return_int_attrib("moves", u.movement_left());
|
||||
return_int_attrib("max_moves", u.total_movement());
|
||||
return_int_attrib("max_attacks", u.max_attacks());
|
||||
return_int_attrib("attacks_left", u.attacks_left());
|
||||
return_tstring_attrib("name", u.name());
|
||||
return_bool_attrib("canrecruit", u.can_recruit());
|
||||
return_int_attrib("level", u.level());
|
||||
return_int_attrib("cost", u.cost());
|
||||
|
||||
return_vector_string_attrib("extra_recruit", u.recruits());
|
||||
return_vector_string_attrib("advances_to", u.advances_to());
|
||||
|
||||
if(strcmp(m, "alignment") == 0) {
|
||||
lua_push(L, u.alignment());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(strcmp(m, "upkeep") == 0) {
|
||||
unit::t_upkeep upkeep = u.upkeep_raw();
|
||||
if(boost::get<unit::upkeep_full>(&upkeep) != nullptr){
|
||||
lua_pushstring(L, "full");
|
||||
} else if(boost::get<unit::upkeep_loyal>(&upkeep) != nullptr){
|
||||
lua_pushstring(L, "loyal");
|
||||
} else {
|
||||
lua_push(L, boost::get<int>(upkeep));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "advancements") == 0) {
|
||||
lua_push(L, u.modification_advancements());
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "overlays") == 0) {
|
||||
lua_push(L, u.overlays());
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "traits") == 0) {
|
||||
lua_push(L, u.get_traits_list());
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "abilities") == 0) {
|
||||
lua_push(L, u.get_ability_list());
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "status") == 0) {
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawseti(L, -2, 1);
|
||||
luaL_setmetatable(L, ustatusKey);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "variables") == 0) {
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawseti(L, -2, 1);
|
||||
luaL_setmetatable(L, unitvarKey);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(m, "attacks") == 0) {
|
||||
push_unit_attacks_table(L, 1);
|
||||
return 1;
|
||||
}
|
||||
return_cfg_attrib("recall_filter", cfg = u.recall_filter());
|
||||
return_bool_attrib("hidden", u.get_hidden());
|
||||
return_bool_attrib("petrified", u.incapacitated());
|
||||
return_bool_attrib("resting", u.resting());
|
||||
return_string_attrib("role", u.get_role());
|
||||
return_string_attrib("race", u.race()->id());
|
||||
return_string_attrib("gender", gender_string(u.gender()));
|
||||
return_string_attrib("variation", u.variation());
|
||||
return_bool_attrib("zoc", u.get_emit_zoc());
|
||||
return_string_attrib("facing", map_location::write_direction(u.facing()));
|
||||
return_string_attrib("portrait", u.big_profile() == u.absolute_image() ? u.absolute_image() + u.image_mods() : u.big_profile());
|
||||
return_cfg_attrib("__cfg", u.write(cfg); u.get_location().write(cfg));
|
||||
|
||||
return lua_kernel_base::get_lua_kernel<game_lua_kernel>(L).return_unit_method(L, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets some data on a unit (__newindex metamethod).
|
||||
* - Arg 1: full userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the property.
|
||||
* - Arg 3: something containing the attribute.
|
||||
*/
|
||||
static int impl_unit_set(lua_State *L)
|
||||
{
|
||||
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
unit* pu = lu->get();
|
||||
if (!pu) return luaL_argerror(L, 1, "unknown unit");
|
||||
unit &u = *pu;
|
||||
|
||||
// Find the corresponding attribute.
|
||||
//modify_int_attrib_check_range("side", u.set_side(value), 1, static_cast<int>(teams().size())); TODO: Figure out if this is a good idea, to refer to teams() and make this depend on having a gamestate
|
||||
modify_int_attrib("side", u.set_side(value));
|
||||
modify_int_attrib("moves", u.set_movement(value));
|
||||
modify_int_attrib("hitpoints", u.set_hitpoints(value));
|
||||
modify_int_attrib("experience", u.set_experience(value));
|
||||
modify_int_attrib("recall_cost", u.set_recall_cost(value));
|
||||
modify_int_attrib("attacks_left", u.set_attacks(value));
|
||||
modify_int_attrib("level", u.set_level(value));
|
||||
modify_bool_attrib("resting", u.set_resting(value));
|
||||
modify_tstring_attrib("name", u.set_name(value));
|
||||
modify_string_attrib("role", u.set_role(value));
|
||||
modify_string_attrib("facing", u.set_facing(map_location::parse_direction(value)));
|
||||
modify_bool_attrib("hidden", u.set_hidden(value));
|
||||
modify_bool_attrib("zoc", u.set_emit_zoc(value));
|
||||
modify_bool_attrib("canrecruit", u.set_can_recruit(value));
|
||||
|
||||
modify_vector_string_attrib("extra_recruit", u.set_recruits(vector));
|
||||
modify_vector_string_attrib("advances_to", u.set_advances_to(vector));
|
||||
if(strcmp(m, "alignment") == 0) {
|
||||
u.set_alignment(lua_check<unit_type::ALIGNMENT>(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strcmp(m, "advancements") == 0) {
|
||||
u.set_advancements(lua_check<std::vector<config> >(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strcmp(m, "upkeep") == 0) {
|
||||
if(lua_isnumber(L, 3)) {
|
||||
u.set_upkeep(luaL_checkint(L, 3));
|
||||
return 0;
|
||||
}
|
||||
const char* v = luaL_checkstring(L, 3);
|
||||
if(strcmp(m, "loyal") == 0) {
|
||||
u.set_upkeep(unit::upkeep_loyal());
|
||||
} else if(strcmp(m, "full") == 0) {
|
||||
u.set_upkeep(unit::upkeep_full());
|
||||
} else {
|
||||
std::string err_msg = "unknown upkeep value of unit: ";
|
||||
err_msg += v;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(!lu->on_map()) {
|
||||
map_location loc = u.get_location();
|
||||
modify_int_attrib("x", loc.x = value - 1; u.set_location(loc));
|
||||
modify_int_attrib("y", loc.y = value - 1; u.set_location(loc));
|
||||
}
|
||||
|
||||
std::string err_msg = "unknown modifiable property of unit: ";
|
||||
err_msg += m;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a unit (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Ret 1: boolean.
|
||||
*/
|
||||
static int impl_unit_status_get(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit status");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
if(!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
lua_pushboolean(L, u->get_state(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status of a unit (__newindex metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Arg 3: boolean.
|
||||
*/
|
||||
static int impl_unit_status_set(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit status");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
unit* u = luaW_tounit(L, -1);
|
||||
if(!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
u->set_state(m, luaW_toboolean(L, 3));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the variable of a unit (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Ret 1: boolean.
|
||||
*/
|
||||
static int impl_unit_variables_get(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit variables");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
if(!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
return_cfgref_attrib("__cfg", u->variables());
|
||||
|
||||
variable_access_const v(m, u->variables());
|
||||
return luaW_pushvariable(L, v) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the variable of a unit (__newindex metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Arg 2: string containing the name of the status.
|
||||
* - Arg 3: scalar.
|
||||
*/
|
||||
static int impl_unit_variables_set(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit variables");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
unit* u = luaW_tounit(L, -1);
|
||||
if(!u) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
if(strcmp(m, "__cfg") == 0) {
|
||||
u->variables() = luaW_checkconfig(L, 3);
|
||||
return 0;
|
||||
}
|
||||
variable_access_create v(m, u->variables());
|
||||
luaW_checkvariable(L, v, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace lua_units {
|
||||
std::string register_metatables(lua_State* L)
|
||||
{
|
||||
std::ostringstream cmd_out;
|
||||
|
||||
// Create the getunit metatable.
|
||||
cmd_out << "Adding getunit metatable...\n";
|
||||
|
||||
luaL_newmetatable(L, getunitKey);
|
||||
lua_pushcfunction(L, impl_unit_collect);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
lua_pushcfunction(L, impl_unit_equality);
|
||||
lua_setfield(L, -2, "__eq");
|
||||
lua_pushcfunction(L, impl_unit_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
|
||||
// Create the unit status metatable.
|
||||
cmd_out << "Adding unit status metatable...\n";
|
||||
|
||||
luaL_newmetatable(L, ustatusKey);
|
||||
lua_pushcfunction(L, impl_unit_status_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_status_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit status");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
|
||||
// Create the unit variables metatable.
|
||||
cmd_out << "Adding unit variables metatable...\n";
|
||||
|
||||
luaL_newmetatable(L, unitvarKey);
|
||||
lua_pushcfunction(L, impl_unit_variables_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_variables_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit variables");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
|
||||
return cmd_out.str();
|
||||
}
|
||||
}
|
|
@ -17,42 +17,60 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include "lua_types.hpp" // the luatype typedef
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "units/ptr.hpp"
|
||||
|
||||
struct lua_State;
|
||||
class lua_unit;
|
||||
struct map_location;
|
||||
|
||||
/**
|
||||
* Test if a Lua value is a unit
|
||||
*/
|
||||
bool luaW_isunit(lua_State *, int index);
|
||||
|
||||
/**
|
||||
* Converts a Lua value to a unit pointer.
|
||||
*/
|
||||
unit* luaW_tounit(lua_State *L, int index, bool only_on_map = false);
|
||||
|
||||
/**
|
||||
* Displays a message in the chat window.
|
||||
*/
|
||||
void chat_message(std::string const &caption, std::string const &msg);
|
||||
|
||||
/**
|
||||
* Calls a Lua function stored below its @a nArgs arguments at the top of the stack.
|
||||
* @param nRets LUA_MULTRET for unbounded return values.
|
||||
* @return true if the call was successful and @a nRets return values are available.
|
||||
*/
|
||||
bool luaW_pcall(lua_State *L, int nArgs, int nRets, bool allow_wml_error = false);
|
||||
|
||||
/**
|
||||
* Converts a Lua value to a unit pointer.
|
||||
*/
|
||||
unit& luaW_checkunit(lua_State *L, int index, bool only_on_map = false);
|
||||
class lua_unit;
|
||||
lua_unit* luaW_pushlocalunit(lua_State *L, unit& u);
|
||||
|
||||
/**
|
||||
* Similar to luaW_checkunit/luaW_tounit but returns a unit_ptr, use this instead of
|
||||
* luaW_checkunit/luaW_tounit when uasing an api that needs unit_ptr.
|
||||
* Pushes a private unit on the stack.
|
||||
*/
|
||||
lua_unit* luaW_pushlocalunit(lua_State *L, unit& u);
|
||||
|
||||
/**
|
||||
* Similar to luaW_tounit but returns a unit_ptr; use this instead of
|
||||
* luaW_tounit when using an api that needs unit_ptr.
|
||||
*/
|
||||
unit_ptr luaW_tounit_ptr(lua_State *L, int index, bool only_on_map);
|
||||
|
||||
/**
|
||||
* Similar to luaW_checkunit but returns a unit_ptr; use this instead of
|
||||
* luaW_checkunit when using an api that needs unit_ptr.
|
||||
*/
|
||||
unit_ptr luaW_checkunit_ptr(lua_State *L, int index, bool only_on_map);
|
||||
|
||||
struct map_location;
|
||||
/**
|
||||
* Similar to luaW_tounit but returns a lua_unit; use this if you need
|
||||
* to handle map and recall units differently, for example.
|
||||
*
|
||||
* Note that this only returns null if the element on the stack was not a unit,
|
||||
* so it may be an invalid unit.
|
||||
*/
|
||||
lua_unit* luaW_tounit_ref(lua_State *L, int index);
|
||||
|
||||
/**
|
||||
* Similar to luaW_checkunit but returns a lua_unit; use this if you need
|
||||
* to handle map and recall units differently, for example.
|
||||
*/
|
||||
lua_unit* luaW_checkunit_ref(lua_State *L, int index);
|
||||
|
||||
|
||||
/**
|
||||
* Storage for a unit, either owned by the Lua code (#ptr != 0), a
|
||||
|
@ -65,22 +83,43 @@ class lua_unit
|
|||
unit_ptr ptr;
|
||||
int side;
|
||||
unit* c_ptr;
|
||||
lua_unit(lua_unit const &);
|
||||
lua_unit(lua_unit const &) = delete;
|
||||
lua_unit& operator=(const lua_unit&) = delete;
|
||||
|
||||
template<typename... Args>
|
||||
friend lua_unit* luaW_pushunit(lua_State *L, Args... args);
|
||||
friend lua_unit* luaW_pushlocalunit(lua_State *L, unit& u);
|
||||
static void setmetatable(lua_State *L);
|
||||
public:
|
||||
lua_unit(size_t u): uid(u), ptr(), side(0), c_ptr() {}
|
||||
lua_unit(unit_ptr u): uid(0), ptr(u), side(0), c_ptr() {}
|
||||
lua_unit(int s, size_t u): uid(u), ptr(), side(s), c_ptr() {}
|
||||
lua_unit(unit& u): uid(0), ptr(), side(0), c_ptr(&u) {}
|
||||
~lua_unit();
|
||||
|
||||
bool on_map() const { return !ptr && side == 0; }
|
||||
int on_recall_list() const { return side; }
|
||||
|
||||
unit* get();
|
||||
unit_ptr get_shared();
|
||||
|
||||
unit* operator->() {return get();}
|
||||
unit& operator*() {return *get();}
|
||||
|
||||
void clear_ref() { uid = 0; ptr = unit_ptr(); side = 0; c_ptr = nullptr; }
|
||||
// Clobbers loc
|
||||
bool put_map(const map_location &loc);
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
inline lua_unit* luaW_pushunit(lua_State *L, Args... args) {
|
||||
lua_unit* lu = new(L) lua_unit(args...);
|
||||
lua_unit::setmetatable(L);
|
||||
return lu;
|
||||
}
|
||||
|
||||
namespace lua_units {
|
||||
std::string register_metatables(lua_State *L);
|
||||
}
|
||||
|
||||
#endif
|
230
src/scripting/lua_unit_attacks.cpp
Normal file
230
src/scripting/lua_unit_attacks.cpp
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
Copyright (C) 2009 - 2016 by Guillaume Melquiond <guillaume.melquiond@gmail.com>
|
||||
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 "lua_unit_attacks.hpp"
|
||||
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_unit.hpp"
|
||||
#include "units/unit.hpp"
|
||||
|
||||
#include "lua/lauxlib.h"
|
||||
#include "lua/lua.h" // for lua_State, lua_settop, etc
|
||||
|
||||
static const char uattacksKey[] = "unit attacks table";
|
||||
static const char uattackKey[] = "unit attack";
|
||||
|
||||
void push_unit_attacks_table(lua_State* L, int idx)
|
||||
{
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, idx);
|
||||
// hack: store the unit_type at -1 because we want positive indices to refer to the attacks.
|
||||
lua_rawseti(L, -2, -1);
|
||||
luaL_setmetatable(L, uattacksKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attacks of a unit or unit type (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit or unit type.
|
||||
* - Arg 2: index (int) or id (string) identifying a particular attack.
|
||||
* - Ret 1: the unit's attacks.
|
||||
*/
|
||||
static int impl_unit_attacks_get(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attacks");
|
||||
}
|
||||
lua_rawgeti(L, 1, -1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
const unit_type* ut = static_cast<const unit_type*>(luaL_testudata(L, -1, "unit type"));
|
||||
if(!u && !ut) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
const attack_type* attack = nullptr;
|
||||
const std::vector<attack_type>& attacks = u ? u->attacks() : ut->attacks();
|
||||
if(!lua_isnumber(L,2)) {
|
||||
std::string attack_id = luaL_checkstring(L, 2);
|
||||
for(const attack_type& at : attacks) {
|
||||
if(at.id() == attack_id) {
|
||||
attack = &at;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(attack == nullptr) {
|
||||
//return nil on invalid index, just like lua tables do.
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
size_t index = luaL_checkinteger(L, 2) - 1;
|
||||
if(index >= attacks.size()) {
|
||||
//return nil on invalid index, just like lua tables do.
|
||||
return 0;
|
||||
}
|
||||
attack = &attacks[index];
|
||||
}
|
||||
|
||||
// stack { lua_unit }, id/index, lua_unit
|
||||
lua_createtable(L, 2, 0);
|
||||
// stack { lua_unit }, id/index, lua_unit, table
|
||||
lua_pushvalue(L, -2);
|
||||
// stack { lua_unit }, id/index, lua_unit, table, lua_unit
|
||||
lua_rawseti(L, -2, 1);
|
||||
// stack { lua_unit }, id/index, lua_unit, table
|
||||
lua_pushstring(L, attack->id().c_str());
|
||||
// stack { lua_unit }, id/index, lua_unit, table, attack id
|
||||
lua_rawseti(L, -2, 2);
|
||||
// stack { lua_unit }, id/index, lua_unit, table
|
||||
luaL_setmetatable(L, uattackKey);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the attacks of a unit (__len metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id.
|
||||
* - Ret 1: size of unit attacks vector.
|
||||
*/
|
||||
static int impl_unit_attacks_len(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attacks");
|
||||
}
|
||||
lua_rawgeti(L, 1, -1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
const unit_type* ut = static_cast<const unit_type*>(luaL_testudata(L, -1, "unit type"));
|
||||
if(!u && !ut) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
lua_pushinteger(L, (u ? u->attacks() : ut->attacks()).size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a propoerty of a units attack (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id. and a string identyfying the attack.
|
||||
* - Arg 2: string
|
||||
* - Ret 1:
|
||||
*/
|
||||
static int impl_unit_attack_get(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attack");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
const unit* u = luaW_tounit(L, -1);
|
||||
const unit_type* ut = static_cast<const unit_type*>(luaL_testudata(L, -1, "unit type"));
|
||||
if(!u && !ut) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
lua_rawgeti(L, 1, 2);
|
||||
std::string attack_id = luaL_checkstring(L, -1);
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
for(const attack_type& attack : u ? u->attacks() : ut->attacks()) {
|
||||
if(attack.id() == attack_id) {
|
||||
return_string_attrib("description", attack.name());
|
||||
return_string_attrib("name", attack.id());
|
||||
return_string_attrib("type", attack.type());
|
||||
return_string_attrib("icon", attack.icon());
|
||||
return_string_attrib("range", attack.range());
|
||||
return_int_attrib("damage", attack.damage());
|
||||
return_int_attrib("number", attack.num_attacks());
|
||||
return_int_attrib("attack_weight", attack.attack_weight());
|
||||
return_int_attrib("defense_weight", attack.defense_weight());
|
||||
return_int_attrib("accuracy", attack.accuracy());
|
||||
return_int_attrib("movement_used", attack.movement_used());
|
||||
return_int_attrib("parry", attack.parry());
|
||||
return_cfgref_attrib("specials", attack.specials());
|
||||
return_cfgref_attrib("__cfg", attack.to_config());
|
||||
std::string err_msg = "unknown property of attack: ";
|
||||
err_msg += m;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
}
|
||||
return luaL_argerror(L, 1, "invalid attack id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a propoerty of a units attack (__index metamethod).
|
||||
* - Arg 1: table containing the userdata containing the unit id. and a string identyfying the attack.
|
||||
* - Arg 2: string
|
||||
* - Ret 1:
|
||||
*/
|
||||
static int impl_unit_attack_set(lua_State *L)
|
||||
{
|
||||
if(!lua_istable(L, 1)) {
|
||||
return luaL_typerror(L, 1, "unit attack");
|
||||
}
|
||||
lua_rawgeti(L, 1, 1);
|
||||
unit* u = luaW_tounit(L, -1);
|
||||
const unit_type* ut = static_cast<const unit_type*>(luaL_testudata(L, -1, "unit type"));
|
||||
if(!u && !ut) {
|
||||
return luaL_argerror(L, 1, "unknown unit");
|
||||
}
|
||||
lua_rawgeti(L, 1, 2);
|
||||
std::string attack_id = luaL_checkstring(L, -1);
|
||||
char const *m = luaL_checkstring(L, 2);
|
||||
for(attack_type& attack : u ? u->attacks() : ut->attacks()) {
|
||||
if(attack.id() == attack_id) {
|
||||
modify_tstring_attrib("description", attack.set_name(value));
|
||||
// modify_string_attrib("name", attack.set_id(value));
|
||||
modify_string_attrib("type", attack.set_type(value));
|
||||
modify_string_attrib("icon", attack.set_icon(value));
|
||||
modify_string_attrib("range", attack.set_range(value));
|
||||
modify_int_attrib("damage", attack.set_damage(value));
|
||||
modify_int_attrib("number", attack.set_num_attacks(value));
|
||||
modify_int_attrib("attack_weight", attack.set_attack_weight(value));
|
||||
modify_int_attrib("defense_weight", attack.set_defense_weight(value));
|
||||
modify_int_attrib("accuracy", attack.set_accuracy(value));
|
||||
modify_int_attrib("movement_used", attack.set_movement_used(value));
|
||||
modify_int_attrib("parry", attack.set_parry(value));
|
||||
|
||||
if(strcmp(m, "specials") == 0) {
|
||||
attack.set_specials(luaW_checkconfig(L, 3));
|
||||
return 0;
|
||||
}
|
||||
return_cfgref_attrib("specials", attack.specials());
|
||||
std::string err_msg = "unknown modifyable property of attack: ";
|
||||
err_msg += m;
|
||||
return luaL_argerror(L, 2, err_msg.c_str());
|
||||
}
|
||||
}
|
||||
return luaL_argerror(L, 1, "invalid attack id");
|
||||
}
|
||||
|
||||
namespace lua_units {
|
||||
std::string register_attacks_metatables(lua_State* L)
|
||||
{
|
||||
std::ostringstream cmd_out;
|
||||
|
||||
// Create the unit attacks metatable.
|
||||
cmd_out << "Adding unit attacks metatable...\n";
|
||||
|
||||
luaL_newmetatable(L, uattacksKey);
|
||||
lua_pushcfunction(L, impl_unit_attacks_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_attacks_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pushstring(L, "unit attacks");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
|
||||
// Create the unit attack metatable
|
||||
luaL_newmetatable(L, uattackKey);
|
||||
lua_pushcfunction(L, impl_unit_attack_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, impl_unit_attack_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pushstring(L, "unit attack");
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
|
||||
return cmd_out.str();
|
||||
}
|
||||
}
|
28
src/scripting/lua_unit_attacks.hpp
Normal file
28
src/scripting/lua_unit_attacks.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2009 - 2016 by Guillaume Melquiond <guillaume.melquiond@gmail.com>
|
||||
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 SCRIPTING_LUA_UNIT_ATTACKS_HPP
|
||||
#define SCRIPTING_LUA_UNIT_ATTACKS_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
void push_unit_attacks_table(lua_State* L, int idx);
|
||||
|
||||
namespace lua_units {
|
||||
std::string register_attacks_metatables(lua_State* L);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,6 +15,7 @@
|
|||
#include "scripting/lua_unit_type.hpp"
|
||||
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_unit_attacks.hpp"
|
||||
#include "scripting/push_check.hpp"
|
||||
#include "units/types.hpp"
|
||||
|
||||
|
@ -73,13 +74,7 @@ static int impl_unit_type_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
if (strcmp(m, "attacks") == 0) {
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_pushvalue(L, 1);
|
||||
// hack: store the unit_type at -1 because we want positive indices to refer to the attacks.
|
||||
lua_rawseti(L, -2, -1);
|
||||
lua_pushlightuserdata(L, uattacksKey);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_setmetatable(L, -2);
|
||||
push_unit_attacks_table(L, 1);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "config.hpp"
|
||||
#include "game_errors.hpp"
|
||||
#include "log.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
#include "scripting/lua_common.hpp"
|
||||
#include "scripting/lua_rng.hpp"
|
||||
#include "scripting/lua_pathfind_cost_calculator.hpp"
|
||||
|
|
|
@ -2380,11 +2380,11 @@ unit& unit::clone(bool is_temporary)
|
|||
}
|
||||
|
||||
|
||||
unit_movement_resetter::unit_movement_resetter(unit &u, bool operate) :
|
||||
u_(u), moves_(u.movement_left(true))
|
||||
unit_movement_resetter::unit_movement_resetter(const unit &u, bool operate) :
|
||||
u_(const_cast<unit&>(u)), moves_(u.movement_left(true))
|
||||
{
|
||||
if (operate) {
|
||||
u.set_movement(u.total_movement());
|
||||
u_.set_movement(u_.total_movement());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ private:
|
|||
struct unit_movement_resetter
|
||||
: private boost::noncopyable
|
||||
{
|
||||
unit_movement_resetter(unit& u, bool operate=true);
|
||||
unit_movement_resetter(const unit& u, bool operate=true);
|
||||
~unit_movement_resetter();
|
||||
|
||||
private:
|
||||
|
|
Loading…
Add table
Reference in a new issue