diff options
Diffstat (limited to 'src')
51 files changed, 802 insertions, 503 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp index f889b19..b56fd65 100644 --- a/src/admin/ladmin.cpp +++ b/src/admin/ladmin.cpp @@ -2840,34 +2840,36 @@ void term_func(void) //------------------------ // Main function of ladmin //------------------------ -int do_init(int argc, ZString *argv) +int do_init(Slice<ZString> argv) { + ZString argv0 = argv.pop_front(); bool loaded_config_yet = false; - for (int i = 1; i < argc; ++i) + while (argv) { - if (argv[i].startswith('-')) + ZString argvi = argv.pop_front(); + if (argvi.startswith('-')) { - if (argv[i] == "--help") + if (argvi == "--help") { PRINTF("Usage: %s [--help] [--version] [files...]\n", - argv[0]); + argv0); exit(0); } - else if (argv[i] == "--version") + else if (argvi == "--version") { PRINTF("%s\n", CURRENT_VERSION_STRING); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argv[i]); + FPRINTF(stderr, "Unknown argument: %s\n", argvi); runflag = false; } } else { loaded_config_yet = true; - runflag &= load_config_file(argv[i], admin_confs); + runflag &= load_config_file(argvi, admin_confs); } } diff --git a/src/char/char.cpp b/src/char/char.cpp index b74df46..91ff2e2 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -46,11 +46,11 @@ #include "../poison.hpp" static -struct mmo_map_server server[MAX_MAP_SERVERS]; +Array<struct mmo_map_server, MAX_MAP_SERVERS> server; static -Session *server_session[MAX_MAP_SERVERS]; +Array<Session *, MAX_MAP_SERVERS> server_session; static -int server_freezeflag[MAX_MAP_SERVERS]; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed +Array<int, MAX_MAP_SERVERS> server_freezeflag; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed static int anti_freeze_enable = 0; static @@ -313,6 +313,7 @@ AString mmo_char_tostr(struct CharPair *cp) } str_p += '\t'; + assert (p->global_reg_num < GLOBAL_REG_NUM); for (int i = 0; i < p->global_reg_num; i++) if (p->global_reg[i].str) str_p += STRPRINTF("%s,%d ", @@ -411,14 +412,14 @@ bool extract(XString str, CharPair *cp) if (inventory.size() > MAX_INVENTORY) return false; - std::copy(inventory.begin(), inventory.end(), p->inventory); + std::copy(inventory.begin(), inventory.end(), p->inventory.begin()); // number of inventory items is not saved - it just detects nameid 0 // cart was here - no longer supported for (struct skill_loader& sk : skills) { - if (sk.id > MAX_SKILL) + if (sk.id >= MAX_SKILL) return false; p->skill[sk.id].lv = sk.level; p->skill[sk.id].flags = sk.flags; @@ -426,7 +427,7 @@ bool extract(XString str, CharPair *cp) if (vars.size() > GLOBAL_REG_NUM) return false; - std::copy(vars.begin(), vars.end(), p->global_reg); + std::copy(vars.begin(), vars.end(), p->global_reg.begin()); p->global_reg_num = vars.size(); return true; @@ -964,8 +965,10 @@ int mmo_char_send006b(Session *s, struct char_session_data *sd) } static -int set_account_reg2(int acc, int num, struct global_reg *reg) +int set_account_reg2(int acc, Slice<global_reg> reg) { + size_t num = reg.size(); + assert (num < ACCOUNT_REG2_NUM); int c = 0; for (CharPair& cd : char_keys) { @@ -1309,7 +1312,7 @@ void parse_tologin(Session *ls) if (RFIFOREST(ls) < 4 || RFIFOREST(ls) < RFIFOW(ls, 2)) return; { - struct global_reg reg[ACCOUNT_REG2_NUM]; + Array<struct global_reg, ACCOUNT_REG2_NUM> reg; int j, p, acc; acc = RFIFOL(ls, 4); for (p = 8, j = 0; @@ -1319,7 +1322,7 @@ void parse_tologin(Session *ls) reg[j].str = stringish<VarName>(RFIFO_STRING<32>(ls, p)); reg[j].value = RFIFOL(ls, p + 32); } - set_account_reg2(acc, j, reg); + set_account_reg2(acc, Slice<struct global_reg>(reg.begin(), j)); size_t len = RFIFOW(ls, 2); uint8_t buf[len]; @@ -1980,7 +1983,7 @@ void parse_frommap(Session *ms) if (RFIFOREST(ms) < 4 || RFIFOREST(ms) < RFIFOW(ms, 2)) return; { - struct global_reg reg[ACCOUNT_REG2_NUM]; + Array<struct global_reg, ACCOUNT_REG2_NUM> reg; int p, j; int acc = RFIFOL(ms, 4); for (p = 8, j = 0; @@ -1990,7 +1993,7 @@ void parse_frommap(Session *ms) reg[j].str = stringish<VarName>(RFIFO_STRING<32>(ms, p)); reg[j].value = RFIFOL(ms, p + 32); } - set_account_reg2(acc, j, reg); + set_account_reg2(acc, Slice<struct global_reg>(reg.begin(), j)); // loginサーバーへ送る if (login_session) { @@ -2831,34 +2834,37 @@ bool char_confs(XString key, ZString value) return sum; } -int do_init(int argc, ZString *argv) +int do_init(Slice<ZString> argv) { + ZString argv0 = argv.pop_front(); + bool loaded_config_yet = false; - for (int i = 1; i < argc; ++i) + while (argv) { - if (argv[i].startswith('-')) + ZString argvi = argv.pop_front(); + if (argvi.startswith('-')) { - if (argv[i] == "--help") + if (argvi == "--help") { PRINTF("Usage: %s [--help] [--version] [files...]\n", - argv[0]); + argv0); exit(0); } - else if (argv[i] == "--version") + else if (argvi == "--version") { PRINTF("%s\n", CURRENT_VERSION_STRING); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argv[i]); + FPRINTF(stderr, "Unknown argument: %s\n", argvi); runflag = false; } } else { loaded_config_yet = true; - runflag &= load_config_file(argv[i], char_confs); + runflag &= load_config_file(argvi, char_confs); } } diff --git a/src/char/char.hpp b/src/char/char.hpp index 377b1c6..f765b39 100644 --- a/src/char/char.hpp +++ b/src/char/char.hpp @@ -3,8 +3,6 @@ # include "../strings/fwd.hpp" -# include "../generic/const_array.hpp" - # include "../mmo/ip.hpp" # include "../mmo/mmo.hpp" @@ -17,7 +15,7 @@ struct mmo_map_server IP4Address ip; short port; int users; - MapName maps[MAX_MAP_PER_SERVER]; + Array<MapName, MAX_MAP_PER_SERVER> maps; }; const CharPair *search_character(CharName character_name); diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp index c0bedde..864972d 100644 --- a/src/char/int_party.cpp +++ b/src/char/int_party.cpp @@ -381,6 +381,7 @@ void mapif_party_leaved(int party_id, int account_id, CharName name) static void mapif_party_membermoved(struct party *p, int idx) { + assert (idx < MAX_PARTY); unsigned char buf[29]; WBUFW(buf, 0) = 0x3825; diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp index 0794c8f..d2782b4 100644 --- a/src/char/int_storage.cpp +++ b/src/char/int_storage.cpp @@ -83,8 +83,10 @@ bool extract(XString str, struct storage *p) if (storage_items.size() > MAX_STORAGE) return false; - std::copy(storage_items.begin(), storage_items.end(), p->storage_); + std::copy(storage_items.begin(), storage_items.end(), p->storage_.begin()); + if (p->storage_amount != storage_items.size()) + PRINTF("WARNING: storage desync for %d\n", p->account_id); return true; } diff --git a/src/char/inter.cpp b/src/char/inter.cpp index c287844..0c41c86 100644 --- a/src/char/inter.cpp +++ b/src/char/inter.cpp @@ -35,7 +35,7 @@ AString accreg_txt = "save/accreg.txt"; struct accreg { int account_id, reg_num; - struct global_reg reg[ACCOUNT_REG_NUM]; + Array<struct global_reg, ACCOUNT_REG_NUM> reg; }; static Map<int, struct accreg> accreg_db; @@ -63,6 +63,7 @@ int inter_recv_packet_length[] = static AString inter_accreg_tostr(struct accreg *reg) { + assert(reg->reg_num < ACCOUNT_REG_NUM); MString str; str += STRPRINTF("%d\t", reg->account_id); for (int j = 0; j < reg->reg_num; j++) @@ -85,7 +86,7 @@ bool extract(XString str, struct accreg *reg) if (vars.size() > ACCOUNT_REG_NUM) return false; - std::copy(vars.begin(), vars.end(), reg->reg); + std::copy(vars.begin(), vars.end(), reg->reg.begin()); reg->reg_num = vars.size(); return true; } @@ -263,6 +264,7 @@ void mapif_account_reg_reply(Session *s, int account_id) } else { + assert (reg->reg_num < ACCOUNT_REG_NUM); int j, p; for (j = 0, p = 8; j < reg->reg_num; j++, p += 36) { diff --git a/src/generic/const_array.cpp b/src/generic/const_array.cpp deleted file mode 100644 index 0c09333..0000000 --- a/src/generic/const_array.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "const_array.hpp" - -#include "../poison.hpp" diff --git a/src/generic/const_array.hpp b/src/generic/const_array.hpp deleted file mode 100644 index 1c70f5d..0000000 --- a/src/generic/const_array.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef TMWA_GENERIC_CONST_ARRAY_HPP -#define TMWA_GENERIC_CONST_ARRAY_HPP -// const_array.hpp - just a pointer-to-const and a length -// -// Copyright © 2011-2012 Ben Longbons <b.r.longbons@gmail.com> -// -// This file is part of The Mana World (Athena server) -// -// 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 3 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; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. - -# include "../sanity.hpp" - -# include <cstring> - -# include <iterator> -# include <ostream> -# include <vector> - -# ifdef WORKAROUND_GCC46_COMPILER -// constexpr is buggy with templates in this version -// Is this still needed now that const_string is removed? -# define constexpr /* nothing */ -# endif - -// TODO see if I ever actually use this, and not the subclass -template<class T> -class const_array -{ - const T *d; - size_t n; -public: - typedef const T *iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - - constexpr - const_array(std::nullptr_t) - : d(nullptr), n(0) - {} - - constexpr - const_array(const T *p, size_t z) - : d(p), n(z) - {} - - constexpr - const_array(const T *b, const T *e) - : d(b), n(e - b) - {} - - const_array(std::initializer_list<T> list) - : d(list.begin()), n(list.size()) - {} - - // Implicit conversion from std::vector - const_array(const std::vector<T>& v) - : d(v.data()), n(v.size()) - {} - - // but disallow conversion from a temporary - const_array(std::vector<T>&&) = delete; - - // Oops. see src/warnings.hpp - constexpr - const T *data() const { return d; } - constexpr - size_t size() const { return n; } - constexpr - bool empty() const { return not n; } - constexpr explicit - operator bool() const { return n; } - - constexpr - std::pair<const_array, const_array> cut(size_t o) const - { - return {const_array(d, o), const_array(d + o, n - o)}; - } - - constexpr - const_array first(size_t o) const - { - return cut(o).first; - } - - constexpr - const_array last(size_t l) const - { - return cut(size() - l).second; - } - - constexpr - const_array after(size_t o) const - { - return cut(o).second; - } - - constexpr - iterator begin() const { return d; } - constexpr - iterator end() const { return d + n; } - constexpr - reverse_iterator rbegin() const { return reverse_iterator(end()); } - constexpr - reverse_iterator rend() const { return reverse_iterator(begin()); } - - constexpr - const T& front() const { return *begin(); } - constexpr - const T& back() const { return *rbegin(); } - - // This probably shouldn't be used, but I'm adding it for porting. - T& operator[](size_t i) - { - return const_cast<T&>(d[i]); - } -}; - -# ifdef WORKAROUND_GCC46_COMPILER -# undef constexpr -# endif - -#endif // TMWA_GENERIC_CONST_ARRAY_HPP diff --git a/src/generic/enum.hpp b/src/generic/enum.hpp index 6f29981..29e5c36 100644 --- a/src/generic/enum.hpp +++ b/src/generic/enum.hpp @@ -3,6 +3,8 @@ # include "../sanity.hpp" +# include <cassert> + # include <type_traits> # include "../compat/iter.hpp" @@ -10,17 +12,27 @@ template<class T, class E, E max> struct earray { + constexpr static + size_t size() + { + return static_cast<size_t>(max); + } + // no ctor/dtor and one public member variable for easy initialization - T _data[size_t(max)]; + T _data[size()]; T& operator[](E v) { - return _data[size_t(v)]; + auto i = static_cast<size_t>(v); + assert (i < size()); + return _data[i]; } const T& operator[](E v) const { - return _data[size_t(v)]; + auto i = static_cast<size_t>(v); + assert (i < size()); + return _data[i]; } T *begin() @@ -30,7 +42,7 @@ struct earray T *end() { - return _data + size_t(max); + return _data + size(); } const T *begin() const @@ -40,7 +52,7 @@ struct earray const T *end() const { - return _data + size_t(max); + return _data + size(); } friend bool operator == (const earray& l, const earray& r) @@ -54,23 +66,30 @@ struct earray } }; -template<class T, class E> +template<class T, class E, E max> class eptr { + constexpr static + size_t size() + { + return static_cast<size_t>(max); + } + T *_data; public: eptr(std::nullptr_t=nullptr) : _data(nullptr) {} - template<E max> eptr(earray<T, E, max>& arr) : _data(arr._data) {} - T& operator [](E v) + T& operator [](E v) const { - return _data[size_t(v)]; + auto i = static_cast<size_t>(v); + assert (i < size()); + return _data[i]; } explicit operator bool() @@ -109,6 +128,8 @@ struct remove_enum<E, true> }; +// This really should just go in a namespace +// that's how I use it anyway ... # define ENUM_BITWISE_OPERATORS(E) \ inline \ E operator & (E l, E r) \ diff --git a/src/generic/intern-pool.hpp b/src/generic/intern-pool.hpp index 69f20ef..f9c1e8f 100644 --- a/src/generic/intern-pool.hpp +++ b/src/generic/intern-pool.hpp @@ -29,6 +29,7 @@ public: ZString outtern(size_t sz) const { + assert (sz < names.size()); return names[sz]; } diff --git a/src/generic/matrix.hpp b/src/generic/matrix.hpp index 3530ba7..b337249 100644 --- a/src/generic/matrix.hpp +++ b/src/generic/matrix.hpp @@ -3,6 +3,8 @@ # include "../sanity.hpp" +# include <cassert> + # include "../compat/memory.hpp" template<class T> @@ -34,10 +36,14 @@ public: T& ref(size_t x, size_t y) { + assert (x < _xs); + assert (y < _ys); return _data[x + y * _xs]; } const T& ref(size_t x, size_t y) const { + assert (x < _xs); + assert (y < _ys); return _data[x + y * _xs]; } diff --git a/src/io/cxxstdio.hpp b/src/io/cxxstdio.hpp index 9edeebb..66419df 100644 --- a/src/io/cxxstdio.hpp +++ b/src/io/cxxstdio.hpp @@ -26,7 +26,6 @@ # include "../compat/cast.hpp" -# include "../generic/const_array.hpp" # include "../generic/enum.hpp" # include "fwd.hpp" diff --git a/src/login/login.cpp b/src/login/login.cpp index c9b285f..ddc3d89 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -114,11 +114,11 @@ static int display_parse_fromchar = 0; // 0: no, 1: yes (without packet 0x2714), 2: all packets static -struct mmo_char_server server[MAX_SERVERS]; +Array<struct mmo_char_server, MAX_SERVERS> server; static -Session *server_session[MAX_SERVERS]; +Array<Session *, MAX_SERVERS> server_session; static -int server_freezeflag[MAX_SERVERS]; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed +Array<int, MAX_SERVERS> server_freezeflag; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed static int anti_freeze_enable = 0; static @@ -158,13 +158,14 @@ void SessionDeleter::operator()(SessionData *) #pragma GCC diagnostic pop constexpr int AUTH_FIFO_SIZE = 256; -struct +struct AuthFifo { int account_id, login_id1, login_id2; IP4Address ip; SEX sex; int delflag; -} auth_fifo[AUTH_FIFO_SIZE]; +}; +Array<AuthFifo, AUTH_FIFO_SIZE> auth_fifo; static int auth_fifo_pos = 0; @@ -184,7 +185,7 @@ struct AuthData IP4Address last_ip; // save of last IP of connection VString<254> memo; // a memo field int account_reg2_num; - struct global_reg account_reg2[ACCOUNT_REG2_NUM]; + Array<struct global_reg, ACCOUNT_REG2_NUM> account_reg2; }; static std::vector<AuthData> auth_data; @@ -447,6 +448,7 @@ AString mmo_auth_tostr(const AuthData *p) p->memo, p->ban_until_time); + assert (p->account_reg2_num < ACCOUNT_REG2_NUM); for (int i = 0; i < p->account_reg2_num; i++) if (p->account_reg2[i].str) str += STRPRINTF("%s,%d ", @@ -522,7 +524,7 @@ bool extract(XString line, AuthData *ad) if (vars.size() > ACCOUNT_REG2_NUM) return false; - std::copy(vars.begin(), vars.end(), ad->account_reg2); + std::copy(vars.begin(), vars.end(), ad->account_reg2.begin()); ad->account_reg2_num = vars.size(); return true; @@ -3827,34 +3829,36 @@ bool login_confs(XString key, ZString value) //------------------------------ // Main function of login-server //------------------------------ -int do_init(int argc, ZString *argv) +int do_init(Slice<ZString> argv) { + ZString argv0 = argv.pop_front(); bool loaded_config_yet = false; - for (int i = 1; i < argc; ++i) + while (argv) { - if (argv[i].startswith('-')) + ZString argvi = argv.pop_front(); + if (argvi.startswith('-')) { - if (argv[i] == "--help") + if (argvi == "--help") { PRINTF("Usage: %s [--help] [--version] [files...]\n", - argv[0]); + argv0); exit(0); } - else if (argv[i] == "--version") + else if (argvi == "--version") { PRINTF("%s\n", CURRENT_VERSION_STRING); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argv[i]); + FPRINTF(stderr, "Unknown argument: %s\n", argvi); runflag = false; } } else { loaded_config_yet = true; - runflag &= load_config_file(argv[i], login_confs); + runflag &= load_config_file(argvi, login_confs); } } diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp index 16d1efc..45759a6 100644 --- a/src/map/atcommand.hpp +++ b/src/map/atcommand.hpp @@ -3,8 +3,6 @@ # include "../strings/fwd.hpp" -# include "../generic/const_array.hpp" - # include "map.hpp" bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd, diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 7e563b8..49a0538 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -166,7 +166,7 @@ int battle_get_max_hp(dumb_ptr<block_list> bl) int battle_get_str(dumb_ptr<block_list> bl) { int str = 0; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); @@ -189,7 +189,7 @@ int battle_get_str(dumb_ptr<block_list> bl) int battle_get_agi(dumb_ptr<block_list> bl) { int agi = 0; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); @@ -211,7 +211,7 @@ int battle_get_agi(dumb_ptr<block_list> bl) int battle_get_vit(dumb_ptr<block_list> bl) { int vit = 0; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); @@ -233,7 +233,7 @@ int battle_get_vit(dumb_ptr<block_list> bl) int battle_get_int(dumb_ptr<block_list> bl) { int int_ = 0; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); @@ -255,7 +255,7 @@ int battle_get_int(dumb_ptr<block_list> bl) int battle_get_dex(dumb_ptr<block_list> bl) { int dex = 0; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); @@ -277,7 +277,7 @@ int battle_get_dex(dumb_ptr<block_list> bl) int battle_get_luk(dumb_ptr<block_list> bl) { int luk = 0; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); @@ -300,7 +300,7 @@ static int battle_get_flee(dumb_ptr<block_list> bl) { int flee = 1; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_retr(1, bl); sc_data = battle_get_sc_data(bl); @@ -329,7 +329,7 @@ static int battle_get_hit(dumb_ptr<block_list> bl) { int hit = 1; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_retr(1, bl); sc_data = battle_get_sc_data(bl); @@ -357,7 +357,7 @@ static int battle_get_flee2(dumb_ptr<block_list> bl) { int flee2 = 1; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_retr(1, bl); sc_data = battle_get_sc_data(bl); @@ -389,7 +389,7 @@ static int battle_get_critical(dumb_ptr<block_list> bl) { int critical = 1; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_retr(1, bl); sc_data = battle_get_sc_data(bl); @@ -415,7 +415,7 @@ int battle_get_critical(dumb_ptr<block_list> bl) static int battle_get_baseatk(dumb_ptr<block_list> bl) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int batk = 1; nullpo_retr(1, bl); @@ -442,7 +442,7 @@ int battle_get_baseatk(dumb_ptr<block_list> bl) static int battle_get_atk(dumb_ptr<block_list> bl) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int atk = 0; nullpo_ret(bl); @@ -518,7 +518,7 @@ int battle_get_atk_2(dumb_ptr<block_list> bl) static int battle_get_matk1(dumb_ptr<block_list> bl) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); sc_data = battle_get_sc_data(bl); if (bl->bl_type == BL::MOB) @@ -563,7 +563,7 @@ int battle_get_matk2(dumb_ptr<block_list> bl) */ int battle_get_def(dumb_ptr<block_list> bl) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int def = 0; nullpo_ret(bl); @@ -599,7 +599,7 @@ int battle_get_def(dumb_ptr<block_list> bl) */ int battle_get_mdef(dumb_ptr<block_list> bl) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int mdef = 0; nullpo_ret(bl); @@ -634,7 +634,7 @@ int battle_get_mdef(dumb_ptr<block_list> bl) */ int battle_get_def2(dumb_ptr<block_list> bl) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int def2 = 1; nullpo_retr(1, bl); @@ -715,7 +715,7 @@ interval_t battle_get_adelay(dumb_ptr<block_list> bl) return bl->is_player()->aspd * 2; else { - eptr<struct status_change, StatusChange> sc_data = battle_get_sc_data(bl); + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data = battle_get_sc_data(bl); interval_t adelay = std::chrono::seconds(4); int aspd_rate = 100; if (bl->bl_type == BL::MOB) @@ -743,7 +743,7 @@ interval_t battle_get_amotion(dumb_ptr<block_list> bl) return bl->is_player()->amotion; else { - eptr<struct status_change, StatusChange> sc_data = battle_get_sc_data(bl); + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data = battle_get_sc_data(bl); interval_t amotion = std::chrono::seconds(2); int aspd_rate = 100; if (bl->bl_type == BL::MOB) @@ -846,7 +846,7 @@ int battle_get_stat(SP stat_id, dumb_ptr<block_list> bl) } // StatusChange系の所得 -eptr<struct status_change, StatusChange> battle_get_sc_data(dumb_ptr<block_list> bl) +eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> battle_get_sc_data(dumb_ptr<block_list> bl) { nullpo_retr(nullptr, bl); @@ -1064,7 +1064,7 @@ struct Damage battle_calc_mob_weapon_attack(dumb_ptr<block_list> src, BF flag; int ac_flag = 0; ATK dmg_lv = ATK::ZERO; - eptr<struct status_change, StatusChange> sc_data, t_sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data, t_sc_data; nullpo_retr(wd, src); nullpo_retr(wd, target); @@ -1337,7 +1337,7 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, int div_; BF flag; ATK dmg_lv = ATK::ZERO; - eptr<struct status_change, StatusChange> sc_data, t_sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data, t_sc_data; int atkmax_ = 0, atkmin_ = 0; //二刀流用 int watk, watk_; bool da = false; @@ -1959,7 +1959,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, tick_t tick) { dumb_ptr<map_session_data> sd = NULL; - eptr<struct status_change, StatusChange> t_sc_data = battle_get_sc_data(target); + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> t_sc_data = battle_get_sc_data(target); struct Damage wd; nullpo_retr(ATK::ZERO, src); diff --git a/src/map/battle.hpp b/src/map/battle.hpp index fd452e8..5c62785 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -78,7 +78,7 @@ Race battle_get_race(dumb_ptr<block_list> bl); MobMode battle_get_mode(dumb_ptr<block_list> bl); int battle_get_stat(SP stat_id, dumb_ptr<block_list> bl); -eptr<struct status_change, StatusChange> battle_get_sc_data(dumb_ptr<block_list> bl); +eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> battle_get_sc_data(dumb_ptr<block_list> bl); short *battle_get_sc_count(dumb_ptr<block_list> bl); Opt1 *battle_get_opt1(dumb_ptr<block_list> bl); Opt2 *battle_get_opt2(dumb_ptr<block_list> bl); diff --git a/src/map/clif.cpp b/src/map/clif.cpp index a5b02cd..3290013 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -2021,7 +2021,7 @@ int clif_misceffect(dumb_ptr<block_list> bl, int type) int clif_changeoption(dumb_ptr<block_list> bl) { uint8_t buf[32]; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); @@ -2435,7 +2435,7 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, int div, DamageType type, int damage2) { unsigned char buf[256]; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(src); nullpo_ret(dst); @@ -2800,7 +2800,7 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, int div, SkillID skill_id, int skill_lv, int type) { unsigned char buf[64]; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(src); nullpo_ret(dst); diff --git a/src/map/clif.hpp b/src/map/clif.hpp index c346f7d..571f68e 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -7,8 +7,6 @@ # include "../strings/fwd.hpp" -# include "../generic/const_array.hpp" - # include "../mmo/ip.hpp" # include "../mmo/timer.t.hpp" diff --git a/src/map/intif.cpp b/src/map/intif.cpp index 7f7be73..b2b95fe 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -104,6 +104,7 @@ void intif_saveaccountreg(dumb_ptr<map_session_data> sd) int j, p; nullpo_retv(sd); + assert (sd->status.account_reg_num < ACCOUNT_REG_NUM); WFIFOW(char_session, 0) = 0x3004; WFIFOL(char_session, 4) = sd->bl_id; diff --git a/src/map/intif.hpp b/src/map/intif.hpp index ac2740c..7028ed9 100644 --- a/src/map/intif.hpp +++ b/src/map/intif.hpp @@ -3,8 +3,6 @@ # include "../strings/fwd.hpp" -# include "../generic/const_array.hpp" - # include "map.hpp" int intif_parse(Session *); diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp index 0783dc8..4de2f81 100644 --- a/src/map/magic-expr-eval.hpp +++ b/src/map/magic-expr-eval.hpp @@ -1,6 +1,8 @@ #ifndef TMWA_MAP_MAGIC_EXPR_EVAL_HPP #define TMWA_MAP_MAGIC_EXPR_EVAL_HPP +# include "../range/slice.hpp" + # include "../strings/zstring.hpp" # include "magic-interpreter.hpp" @@ -8,7 +10,7 @@ /* Helper definitions for dealing with functions and operations */ int magic_signature_check(ZString opname, ZString funname, ZString signature, - int args_nr, val_t *args, int line, int column); + Slice<val_t> args, int line, int column); void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, area_t& area); diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp index 1be1b0b..1881afc 100644 --- a/src/map/magic-expr.cpp +++ b/src/map/magic-expr.cpp @@ -261,7 +261,7 @@ void make_spell(val_t *v) } static -int fun_add(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_add(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARG_TYPE(0) == TYPE::INT && ARG_TYPE(1) == TYPE::INT) { @@ -296,21 +296,21 @@ int fun_add(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_sub(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_sub(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) - ARGINT(1); return 0; } static -int fun_mul(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_mul(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) * ARGINT(1); return 0; } static -int fun_div(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_div(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (!ARGINT(1)) return 1; /* division by zero */ @@ -319,7 +319,7 @@ int fun_div(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_mod(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_mod(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (!ARGINT(1)) return 1; /* division by zero */ @@ -328,35 +328,35 @@ int fun_mod(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_or(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_or(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) || ARGINT(1); return 0; } static -int fun_and(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_and(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) && ARGINT(1); return 0; } static -int fun_not(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_not(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = !ARGINT(0); return 0; } static -int fun_neg(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_neg(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ~ARGINT(0); return 0; } static -int fun_gte(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_gte(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING) { @@ -374,7 +374,7 @@ int fun_gte(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_lt(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) +int fun_lt(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args) { fun_gte(env, result, args); RESULTINT = !RESULTINT; @@ -382,7 +382,7 @@ int fun_lt(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) } static -int fun_gt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_gt(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING) { @@ -400,7 +400,7 @@ int fun_gt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_lte(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) +int fun_lte(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args) { fun_gt(env, result, args); RESULTINT = !RESULTINT; @@ -408,7 +408,7 @@ int fun_lte(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) } static -int fun_eq(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_eq(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING) { @@ -440,7 +440,7 @@ int fun_eq(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_ne(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) +int fun_ne(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args) { fun_eq(env, result, args); RESULTINT = !RESULTINT; @@ -448,56 +448,56 @@ int fun_ne(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) } static -int fun_bitand(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_bitand(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) & ARGINT(1); return 0; } static -int fun_bitor(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_bitor(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) | ARGINT(1); return 0; } static -int fun_bitxor(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_bitxor(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) ^ ARGINT(1); return 0; } static -int fun_bitshl(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_bitshl(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) << ARGINT(1); return 0; } static -int fun_bitshr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_bitshr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGINT(0) >> ARGINT(1); return 0; } static -int fun_max(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_max(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = max(ARGINT(0), ARGINT(1)); return 0; } static -int fun_min(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_min(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = min(ARGINT(0), ARGINT(1)); return 0; } static -int fun_if_then_else(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_if_then_else(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARGINT(0)) magic_copy_var(result, &args[1]); @@ -606,7 +606,7 @@ int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) } static -int fun_is_in(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_is_in(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = magic_location_in_area(ARGLOCATION(0).m, ARGLOCATION(0).x, @@ -615,7 +615,7 @@ int fun_is_in(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_skill(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_skill(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ENTITY_TYPE(0) != BL::PC // don't convert to enum until after the range check @@ -633,18 +633,18 @@ int fun_skill(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_his_shroud(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_his_shroud(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->state.shroud_active); return 0; } -#define BATTLE_GETTER(name) \ -static \ -int fun_get_##name(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) \ -{ \ - RESULTINT = battle_get_##name(ARGENTITY(0)); \ - return 0; \ +#define BATTLE_GETTER(name) \ +static \ +int fun_get_##name(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) \ +{ \ + RESULTINT = battle_get_##name(ARGENTITY(0)); \ + return 0; \ } BATTLE_GETTER(str) @@ -659,28 +659,28 @@ BATTLE_GETTER(mdef) BATTLE_GETTER(def) BATTLE_GETTER(max_hp) static -int fun_get_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_get_dir(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTDIR = battle_get_dir(ARGENTITY(0)); return 0; } -#define MMO_GETTER(name) \ -static \ -int fun_get_##name(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) \ -{ \ - if (ENTITY_TYPE(0) == BL::PC) \ - RESULTINT = ARGPC(0)->status.name; \ - else \ - RESULTINT = 0; \ - return 0; \ +#define MMO_GETTER(name) \ +static \ +int fun_get_##name(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) \ +{ \ + if (ENTITY_TYPE(0) == BL::PC) \ + RESULTINT = ARGPC(0)->status.name; \ + else \ + RESULTINT = 0; \ + return 0; \ } MMO_GETTER(sp) MMO_GETTER(max_sp) static -int fun_name_of(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_name_of(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARG_TYPE(0) == TYPE::ENTITY) { @@ -702,7 +702,7 @@ int fun_name_of(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) /* [Freeyorp] I'm putting this one in as name_of seems to have issues with summoned or spawned mobs. */ static -int fun_mob_id(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_mob_id(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ENTITY_TYPE(0) != BL::MOB) return 1; @@ -727,14 +727,14 @@ void COPY_LOCATION(location_t& dest, block_list& src) } static -int fun_location(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_location(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { COPY_LOCATION(RESULTLOCATION, *(ARGENTITY(0))); return 0; } static -int fun_random(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_random(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { int delta = ARGINT(0); if (delta < 0) @@ -752,7 +752,7 @@ int fun_random(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_random_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_random_dir(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARGINT(0)) RESULTDIR = random_::choice({DIR::S, DIR::SW, DIR::W, DIR::NW, DIR::N, DIR::NE, DIR::E, DIR::SE}); @@ -762,14 +762,14 @@ int fun_random_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_hash_entity(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_hash_entity(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARGENTITY(0)->bl_id; return 0; } int // ret -1: not a string, ret 1: no such item, ret 0: OK -magic_find_item(const_array<val_t> args, int index, struct item *item_, int *stackable) +magic_find_item(Slice<val_t> args, int index, struct item *item_, int *stackable) { struct item_data *item_data; int must_add_sequentially; @@ -801,7 +801,7 @@ magic_find_item(const_array<val_t> args, int index, struct item *item_, int *sta } static -int fun_count_item(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_count_item(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; int stackable; @@ -817,7 +817,7 @@ int fun_count_item(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_is_equipped(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_is_equipped(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; int stackable; @@ -843,28 +843,28 @@ int fun_is_equipped(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_is_married(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_is_married(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->status.partner_id); return 0; } static -int fun_is_dead(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_is_dead(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC && pc_isdead(ARGPC(0))); return 0; } static -int fun_is_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_is_pc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC); return 0; } static -int fun_partner(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_partner(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->status.partner_id) { @@ -877,7 +877,7 @@ int fun_partner(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_awayfrom(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_awayfrom(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { location_t *loc = &ARGLOCATION(0); int dx = dirx[ARGDIR(1)]; @@ -896,14 +896,14 @@ int fun_awayfrom(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_failed(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_failed(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = ARG_TYPE(0) == TYPE::FAIL; return 0; } static -int fun_npc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_npc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { NpcName name = stringish<NpcName>(ARGSTR(0)); RESULTENTITY = npc_name2id(name); @@ -911,7 +911,7 @@ int fun_npc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_pc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { CharName name = stringish<CharName>(ARGSTR(0)); RESULTENTITY = map_nick2sd(name); @@ -919,7 +919,7 @@ int fun_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_distance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_distance(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARGLOCATION(0).m != ARGLOCATION(1).m) RESULTINT = 0x7fffffff; @@ -930,7 +930,7 @@ int fun_distance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_rdistance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_rdistance(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ARGLOCATION(0).m != ARGLOCATION(1).m) RESULTINT = 0x7fffffff; @@ -944,7 +944,7 @@ int fun_rdistance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_anchor(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) +int fun_anchor(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args) { dumb_ptr<teleport_anchor_t> anchor = magic_find_anchor(ARGSTR(0)); @@ -964,7 +964,7 @@ int fun_anchor(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) } static -int fun_line_of_sight(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_line_of_sight(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { block_list e1, e2; @@ -1020,14 +1020,14 @@ void magic_random_location(location_t *dest, dumb_ptr<area_t> area) } static -int fun_pick_location(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_pick_location(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { magic_random_location(&result->v.v_location, ARGAREA(0)); return 0; } static -int fun_read_script_int(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_read_script_int(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { dumb_ptr<block_list> subject_p = ARGENTITY(0); VarName var_name = stringish<VarName>(ARGSTR(1)); @@ -1041,7 +1041,7 @@ int fun_read_script_int(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_read_script_str(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_read_script_str(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { dumb_ptr<block_list> subject_p = ARGENTITY(0); VarName var_name = stringish<VarName>(ARGSTR(1)); @@ -1055,7 +1055,7 @@ int fun_read_script_str(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_rbox(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_rbox(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { location_t loc = ARGLOCATION(0); int radius = ARGINT(1); @@ -1071,7 +1071,7 @@ int fun_rbox(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_running_status_update(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_running_status_update(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { if (ENTITY_TYPE(0) != BL::PC && ENTITY_TYPE(0) != BL::MOB) return 1; @@ -1082,28 +1082,28 @@ int fun_running_status_update(dumb_ptr<env_t>, val_t *result, const_array<val_t> } static -int fun_status_option(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_status_option(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = (bool((ARGPC(0))->status.option & static_cast<Option>(ARGINT(1)))); return 0; } static -int fun_element(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_element(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = static_cast<int>(battle_get_element(ARGENTITY(0)).element); return 0; } static -int fun_element_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_element_level(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = battle_get_element(ARGENTITY(0)).level; return 0; } static -int fun_is_exterior(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_is_exterior(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { #warning "Evil assumptions!" RESULTINT = ARGLOCATION(0).m->name_[4] == '1'; @@ -1111,14 +1111,14 @@ int fun_is_exterior(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_contains_string(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_contains_string(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = NULL != strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); return 0; } static -int fun_strstr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_strstr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { const char *offset = strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); RESULTINT = offset - ARGSTR(0).c_str(); @@ -1126,14 +1126,14 @@ int fun_strstr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_strlen(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_strlen(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = strlen(ARGSTR(0).c_str()); return 0; } static -int fun_substr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_substr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { const char *src = ARGSTR(0).c_str(); const int slen = strlen(src); @@ -1159,14 +1159,14 @@ int fun_substr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_sqrt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_sqrt(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { RESULTINT = static_cast<int>(sqrt(ARGINT(0))); return 0; } static -int fun_map_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_map_level(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { #warning "Evil assumptions!" RESULTINT = ARGLOCATION(0).m->name_[4] - '0'; @@ -1174,7 +1174,7 @@ int fun_map_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_map_nr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_map_nr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { #warning "Evil assumptions!" MapName mapname = ARGLOCATION(0).m->name_; @@ -1185,7 +1185,7 @@ int fun_map_nr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_dir_towards(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_dir_towards(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { int dx; int dy; @@ -1251,7 +1251,7 @@ int fun_dir_towards(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) } static -int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) +int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) { dumb_ptr<map_session_data> sd = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -1526,10 +1526,10 @@ TYPE type_key(char ty_key) } int magic_signature_check(ZString opname, ZString funname, ZString signature, - int args_nr, val_t *args, int line, int column) + Slice<val_t> args, int line, int column) { int i; - for (i = 0; i < args_nr; i++) + for (i = 0; i < args.size(); i++) { val_t *arg = &args[i]; char ty_key = signature[i]; @@ -1553,8 +1553,8 @@ int magic_signature_check(ZString opname, ZString funname, ZString signature, if (!ty_key) { FPRINTF(stderr, - "[magic-eval]: L%d:%d: Too many arguments (%d) to %s `%s'\n", - line, column, args_nr, opname, funname); + "[magic-eval]: L%d:%d: Too many arguments (%zu) to %s `%s'\n", + line, column, args.size(), opname, funname); return 1; } @@ -1640,9 +1640,9 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) for (i = 0; i < args_nr; ++i) magic_eval(env, &arguments[i], expr->e.e_funapp.args[i]); - if (magic_signature_check("function", f->name, f->signature, args_nr, arguments, + if (magic_signature_check("function", f->name, f->signature, Slice<val_t>(arguments, args_nr), expr->e.e_funapp.line_nr, expr->e.e_funapp.column) - || f->fun(env, dest, const_array<val_t>(arguments, args_nr))) + || f->fun(env, dest, Slice<val_t>(arguments, args_nr))) dest->ty = TYPE::FAIL; else { diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp index 79fdc3f..b2b0dd2 100644 --- a/src/map/magic-expr.hpp +++ b/src/map/magic-expr.hpp @@ -3,6 +3,8 @@ # include "magic-interpreter.hpp" +# include "../range/slice.hpp" + # include "../strings/fwd.hpp" # include "../strings/zstring.hpp" @@ -24,14 +26,14 @@ struct fun_t ZString name; ZString signature; char ret_ty; - int (*fun)(dumb_ptr<env_t> env, val_t *result, const_array<val_t> arga); + int (*fun)(dumb_ptr<env_t> env, val_t *result, Slice<val_t> arga); }; struct op_t { ZString name; ZString signature; - int (*op)(dumb_ptr<env_t> env, const_array<val_t> arga); + int (*op)(dumb_ptr<env_t> env, Slice<val_t> arga); }; /** @@ -72,7 +74,7 @@ void magic_copy_var(val_t *dest, val_t *src); void magic_random_location(location_t *dest, dumb_ptr<area_t> area); // ret -1: not a string, ret 1: no such item, ret 0: OK -int magic_find_item(const_array<val_t> args, int index, struct item *item, int *stackable); +int magic_find_item(Slice<val_t> args, int index, struct item *item, int *stackable); # define GET_ARG_ITEM(index, dest, stackable) \ switch (magic_find_item(args, index, &dest, &stackable)) \ diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index 4063a68..081651c 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -298,7 +298,7 @@ dumb_ptr<npc_data> local_spell_effect(map_local *m, int x, int y, int effect, } static -int op_sfx(dumb_ptr<env_t>, const_array<val_t> args) +int op_sfx(dumb_ptr<env_t>, Slice<val_t> args) { interval_t delay = static_cast<interval_t>(ARGINT(2)); @@ -319,7 +319,7 @@ int op_sfx(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_instaheal(dumb_ptr<env_t> env, const_array<val_t> args) +int op_instaheal(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> caster = (env->VAR(VAR_CASTER).ty == TYPE::ENTITY) ? map_id2bl(env->VAR(VAR_CASTER).v.v_int) : NULL; @@ -340,7 +340,7 @@ int op_instaheal(dumb_ptr<env_t> env, const_array<val_t> args) } static -int op_itemheal(dumb_ptr<env_t> env, const_array<val_t> args) +int op_itemheal(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); if (subject->bl_type == BL::PC) @@ -370,7 +370,7 @@ using e::Shroud; #define ARGCHAR(n) (ARGENTITY(n)->is_player()) static -int op_shroud(dumb_ptr<env_t>, const_array<val_t> args) +int op_shroud(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> subject = ARGCHAR(0); Shroud arg = static_cast<Shroud>(ARGINT(1)); @@ -389,7 +389,7 @@ int op_shroud(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_reveal(dumb_ptr<env_t>, const_array<val_t> args) +int op_reveal(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> subject = ARGCHAR(0); @@ -400,7 +400,7 @@ int op_reveal(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_message(dumb_ptr<env_t>, const_array<val_t> args) +int op_message(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> subject = ARGCHAR(0); @@ -419,7 +419,7 @@ void timer_callback_kill_npc(TimerData *, tick_t, int npc_id) } static -int op_messenger_npc(dumb_ptr<env_t>, const_array<val_t> args) +int op_messenger_npc(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<npc_data> npc; location_t *loc = &ARGLOCATION(0); @@ -476,7 +476,7 @@ void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int d } static -int op_move(dumb_ptr<env_t>, const_array<val_t> args) +int op_move(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); DIR dir = ARGDIR(1); @@ -491,7 +491,7 @@ int op_move(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_warp(dumb_ptr<env_t>, const_array<val_t> args) +int op_warp(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); location_t *loc = &ARGLOCATION(1); @@ -502,7 +502,7 @@ int op_warp(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_banish(dumb_ptr<env_t>, const_array<val_t> args) +int op_banish(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); @@ -529,7 +529,7 @@ void record_status_change(dumb_ptr<invocation> invocation_, int bl_id, } static -int op_status_change(dumb_ptr<env_t> env, const_array<val_t> args) +int op_status_change(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); int invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION @@ -550,7 +550,7 @@ int op_status_change(dumb_ptr<env_t> env, const_array<val_t> args) } static -int op_stop_status_change(dumb_ptr<env_t>, const_array<val_t> args) +int op_stop_status_change(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); @@ -561,7 +561,7 @@ int op_stop_status_change(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_override_attack(dumb_ptr<env_t> env, const_array<val_t> args) +int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> psubject = ARGENTITY(0); int charges = ARGINT(1); @@ -602,7 +602,7 @@ int op_override_attack(dumb_ptr<env_t> env, const_array<val_t> args) } static -int op_create_item(dumb_ptr<env_t>, const_array<val_t> args) +int op_create_item(dumb_ptr<env_t>, Slice<val_t> args) { struct item item; dumb_ptr<block_list> entity = ARGENTITY(0); @@ -640,7 +640,7 @@ bool AGGRAVATION_MODE_MAKES_AGGRESSIVE(int n) } static -int op_aggravate(dumb_ptr<env_t>, const_array<val_t> args) +int op_aggravate(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<block_list> victim = ARGENTITY(2); int mode = ARGINT(1); @@ -675,7 +675,7 @@ enum class MonsterAttitude }; static -int op_spawn(dumb_ptr<env_t>, const_array<val_t> args) +int op_spawn(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<area_t> area = ARGAREA(0); dumb_ptr<block_list> owner_e = ARGENTITY(1); @@ -766,7 +766,7 @@ const char *get_invocation_name(dumb_ptr<env_t> env) } static -int op_injure(dumb_ptr<env_t> env, const_array<val_t> args) +int op_injure(dumb_ptr<env_t> env, Slice<val_t> args) { dumb_ptr<block_list> caster = ARGENTITY(0); dumb_ptr<block_list> target = ARGENTITY(1); @@ -816,7 +816,7 @@ int op_injure(dumb_ptr<env_t> env, const_array<val_t> args) } static -int op_emote(dumb_ptr<env_t>, const_array<val_t> args) +int op_emote(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<block_list> victim = ARGENTITY(0); int emotion = ARGINT(1); @@ -826,7 +826,7 @@ int op_emote(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_set_script_variable(dumb_ptr<env_t>, const_array<val_t> args) +int op_set_script_variable(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; VarName varname = stringish<VarName>(ARGSTR(1)); @@ -841,7 +841,7 @@ int op_set_script_variable(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_set_script_str(dumb_ptr<env_t>, const_array<val_t> args) +int op_set_script_str(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; VarName varname = stringish<VarName>(ARGSTR(1)); @@ -856,7 +856,7 @@ int op_set_script_str(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_set_hair_colour(dumb_ptr<env_t>, const_array<val_t> args) +int op_set_hair_colour(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -869,7 +869,7 @@ int op_set_hair_colour(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_set_hair_style(dumb_ptr<env_t>, const_array<val_t> args) +int op_set_hair_style(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -882,7 +882,7 @@ int op_set_hair_style(dumb_ptr<env_t>, const_array<val_t> args) } static -int op_drop_item_for (dumb_ptr<env_t>, const_array<val_t> args) +int op_drop_item_for (dumb_ptr<env_t>, Slice<val_t> args) { struct item item; int stackable; @@ -908,7 +908,7 @@ int op_drop_item_for (dumb_ptr<env_t>, const_array<val_t> args) } static -int op_gain_exp(dumb_ptr<env_t>, const_array<val_t> args) +int op_gain_exp(dumb_ptr<env_t>, Slice<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -1468,7 +1468,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) int newpos = run_script_l( ScriptPointer(&*e->e.e_script, invocation_->script_pos), message_recipient, invocation_->bl_id, - 3, arg); + arg); /* Returns the new script position, or -1 once the script is finished */ if (newpos != -1) { @@ -1498,10 +1498,10 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) magic_eval(invocation_->env, &args[i], e->e.e_op.args[i]); if (!magic_signature_check("effect", op->name, op->signature, - e->e.e_op.args_nr, args, + Slice<val_t>(args, e->e.e_op.args_nr), e->e.e_op.line_nr, e->e.e_op.column)) - op->op(invocation_->env, const_array<val_t>(args, e->e.e_op.args_nr)); + op->op(invocation_->env, Slice<val_t>(args, e->e.e_op.args_nr)); for (i = 0; i < e->e.e_op.args_nr; i++) magic_clear_var(&args[i]); diff --git a/src/map/magic-v2.cpp b/src/map/magic-v2.cpp index 1fad61d..41d29cd 100644 --- a/src/map/magic-v2.cpp +++ b/src/map/magic-v2.cpp @@ -254,7 +254,7 @@ namespace magic_v2 return true; } static - bool op_effect(io::LineSpan span, ZString name, const_array<dumb_ptr<expr_t>> argv, dumb_ptr<effect_t>& effect) + bool op_effect(io::LineSpan span, ZString name, Slice<dumb_ptr<expr_t>> argv, dumb_ptr<effect_t>& effect) { op_t *op = magic_get_op(name); if (!op) @@ -290,7 +290,7 @@ namespace magic_v2 return retval; } static - bool fun_expr(io::LineSpan span, ZString name, const_array<dumb_ptr<expr_t>> argv, dumb_ptr<expr_t>& expr) + bool fun_expr(io::LineSpan span, ZString name, Slice<dumb_ptr<expr_t>> argv, dumb_ptr<expr_t>& expr) { fun_t *fun = magic_get_fun(name); if (!fun) @@ -322,7 +322,7 @@ namespace magic_v2 e[0] = left; e[1] = right; dumb_ptr<expr_t> rv; - if (!fun_expr(span, name, const_array<dumb_ptr<expr_t>>(e, 2), rv)) + if (!fun_expr(span, name, e, rv)) abort(); return rv; } diff --git a/src/map/map.cpp b/src/map/map.cpp index e5a3341..f701730 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -72,7 +72,7 @@ Map<int, struct charid2nick> charid_db; static int users = 0; static -dumb_ptr<block_list> object[MAX_FLOORITEM]; +Array<dumb_ptr<block_list>, MAX_FLOORITEM> object; static int first_free_object_id = 0, last_object_id = 0; @@ -546,6 +546,7 @@ int map_addobject(dumb_ptr<block_list> bl) */ int map_delobjectnofree(int id, BL type) { + assert (id < MAX_FLOORITEM); if (!object[id]) return 0; @@ -581,6 +582,7 @@ int map_delobjectnofree(int id, BL type) */ int map_delobject(int id, BL type) { + assert (id < MAX_FLOORITEM); dumb_ptr<block_list> obj = object[id]; if (obj == NULL) @@ -603,6 +605,7 @@ int map_delobject(int id, BL type) void map_foreachobject(std::function<void(dumb_ptr<block_list>)> func, BL type) { + assert (last_object_id < MAX_FLOORITEM); std::vector<dumb_ptr<block_list>> bl_list; for (int i = 2; i <= last_object_id; i++) { @@ -634,6 +637,7 @@ void map_foreachobject(std::function<void(dumb_ptr<block_list>)> func, */ void map_clearflooritem_timer(TimerData *tid, tick_t, int id) { + assert (id < MAX_FLOORITEM); dumb_ptr<block_list> obj = object[id]; assert (obj && obj->bl_type == BL::ITEM); dumb_ptr<flooritem_data> fitem = obj->is_item(); @@ -1669,48 +1673,49 @@ bool map_confs(XString key, ZString value) * Map-Server Init and Command-line Arguments [Valaris] *------------------------------------------------------ */ -int do_init(int argc, ZString *argv) +int do_init(Slice<ZString> argv) { + ZString argv0 = argv.pop_front(); runflag &= magic_init0(); bool loaded_config_yet = false; - for (int i = 1; i < argc; ++i) + while (argv) { - if (argv[i].startswith('-')) + ZString argvi = argv.pop_front(); + if (argvi.startswith('-')) { - if (argv[i] == "--help") + if (argvi == "--help") { PRINTF("Usage: %s [--help] [--version] [--write_atcommand_config outfile] [files...]\n", - argv[0]); + argv0); exit(0); } - else if (argv[i] == "--version") + else if (argvi == "--version") { PRINTF("%s\n", CURRENT_VERSION_STRING); exit(0); } - else if (argv[i] == "--write-atcommand-config") + else if (argvi == "--write-atcommand-config") { - ++i; - if (i == argc) + if (!argv) { PRINTF("Missing argument\n"); exit(1); } - ZString filename = argv[i]; + ZString filename = argv.pop_front(); atcommand_config_write(filename); exit(0); } else { - FPRINTF(stderr, "Unknown argument: %s\n", argv[i]); + FPRINTF(stderr, "Unknown argument: %s\n", argvi); runflag = false; } } else { loaded_config_yet = true; - runflag &= load_config_file(argv[i], map_confs); + runflag &= load_config_file(argvi, map_confs); } } diff --git a/src/map/map.hpp b/src/map/map.hpp index 0f9f3d1..cb57c6b 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -113,7 +113,7 @@ public: struct walkpath_data { unsigned char path_len, path_pos, path_half; - DIR path[MAX_WALKPATH]; + Array<DIR, MAX_WALKPATH> path; }; struct status_change { @@ -173,7 +173,7 @@ struct map_session_data : block_list, SessionData unsigned char tmw_version; // tmw client version CharKey status_key; CharData status; - struct item_data *inventory_data[MAX_INVENTORY]; + Array<struct item_data *, MAX_INVENTORY> inventory_data; earray<short, EQUIP, EQUIP::COUNT> equip_index; int weight, max_weight; MapName mapname_; @@ -275,8 +275,8 @@ struct map_session_data : block_list, SessionData short sc_count; int trade_partner; - int deal_item_index[10]; - int deal_item_amount[10]; + Array<int, TRADE_MAX> deal_item_index; + Array<int, TRADE_MAX> deal_item_amount; int deal_zeny; short deal_locked; @@ -292,7 +292,7 @@ struct map_session_data : block_list, SessionData int pvp_lastusers; std::list<NpcEvent> eventqueuel; - Timer eventtimer[MAX_EVENTTIMER]; + Array<Timer, MAX_EVENTTIMER> eventtimer; struct { @@ -349,7 +349,7 @@ struct npc_data : block_list short flag; std::list<RString> eventqueuel; - Timer eventtimer[MAX_EVENTTIMER]; + Array<Timer, MAX_EVENTTIMER> eventtimer; short arenaflag; private: @@ -517,13 +517,7 @@ struct map_local : map_abstract MapFlags flag; struct point save; struct point resave; - dumb_ptr<npc_data> npc[MAX_NPC_PER_MAP]; - struct - { - int drop_id; - int drop_type; - int drop_per; - } drop_list[MAX_DROP_PER_MAP]; + Array<dumb_ptr<npc_data>, MAX_NPC_PER_MAP> npc; }; struct map_remote : map_abstract @@ -535,6 +529,8 @@ struct map_remote : map_abstract inline MapCell read_gatp(map_local *m, int x, int y) { + assert (0 <= x && x < m->xs); + assert (0 <= y && y < m->ys); return m->gat[x + y * m->xs]; } diff --git a/src/map/mapflag.cpp b/src/map/mapflag.cpp index 097f4d1..51af30a 100644 --- a/src/map/mapflag.cpp +++ b/src/map/mapflag.cpp @@ -40,41 +40,41 @@ bool extract<MapFlag, void, void>(XString str, MapFlag *mf) { const struct { - char str[32]; + ZString str; MapFlag id; } flags[] = { - //{"alias", MapFlag::ALIAS}, - //{"nomemo", MapFlag::NOMEMO}, - {"noteleport", MapFlag::NOTELEPORT}, - {"noreturn", MapFlag::NORETURN}, - {"monster_noteleport", MapFlag::MONSTER_NOTELEPORT}, - {"nosave", MapFlag::NOSAVE}, - //{"nobranch", MapFlag::NOBRANCH}, - {"nopenalty", MapFlag::NOPENALTY}, - {"pvp", MapFlag::PVP}, - {"pvp_noparty", MapFlag::PVP_NOPARTY}, - //{"pvp_noguild", MapFlag::PVP_NOGUILD}, - //{"pvp_nightmaredrop", MapFlag::PVP_NIGHTMAREDROP}, - {"pvp_nocalcrank", MapFlag::PVP_NOCALCRANK}, - //{"gvg", MapFlag::GVG}, - //{"gvg_noparty", MapFlag::GVG_NOPARTY}, - //{"nozenypenalty", MapFlag::NOZENYPENALTY}, - //{"notrade", MapFlag::NOTRADE}, - //{"noskill", MapFlag::NOSKILL}, - {"nowarp", MapFlag::NOWARP}, - {"nowarpto", MapFlag::NOWARPTO}, - {"nopvp", MapFlag::NOPVP}, - //{"noicewall", MapFlag::NOICEWALL}, - {"snow", MapFlag::SNOW}, - {"fog", MapFlag::FOG}, - {"sakura", MapFlag::SAKURA}, - {"leaves", MapFlag::LEAVES}, - {"rain", MapFlag::RAIN}, - {"no_player_drops", MapFlag::NO_PLAYER_DROPS}, - {"town", MapFlag::TOWN}, - {"outside", MapFlag::OUTSIDE}, - {"resave", MapFlag::RESAVE}, + //{ZString("alias"), MapFlag::ALIAS}, + //{ZString("nomemo"), MapFlag::NOMEMO}, + {ZString("noteleport"), MapFlag::NOTELEPORT}, + {ZString("noreturn"), MapFlag::NORETURN}, + {ZString("monster_noteleport"), MapFlag::MONSTER_NOTELEPORT}, + {ZString("nosave"), MapFlag::NOSAVE}, + //{ZString("nobranch"), MapFlag::NOBRANCH}, + {ZString("nopenalty"), MapFlag::NOPENALTY}, + {ZString("pvp"), MapFlag::PVP}, + {ZString("pvp_noparty"), MapFlag::PVP_NOPARTY}, + //{ZString("pvp_noguild"), MapFlag::PVP_NOGUILD}, + //{ZString("pvp_nightmaredrop"), MapFlag::PVP_NIGHTMAREDROP}, + {ZString("pvp_nocalcrank"), MapFlag::PVP_NOCALCRANK}, + //{ZString("gvg"), MapFlag::GVG}, + //{ZString("gvg_noparty"), MapFlag::GVG_NOPARTY}, + //{ZString("nozenypenalty"), MapFlag::NOZENYPENALTY}, + //{ZString("notrade"), MapFlag::NOTRADE}, + //{ZString("noskill"), MapFlag::NOSKILL}, + {ZString("nowarp"), MapFlag::NOWARP}, + {ZString("nowarpto"), MapFlag::NOWARPTO}, + {ZString("nopvp"), MapFlag::NOPVP}, + //{ZString("noicewall"), MapFlag::NOICEWALL}, + {ZString("snow"), MapFlag::SNOW}, + {ZString("fog"), MapFlag::FOG}, + {ZString("sakura"), MapFlag::SAKURA}, + {ZString("leaves"), MapFlag::LEAVES}, + {ZString("rain"), MapFlag::RAIN}, + {ZString("no_player_drops"), MapFlag::NO_PLAYER_DROPS}, + {ZString("town"), MapFlag::TOWN}, + {ZString("outside"), MapFlag::OUTSIDE}, + {ZString("resave"), MapFlag::RESAVE}, }; for (auto& pair : flags) if (str == pair.str) diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 61dcfb6..c4a4304 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -1305,7 +1305,7 @@ int mob_can_reach(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int range) int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist) { dumb_ptr<map_session_data> sd; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; MobMode mode; nullpo_ret(md); @@ -3560,15 +3560,15 @@ bool extract<MobSkillCondition, void, void>(XString str, MobSkillCondition *msc) { const struct { - char str[32]; + ZString str; MobSkillCondition id; } cond1[] = { - {"always", MobSkillCondition::MSC_ALWAYS}, - {"myhpltmaxrate", MobSkillCondition::MSC_MYHPLTMAXRATE}, - {"notintown", MobSkillCondition::MSC_NOTINTOWN}, - {"slavelt", MobSkillCondition::MSC_SLAVELT}, - {"slavele", MobSkillCondition::MSC_SLAVELE}, + {ZString("always"), MobSkillCondition::MSC_ALWAYS}, + {ZString("myhpltmaxrate"), MobSkillCondition::MSC_MYHPLTMAXRATE}, + {ZString("notintown"), MobSkillCondition::MSC_NOTINTOWN}, + {ZString("slavelt"), MobSkillCondition::MSC_SLAVELT}, + {ZString("slavele"), MobSkillCondition::MSC_SLAVELE}, }; for (auto& pair : cond1) if (str == pair.str) @@ -3584,14 +3584,14 @@ bool extract<MobSkillState, void, void>(XString str, MobSkillState *mss) { const struct { - char str[32]; + ZString str; MobSkillState id; } state[] = { - {"any", MobSkillState::ANY}, - {"idle", MobSkillState::MSS_IDLE}, - {"walk", MobSkillState::MSS_WALK}, - {"attack", MobSkillState::MSS_ATTACK}, + {ZString("any"), MobSkillState::ANY}, + {ZString("idle"), MobSkillState::MSS_IDLE}, + {ZString("walk"), MobSkillState::MSS_WALK}, + {ZString("attack"), MobSkillState::MSS_ATTACK}, }; for (auto& pair : state) if (str == pair.str) @@ -3607,12 +3607,12 @@ bool extract<MobSkillTarget, void, void>(XString str, MobSkillTarget *mst) { const struct { - char str[32]; + ZString str; MobSkillTarget id; } target[] = { - {"target", MobSkillTarget::MST_TARGET}, - {"self", MobSkillTarget::MST_SELF}, + {ZString("target"), MobSkillTarget::MST_TARGET}, + {ZString("self"), MobSkillTarget::MST_SELF}, }; for (auto& pair : target) if (str == pair.str) diff --git a/src/map/npc.cpp b/src/map/npc.cpp index dd75691..514c042 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -200,7 +200,7 @@ void npc_timer_event(NpcEvent eventname) */ static void npc_event_doall_sub(NpcEvent key, struct event_data *ev, - int *c, ScriptLabel name, int rid, int argc, argrec_t *argv) + int *c, ScriptLabel name, int rid, Slice<argrec_t> argv) { ScriptLabel p = key.label; @@ -209,45 +209,45 @@ void npc_event_doall_sub(NpcEvent key, struct event_data *ev, if (name == p) { run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, - argc, argv); + argv); (*c)++; } } -int npc_event_doall_l(ScriptLabel name, int rid, int argc, argrec_t *args) +int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> args) { int c = 0; for (auto& pair : ev_db) - npc_event_doall_sub(pair.first, &pair.second, &c, name, rid, argc, args); + npc_event_doall_sub(pair.first, &pair.second, &c, name, rid, args); return c; } static void npc_event_do_sub(NpcEvent key, struct event_data *ev, - int *c, NpcEvent name, int rid, int argc, argrec_t *argv) + int *c, NpcEvent name, int rid, Slice<argrec_t> argv) { nullpo_retv(ev); if (name == key) { run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, - argc, argv); + argv); (*c)++; } } -int npc_event_do_l(NpcEvent name, int rid, int argc, argrec_t *args) +int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> args) { int c = 0; if (!name.npc) { - return npc_event_doall_l(name.label, rid, argc, args); + return npc_event_doall_l(name.label, rid, args); } for (auto& pair : ev_db) - npc_event_do_sub(pair.first, &pair.second, &c, name, rid, argc, args); + npc_event_do_sub(pair.first, &pair.second, &c, name, rid, args); return c; } diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 93f2030..8d2dc5b 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -51,17 +51,17 @@ void npc_delsrcfile(XString); bool do_init_npc(void); int npc_event_do_oninit(void); -int npc_event_doall_l(ScriptLabel name, int rid, int argc, struct argrec_t *argv); -int npc_event_do_l(NpcEvent name, int rid, int argc, struct argrec_t *argv); +int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> argv); +int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> argv); inline int npc_event_doall(ScriptLabel name) { - return npc_event_doall_l(name, 0, 0, NULL); + return npc_event_doall_l(name, 0, nullptr); } inline int npc_event_do(NpcEvent name) { - return npc_event_do_l(name, 0, 0, NULL); + return npc_event_do_l(name, 0, nullptr); } void npc_timerevent_start(dumb_ptr<npc_data_script> nd); diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 10c2b22..343e0fc 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -589,7 +589,7 @@ static int pc_isequip(dumb_ptr<map_session_data> sd, int n) { struct item_data *item; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; //転生や養子の場合の元の職業を算出する nullpo_ret(sd); @@ -1074,7 +1074,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) }; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, - 2, arg); + arg); } sd->state.lr_flag = 0; } @@ -1091,7 +1091,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->attackrange += sd->inventory_data[index]->range; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, - 2, arg); + arg); } } else if (sd->inventory_data[index]->type == ItemType::ARMOR) @@ -1104,7 +1104,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->watk += sd->inventory_data[index]->atk; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, - 2, arg); + arg); } } } @@ -1130,7 +1130,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->state.lr_flag = 2; run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, - 2, arg); + arg); sd->state.lr_flag = 0; sd->arrow_atk += sd->inventory_data[index]->atk; } @@ -2702,7 +2702,7 @@ void pc_attack_timer(TimerData *, tick_t tick, int id) { dumb_ptr<map_session_data> sd; dumb_ptr<block_list> bl; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int dist, range; sd = map_id2sd(id); @@ -3514,10 +3514,10 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, {"@victimrid", sd->bl_id}, {"@victimlvl", sd->status.base_level}, }; - npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"), sd->bl_id, 3, arg); - npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"), src->bl_id, 3, arg); + npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"), sd->bl_id, arg); + npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"), src->bl_id, arg); } - npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"), sd->bl_id, 0, NULL); + npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"), sd->bl_id, nullptr); return 0; } @@ -4084,6 +4084,7 @@ int pc_readglobalreg(dumb_ptr<map_session_data> sd, VarName reg) nullpo_ret(sd); + assert (sd->status.global_reg_num < GLOBAL_REG_NUM); for (i = 0; i < sd->status.global_reg_num; i++) { if (sd->status.global_reg[i].str == reg) @@ -4109,6 +4110,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, VarName reg, int val) sd->die_counter = val; pc_calcstatus(sd, 0); } + assert (sd->status.global_reg_num < GLOBAL_REG_NUM); if (val == 0) { for (i = 0; i < sd->status.global_reg_num; i++) @@ -4155,6 +4157,7 @@ int pc_readaccountreg(dumb_ptr<map_session_data> sd, VarName reg) nullpo_ret(sd); + assert (sd->status.account_reg_num < ACCOUNT_REG_NUM); for (i = 0; i < sd->status.account_reg_num; i++) { if (sd->status.account_reg[i].str == reg) diff --git a/src/map/script.cpp b/src/map/script.cpp index cbb6d96..18055b8 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -78,20 +78,20 @@ Map<ScriptLabel, int> scriptlabel_db; UPMap<RString, const ScriptBuffer> userfunc_db; static -const char *pos_str[11] = -{ - "Head", - "Body", - "Left hand", - "Right hand", - "Robe", - "Shoes", - "Accessory 1", - "Accessory 2", - "Head 2", - "Head 3", - "Not Equipped", -}; +Array<ZString, 11> pos_str //= +{{ + ZString("Head"), + ZString("Body"), + ZString("Left hand"), + ZString("Right hand"), + ZString("Robe"), + ZString("Shoes"), + ZString("Accessory 1"), + ZString("Accessory 2"), + ZString("Head 2"), + ZString("Head 3"), + ZString("Not Equipped"), +}}; static struct Script_Config @@ -2202,8 +2202,8 @@ void builtin_strcharinfo(ScriptState *st) // indexed by the equip_* in db/const.txt // TODO change to use EQUIP static -EPOS equip[11] = -{ +Array<EPOS, 11> equip //= +{{ EPOS::HAT, EPOS::MISC1, EPOS::SHIELD, @@ -2215,7 +2215,7 @@ EPOS equip[11] = EPOS::TORSO, EPOS::LEGS, EPOS::ARROW, -}; +}}; /*========================================== * GetEquipID(Pos); Pos: 1-10 @@ -4693,11 +4693,11 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) */ int run_script(ScriptPointer sp, int rid, int oid) { - return run_script_l(sp, rid, oid, 0, NULL); + return run_script_l(sp, rid, oid, nullptr); } int run_script_l(ScriptPointer sp, int rid, int oid, - int args_nr, argrec_t *args) + Slice<argrec_t> args) { struct script_stack stack; ScriptState st; @@ -4717,7 +4717,7 @@ int run_script_l(ScriptPointer sp, int rid, int oid, st.scriptp = sp; st.rid = rid; st.oid = oid; - for (i = 0; i < args_nr; i++) + for (i = 0; i < args.size(); i++) { if (args[i].name.back() == '$') pc_setregstr(sd, SIR::from(variable_names.intern(args[i].name)), args[i].v.s); diff --git a/src/map/script.hpp b/src/map/script.hpp index 8c072b3..ea087c2 100644 --- a/src/map/script.hpp +++ b/src/map/script.hpp @@ -6,6 +6,8 @@ # include <vector> +# include "../range/slice.hpp" + # include "../strings/rstring.hpp" # include "../strings/astring.hpp" # include "../strings/zstring.hpp" @@ -153,7 +155,7 @@ struct argrec_t argrec_t(ZString n, int i) : name(n), v(i) {} argrec_t(ZString n, ZString z) : name(n), v(z) {} }; -int run_script_l(ScriptPointer, int, int, int, argrec_t *args); +int run_script_l(ScriptPointer, int, int, Slice<argrec_t> args); int run_script(ScriptPointer, int, int); struct ScriptLabel; diff --git a/src/map/skill-pools.cpp b/src/map/skill-pools.cpp index 31998f8..2ac3a93 100644 --- a/src/map/skill-pools.cpp +++ b/src/map/skill-pools.cpp @@ -7,7 +7,7 @@ #include "../poison.hpp" -SkillID skill_pool_skills[MAX_POOL_SKILLS]; +Array<SkillID, MAX_POOL_SKILLS> skill_pool_skills; int skill_pool_skills_size = 0; void skill_pool_register(SkillID id) diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 72d7f7a..c29704a 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -232,7 +232,7 @@ int skill_attack(BF attack_type, dumb_ptr<block_list> src, SkillID skillid, int skilllv, tick_t tick, BCT flag) { struct Damage dmg; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int type, lv, damage; nullpo_ret(src); @@ -550,7 +550,7 @@ int skill_castend_nodamage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, interval_t skill_castfix(dumb_ptr<block_list> bl, interval_t interval) { dumb_ptr<mob_data> md; // [Valaris] - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int dex; int castrate = 100; SkillID skill; @@ -601,7 +601,7 @@ interval_t skill_castfix(dumb_ptr<block_list> bl, interval_t interval) */ interval_t skill_delayfix(dumb_ptr<block_list> bl, interval_t interval) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_retr(interval_t::zero(), bl); @@ -663,7 +663,7 @@ int skill_castcancel(dumb_ptr<block_list> bl, int) */ int skill_status_change_active(dumb_ptr<block_list> bl, StatusChange type) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; nullpo_ret(bl); if (bl->bl_type != BL::PC && bl->bl_type != BL::MOB) @@ -682,7 +682,7 @@ int skill_status_change_active(dumb_ptr<block_list> bl, StatusChange type) void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerData *tid) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; int opt_flag = 0, calc_flag = 0; short *sc_count; Option *option; @@ -806,7 +806,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange { dumb_ptr<block_list> bl; dumb_ptr<map_session_data> sd = NULL; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; //short *sc_count; //使ってない? if ((bl = map_id2bl(id)) == NULL) @@ -907,7 +907,7 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, interval_t tick, int spell_invocation) { dumb_ptr<map_session_data> sd = NULL; - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short *sc_count; Option *option; Opt1 *opt1; @@ -1081,7 +1081,7 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, */ int skill_status_change_clear(dumb_ptr<block_list> bl, int type) { - eptr<struct status_change, StatusChange> sc_data; + eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short *sc_count; Option *option; Opt1 *opt1; diff --git a/src/map/skill.hpp b/src/map/skill.hpp index b612268..ece2ab5 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -22,17 +22,16 @@ struct skill_db_ SkillFlags poolflags; int max_raise; // `max' is the global max, `max_raise' is the maximum attainable via skill-ups int num_k; - int cast[MAX_SKILL_LEVEL], delay[MAX_SKILL_LEVEL]; - int upkeep_time[MAX_SKILL_LEVEL], upkeep_time2[MAX_SKILL_LEVEL]; + Array<int, MAX_SKILL_LEVEL> cast, delay; + Array<int, MAX_SKILL_LEVEL> upkeep_time, upkeep_time2; bool castcancel; int cast_def_rate; int inf2, maxcount; - int hp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL], - hp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL], - zeny[MAX_SKILL_LEVEL]; + Array<int, MAX_SKILL_LEVEL> hp, sp, mhp, + hprate, sp_rate, + zeny; int weapon; - int itemid[10], amount[10]; - int castnodex[MAX_SKILL_LEVEL]; + Array<int, MAX_SKILL_LEVEL> castnodex; }; extern earray<skill_db_, SkillID, SkillID::MAX_SKILL_DB> skill_db; @@ -115,7 +114,7 @@ constexpr int MAX_SKILL_POOL = 3; // Max. # of skills that may be classified as pool skills in db/skill_db.txt constexpr int MAX_POOL_SKILLS = 128; -extern SkillID skill_pool_skills[MAX_POOL_SKILLS]; // All pool skills +extern Array<SkillID, MAX_POOL_SKILLS> skill_pool_skills; // All pool skills extern int skill_pool_skills_size; // Number of entries in skill_pool_skills // Yields all active skills in the skill pool; no more than MAX_SKILL_POOL. Return is number of skills. diff --git a/src/map/tmw.hpp b/src/map/tmw.hpp index 65e71fb..65eb28a 100644 --- a/src/map/tmw.hpp +++ b/src/map/tmw.hpp @@ -3,8 +3,6 @@ # include "../strings/fwd.hpp" -# include "../generic/const_array.hpp" - # include "../mmo/dumb_ptr.hpp" # include "map.hpp" diff --git a/src/map/trade.cpp b/src/map/trade.cpp index e9c5fd4..bd6e2bf 100644 --- a/src/map/trade.cpp +++ b/src/map/trade.cpp @@ -137,7 +137,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) && target_sd->inventory_data[i] == NULL) free_++; } - for (trade_i = 0; trade_i < 10; trade_i++) + for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { if (sd->deal_item_amount[trade_i] == 0) { @@ -238,7 +238,7 @@ void trade_tradeok(dumb_ptr<map_session_data> sd) nullpo_retv(sd); - for (trade_i = 0; trade_i < 10; trade_i++) + for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { if (sd->deal_item_amount[trade_i] > sd->status.inventory[sd->deal_item_index[trade_i] - 2].amount @@ -272,7 +272,7 @@ void trade_tradecancel(dumb_ptr<map_session_data> sd) if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) { - for (trade_i = 0; trade_i < 10; trade_i++) + for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { //give items back (only virtual) if (sd->deal_item_amount[trade_i] != 0) { @@ -352,7 +352,7 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd) } sd->trade_partner = 0; target_sd->trade_partner = 0; - for (trade_i = 0; trade_i < 10; trade_i++) + for (trade_i = 0; trade_i < TRADE_MAX; trade_i++) { if (sd->deal_item_amount[trade_i] != 0) { diff --git a/src/mmo/core.cpp b/src/mmo/core.cpp index 1a9a52e..26b5128 100644 --- a/src/mmo/core.cpp +++ b/src/mmo/core.cpp @@ -83,7 +83,7 @@ int main(int argc, char **argv) ZString *args = static_cast<ZString *>(alloca(argc * sizeof(ZString))); for (int i = 0; i < argc; ++i) args[i] = ZString(strings::really_construct_from_a_pointer, argv[i], nullptr); - do_init(argc, args); + do_init(Slice<ZString>(args, argc)); if (!runflag) { diff --git a/src/mmo/core.hpp b/src/mmo/core.hpp index 1788ece..7a26f7d 100644 --- a/src/mmo/core.hpp +++ b/src/mmo/core.hpp @@ -3,6 +3,8 @@ # include "../sanity.hpp" +# include "../range/slice.hpp" + # include "../strings/fwd.hpp" /// core.c contains a server-independent main() function @@ -13,7 +15,7 @@ extern volatile bool runflag; /// This is an external function defined by each server /// This function must register stuff for the parse loop -extern int do_init(int, ZString *); +extern int do_init(Slice<ZString>); /// Cleanup function called whenever a signal kills us /// or when if we manage to exit() gracefully. diff --git a/src/mmo/dumb_ptr.hpp b/src/mmo/dumb_ptr.hpp index 98c6308..9632945 100644 --- a/src/mmo/dumb_ptr.hpp +++ b/src/mmo/dumb_ptr.hpp @@ -29,8 +29,6 @@ # include "../strings/zstring.hpp" # include "../strings/xstring.hpp" -# include "../generic/const_array.hpp" - // unmanaged new/delete-able pointer // should be replaced by std::unique_ptr<T> template<class T> diff --git a/src/mmo/extract.hpp b/src/mmo/extract.hpp index 0ea9eb9..622281b 100644 --- a/src/mmo/extract.hpp +++ b/src/mmo/extract.hpp @@ -25,8 +25,6 @@ # include "../strings/xstring.hpp" -# include "../generic/const_array.hpp" - # include "mmo.hpp" # include "utils.hpp" diff --git a/src/mmo/mmo.hpp b/src/mmo/mmo.hpp index 6b3cd53..f867492 100644 --- a/src/mmo/mmo.hpp +++ b/src/mmo/mmo.hpp @@ -21,6 +21,7 @@ constexpr int MAX_MAP_PER_SERVER = 512; constexpr int MAX_INVENTORY = 100; constexpr int MAX_AMOUNT = 30000; constexpr int MAX_ZENY = 1000000000; // 1G zeny +constexpr int TRADE_MAX = 10; enum class SkillID : uint16_t; constexpr SkillID MAX_SKILL = SkillID(474); // not 450 @@ -43,6 +44,20 @@ constexpr int MAX_PARTY = 12; # define MIN_CLOTH_COLOR battle_config.min_cloth_color # define MAX_CLOTH_COLOR battle_config.max_cloth_color +template<class T, size_t n> +struct Array +{ + T data[n]; +public: + T& operator [](size_t i) { assert (i < n); return data[i]; } + const T& operator [](size_t i) const { assert (i < n); return data[i]; } + + T *begin() { return data + 0; } + T *end() { return data + n; } + const T *begin() const { return data + 0; } + const T *end() const { return data + n; } +}; + struct AccountName : VString<23> {}; struct AccountPass : VString<23> {}; struct AccountCrypt : VString<39> {}; @@ -319,14 +334,14 @@ struct CharData unsigned int mapport; struct point last_point, save_point; - struct item inventory[MAX_INVENTORY]; + Array<struct item, MAX_INVENTORY> inventory; earray<skill_value, SkillID, MAX_SKILL> skill; int global_reg_num; - struct global_reg global_reg[GLOBAL_REG_NUM]; + Array<struct global_reg, GLOBAL_REG_NUM> global_reg; int account_reg_num; - struct global_reg account_reg[ACCOUNT_REG_NUM]; + Array<struct global_reg, ACCOUNT_REG_NUM> account_reg; int account_reg2_num; - struct global_reg account_reg2[ACCOUNT_REG2_NUM]; + Array<struct global_reg, ACCOUNT_REG2_NUM> account_reg2; }; struct CharPair @@ -345,11 +360,9 @@ struct storage int account_id; short storage_status; short storage_amount; - struct item storage_[MAX_STORAGE]; + Array<struct item, MAX_STORAGE> storage_; }; -//struct map_session_data; - struct GM_Account { int account_id; @@ -371,7 +384,7 @@ struct party PartyName name; int exp; int item; - struct party_member member[MAX_PARTY]; + Array<struct party_member, MAX_PARTY> member; }; #endif // TMWA_MMO_MMO_HPP diff --git a/src/mmo/utils.hpp b/src/mmo/utils.hpp index 5e9de26..40ff595 100644 --- a/src/mmo/utils.hpp +++ b/src/mmo/utils.hpp @@ -10,7 +10,6 @@ # include "../strings/fwd.hpp" # include "../strings/vstring.hpp" -# include "../generic/const_array.hpp" # include "../generic/operators.hpp" # include "../io/fwd.hpp" diff --git a/src/range/slice.cpp b/src/range/slice.cpp new file mode 100644 index 0000000..5b23447 --- /dev/null +++ b/src/range/slice.cpp @@ -0,0 +1 @@ +#include "slice.hpp" diff --git a/src/range/slice.hpp b/src/range/slice.hpp new file mode 100644 index 0000000..f645595 --- /dev/null +++ b/src/range/slice.hpp @@ -0,0 +1,74 @@ +#ifndef TMWA_GENERIC_SLICE_HPP +#define TMWA_GENERIC_SLICE_HPP +// slice.hpp - a borrowed array +// +// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// 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 3 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; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +# include "../sanity.hpp" + +# include <cstddef> + +# include <type_traits> + +# include <vector> + +template<class T> +class Slice +{ + T *_begin; + T *_end; +public: + class iterator; + + Slice(std::nullptr_t); + Slice(T *b, T *e); + Slice(T *b, size_t l); + template<class U, typename=typename std::enable_if<sizeof(T) == sizeof(U) && std::is_base_of<T, U>::value>::type> + Slice(Slice<U> o); + template<size_t n, typename=typename std::enable_if<sizeof(T) != 1>::type> + Slice(T (&arr)[n]); + // TODO: come up with something else once using ranges (wrap all containers?) + Slice(std::vector<T>& vec); + + iterator begin() const; + iterator end() const; + T *data() const; + size_t size() const; + operator bool() const; + bool operator not() const; + T& front() const; + T& back() const; + T& pop_front(); + T& pop_back(); + __attribute__((deprecated("use iterators instead"))) + T& operator[](size_t o); + + Slice slice_t(size_t o) const; + Slice slice_h(size_t o) const; + Slice rslice_t(size_t no) const; + Slice rslice_h(size_t no) const; + Slice islice_t(iterator it) const; + Slice islice_h(iterator it) const; + Slice lslice(size_t o, size_t l) const; + Slice pslice(size_t b, size_t e) const; + Slice islice(iterator b, iterator e) const; +}; + +# include "slice.tcc" + +#endif // TMWA_GENERIC_SLICE_HPP diff --git a/src/range/slice.tcc b/src/range/slice.tcc new file mode 100644 index 0000000..3a1ceb5 --- /dev/null +++ b/src/range/slice.tcc @@ -0,0 +1,216 @@ +// strings/base.tcc - Inline functions for strings/base.hpp +// +// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// 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 3 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; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <cassert> + +#include <algorithm> + +// simple pointer-wrapping iterator +template<class T> +class Slice<T>::iterator +{ + typedef iterator X; + + T *_ptr; +public: + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; + + iterator(T *p=nullptr) : _ptr(p) {} + + // iterator + reference operator *() const { return *_ptr; } + X& operator ++() { ++_ptr; return *this; } + // equality comparable + friend bool operator == (X l, X r) { return l._ptr == r._ptr; } + // input iterator + friend bool operator != (X l, X r) { return !(l == r); } + pointer operator->() const { return _ptr; } + X operator++ (int) { X out = *this; ++*this; return out; } + // forward iterator is mostly semantical, and the ctor is above + // bidirectional iterator + X& operator --() { --_ptr; return *this; } + X operator-- (int) { X out = *this; --*this; return out; } + // random access iterator + X& operator += (difference_type n) { _ptr += n; return *this; } + friend X operator + (X a, difference_type n) { return a += n; } + friend X operator + (difference_type n, X a) { return a += n; } + X& operator -= (difference_type n) { _ptr -= n; return *this; } + friend X operator - (X a, difference_type n) { return a -= n; } + friend difference_type operator - (X b, X a) { return b._ptr - a._ptr; } + reference operator[](difference_type n) const { return _ptr[n]; } + friend bool operator < (X a, X b) { return a._ptr < b._ptr; } + friend bool operator > (X a, X b) { return b < a; } + friend bool operator >= (X a, X b) { return !(a < b); } + friend bool operator <= (X a, X b) { return !(a > b); } +}; + +template<class T> +Slice<T>::Slice(std::nullptr_t) : _begin(nullptr), _end(nullptr) +{} + +template<class T> +Slice<T>::Slice(T *b, T *e) : _begin(b), _end(e) +{} + +template<class T> +Slice<T>::Slice(T *b, size_t l) : _begin(b), _end(b + l) +{} + +template<class T> +template<class U, typename> +Slice<T>::Slice(Slice<U> o) : _begin(o.data()), _end(o.data() + o.size()) +{} + +template<class T> +template<size_t n, typename> +Slice<T>::Slice(T (&arr)[n]) : _begin(arr), _end(arr + n) +{} + +template<class T> +Slice<T>::Slice(std::vector<T>& vec) : _begin(&*vec.begin()), _end(&*vec.end()) +{} + + +template<class T> +typename Slice<T>::iterator Slice<T>::begin() const +{ + return _begin; +} + +template<class T> +typename Slice<T>::iterator Slice<T>::end() const +{ + return _end; +} + +template<class T> +T *Slice<T>::data() const +{ + return _begin; +} + +template<class T> +size_t Slice<T>::size() const +{ + return _end - _begin; +} + +template<class T> +Slice<T>::operator bool() const +{ + return _begin != _end; +} + +template<class T> +bool Slice<T>::operator not() const +{ + return _begin == _end; +} + +template<class T> +T& Slice<T>::front() const +{ + return _begin[0]; +} + +template<class T> +T& Slice<T>::back() const +{ + return _end[-1]; +} + +template<class T> +T& Slice<T>::pop_front() +{ + ++_begin; + return _begin[0 - 1]; +} + +template<class T> +T& Slice<T>::pop_back() +{ + --_end; + return _end[-1 + 1]; +} + +template<class T> +T& Slice<T>::operator[](size_t o) +{ + assert (o < size()); + return _begin[o]; +} + + +template<class T> +Slice<T> Slice<T>::slice_t(size_t o) const +{ + return Slice(_begin + o, _end); +} + +template<class T> +Slice<T> Slice<T>::slice_h(size_t o) const +{ + return Slice(_begin, _begin + o); +} + +template<class T> +Slice<T> Slice<T>::rslice_t(size_t no) const +{ + return Slice(_end - no, _end); +} + +template<class T> +Slice<T> Slice<T>::rslice_h(size_t no) const +{ + return Slice(_begin, _end - no); +} + +template<class T> +Slice<T> Slice<T>::islice_t(iterator it) const +{ + return Slice(&*it, _end); +} + +template<class T> +Slice<T> Slice<T>::islice_h(iterator it) const +{ + return Slice(_begin, &*it); +} + +template<class T> +Slice<T> Slice<T>::lslice(size_t o, size_t l) const +{ + return Slice(_begin + o, _begin + o + l); +} + +template<class T> +Slice<T> Slice<T>::pslice(size_t b, size_t e) const +{ + return Slice(_begin + b, _begin + e); +} + +template<class T> +Slice<T> Slice<T>::islice(iterator b, iterator e) const +{ + return Slice(&*b, &*e); +} diff --git a/src/range/slice_test.cpp b/src/range/slice_test.cpp new file mode 100644 index 0000000..5bd2748 --- /dev/null +++ b/src/range/slice_test.cpp @@ -0,0 +1,89 @@ +#include "slice.hpp" + +#include <gtest/gtest.h> + +TEST(slice, slice) +{ + int init[] = {1, 2, 3, 4, 5}; + + Slice<int> slice(std::begin(init), std::end(init)); + EXPECT_EQ(slice.data(), init); + EXPECT_EQ(slice.size(), 5); + + Slice<int> head = slice.slice_h(2); + Slice<int> tail = slice.slice_t(2); + EXPECT_EQ(head.size(), 2); + EXPECT_EQ(tail.size(), 3); + EXPECT_EQ(head.front(), 1); + EXPECT_EQ(head.back(), 2); + EXPECT_EQ(tail.front(), 3); + EXPECT_EQ(tail.back(), 5); + + head = slice.rslice_h(3); + tail = slice.rslice_t(3); + EXPECT_EQ(head.size(), 2); + EXPECT_EQ(tail.size(), 3); + EXPECT_EQ(head.front(), 1); + EXPECT_EQ(head.back(), 2); + EXPECT_EQ(tail.front(), 3); + EXPECT_EQ(tail.back(), 5); + + head = slice.islice_h(slice.begin() + 2); + tail = slice.islice_t(slice.end() - 3); + EXPECT_EQ(head.size(), 2); + EXPECT_EQ(tail.size(), 3); + EXPECT_EQ(head.front(), 1); + EXPECT_EQ(head.back(), 2); + EXPECT_EQ(tail.front(), 3); + EXPECT_EQ(tail.back(), 5); + + tail = slice.lslice(1, 3); + EXPECT_EQ(tail.size(), 3); + EXPECT_EQ(tail.front(), 2); + EXPECT_EQ(tail.back(), 4); + + tail = slice.pslice(1, 4); + EXPECT_EQ(tail.size(), 3); + EXPECT_EQ(tail.front(), 2); + EXPECT_EQ(tail.back(), 4); + + tail = slice.islice(slice.begin() + 1, slice.end() - 1); + EXPECT_EQ(tail.size(), 3); + EXPECT_EQ(tail.front(), 2); + EXPECT_EQ(tail.back(), 4); + + head = slice; + while (head) + { + size_t headsize = head.size(); + EXPECT_EQ(head.back(), headsize); + EXPECT_EQ(head.pop_back(), headsize); + } + + tail = slice; + while (!!tail) + { + size_t tailsize = tail.size(); + EXPECT_EQ(tail.front(), 6 - tailsize); + EXPECT_EQ(tail.pop_front(), 6 - tailsize); + } +} + +TEST(slice, cast) +{ + struct Foo + { + int x; + }; + struct Bar : Foo + { + }; + + Bar bars[2] = {Bar(), Bar()}; + + Slice<Bar> slice(bars, 2); + Slice<Foo> foos(slice); + + EXPECT_EQ(foos.size(), slice.size()); + EXPECT_EQ(&foos.end()[-1], &slice.end()[-1]); +} diff --git a/src/strings/base.hpp b/src/strings/base.hpp index cd8d46f..c5181da 100644 --- a/src/strings/base.hpp +++ b/src/strings/base.hpp @@ -31,6 +31,8 @@ // than would probably be necessary in an ideal language. namespace strings { + // TODO reimplement some things in terms of Slice and Slice::iterator? + // simple pointer-wrapping iterator that can be used to get distinct // types for different containers. template<class Tag> diff --git a/src/strings/pair.hpp b/src/strings/pair.hpp index a519ddb..a592a91 100644 --- a/src/strings/pair.hpp +++ b/src/strings/pair.hpp @@ -28,9 +28,7 @@ namespace strings { // TODO instead typedef ranges::Contiguous<const char> - // or whatever it becomes once it exists. - // const_array is just a hack, as evidenced by the fact - // that it's not really const. + // or whatever it becomes once it exists (probably grown from Slice). class XPair { const char *_begin; |