The Battle for Wesnoth  1.15.0-dev
lua_team.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by Chris Beck <render787@gmail.com>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "scripting/lua_team.hpp"
16 
17 #include "scripting/lua_common.hpp"
18 #include "team.hpp"
19 #include "resources.hpp" // for gameboard
20 #include "game_board.hpp"
21 
22 #include <string>
23 
24 #include "lua/lua.h"
25 #include "lua/lauxlib.h"
26 
27 /**
28  * Implementation for a lua reference to a team,
29  * used by the wesnoth in-game sides table.
30  *
31  * (The userdata has type team** because lua holds
32  * only a pointer to a team, not a full-size team.
33  * If it were a full object then we would cast to
34  * type team *, since checkudata returns a pointer
35  * to the type corresponding to the sizeof expr
36  * used when we allocated the userdata.)
37  */
38 
39 // Registry key
40 static const char * Team = "side";
41 
42 /**
43  * Gets some data on a side (__index metamethod).
44  * - Arg 1: full userdata containing the team.
45  * - Arg 2: string containing the name of the property.
46  * - Ret 1: something containing the attribute.
47  */
48 static int impl_side_get(lua_State *L)
49 {
50  // Hidden metamethod, so arg1 has to be a pointer to a team.
51  team &t = luaW_checkteam(L, 1);
52  char const *m = luaL_checkstring(L, 2);
53 
54  // Find the corresponding attribute.
55  return_int_attrib("side", t.side());
56  return_string_attrib("save_id", t.save_id());
57  return_int_attrib("gold", t.gold());
58  return_tstring_attrib("objectives", t.objectives());
59  return_int_attrib("village_gold", t.village_gold());
60  return_int_attrib("village_support", t.village_support());
61  return_int_attrib("recall_cost", t.recall_cost());
62  return_int_attrib("base_income", t.base_income());
63  return_int_attrib("total_income", t.total_income());
64  return_bool_attrib("objectives_changed", t.objectives_changed());
65  return_bool_attrib("fog", t.uses_fog());
66  return_bool_attrib("shroud", t.uses_shroud());
67  return_bool_attrib("hidden", t.hidden());
68  return_bool_attrib("scroll_to_leader", t.get_scroll_to_leader());
69  return_string_attrib("flag", t.flag().empty() ? game_config::images::flag : t.flag());
71  return_tstring_attrib("user_team_name", t.user_team_name());
72  return_string_attrib("team_name", t.team_name());
73  return_string_attrib("faction", t.faction());
74  return_tstring_attrib("faction_name", t.faction_name());
75  return_string_attrib("color", t.color());
76  return_cstring_attrib("controller", t.controller().to_string().c_str());
77  return_bool_attrib("is_local", t.is_local());
78  return_string_attrib("defeat_condition", t.defeat_condition().to_string());
79  return_string_attrib("share_vision", t.share_vision().to_string());
80  return_float_attrib("carryover_bonus", t.carryover_bonus());
81  return_int_attrib("carryover_percentage", t.carryover_percentage());
82  return_bool_attrib("carryover_add", t.carryover_add());
83  return_bool_attrib("lost", t.lost());
84  return_bool_attrib("persistent", t.persistent());
85  return_bool_attrib("suppress_end_turn_confirmation", t.no_turn_confirmation());
86  return_string_attrib("share_vision", t.share_vision().to_string());
87  return_bool_attrib("share_maps", t.share_maps());
88  return_bool_attrib("share_view", t.share_view());
89  return_bool_attrib("chose_random", t.chose_random());
90  return_tstring_attrib("side_name", t.side_name_tstr());
91 
92  if (strcmp(m, "recruit") == 0) {
93  const std::set<std::string>& recruits = t.recruits();
94  lua_createtable(L, recruits.size(), 0);
95  int i = 1;
96  for (const std::string& r : t.recruits()) {
97  lua_pushstring(L, r.c_str());
98  lua_rawseti(L, -2, i++);
99  }
100  return 1;
101  }
102 
103  // These are blocked together because they are all part of the team_data struct.
104  // Some of these values involve iterating over the units map to calculate them.
105  auto d = [&](){ return resources::gameboard->calculate_team_data(t); };
106  return_int_attrib("num_units", d().units);
107  return_int_attrib("total_upkeep", d().upkeep);
108  return_int_attrib("num_villages", d().villages);
109  return_int_attrib("expenses", d().expenses);
110  return_int_attrib("net_income", d().net_income);
111 
112  return_cfg_attrib("__cfg", t.write(cfg));
113  if(luaW_getmetafield(L, 1, m)) {
114  return 1;
115  }
116  return 0;
117 }
118 
119 /**
120  * Sets some data on a side (__newindex metamethod).
121  * - Arg 1: full userdata containing the team.
122  * - Arg 2: string containing the name of the property.
123  * - Arg 3: something containing the attribute.
124  */
125 static int impl_side_set(lua_State *L)
126 {
127  // Hidden metamethod, so arg1 has to be a pointer to a team.
128  team &t = luaW_checkteam(L, 1);
129  char const *m = luaL_checkstring(L, 2);
130 
131  // Find the corresponding attribute.
132  modify_int_attrib("gold", t.set_gold(value));
133  modify_tstring_attrib("objectives", t.set_objectives(value, true));
134  //maybe add a setter for save_id too?
135  modify_int_attrib("village_gold", t.set_village_gold(value));
136  modify_int_attrib("village_support", t.set_village_support(value));
137  modify_int_attrib("recall_cost", t.set_recall_cost(value));
138  modify_int_attrib("base_income", t.set_base_income(value));
139  modify_bool_attrib("objectives_changed", t.set_objectives_changed(value));
140  modify_bool_attrib("hidden", t.set_hidden(value));
141  modify_bool_attrib("scroll_to_leader", t.set_scroll_to_leader(value));
142  modify_tstring_attrib("user_team_name", t.change_team(t.team_name(), value));
143  modify_string_attrib("team_name", t.change_team(value, t.user_team_name()));
144  modify_string_attrib("controller", t.change_controller_by_wml(value));
145  modify_string_attrib("color", t.set_color(value));
146  modify_string_attrib("defeat_condition", t.set_defeat_condition_string(value));
147  modify_int_attrib("carryover_percentage", t.set_carryover_percentage(value));
148  modify_bool_attrib("carryover_add", t.set_carryover_add(value));
149  modify_bool_attrib("lost", t.set_lost(value));
150  modify_bool_attrib("persistent", t.set_persistent(value));
151  modify_bool_attrib("suppress_end_turn_confirmation", t.set_no_turn_confirmation(value));
152  modify_bool_attrib("shroud", t.set_shroud(value));
153  modify_bool_attrib("fog", t.set_fog(value));
154  modify_string_attrib("flag_icon", t.set_flag_icon(value));
155  modify_tstring_attrib("side_name", t.set_side_name(value));
156  modify_string_attrib("share_vision", {
157  team::SHARE_VISION v;
158  if(v.parse(value)) {
159  t.set_share_vision(v);
160  } else {
161  return luaL_argerror(L, 3, "Invalid share_vision value (should be 'all', 'none', or 'shroud')");
162  }
163  });
164 
165  if (strcmp(m, "carryover_bonus") == 0) {
167  return 0;
168  }
169 
170  if (strcmp(m, "recruit") == 0) {
171  t.set_recruits(std::set<std::string>());
172  if (!lua_istable(L, 3)) return 0;
173  for (int i = 1;; ++i) {
174  lua_rawgeti(L, 3, i);
175  if (lua_isnil(L, -1)) break;
176  t.add_recruit(lua_tostring(L, -1));
177  lua_pop(L, 1);
178  }
179  return 0;
180  }
181 
182  std::string err_msg = "unknown modifiable property of side: ";
183  err_msg += m;
184  return luaL_argerror(L, 2, err_msg.c_str());
185 }
186 
188 {
189  // Hidden metamethod, so arg1 has to be a pointer to a team.
190  team &t1 = luaW_checkteam(L, 1);
191  if(team* t2 = luaW_toteam(L, 2)) {
192  lua_pushboolean(L, t1.side() == t2->side());
193  } else {
194  lua_pushboolean(L, false);
195  }
196  return 1;
197 }
198 
199 namespace lua_team {
200 
201  std::string register_metatable(lua_State * L)
202  {
204 
205  static luaL_Reg const callbacks[] {
206  { "__index", &impl_side_get},
207  { "__newindex", &impl_side_set},
208  { "__eq", &impl_side_equal},
209  { nullptr, nullptr }
210  };
211  luaL_setfuncs(L, callbacks, 0);
212 
213  lua_pushstring(L, Team);
214  lua_setfield(L, -2, "__metatable");
215  // Side methods
216  luaW_getglobal(L, "wesnoth", "match_side");
217  lua_setfield(L, -2, "matches");
218 
219  return "Adding getside metatable...\n";
220  }
221 }
222 
224 {
225  team** t = static_cast<team**>(lua_newuserdata(L, sizeof(team*)));
226  *t = &tm;
228 }
229 
231 {
232  return **static_cast<team **>(luaL_checkudata(L, idx, Team));
233 }
234 
236 {
237  if(void* p = luaL_testudata(L, idx, Team)) {
238  return *static_cast<team **>(p);
239  }
240  return nullptr;
241 }
#define modify_bool_attrib(name, accessor)
Definition: lua_common.hpp:332
bool no_turn_confirmation() const
Definition: team.hpp:361
LUALIB_API void * luaL_checkudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:333
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:683
void set_shroud(bool shroud)
Definition: team.hpp:322
#define return_tstring_attrib(name, accessor)
Definition: lua_common.hpp:194
LUALIB_API lua_Number luaL_checknumber(lua_State *L, int arg)
Definition: lauxlib.cpp:408
void set_side_name(const t_string &new_name)
Definition: team.hpp:306
team & luaW_checkteam(lua_State *L, int idx)
Test if the top stack element is a team, and if not, error.
Definition: lua_team.cpp:230
void set_carryover_add(bool value)
Definition: team.hpp:352
void luaW_pushteam(lua_State *L, team &tm)
Create a full userdata containing a pointer to the team.
Definition: lua_team.cpp:223
bool persistent() const
Definition: team.hpp:345
void set_objectives(const t_string &new_objectives, bool silently=false)
Definition: team.cpp:623
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:556
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:657
t_string side_name_tstr() const
Definition: team.hpp:305
This namespace contains bindings for lua to hold a pointer to a team, and to access and modify it...
Definition: lua_team.cpp:199
const std::string & flag() const
Definition: team.hpp:298
bool carryover_add() const
Definition: team.hpp:353
bool share_view() const
Definition: team.hpp:387
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:816
bool objectives_changed() const
Definition: team.hpp:239
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:210
void set_recall_cost(int cost)
Definition: team.hpp:194
const std::string & save_id() const
Definition: team.hpp:230
#define d
void set_persistent(bool value)
Definition: team.hpp:346
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:312
void set_defeat_condition_string(const std::string &value)
sets the defeat condition if
Definition: team.hpp:341
void add_recruit(const std::string &)
Definition: team.cpp:465
-file sdl_utils.hpp
void set_share_vision(const std::string &vision_status)
Definition: team.hpp:390
void set_hidden(bool value)
Definition: team.hpp:344
double carryover_bonus() const
Definition: team.hpp:355
void set_carryover_percentage(int value)
Definition: team.hpp:350
int village_support() const
Definition: team.hpp:198
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1183
const std::string & faction() const
Definition: team.hpp:307
static const char * Team
Implementation for a lua reference to a team, used by the wesnoth in-game sides table.
Definition: lua_team.cpp:40
void set_scroll_to_leader(bool value)
Definition: team.hpp:220
#define lua_pop(L, n)
Definition: lua.h:344
std::string flag_icon
bool uses_fog() const
Definition: team.hpp:315
int gold() const
Definition: team.hpp:188
int village_gold() const
Definition: team.hpp:191
void set_no_turn_confirmation(bool value)
Definition: team.hpp:362
std::string register_metatable(lua_State *L)
Definition: lua_team.cpp:201
void write(config &cfg) const
Definition: team.cpp:403
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
SHARE_VISION share_vision() const
Definition: team.hpp:388
#define modify_tstring_attrib(name, accessor)
Definition: lua_common.hpp:276
void set_carryover_bonus(double value)
Definition: team.hpp:354
LUALIB_API int luaL_argerror(lua_State *L, int arg, const char *extramsg)
Definition: lauxlib.cpp:164
#define modify_string_attrib(name, accessor)
Definition: lua_common.hpp:285
#define return_int_attrib(name, accessor)
Definition: lua_common.hpp:219
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil...
Definition: lua_common.cpp:851
static int impl_side_equal(lua_State *L)
Definition: lua_team.cpp:187
team_data calculate_team_data(const class team &tm) const
bool uses_shroud() const
Definition: team.hpp:314
int carryover_percentage() const
Definition: team.hpp:351
void set_lost(bool value=true)
Definition: team.hpp:347
game_board * gameboard
Definition: resources.cpp:20
const t_string & faction_name() const
Definition: team.hpp:308
void set_village_support(int support)
Definition: team.hpp:200
bool chose_random() const
Definition: team.hpp:407
LUALIB_API void * luaL_testudata(lua_State *L, int ud, const char *tname)
Definition: lauxlib.cpp:318
void set_fog(bool fog)
Definition: team.hpp:323
bool hidden() const
Definition: team.hpp:343
int recall_cost() const
Definition: team.hpp:192
void set_village_gold(int income)
Definition: team.hpp:193
#define return_cfg_attrib(name, accessor)
Definition: lua_common.hpp:243
LUALIB_API int luaL_newmetatable(lua_State *L, const char *tname)
Definition: lauxlib.cpp:299
#define lua_isnil(L, n)
Definition: lua.h:355
std::size_t i
Definition: function.cpp:933
void set_gold(int amount)
Definition: team.hpp:205
static int impl_side_set(lua_State *L)
Sets some data on a side (__newindex metamethod).
Definition: lua_team.cpp:125
mock_party p
const std::string & flag_icon() const
Definition: team.hpp:299
const t_string & objectives() const
Definition: team.hpp:238
#define lua_tostring(L, i)
Definition: lua.h:366
DEFEAT_CONDITION defeat_condition() const
Definition: team.hpp:338
void set_flag_icon(const std::string &flag_icon)
Definition: team.hpp:302
void set_objectives_changed(bool c=true) const
Definition: team.hpp:235
void change_controller_by_wml(const std::string &new_controller)
Definition: team.cpp:571
bool is_local() const
Definition: team.hpp:258
team * luaW_toteam(lua_State *L, int idx)
Test if the top stack element is a team, and if so, return it.
Definition: lua_team.cpp:235
bool get_scroll_to_leader() const
Definition: team.hpp:219
#define return_bool_attrib(name, accessor)
Definition: lua_common.hpp:235
bool luaW_getmetafield(lua_State *L, int idx, const char *key)
Like luaL_getmetafield, but returns false if key is an empty string or begins with two underscores...
Definition: lua_common.cpp:494
const std::string & color() const
Definition: team.hpp:254
bool share_maps() const
Definition: team.hpp:386
double t
Definition: astarsearch.cpp:63
#define lua_istable(L, n)
Definition: lua.h:353
#define return_float_attrib(name, accessor)
Definition: lua_common.hpp:227
static int impl_side_get(lua_State *L)
Gets some data on a side (__index metamethod).
Definition: lua_team.cpp:48
void change_team(const std::string &name, const t_string &user_name)
Definition: team.cpp:598
int base_income() const
Definition: team.hpp:190
void set_base_income(int amount)
Definition: team.hpp:208
void set_recruits(const std::set< std::string > &recruits)
Definition: team.cpp:458
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:934
int side() const
Definition: team.hpp:187
int total_income() const
Definition: team.hpp:195
LUA_API const char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.cpp:491
LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
Definition: lapi.cpp:776
bool lost() const
Definition: team.hpp:348
const std::string & team_name() const
Definition: team.hpp:294
const t_string & user_team_name() const
Definition: team.hpp:295
const std::set< std::string > & recruits() const
Definition: team.hpp:222
#define modify_int_attrib(name, accessor)
Definition: lua_common.hpp:294
void set_color(const std::string &color)
Definition: team.hpp:255
#define return_cstring_attrib(name, accessor)
Definition: lua_common.hpp:202
#define luaL_checkstring(L, n)
Definition: lauxlib.h:124
CONTROLLER controller() const
Definition: team.hpp:253