The Battle for Wesnoth  1.15.2+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 https://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"
19 #include "team.hpp"
20 #include "resources.hpp" // for gameboard
21 #include "game_board.hpp"
22 #include "game_display.hpp"
23 
24 #include <string>
25 
26 #include "lua/lua.h"
27 #include "lua/lauxlib.h"
28 
29 /**
30  * Implementation for a lua reference to a team,
31  * used by the wesnoth in-game sides table.
32  *
33  * (The userdata has type team** because lua holds
34  * only a pointer to a team, not a full-size team.
35  * If it were a full object then we would cast to
36  * type team *, since checkudata returns a pointer
37  * to the type corresponding to the sizeof expr
38  * used when we allocated the userdata.)
39  */
40 
41 // Registry key
42 static const char * Team = "side";
43 
44 /**
45  * Gets some data on a side (__index metamethod).
46  * - Arg 1: full userdata containing the team.
47  * - Arg 2: string containing the name of the property.
48  * - Ret 1: something containing the attribute.
49  */
50 static int impl_side_get(lua_State *L)
51 {
52  // Hidden metamethod, so arg1 has to be a pointer to a team.
53  team &t = luaW_checkteam(L, 1);
54  char const *m = luaL_checkstring(L, 2);
55 
56  // Find the corresponding attribute.
57  return_int_attrib("side", t.side());
58  return_string_attrib("save_id", t.save_id());
59  return_int_attrib("gold", t.gold());
60  return_tstring_attrib("objectives", t.objectives());
61  return_int_attrib("village_gold", t.village_gold());
62  return_int_attrib("village_support", t.village_support());
63  return_int_attrib("num_villages", t.villages().size());
64  return_int_attrib("recall_cost", t.recall_cost());
65  return_int_attrib("base_income", t.base_income());
66  return_int_attrib("total_income", t.total_income());
67  return_bool_attrib("objectives_changed", t.objectives_changed());
68  return_bool_attrib("fog", t.uses_fog());
69  return_bool_attrib("shroud", t.uses_shroud());
70  return_bool_attrib("hidden", t.hidden());
71  return_bool_attrib("scroll_to_leader", t.get_scroll_to_leader());
72  return_string_attrib("flag", t.flag().empty() ? game_config::images::flag : t.flag());
74  return_tstring_attrib("user_team_name", t.user_team_name());
75  return_string_attrib("team_name", t.team_name());
76  return_string_attrib("faction", t.faction());
77  return_tstring_attrib("faction_name", t.faction_name());
78  return_string_attrib("color", t.color());
79  return_cstring_attrib("controller", t.controller().to_string().c_str());
80  return_bool_attrib("is_local", t.is_local());
81  return_string_attrib("defeat_condition", t.defeat_condition().to_string());
82  return_string_attrib("share_vision", t.share_vision().to_string());
83  return_float_attrib("carryover_bonus", t.carryover_bonus());
84  return_int_attrib("carryover_percentage", t.carryover_percentage());
85  return_bool_attrib("carryover_add", t.carryover_add());
86  return_bool_attrib("lost", t.lost());
87  return_bool_attrib("persistent", t.persistent());
88  return_bool_attrib("suppress_end_turn_confirmation", t.no_turn_confirmation());
89  return_string_attrib("share_vision", t.share_vision().to_string());
90  return_bool_attrib("share_maps", t.share_maps());
91  return_bool_attrib("share_view", t.share_view());
92  return_bool_attrib("chose_random", t.chose_random());
93  return_tstring_attrib("side_name", t.side_name_tstr());
94 
95  if (strcmp(m, "recruit") == 0) {
96  const std::set<std::string>& recruits = t.recruits();
97  lua_createtable(L, recruits.size(), 0);
98  int i = 1;
99  for (const std::string& r : t.recruits()) {
100  lua_pushstring(L, r.c_str());
101  lua_rawseti(L, -2, i++);
102  }
103  return 1;
104  }
105 
106  // These are blocked together because they are all part of the team_data struct.
107  // Some of these values involve iterating over the units map to calculate them.
108  auto d = [&](){ return team_data(*resources::gameboard, t); };
109  return_int_attrib("num_units", d().units);
110  return_int_attrib("total_upkeep", d().upkeep);
111  return_int_attrib("expenses", d().expenses);
112  return_int_attrib("net_income", d().net_income);
113 
114  return_cfg_attrib("__cfg", t.write(cfg));
115  if(luaW_getmetafield(L, 1, m)) {
116  return 1;
117  }
118  return 0;
119 }
120 
121 /**
122  * Sets some data on a side (__newindex metamethod).
123  * - Arg 1: full userdata containing the team.
124  * - Arg 2: string containing the name of the property.
125  * - Arg 3: something containing the attribute.
126  */
127 static int impl_side_set(lua_State *L)
128 {
129  // Hidden metamethod, so arg1 has to be a pointer to a team.
130  team &t = luaW_checkteam(L, 1);
131  char const *m = luaL_checkstring(L, 2);
132 
133  const auto& reinit_flag_for_team = [&L] (const team& t) -> void {
134  auto* disp = lua_kernel_base::get_lua_kernel<game_lua_kernel>(L).get_display();
135  if(disp) {
136  disp->reinit_flags_for_team(t);
137  }
138  };
139  // Find the corresponding attribute.
140  modify_int_attrib("gold", t.set_gold(value));
141  modify_tstring_attrib("objectives", t.set_objectives(value, true));
142  //maybe add a setter for save_id too?
143  modify_int_attrib("village_gold", t.set_village_gold(value));
144  modify_int_attrib("village_support", t.set_village_support(value));
145  modify_int_attrib("recall_cost", t.set_recall_cost(value));
146  modify_int_attrib("base_income", t.set_base_income(value));
147  modify_bool_attrib("objectives_changed", t.set_objectives_changed(value));
148  modify_bool_attrib("hidden", t.set_hidden(value));
149  modify_bool_attrib("scroll_to_leader", t.set_scroll_to_leader(value));
150  modify_string_attrib("flag", {
151  t.set_flag(value);
152  reinit_flag_for_team(t);
153  });
154  modify_string_attrib("flag_icon", t.set_flag_icon(value));
155  modify_tstring_attrib("user_team_name", t.change_team(t.team_name(), value));
156  modify_string_attrib("team_name", t.change_team(value, t.user_team_name()));
157  modify_string_attrib("controller", t.change_controller_by_wml(value));
158  modify_string_attrib("color", {
159  t.set_color(value);
160  reinit_flag_for_team(t);
161  });
162  modify_string_attrib("defeat_condition", t.set_defeat_condition_string(value));
163  modify_int_attrib("carryover_percentage", t.set_carryover_percentage(value));
164  modify_bool_attrib("carryover_add", t.set_carryover_add(value));
165  modify_bool_attrib("lost", t.set_lost(value));
166  modify_bool_attrib("persistent", t.set_persistent(value));
167  modify_bool_attrib("suppress_end_turn_confirmation", t.set_no_turn_confirmation(value));
168  modify_bool_attrib("shroud", t.set_shroud(value));
169  modify_bool_attrib("fog", t.set_fog(value));
170  modify_string_attrib("flag_icon", t.set_flag_icon(value));
171  modify_tstring_attrib("side_name", t.set_side_name(value));
172  modify_string_attrib("share_vision", {
173  team::SHARE_VISION v;
174  if(v.parse(value)) {
175  t.set_share_vision(v);
176  } else {
177  return luaL_argerror(L, 3, "Invalid share_vision value (should be 'all', 'none', or 'shroud')");
178  }
179  });
180 
181  if (strcmp(m, "carryover_bonus") == 0) {
183  return 0;
184  }
185 
186  if (strcmp(m, "recruit") == 0) {
187  t.set_recruits(std::set<std::string>());
188  if (!lua_istable(L, 3)) return 0;
189  for (int i = 1;; ++i) {
190  lua_rawgeti(L, 3, i);
191  if (lua_isnil(L, -1)) break;
192  t.add_recruit(lua_tostring(L, -1));
193  lua_pop(L, 1);
194  }
195  return 0;
196  }
197 
198  std::string err_msg = "unknown modifiable property of side: ";
199  err_msg += m;
200  return luaL_argerror(L, 2, err_msg.c_str());
201 }
202 
204 {
205  // Hidden metamethod, so arg1 has to be a pointer to a team.
206  team &t1 = luaW_checkteam(L, 1);
207  if(team* t2 = luaW_toteam(L, 2)) {
208  lua_pushboolean(L, t1.side() == t2->side());
209  } else {
210  lua_pushboolean(L, false);
211  }
212  return 1;
213 }
214 
215 namespace lua_team {
216 
217  std::string register_metatable(lua_State * L)
218  {
220 
221  static luaL_Reg const callbacks[] {
222  { "__index", &impl_side_get},
223  { "__newindex", &impl_side_set},
224  { "__eq", &impl_side_equal},
225  { nullptr, nullptr }
226  };
227  luaL_setfuncs(L, callbacks, 0);
228 
229  lua_pushstring(L, Team);
230  lua_setfield(L, -2, "__metatable");
231  // Side methods
232  luaW_getglobal(L, "wesnoth", "match_side");
233  lua_setfield(L, -2, "matches");
234 
235  return "Adding getside metatable...\n";
236  }
237 }
238 
240 {
241  team** t = static_cast<team**>(lua_newuserdata(L, sizeof(team*)));
242  *t = &tm;
244 }
245 
247 {
248  return **static_cast<team **>(luaL_checkudata(L, idx, Team));
249 }
250 
252 {
253  if(void* p = luaL_testudata(L, idx, Team)) {
254  return *static_cast<team **>(p);
255  }
256  return nullptr;
257 }
#define modify_bool_attrib(name, accessor)
Definition: lua_common.hpp:339
bool no_turn_confirmation() const
Definition: team.hpp:365
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:684
void set_shroud(bool shroud)
Definition: team.hpp:326
#define return_tstring_attrib(name, accessor)
Definition: lua_common.hpp:201
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:310
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:246
void set_carryover_add(bool value)
Definition: team.hpp:356
void luaW_pushteam(lua_State *L, team &tm)
Create a full userdata containing a pointer to the team.
Definition: lua_team.cpp:239
bool persistent() const
Definition: team.hpp:349
void set_objectives(const t_string &new_objectives, bool silently=false)
Definition: team.cpp:643
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.cpp:557
LUA_API int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:658
t_string side_name_tstr() const
Definition: team.hpp:309
This namespace contains bindings for lua to hold a pointer to a team, and to access and modify it...
Definition: lua_team.cpp:215
const std::string & flag() const
Definition: team.hpp:301
bool carryover_add() const
Definition: team.hpp:357
bool share_view() const
Definition: team.hpp:390
LUA_API void lua_rawseti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.cpp:817
bool objectives_changed() const
Definition: team.hpp:241
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:217
void set_recall_cost(int cost)
Definition: team.hpp:195
const std::string & save_id() const
Definition: team.hpp:231
#define d
void set_persistent(bool value)
Definition: team.hpp:350
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:345
void add_recruit(const std::string &)
Definition: team.cpp:479
-file sdl_utils.hpp
void set_share_vision(const std::string &vision_status)
Definition: team.hpp:393
void set_hidden(bool value)
Definition: team.hpp:348
double carryover_bonus() const
Definition: team.hpp:359
void set_carryover_percentage(int value)
Definition: team.hpp:354
int village_support() const
Definition: team.hpp:199
LUA_API void * lua_newuserdata(lua_State *L, size_t size)
Definition: lapi.cpp:1184
const std::string & faction() const
Definition: team.hpp:311
static const char * Team
Implementation for a lua reference to a team, used by the wesnoth in-game sides table.
Definition: lua_team.cpp:42
void set_scroll_to_leader(bool value)
Definition: team.hpp:221
#define lua_pop(L, n)
Definition: lua.h:344
std::string flag_icon
bool uses_fog() const
Definition: team.hpp:319
int gold() const
Definition: team.hpp:189
int village_gold() const
Definition: team.hpp:192
void set_no_turn_confirmation(bool value)
Definition: team.hpp:366
std::string register_metatable(lua_State *L)
Definition: lua_team.cpp:217
void set_flag(const std::string &flag)
Definition: team.hpp:305
void write(config &cfg) const
Definition: team.cpp:405
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:391
#define modify_tstring_attrib(name, accessor)
Definition: lua_common.hpp:283
void set_carryover_bonus(double value)
Definition: team.hpp:358
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:292
#define return_int_attrib(name, accessor)
Definition: lua_common.hpp:226
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:203
bool uses_shroud() const
Definition: team.hpp:318
int carryover_percentage() const
Definition: team.hpp:355
void set_lost(bool value=true)
Definition: team.hpp:351
game_board * gameboard
Definition: resources.cpp:20
const t_string & faction_name() const
Definition: team.hpp:312
void set_village_support(int support)
Definition: team.hpp:201
bool chose_random() const
Definition: team.hpp:410
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:327
bool hidden() const
Definition: team.hpp:347
int recall_cost() const
Definition: team.hpp:193
void set_village_gold(int income)
Definition: team.hpp:194
#define return_cfg_attrib(name, accessor)
Definition: lua_common.hpp:250
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:206
static int impl_side_set(lua_State *L)
Sets some data on a side (__newindex metamethod).
Definition: lua_team.cpp:127
mock_party p
const std::string & flag_icon() const
Definition: team.hpp:302
const t_string & objectives() const
Definition: team.hpp:240
#define lua_tostring(L, i)
Definition: lua.h:366
DEFEAT_CONDITION defeat_condition() const
Definition: team.hpp:342
void set_flag_icon(const std::string &flag_icon)
Definition: team.hpp:306
void set_objectives_changed(bool c=true) const
Definition: team.hpp:237
void change_controller_by_wml(const std::string &new_controller)
Definition: team.cpp:585
bool is_local() const
Definition: team.hpp:261
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:251
bool get_scroll_to_leader() const
Definition: team.hpp:220
#define return_bool_attrib(name, accessor)
Definition: lua_common.hpp:242
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:256
bool share_maps() const
Definition: team.hpp:389
double t
Definition: astarsearch.cpp:64
#define lua_istable(L, n)
Definition: lua.h:353
#define return_float_attrib(name, accessor)
Definition: lua_common.hpp:234
static int impl_side_get(lua_State *L)
Gets some data on a side (__index metamethod).
Definition: lua_team.cpp:50
void change_team(const std::string &name, const t_string &user_name)
Definition: team.cpp:618
int base_income() const
Definition: team.hpp:191
void set_base_income(int amount)
Definition: team.hpp:209
void set_recruits(const std::set< std::string > &recruits)
Definition: team.cpp:472
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:934
int side() const
Definition: team.hpp:188
int total_income() const
Definition: team.hpp:196
const std::set< map_location > & villages() const
Definition: team.hpp:184
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:777
bool lost() const
Definition: team.hpp:352
const std::string & team_name() const
Definition: team.hpp:297
const t_string & user_team_name() const
Definition: team.hpp:298
const std::set< std::string > & recruits() const
Definition: team.hpp:223
#define modify_int_attrib(name, accessor)
Definition: lua_common.hpp:301
void set_color(const std::string &color)
Definition: team.hpp:258
#define return_cstring_attrib(name, accessor)
Definition: lua_common.hpp:209
#define luaL_checkstring(L, n)
Definition: lauxlib.h:124
CONTROLLER controller() const
Definition: team.hpp:255