From b17b9021ecf9b16c265d0a6b60faa761b34eae35 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Tue, 12 Feb 2013 20:18:58 -0800 Subject: Replace mt_rand with Also add some utility methods and classes. --- GNUmakefile | 8 +- src/common/core.cpp | 5 +- src/common/md5calc.cpp | 7 +- src/common/mt_rand.cpp | 123 ----------- src/common/mt_rand.hpp | 24 --- src/common/random.cpp | 8 + src/common/random.hpp | 69 ++++++ src/common/random.t.hpp | 23 ++ src/common/random2.hpp | 74 +++++++ src/login/login.cpp | 10 +- src/map/atcommand.cpp | 148 ++----------- src/map/battle.cpp | 260 ++++------------------ src/map/battle.hpp | 21 +- src/map/clif.cpp | 2 +- src/map/itemdb.cpp | 158 +------------- src/map/itemdb.hpp | 2 - src/map/magic-expr.cpp | 47 +--- src/map/magic-stmt.cpp | 30 +-- src/map/map.cpp | 90 +++----- src/map/map.hpp | 6 +- src/map/mob.cpp | 556 +++++++++++------------------------------------- src/map/mob.hpp | 19 +- src/map/npc.cpp | 35 --- src/map/path.cpp | 53 +---- src/map/pc.cpp | 285 +------------------------ src/map/pc.hpp | 6 - src/map/script.cpp | 50 ++--- src/map/skill.cpp | 14 +- 28 files changed, 458 insertions(+), 1675 deletions(-) delete mode 100644 src/common/mt_rand.cpp delete mode 100644 src/common/mt_rand.hpp create mode 100644 src/common/random.cpp create mode 100644 src/common/random.hpp create mode 100644 src/common/random.t.hpp create mode 100644 src/common/random2.hpp diff --git a/GNUmakefile b/GNUmakefile index 676adfa..9accaab 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -59,10 +59,10 @@ eathena-monitor: ${BUILD_DIR}/tool/eathena-monitor cp -f $< $@ # Executable dependencies - generated by hand -${BUILD_DIR}/char/char: ${BUILD_DIR}/char/char.o ${BUILD_DIR}/char/inter.o ${BUILD_DIR}/char/int_party.o ${BUILD_DIR}/char/int_storage.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/mt_rand.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o -${BUILD_DIR}/ladmin/ladmin: ${BUILD_DIR}/ladmin/ladmin.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/mt_rand.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o -${BUILD_DIR}/login/login: ${BUILD_DIR}/login/login.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/mt_rand.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o -${BUILD_DIR}/map/map: ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/tmw.o ${BUILD_DIR}/map/magic-interpreter-lexer.o ${BUILD_DIR}/map/magic-interpreter-parser.o ${BUILD_DIR}/map/magic-interpreter-base.o ${BUILD_DIR}/map/magic-expr.o ${BUILD_DIR}/map/magic-stmt.o ${BUILD_DIR}/map/magic.o ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/chrif.o ${BUILD_DIR}/map/clif.o ${BUILD_DIR}/map/pc.o ${BUILD_DIR}/map/npc.o ${BUILD_DIR}/map/chat.o ${BUILD_DIR}/map/path.o ${BUILD_DIR}/map/itemdb.o ${BUILD_DIR}/map/mob.o ${BUILD_DIR}/map/script.o ${BUILD_DIR}/map/storage.o ${BUILD_DIR}/map/skill.o ${BUILD_DIR}/map/skill-pools.o ${BUILD_DIR}/map/atcommand.o ${BUILD_DIR}/map/battle.o ${BUILD_DIR}/map/intif.o ${BUILD_DIR}/map/trade.o ${BUILD_DIR}/map/party.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/grfio.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/mt_rand.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o +${BUILD_DIR}/char/char: ${BUILD_DIR}/char/char.o ${BUILD_DIR}/char/inter.o ${BUILD_DIR}/char/int_party.o ${BUILD_DIR}/char/int_storage.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o +${BUILD_DIR}/ladmin/ladmin: ${BUILD_DIR}/ladmin/ladmin.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o +${BUILD_DIR}/login/login: ${BUILD_DIR}/login/login.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o +${BUILD_DIR}/map/map: ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/tmw.o ${BUILD_DIR}/map/magic-interpreter-lexer.o ${BUILD_DIR}/map/magic-interpreter-parser.o ${BUILD_DIR}/map/magic-interpreter-base.o ${BUILD_DIR}/map/magic-expr.o ${BUILD_DIR}/map/magic-stmt.o ${BUILD_DIR}/map/magic.o ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/chrif.o ${BUILD_DIR}/map/clif.o ${BUILD_DIR}/map/pc.o ${BUILD_DIR}/map/npc.o ${BUILD_DIR}/map/chat.o ${BUILD_DIR}/map/path.o ${BUILD_DIR}/map/itemdb.o ${BUILD_DIR}/map/mob.o ${BUILD_DIR}/map/script.o ${BUILD_DIR}/map/storage.o ${BUILD_DIR}/map/skill.o ${BUILD_DIR}/map/skill-pools.o ${BUILD_DIR}/map/atcommand.o ${BUILD_DIR}/map/battle.o ${BUILD_DIR}/map/intif.o ${BUILD_DIR}/map/trade.o ${BUILD_DIR}/map/party.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/grfio.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/random.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/utils.o ${BUILD_DIR}/common/cxxstdio.o ${BUILD_DIR}/common/extract.o ${BUILD_DIR}/tool/eathena-monitor: ${BUILD_DIR}/tool/eathena-monitor.o # silence build warnings for code beyond my control diff --git a/src/common/core.cpp b/src/common/core.cpp index ae0e3eb..994de93 100644 --- a/src/common/core.cpp +++ b/src/common/core.cpp @@ -8,7 +8,7 @@ #include #include -#include "mt_rand.hpp" +#include "random.hpp" #include "socket.hpp" #include "timer.hpp" @@ -68,9 +68,6 @@ bool runflag = true; */ int main(int argc, char **argv) { - /// Note that getpid() and getppid() may be very close - mt_seed(time(NULL) ^ (getpid() << 16) ^ (getppid() << 8)); - do_socket(); do_init(argc, argv); diff --git a/src/common/md5calc.cpp b/src/common/md5calc.cpp index c9c2415..1625912 100644 --- a/src/common/md5calc.cpp +++ b/src/common/md5calc.cpp @@ -2,7 +2,7 @@ #include -#include "mt_rand.hpp" +#include "random.hpp" #include "../poison.hpp" @@ -305,8 +305,9 @@ const char *MD5_saltcrypt(const char *key, const char *salt) const char *make_salt(void) { static char salt[6]; - for (int i=0; i<5; i++) - salt[i] = MPRAND(48, 78); + for (int i = 0; i < 5; i++) + // 126 would probably actually be okay + salt[i] = random_::in(48, 125); return salt; } diff --git a/src/common/mt_rand.cpp b/src/common/mt_rand.cpp deleted file mode 100644 index fbbf71f..0000000 --- a/src/common/mt_rand.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -// This is the ``Mersenne Twister'' random number generator MT19937, which -// generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) -// starting from any odd seed in 0..(2^32 - 1). This version is a recode -// by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by -// Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in -// July-August 1997). -// -// Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha -// running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to -// generate 300 million random numbers; after recoding: 24.0 sec. for the same -// (i.e., 46.5% of original time), so speed is now about 12.5 million random -// number generations per second on this machine. -// -// According to the URL -// (and paraphrasing a bit in places), the Mersenne Twister is ``designed -// with consideration of the flaws of various existing generators,'' has -// a period of 2^19937 - 1, gives a sequence that is 623-dimensionally -// equidistributed, and ``has passed many stringent tests, including the -// die-hard test of G. Marsaglia and the load test of P. Hellekalek and -// S. Wegenkittl.'' It is efficient in memory usage (typically using 2506 -// to 5012 bytes of static data, depending on data type sizes, and the code -// is quite short as well). It generates random numbers in batches of 624 -// at a time, so the caching and pipelining of modern systems is exploited. -// It is also divide- and mod-free. -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the GNU Library General Public License as published by -// the Free Software Foundation (either version 2 of the License or, at your -// option, any later version). This library 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 Library General Public License for more details. You should have -// received a copy of the GNU Library General Public License along with this -// library; if not, write to the Free Software Foundation, Inc., 59 Temple -// Place, Suite 330, Boston, MA 02111-1307, USA. -// -// The code as Shawn received it included the following notice: -// -// Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. When -// you use this, send an e-mail to with -// an appropriate reference to your work. -// -// It would be nice to CC: when you write. -// -*/ - -#include "mt_rand.hpp" - -#include - -#include "../poison.hpp" - -#define N 624 // length of state vector -#define M 397 // a period parameter -#define K 0x9908B0DFU // a magic constant - -#define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u -#define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u -#define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u -#define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v - -static -uint32_t state[N+1]; // state vector the +1 is needed due to the coding -static -uint32_t *next; // next random value is computed from here -static -int left = -1; // can *next++ this many times before reloading - -void mt_seed(uint32_t seed) -{ - uint32_t x = seed | 1U; - uint32_t *s = state; - left = 0; - - for (int j = N; *s++ = x, --j; x *= 69069U); -} - -static -void mt_reload(void) -{ - // if mt_seed has never been called - if (left < -1) - mt_seed(time(NULL)); - - // conceptually, these are indices into the state that wrap - uint32_t *p0 = state; - uint32_t *p2 = state + 2; - uint32_t *pM = state + M; - - uint32_t s0 = state[0]; - uint32_t s1 = state[1]; - - // regenerate the lower N-M elements of the state - for (int j = N-M+1; --j != 0; s0 = s1, s1 = *p2++) - *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); - - pM = state; - // regenerate the next M-1 elements of the state - // note that s1 is set to state[N] at the end, but discarded - for (int j = M; --j != 0; s0 = s1, s1 = *p2++) - *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); - - // regenerate the last 1 element of the state - s1 = state[0]; - *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); - - // ready for the normal mt_random algorithm - left = N; - next = state; -} - -uint32_t mt_random(void) -{ - if (--left < 0) - mt_reload(); - - uint32_t y = *next++; - y ^= (y >> 11); - y ^= (y << 7) & 0x9D2C5680U; - y ^= (y << 15) & 0xEFC60000U; - return y ^ (y >> 18); -} diff --git a/src/common/mt_rand.hpp b/src/common/mt_rand.hpp deleted file mode 100644 index ae5986b..0000000 --- a/src/common/mt_rand.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MT_RAND_HPP -#define MT_RAND_HPP - -# include "sanity.hpp" - -/// Initialize the generator (called automatically with time() if you don't) -void mt_seed(uint32_t seed); -/// Get a random number -uint32_t mt_random(void); - -/** - * ModuloRand and ModuloPlusRand - * These macros are used to replace the vast number of calls to rand()%mod - * TODO eliminate the rest of the calls to rand() - * MRAND(10) returns 0..9 - * MPRAND(5,10) returns 5..14 - */ -// The cast is essential because the result is sometimes -// compared with a possibly negative number. -// Because it's using modulus, high numbers shouldn't happen anyway. -# define MRAND(mod) ((int)(mt_random() % (mod))) -# define MPRAND(add, mod) ((add) + MRAND(mod)) - -#endif // MT_RAND_HPP diff --git a/src/common/random.cpp b/src/common/random.cpp new file mode 100644 index 0000000..273dcec --- /dev/null +++ b/src/common/random.cpp @@ -0,0 +1,8 @@ +#include "random2.hpp" + +#include "../poison.hpp" + +namespace random_ +{ + std::mt19937 generate{std::random_device()()}; +} // namespace random_ diff --git a/src/common/random.hpp b/src/common/random.hpp new file mode 100644 index 0000000..44057ed --- /dev/null +++ b/src/common/random.hpp @@ -0,0 +1,69 @@ +#ifndef RANDOM_HPP +#define RANDOM_HPP + +# include "random.t.hpp" + +# include "sanity.hpp" + +# include + +// This is not namespace random since that collides with a C function, +// but this can be revisited when everything goes into namespace tmwa. +namespace random_ +{ + /// Get a random number from 0 .. 2**32 - 1 + extern std::mt19937 generate; + + /// Get a random number from 0 .. bound - 1 + inline + int to(int bound) + { + std::uniform_int_distribution dist(0, bound - 1); + return dist(generate); + } + + /// Get a random number from low .. high (inclusive!) + inline + int in(int low, int high) + { + std::uniform_int_distribution dist(low, high); + return dist(generate); + } + + inline + bool coin() + { + // sigh, can't specify directly ... + std::uniform_int_distribution dist(false, true); + return dist(generate); + } + + inline + bool chance(Fraction f) + { + if (f.num <= 0) + return false; + if (f.num >= f.den) + return true; + return random_::to(f.den) < f.num; + } + + // C is usually one of: + // std::vector + // std::initializer_list + // std::array + template + auto choice(C&& c) -> decltype(*c.begin()) + { + return *(c.begin() + random_::to(c.size())); + } + + // allow bare braces + template + T choice(std::initializer_list&& il) + { + return random_::choice(il); + } +} // namespace random_ + +#endif // RANDOM_HPP diff --git a/src/common/random.t.hpp b/src/common/random.t.hpp new file mode 100644 index 0000000..98a6c59 --- /dev/null +++ b/src/common/random.t.hpp @@ -0,0 +1,23 @@ +#ifndef RANDOM_T_HPP +#define RANDOM_T_HPP + +namespace random_ +{ + struct Fraction + { + int num, den; + }; + + template + struct Fixed + { + T num; + + operator Fraction() + { + return {num, den}; + } + }; +} // namespace random_ + +#endif // RANDOM_T_HPP diff --git a/src/common/random2.hpp b/src/common/random2.hpp new file mode 100644 index 0000000..86deddf --- /dev/null +++ b/src/common/random2.hpp @@ -0,0 +1,74 @@ +#ifndef RANDOM2_HPP +#define RANDOM2_HPP + +# include "random.hpp" +# include "utils2.hpp" + +# include + +namespace random_ +{ + namespace detail + { + struct RandomIterator + { + int bound; + int current; + bool frist; + + void operator ++() + { + frist = false; + // TODO: reimplement in terms of LFSRs, so that certain + // blockage patterns don't favor adjacent cells. + current = current + 1; + if (current == bound) + current = 0; + } + int operator *() + { + return current; + } + }; + + inline + bool operator == (RandomIterator l, RandomIterator r) + { + return l.current == r.current && l.frist == r.frist; + } + + inline + bool operator != (RandomIterator l, RandomIterator r) + { + return !(l == r); + } + } + + /// Yield every cell from 0 .. bound - 1 in some order. + /// The starting position is random, but not the order itself. + /// + /// Expected usage: + /// for (int i : random_::iterator(vec.size())) + /// if (vec[i].okay()) + /// return frob(vec[i]); + inline + IteratorPair iterator(int bound) + { + int current = random_::to(bound); + return + { + detail::RandomIterator{bound, current, true}, + detail::RandomIterator{bound, current, false} + }; + } + + /// similar to std::random_shuffle(c.begin(), c.end()), but guaranteed + /// to use a good source of randomness. + template + void shuffle(C&& c) + { + std::random_shuffle(c.begin(), c.end(), random_::to); + } +} // namespace random_ + +#endif // RANDOM2_HPP diff --git a/src/login/login.cpp b/src/login/login.cpp index e2b64b8..94ae4b5 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -20,7 +20,7 @@ #include "../common/lock.hpp" #include "../common/md5calc.hpp" #include "../common/mmo.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" #include "../common/version.hpp" @@ -1046,8 +1046,8 @@ int mmo_auth(struct mmo_account *account, int fd) stamp_time(tmpstr); account->account_id = auth_dat[i].account_id; - account->login_id1 = mt_random(); - account->login_id2 = mt_random(); + account->login_id1 = random_::generate(); + account->login_id2 = random_::generate(); memcpy(account->lastlogin, auth_dat[i].lastlogin, 24); memcpy(auth_dat[i].lastlogin, tmpstr, 24); account->sex = auth_dat[i].sex; @@ -3291,9 +3291,9 @@ void parse_login(int fd) // TODO fix or get rid of this // Creation of the coding key memset(ld->md5key, '\0', sizeof(ld->md5key)); - ld->md5keylen = MRAND(4) + 12; + ld->md5keylen = random_::in(12, 15); for (int i = 0; i < ld->md5keylen; i++) - ld->md5key[i] = MRAND(255) + 1; + ld->md5key[i] = random_::in(1, 255); RFIFOSKIP(fd, 2); WFIFOW(fd, 0) = 0x01dc; diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 6c82e65..479b7c3 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -7,7 +7,7 @@ #include "../common/core.hpp" #include "../common/cxxstdio.hpp" #include "../common/mmo.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" @@ -127,8 +127,6 @@ ATCOMMAND_FUNC(enablenpc); ATCOMMAND_FUNC(disablenpc); ATCOMMAND_FUNC(servertime); // by Yor ATCOMMAND_FUNC(chardelitem); // by Yor -ATCOMMAND_FUNC(jail); // by Yor -ATCOMMAND_FUNC(unjail); // by Yor ATCOMMAND_FUNC(ignorelist); // by Yor ATCOMMAND_FUNC(charignorelist); // by Yor ATCOMMAND_FUNC(inall); // by Yor @@ -291,8 +289,6 @@ AtCommandInfo atcommand_info[] = { {AtCommand_ServerTime, "@servertime", 0, atcommand_servertime}, // by Yor {AtCommand_CharDelItem, "@chardelitem", 60, atcommand_chardelitem}, // by Yor {AtCommand_ListNearby, "@listnearby", 40, atcommand_list_nearby}, // by Yor - {AtCommand_Jail, "@jail", 60, atcommand_jail}, // by Yor - {AtCommand_UnJail, "@unjail", 60, atcommand_unjail}, // by Yor {AtCommand_IgnoreList, "@ignorelist", 0, atcommand_ignorelist}, // by Yor {AtCommand_CharIgnoreList, "@charignorelist", 20, atcommand_charignorelist}, // by Yor {AtCommand_IgnoreList, "@inall", 20, atcommand_inall}, // by Yor @@ -689,9 +685,9 @@ int atcommand_charwarp(const int fd, struct map_session_data *sd, } if (x <= 0) - x = MRAND(399) + 1; + x = random_::in(1, 399); if (y <= 0) - y = MRAND(399) + 1; + y = random_::in(1, 399); if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) strcat(map_name, ".gat"); @@ -770,9 +766,9 @@ int atcommand_warp(const int fd, struct map_session_data *sd, } if (x <= 0) - x = MRAND(399) + 1; + x = random_::in(1, 399); if (y <= 0) - y = MRAND(399) + 1; + y = random_::in(1, 399); if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) strcat(map_name, ".gat"); @@ -904,9 +900,9 @@ int atcommand_jump(const int fd, struct map_session_data *sd, sscanf(message, "%d %d", &x, &y); if (x <= 0) - x = MRAND(399) + 1; + x = random_::in(1, 399); if (y <= 0) - y = MRAND(399) + 1; + y = random_::in(1, 399); if (x > 0 && x < 800 && y > 0 && y < 800) { if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto @@ -2199,13 +2195,14 @@ int atcommand_spawn(const int fd, struct map_session_data *sd, j = 0; k = 0; while (j++ < 8 && k == 0) - { // try 8 times to spawn the monster (needed for close area) + { + // try 8 times to spawn the monster (needed for close area) if (x <= 0) - mx = sd->bl.x + (MRAND(range) - (range / 2)); + mx = sd->bl.x + random_::in(-range / 2, range / 2 ); else mx = x; if (y <= 0) - my = sd->bl.y + (MRAND(range) - (range / 2)); + my = sd->bl.y + random_::in(-range / 2, range / 2); else my = y; k = mob_once_spawn(sd, "this", mx, my, "", mob_id, 1, ""); @@ -4866,125 +4863,6 @@ int atcommand_chardelitem(const int fd, struct map_session_data *sd, return 0; } -/*========================================== - * @jail by [Yor] - * Special warp! No check with nowarp and nowarpto flag - *------------------------------------------ - */ -int atcommand_jail(const int fd, struct map_session_data *sd, - const char *, const char *message) -{ - char character[100]; - struct map_session_data *pl_sd; - int x, y; - - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) - { - clif_displaymessage(fd, - "Please, enter a player name (usage: @jail )."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) - { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) - { // you can jail only lower or same GM - switch (MRAND(2)) - { - case 0: - x = 24; - y = 75; - break; - default: - x = 49; - y = 75; - break; - } - if (pc_setpos(pl_sd, "sec_pri.gat", x, y, BeingRemoveWhy::WARPED) == 0) - { - pc_setsavepoint(pl_sd, "sec_pri.gat", x, y); // Save Char Respawn Point in the jail room [Lupus] - clif_displaymessage(pl_sd->fd, "GM has send you in jails."); - clif_displaymessage(fd, "Player warped in jails."); - } - else - { - clif_displaymessage(fd, "Map not found."); - return -1; - } - } - else - { - clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player."); - return -1; - } - } - else - { - clif_displaymessage(fd, "Character not found."); - return -1; - } - - return 0; -} - -/*========================================== - * @unjail/@discharge by [Yor] - * Special warp! No check with nowarp and nowarpto flag - *------------------------------------------ - */ -int atcommand_unjail(const int fd, struct map_session_data *sd, - const char *, const char *message) -{ - char character[100]; - struct map_session_data *pl_sd; - - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) - { - clif_displaymessage(fd, - "Please, enter a player name (usage: @unjail/@discharge )."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) - { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) - { // you can jail only lower or same GM - if (pl_sd->bl.m != map_mapname2mapid("sec_pri.gat")) - { - clif_displaymessage(fd, "This player is not in jails."); - return -1; - } - else if (pc_setpos(pl_sd, "prontera.gat", 156, 191, BeingRemoveWhy::WARPED) == 0) - { - pc_setsavepoint(pl_sd, "prontera.gat", 156, 191); // Save char respawn point in Prontera - clif_displaymessage(pl_sd->fd, "GM has discharge you."); - clif_displaymessage(fd, "Player warped to Prontera."); - } - else - { - clif_displaymessage(fd, "Map not found."); - return -1; - } - } - else - { - clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player."); - return -1; - } - } - else - { - clif_displaymessage(fd, "Character not found."); - return -1; - } - - return 0; -} - /*========================================== * @broadcast by [Valaris] *------------------------------------------ @@ -6191,8 +6069,8 @@ int atcommand_summon(const int, struct map_session_data *sd, if (mob_id == 0) return -1; - x = sd->bl.x + (MRAND(10) - 5); - y = sd->bl.y + (MRAND(10) - 5); + x = sd->bl.x + random_::in(-5, 4); + y = sd->bl.y + random_::in(-5, 4); id = mob_once_spawn(sd, "this", x, y, "--ja--", mob_id, 1, ""); if ((md = (struct mob_data *) map_id2bl(id))) diff --git a/src/map/battle.cpp b/src/map/battle.cpp index fe8dfe4..dad78cb 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -5,7 +5,7 @@ #include #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "clif.hpp" @@ -133,12 +133,6 @@ int battle_get_max_hp(struct block_list *bl) if (bl->type == BL::MOB && ((struct mob_data *) bl)) { max_hp = ((struct mob_data *) bl)->stats[mob_stat::MAX_HP]; - if (mob_db[((struct mob_data *) bl)->mob_class].mexp > 0) - { - if (battle_config.mvp_hp_rate != 100) - max_hp = (max_hp * battle_config.mvp_hp_rate) / 100; - } - else { if (battle_config.monster_hp_rate != 100) max_hp = (max_hp * battle_config.monster_hp_rate) / 100; @@ -816,23 +810,6 @@ MobMode battle_get_mode(struct block_list *bl) return MobMode::CAN_MOVE; } -int battle_get_mexp(struct block_list *bl) -{ - nullpo_ret(bl); - if (bl->type == BL::MOB) - { - const struct mob_data *mob = (struct mob_data *) bl; - const int retval = - (mob_db[mob->mob_class].mexp * - (int)(mob->stats[mob_stat::XP_BONUS])) >> MOB_XP_BONUS_SHIFT; - FPRINTF(stderr, "Modifier of %x: -> %d\n", mob->stats[mob_stat::XP_BONUS], - retval); - return retval; - } - else - return 0; -} - int battle_get_stat(SP stat_id, struct block_list *bl) { switch (stat_id) @@ -1154,7 +1131,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, if ((skill_num == SkillID::ZERO) && skill_lv >= 0 && battle_config.enemy_critical - && (MRAND(1000)) < cri) + && random_::chance({cri, 1000})) // 判定(スキルの場合は無視) // 敵の判定 { @@ -1166,7 +1143,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, int vitbonusmax; if (atkmax > atkmin) - damage += atkmin + MRAND((atkmax - atkmin + 1)); + damage += random_::in(atkmin, atkmax); else damage += atkmin; @@ -1238,18 +1215,11 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, t_def = def2 * 8 / 10; vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1; - if (battle_config.monster_defense_type) { - damage = - damage - (def1 * battle_config.monster_defense_type) - - t_def - - ((vitbonusmax < 1) ? 0 : MRAND((vitbonusmax + 1))); - } - else - { - damage = - damage * (100 - def1) / 100 - t_def - - ((vitbonusmax < 1) ? 0 : MRAND((vitbonusmax + 1))); + damage = damage * (100 - def1) / 100; + damage -= t_def; + if (vitbonusmax > 0) + damage -= random_::in(0, vitbonusmax); } } } @@ -1263,7 +1233,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, if (hitrate < 1000000) hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate)); - if (type == DamageType::NORMAL && MRAND(100) >= hitrate) + if (type == DamageType::NORMAL && !random_::chance({hitrate, 100})) { damage = damage2 = 0; dmg_lv = ATK::FLEE; @@ -1278,7 +1248,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, // 完全回避の判定 if (skill_num == SkillID::ZERO && skill_lv >= 0 && tsd != NULL - && MRAND(1000) < battle_get_flee2(target)) + && random_::chance({battle_get_flee2(target), 1000})) { damage = 0; type = DamageType::FLEE2; @@ -1288,7 +1258,7 @@ struct Damage battle_calc_mob_weapon_attack(struct block_list *src, if (battle_config.enemy_perfect_flee) { if (skill_num == SkillID::ZERO && skill_lv >= 0 && tmd != NULL - && MRAND(1000) < battle_get_flee2(target)) + && random_::chance({battle_get_flee2(target), 1000})) { damage = 0; type = DamageType::FLEE2; @@ -1359,7 +1329,6 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, int watk, watk_; bool da = false; int ac_flag = 0; - int idef_flag = 0, idef_flag_ = 0; int target_distance; nullpo_retr(wd, src); @@ -1471,13 +1440,13 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, atkmin_ = atkmax_; if (sd->double_rate > 0 && skill_num == SkillID::ZERO && skill_lv >= 0) - da = MRAND(100) < sd->double_rate; + da = random_::chance({sd->double_rate, 100}); // 過剰精錬ボーナス if (sd->overrefine > 0) - damage += MPRAND(1, sd->overrefine); + damage += random_::in(1, sd->overrefine); if (sd->overrefine_ > 0) - damage2 += MPRAND(1, sd->overrefine_); + damage2 += random_::in(1, sd->overrefine_); if (!da) { //ダブルアタックが発動していない @@ -1497,8 +1466,10 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, if (tsd && tsd->critical_def) cri = cri * (100 - tsd->critical_def) / 100; - if (!da && skill_num == SkillID::ZERO && skill_lv >= 0 && //ダブルアタックが発動していない - (MRAND(1000)) < cri) // 判定(スキルの場合は無視) + //ダブルアタックが発動していない + // 判定(スキルの場合は無視) + if (!da && skill_num == SkillID::ZERO && skill_lv >= 0 + && random_::chance({cri, 1000})) { damage += atkmax; damage2 += atkmax_; @@ -1516,11 +1487,11 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, int vitbonusmax; if (atkmax > atkmin) - damage += atkmin + MRAND((atkmax - atkmin + 1)); + damage += random_::in(atkmin, atkmax); else damage += atkmin; if (atkmax_ > atkmin_) - damage2 += atkmin_ + MRAND((atkmax_ - atkmin_ + 1)); + damage2 += random_::in(atkmin_, atkmax_); else damage2 += atkmin_; if (sd->atk_rate != 100) @@ -1532,7 +1503,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, if (sd->state.arrow_atk) { if (sd->arrow_atk > 0) - damage += MRAND((sd->arrow_atk + 1)); + damage += random_::in(0, sd->arrow_atk); hitrate += sd->arrow_hit; } @@ -1604,42 +1575,20 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, t_def = def2 * 8 / 10; vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1; - if (!idef_flag) { - if (battle_config.player_defense_type) - { - damage = - damage - - (def1 * battle_config.player_defense_type) - - t_def - - ((vitbonusmax < - 1) ? 0 : MRAND((vitbonusmax + 1))); - } - else { - damage = - damage * (100 - def1) / 100 - t_def - - ((vitbonusmax < - 1) ? 0 : MRAND((vitbonusmax + 1))); + damage = damage * (100 - def1) / 100; + damage -= t_def; + if (vitbonusmax > 0) + damage -= random_::in(0, vitbonusmax); } } - if (!idef_flag_) { - if (battle_config.player_defense_type) - { - damage2 = - damage2 - - (def1 * battle_config.player_defense_type) - - t_def - - ((vitbonusmax < - 1) ? 0 : MRAND((vitbonusmax + 1))); - } - else { - damage2 = - damage2 * (100 - def1) / 100 - t_def - - ((vitbonusmax < - 1) ? 0 : MRAND((vitbonusmax + 1))); + damage2 = damage2 * (100 - def1) / 100; + damage2 -= t_def; + if (vitbonusmax > 0) + damage2 -= random_::in(0, vitbonusmax); } } } @@ -1664,13 +1613,13 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, if (sd->perfect_hit > 0) { - if (MRAND(100) < sd->perfect_hit) + if (random_::chance({sd->perfect_hit, 100})) hitrate = 1000000; } // 回避修正 hitrate = (hitrate < 5) ? 5 : hitrate; - if (type == DamageType::NORMAL && MRAND(100) >= hitrate) + if (type == DamageType::NORMAL && !random_::chance({hitrate, 100})) { damage = damage2 = 0; dmg_lv = ATK::FLEE; @@ -1735,7 +1684,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, // 完全回避の判定 if (skill_num == SkillID::ZERO && skill_lv >= 0 && tsd != NULL && div_ < 255 - && MRAND(1000) < battle_get_flee2(target)) + && random_::chance({battle_get_flee2(target), 1000})) { damage = damage2 = 0; type = DamageType::FLEE2; @@ -1746,7 +1695,7 @@ struct Damage battle_calc_pc_weapon_attack(struct block_list *src, if (battle_config.enemy_perfect_flee) { if (skill_num == SkillID::ZERO && skill_lv >= 0 && tmd != NULL && div_ < 255 - && MRAND(1000) < battle_get_flee2(target)) + && random_::chance({battle_get_flee2(target), 1000})) { damage = damage2 = 0; type = DamageType::FLEE2; @@ -1818,39 +1767,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src, else if (src->type == BL::MOB) wd = battle_calc_mob_weapon_attack(src, target, skill_num, skill_lv, wflag); - if (battle_config.equipment_breaking && src->type == BL::PC - && (wd.damage > 0 || wd.damage2 > 0)) - { - struct map_session_data *sd = (struct map_session_data *) src; - if (sd->status.weapon && sd->status.weapon != 11) - { - int breakrate = 1; - if (wd.type == DamageType::CRITICAL) - breakrate *= 2; - if (MRAND(10000) < - breakrate * battle_config.equipment_break_rate / 100 - || breakrate >= 10000) - { - pc_breakweapon(sd); - memset(&wd, 0, sizeof(wd)); - } - } - } - - if (battle_config.equipment_breaking && target->type == BL::PC - && (wd.damage > 0 || wd.damage2 > 0)) - { - int breakrate = 1; - if (wd.type == DamageType::CRITICAL) - breakrate *= 2; - if (MRAND(10000) < - breakrate * battle_config.equipment_break_rate / 100 - || breakrate >= 10000) - { - pc_breakarmor((struct map_session_data *) target); - } - } - return wd; } @@ -1877,41 +1793,31 @@ struct Damage battle_calc_magic_attack(struct block_list *bl, matk2 = battle_get_matk2(bl); MobMode t_mode = battle_get_mode(target); -#define MATK_FIX(a, b) \ -{ \ - matk1 = matk1 * (a) / (b); \ - matk2 = matk2 * (a) / (b); \ -} - if (bl->type == BL::PC && (sd = (struct map_session_data *) bl)) { sd->state.attack_type = BF::MAGIC; if (sd->matk_rate != 100) - MATK_FIX(sd->matk_rate, 100); + { + matk1 = matk1 * sd->matk_rate / 100; + matk2 = matk2 * sd->matk_rate / 100; + } sd->state.arrow_atk = 0; } BF aflag = BF::MAGIC | BF::LONG | BF::SKILL; if (normalmagic_flag) - { // 一般魔法ダメージ計算 - int imdef_flag = 0; + { + // 一般魔法ダメージ計算 if (matk1 > matk2) - damage = matk2 + MRAND((matk1 - matk2 + 1)); + damage = random_::in(matk2, matk1); else damage = matk2; - if (!imdef_flag) { - if (battle_config.magic_defense_type) { - damage = - damage - (mdef1 * battle_config.magic_defense_type) - - mdef2; - } - else - { - damage = (damage * (100 - mdef1)) / 100 - mdef2; + damage = (damage * (100 - mdef1)) / 100; + damage -= mdef2; } } @@ -2171,22 +2077,22 @@ ATK battle_weapon_attack(struct block_list *src, struct block_list *target, { int hp = 0, sp = 0; if (sd->hp_drain_rate && wd.damage > 0 - && MRAND(100) < sd->hp_drain_rate) + && random_::chance({sd->hp_drain_rate, 100})) { hp += (wd.damage * sd->hp_drain_per) / 100; } if (sd->hp_drain_rate_ && wd.damage2 > 0 - && MRAND(100) < sd->hp_drain_rate_) + && random_::chance({sd->hp_drain_rate_, 100})) { hp += (wd.damage2 * sd->hp_drain_per_) / 100; } if (sd->sp_drain_rate && wd.damage > 0 - && MRAND(100) < sd->sp_drain_rate) + && random_::chance({sd->sp_drain_rate, 100})) { sp += (wd.damage * sd->sp_drain_per) / 100; } if (sd->sp_drain_rate_ && wd.damage2 > 0 - && MRAND(100) < sd->sp_drain_rate_) + && random_::chance({sd->sp_drain_rate_, 100})) { sp += (wd.damage2 * sd->sp_drain_per_) / 100; } @@ -2412,11 +2318,7 @@ int battle_config_read(const char *cfgName) battle_config.item_first_get_time = 3000; battle_config.item_second_get_time = 1000; battle_config.item_third_get_time = 1000; - battle_config.mvp_item_first_get_time = 10000; - battle_config.mvp_item_second_get_time = 10000; - battle_config.mvp_item_third_get_time = 2000; - battle_config.drop_rate0item = 0; battle_config.base_exp_rate = 100; battle_config.job_exp_rate = 100; battle_config.pvp_exp = 1; @@ -2427,9 +2329,6 @@ int battle_config_read(const char *cfgName) battle_config.zeny_penalty = 0; battle_config.restart_hp_rate = 0; battle_config.restart_sp_rate = 0; - battle_config.mvp_item_rate = 100; - battle_config.mvp_exp_rate = 100; - battle_config.mvp_hp_rate = 100; battle_config.monster_hp_rate = 100; battle_config.monster_max_aspd = 199; battle_config.atc_gmonly = 0; @@ -2482,14 +2381,11 @@ int battle_config_read(const char *cfgName) battle_config.agi_penaly_type = 0; battle_config.agi_penaly_count = 3; battle_config.agi_penaly_num = 0; - battle_config.agi_penaly_count_lv = int(ATK::FLEE); // FIXME + battle_config.agi_penaly_count_lv = static_cast(ATK::FLEE); // FIXME battle_config.vit_penaly_type = 0; battle_config.vit_penaly_count = 3; battle_config.vit_penaly_num = 0; - battle_config.vit_penaly_count_lv = int(ATK::DEF); // FIXME - battle_config.player_defense_type = 0; - battle_config.monster_defense_type = 0; - battle_config.magic_defense_type = 0; + battle_config.vit_penaly_count_lv = static_cast(ATK::DEF); // FIXME battle_config.pc_skill_reiteration = 0; battle_config.monster_skill_reiteration = 0; battle_config.pc_skill_nofootset = 0; @@ -2527,28 +2423,9 @@ int battle_config_read(const char *cfgName) battle_config.invite_request_check = 1; battle_config.skill_removetrap_type = 0; battle_config.disp_experience = 0; - battle_config.item_rate_common = 100; - battle_config.item_rate_equip = 100; - battle_config.item_rate_card = 100; - battle_config.item_rate_heal = 100; // Added by Valaris - battle_config.item_rate_use = 100; // End - battle_config.item_drop_common_min = 1; // Added by TyrNemesis^ - battle_config.item_drop_common_max = 10000; - battle_config.item_drop_equip_min = 1; - battle_config.item_drop_equip_max = 10000; - battle_config.item_drop_card_min = 1; - battle_config.item_drop_card_max = 10000; - battle_config.item_drop_mvp_min = 1; - battle_config.item_drop_mvp_max = 10000; // End Addition - battle_config.item_drop_heal_min = 1; // Added by Valaris - battle_config.item_drop_heal_max = 10000; - battle_config.item_drop_use_min = 1; - battle_config.item_drop_use_max = 10000; // End battle_config.prevent_logout = 1; // Added by RoVeRT battle_config.maximum_level = 255; // Added by Valaris battle_config.drops_by_luk = 0; // [Valaris] - battle_config.equipment_breaking = 0; // [Valaris] - battle_config.equipment_break_rate = 100; // [Valaris] battle_config.pk_mode = 0; // [Valaris] battle_config.multi_level_up = 0; // [Valaris] battle_config.backstab_bow_penalty = 0; // Akaru @@ -2623,11 +2500,6 @@ int battle_config_read(const char *cfgName) {"item_first_get_time", &battle_config.item_first_get_time}, {"item_second_get_time", &battle_config.item_second_get_time}, {"item_third_get_time", &battle_config.item_third_get_time}, - {"mvp_item_first_get_time", &battle_config.mvp_item_first_get_time}, - {"mvp_item_second_get_time", &battle_config.mvp_item_second_get_time}, - {"mvp_item_third_get_time", &battle_config.mvp_item_third_get_time}, - {"item_rate", &battle_config.item_rate}, - {"drop_rate0item", &battle_config.drop_rate0item}, {"base_exp_rate", &battle_config.base_exp_rate}, {"job_exp_rate", &battle_config.job_exp_rate}, {"pvp_exp", &battle_config.pvp_exp}, @@ -2638,9 +2510,6 @@ int battle_config_read(const char *cfgName) {"zeny_penalty", &battle_config.zeny_penalty}, {"restart_hp_rate", &battle_config.restart_hp_rate}, {"restart_sp_rate", &battle_config.restart_sp_rate}, - {"mvp_hp_rate", &battle_config.mvp_hp_rate}, - {"mvp_item_rate", &battle_config.mvp_item_rate}, - {"mvp_exp_rate", &battle_config.mvp_exp_rate}, {"monster_hp_rate", &battle_config.monster_hp_rate}, {"monster_max_aspd", &battle_config.monster_max_aspd}, {"atcommand_gm_only", &battle_config.atc_gmonly}, @@ -2700,9 +2569,6 @@ int battle_config_read(const char *cfgName) {"vit_penaly_count", &battle_config.vit_penaly_count}, {"vit_penaly_num", &battle_config.vit_penaly_num}, {"vit_penaly_count_lv", &battle_config.vit_penaly_count_lv}, - {"player_defense_type", &battle_config.player_defense_type}, - {"monster_defense_type", &battle_config.monster_defense_type}, - {"magic_defense_type", &battle_config.magic_defense_type}, {"player_skill_reiteration", &battle_config.pc_skill_reiteration}, {"monster_skill_reiteration", &battle_config.monster_skill_reiteration}, {"player_skill_nofootset", &battle_config.pc_skill_nofootset}, @@ -2740,26 +2606,11 @@ int battle_config_read(const char *cfgName) {"skill_removetrap_type", &battle_config.skill_removetrap_type}, {"disp_experience", &battle_config.disp_experience}, {"riding_weight", &battle_config.riding_weight}, - {"item_rate_common", &battle_config.item_rate_common}, // Added by RoVeRT - {"item_rate_equip", &battle_config.item_rate_equip}, - {"item_rate_card", &battle_config.item_rate_card}, // End Addition - {"item_rate_heal", &battle_config.item_rate_heal}, // Added by Valaris - {"item_rate_use", &battle_config.item_rate_use}, // End - {"item_drop_common_min", &battle_config.item_drop_common_min}, // Added by TyrNemesis^ - {"item_drop_common_max", &battle_config.item_drop_common_max}, - {"item_drop_equip_min", &battle_config.item_drop_equip_min}, - {"item_drop_equip_max", &battle_config.item_drop_equip_max}, - {"item_drop_card_min", &battle_config.item_drop_card_min}, - {"item_drop_card_max", &battle_config.item_drop_card_max}, - {"item_drop_mvp_min", &battle_config.item_drop_mvp_min}, - {"item_drop_mvp_max", &battle_config.item_drop_mvp_max}, // End Addition {"prevent_logout", &battle_config.prevent_logout}, // Added by RoVeRT {"alchemist_summon_reward", &battle_config.alchemist_summon_reward}, // [Valaris] {"maximum_level", &battle_config.maximum_level}, // [Valaris] {"drops_by_luk", &battle_config.drops_by_luk}, // [Valaris] {"monsters_ignore_gm", &battle_config.monsters_ignore_gm}, // [Valaris] - {"equipment_breaking", &battle_config.equipment_breaking}, // [Valaris] - {"equipment_break_rate", &battle_config.equipment_break_rate}, // [Valaris] {"pk_mode", &battle_config.pk_mode}, // [Valaris] {"multi_level_up", &battle_config.multi_level_up}, // [Valaris] {"backstab_bow_penalty", &battle_config.backstab_bow_penalty}, @@ -2867,23 +2718,6 @@ int battle_config_read(const char *cfgName) if (battle_config.vit_penaly_count < 2) battle_config.vit_penaly_count = 2; - if (battle_config.item_drop_common_min < 1) // Added by TyrNemesis^ - battle_config.item_drop_common_min = 1; - if (battle_config.item_drop_common_max > 10000) - battle_config.item_drop_common_max = 10000; - if (battle_config.item_drop_equip_min < 1) - battle_config.item_drop_equip_min = 1; - if (battle_config.item_drop_equip_max > 10000) - battle_config.item_drop_equip_max = 10000; - if (battle_config.item_drop_card_min < 1) - battle_config.item_drop_card_min = 1; - if (battle_config.item_drop_card_max > 10000) - battle_config.item_drop_card_max = 10000; - if (battle_config.item_drop_mvp_min < 1) - battle_config.item_drop_mvp_min = 1; - if (battle_config.item_drop_mvp_max > 10000) - battle_config.item_drop_mvp_max = 10000; // End Addition - if (battle_config.hack_info_GM_level < 0) // added by [Yor] battle_config.hack_info_GM_level = 0; else if (battle_config.hack_info_GM_level > 100) diff --git a/src/map/battle.hpp b/src/map/battle.hpp index 263e3f6..6d9d8dd 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -74,7 +74,6 @@ Element battle_get_elem_type(struct block_list *bl) int battle_get_party_id(struct block_list *bl); Race battle_get_race(struct block_list *bl); MobMode battle_get_mode(struct block_list *bl); -int battle_get_mexp(struct block_list *bl); int battle_get_stat(SP stat_id, struct block_list *bl); eptr battle_get_sc_data(struct block_list *bl); @@ -112,11 +111,7 @@ extern struct Battle_Config int item_first_get_time; int item_second_get_time; int item_third_get_time; - int mvp_item_first_get_time; - int mvp_item_second_get_time; - int mvp_item_third_get_time; - int item_rate, base_exp_rate, job_exp_rate; // removed item rate, depreciated - int drop_rate0item; + int base_exp_rate, job_exp_rate; int death_penalty_type; int death_penalty_base, death_penalty_job; int pvp_exp; // [MouseJstr] @@ -124,8 +119,6 @@ extern struct Battle_Config int zeny_penalty; int restart_hp_rate; int restart_sp_rate; - int mvp_item_rate, mvp_exp_rate; - int mvp_hp_rate; int monster_hp_rate; int monster_max_aspd; int atc_gmonly; @@ -182,9 +175,6 @@ extern struct Battle_Config int vit_penaly_type; int vit_penaly_count; int vit_penaly_num; - int player_defense_type; - int monster_defense_type; - int magic_defense_type; int pc_skill_reiteration; int monster_skill_reiteration; int pc_skill_nofootset; @@ -212,13 +202,6 @@ extern struct Battle_Config int mob_attack_attr_none; int mob_ghostring_fix; int pc_attack_attr_none; - int item_rate_common, item_rate_card, item_rate_equip, item_rate_heal, item_rate_use; // Added by RoVeRT, Additional Heal and Usable item rate by Val - int item_drop_common_min, item_drop_common_max; // Added by TyrNemesis^ - int item_drop_card_min, item_drop_card_max; - int item_drop_equip_min, item_drop_equip_max; - int item_drop_mvp_min, item_drop_mvp_max; // End Addition - int item_drop_heal_min, item_drop_heal_max; // Added by Valatris - int item_drop_use_min, item_drop_use_max; //End int prevent_logout; // Added by RoVeRT @@ -226,8 +209,6 @@ extern struct Battle_Config int maximum_level; int drops_by_luk; int monsters_ignore_gm; - int equipment_breaking; - int equipment_break_rate; int multi_level_up; int pk_mode; int show_mob_hp; // end additions [Valaris] diff --git a/src/map/clif.cpp b/src/map/clif.cpp index b0fef3a..2da8a14 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -8,7 +8,7 @@ #include "../common/cxxstdio.hpp" #include "../common/md5calc.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 06b2873..9c6d4e6 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -5,7 +5,7 @@ #include "../common/cxxstdio.hpp" #include "../common/db.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" @@ -20,17 +20,6 @@ constexpr int MAX_RANDITEM = 2000; static struct dbt *item_db; -static -struct random_item_data blue_box[MAX_RANDITEM], - violet_box[MAX_RANDITEM], card_album[MAX_RANDITEM], - gift_box[MAX_RANDITEM], scroll[MAX_RANDITEM]; -static -int blue_box_count = 0, violet_box_count = 0, card_album_count = - 0, gift_box_count = 0, scroll_count = 0; -static -int blue_box_default = 0, violet_box_default = 0, card_album_default = - 0, gift_box_default = 0, scroll_default = 0; - // Function declarations static @@ -38,8 +27,6 @@ void itemdb_read(void); static int itemdb_readdb(void); static -int itemdb_read_randomitem(void); -static int itemdb_read_itemavail(void); static int itemdb_read_noequip(void); @@ -68,56 +55,6 @@ struct item_data *itemdb_searchname(const char *str) return item; } -/*========================================== - * 箱系アイテム検索 - *------------------------------------------ - */ -int itemdb_searchrandomid(int flags) -{ - int nameid = 0, i, index, count; - struct random_item_data *list = NULL; - - struct - { - int nameid, count; - struct random_item_data *list; - } data[] = - { - { - 0, 0, NULL}, - { - blue_box_default, blue_box_count, blue_box}, - { - violet_box_default, violet_box_count, violet_box}, - { - card_album_default, card_album_count, card_album}, - { - gift_box_default, gift_box_count, gift_box}, - { - scroll_default, scroll_count, scroll},}; - - if (flags >= 1 && flags <= 5) - { - nameid = data[flags].nameid; - count = data[flags].count; - list = data[flags].list; - - if (count > 0) - { - for (i = 0; i < 1000; i++) - { - index = MRAND(count); - if (MRAND(1000000) < list[index].per) - { - nameid = list[index].nameid; - break; - } - } - } - } - return nameid; -} - /*========================================== * DBの存在確認 *------------------------------------------ @@ -322,98 +259,6 @@ int itemdb_readdb(void) // Removed item_value_db, don't re-add! -/*========================================== - * ランダムアイテム出現データの読み込み - *------------------------------------------ - */ -static -int itemdb_read_randomitem(void) -{ - FILE *fp; - char line[1024]; - int ln = 0; - int nameid, i, j; - char *str[10], *p; - - const struct - { - char filename[64]; - struct random_item_data *pdata; - int *pcount, *pdefault; - } data[] = - { - { - "db/item_bluebox.txt", blue_box, &blue_box_count, - &blue_box_default}, - { - "db/item_violetbox.txt", violet_box, &violet_box_count, - &violet_box_default}, - { - "db/item_cardalbum.txt", card_album, &card_album_count, - &card_album_default}, - { - "db/item_giftbox.txt", gift_box, &gift_box_count, - &gift_box_default}, - { - "db/item_scroll.txt", scroll, &scroll_count, &scroll_default},}; - - for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) - { - struct random_item_data *pd = data[i].pdata; - int *pc = data[i].pcount; - int *pdefault = data[i].pdefault; - const char *fn = data[i].filename; - - *pdefault = 0; - if ((fp = fopen_(fn, "r")) == NULL) - { - PRINTF("can't read %s\n", fn); - continue; - } - - while (fgets(line, 1020, fp)) - { - if (line[0] == '/' && line[1] == '/') - continue; - memset(str, 0, sizeof(str)); - for (j = 0, p = line; j < 3 && p; j++) - { - str[j] = p; - p = strchr(p, ','); - if (p) - *p++ = 0; - } - - if (str[0] == NULL) - continue; - - nameid = atoi(str[0]); - if (nameid < 0 || nameid >= 20000) - continue; - if (nameid == 0) - { - if (str[2]) - *pdefault = atoi(str[2]); - continue; - } - - if (str[2]) - { - pd[*pc].nameid = nameid; - pd[(*pc)++].per = atoi(str[2]); - } - - if (ln >= MAX_RANDITEM) - break; - ln++; - } - fclose_(fp); - PRINTF("read %s done (count=%d)\n", fn, *pc); - } - - return 0; -} - /*========================================== * アイテム使用可能フラグのオーバーライド *------------------------------------------ @@ -585,7 +430,6 @@ static void itemdb_read(void) { itemdb_readdb(); - itemdb_read_randomitem(); itemdb_read_itemavail(); itemdb_read_noequip(); } diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 688fac1..3b808a8 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -87,8 +87,6 @@ int itemdb_viewid(int n) return itemdb_search(n)->view_id; } -int itemdb_searchrandomid(int flags); - inline int itemdb_value_sell(int n) { diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp index 65dafe4..ea853a1 100644 --- a/src/map/magic-expr.cpp +++ b/src/map/magic-expr.cpp @@ -5,7 +5,7 @@ #include #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "battle.hpp" #include "npc.hpp" @@ -709,7 +709,7 @@ int fun_random(env_t *, int, val_t *result, val_t *args) RESULTINT = 0; return 0; } - RESULTINT = MRAND(delta); + RESULTINT = random_::to(delta); if (ARGINT(0) < 0) RESULTINT = -RESULTINT; @@ -720,9 +720,9 @@ static int fun_random_dir(env_t *, int, val_t *result, val_t *args) { if (ARGINT(0)) - RESULTDIR = DIR(MRAND(8)); + RESULTDIR = random_::choice({DIR::S, DIR::SW, DIR::W, DIR::NW, DIR::N, DIR::NE, DIR::E, DIR::SE}); else - RESULTDIR = DIR(MRAND(4) * 2); + RESULTDIR = random_::choice({DIR::S, DIR::W, DIR::N, DIR::E}); return 0; } @@ -945,8 +945,7 @@ void magic_random_location(location_t *dest, area_t *area) { case AREA::UNION: { - int rv = MRAND(area->size); - if (rv < area->a.a_union[0]->size) + if (random_::chance({area->a.a_union[0]->size, area->size})) magic_random_location(dest, area->a.a_union[0]); else magic_random_location(dest, area->a.a_union[1]); @@ -966,39 +965,13 @@ void magic_random_location(location_t *dest, area_t *area) if (h <= 1) h = 1; - x += MRAND(w); - y += MRAND(h); - - if (!map_is_solid(m, x, y)) - { - int start_x = x; - int start_y = y; - int i; - DIR initial_dir = DIR(MRAND(8)); - DIR dir = initial_dir; - - /* try all directions, up to a distance to 10, for a free slot */ - do - { - x = start_x; - y = start_y; - - for (i = 0; i < 10 && map_is_solid(m, x, y); i++) - { - x += dirx[dir]; - y += diry[dir]; - } - - dir = DIR((uint8_t(dir) + 1) % 8); - } - while (map_is_solid(m, x, y) && dir != initial_dir); - - } - /* We've tried our best. If the map is still solid, the engine will automatically randomise the target location if we try to warp. */ + // This is not exactly the same as the old logic, + // but it's better. + auto pair = map_randfreecell(m, x, y, w, h); dest->m = m; - dest->x = x; - dest->y = y; + dest->x = pair.first; + dest->y = pair.second; break; } diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index fdb95fc..c729cfd 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -1,7 +1,7 @@ #include #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random2.hpp" #include "../common/timer.hpp" #include "magic-expr.hpp" @@ -1235,36 +1235,18 @@ effect_t *run_foreach(invocation_t *invocation, effect_t *foreach, cont_activation_record_t *ar = add_stack_entry(invocation, CONT_STACK::FOREACH, return_location); int entities_allocd = 64; - int *entities_collect; int *entities; - int *shuffle_board; int entities_nr = 0; - int i; if (!ar) return return_location; - CREATE(entities_collect, int, entities_allocd); - + CREATE(entities, int, entities_allocd); find_entities_in_area(area.v.v_area, &entities_allocd, &entities_nr, - &entities_collect, filter); - - /* Now shuffle */ - CREATE(shuffle_board, int, entities_nr); - CREATE(entities, int, entities_nr); - for (i = 0; i < entities_nr; i++) - shuffle_board[i] = i; - - for (i = entities_nr - 1; i >= 0; i--) - { - int random_index = MRAND(i + 1); - entities[i] = entities_collect[shuffle_board[random_index]]; - shuffle_board[random_index] = shuffle_board[i]; // thus, we are guaranteed only to use unused indices - } - - free(entities_collect); - free(shuffle_board); - /* Done shuffling */ + &entities, filter); + RECREATE(entities, int, entities_nr); + // iterator_pair will go away when this gets properly containerized. + random_::shuffle(iterator_pair(entities, entities + entities_nr)); ar->c.c_foreach.id = id; ar->c.c_foreach.body = body; diff --git a/src/map/map.cpp b/src/map/map.cpp index 7e2bf13..6ed7662 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -13,7 +13,7 @@ #include "../common/cxxstdio.hpp" #include "../common/db.hpp" #include "../common/grfio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random2.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" @@ -768,56 +768,24 @@ void map_clearflooritem_timer(TimerData *tid, tick_t, int id) map_delobject(fitem->bl.id, BL::ITEM); } -/*========================================== - * (m,x,y)の周囲rangeマス内の空き(=侵入可能)cellの - * 内から適当なマス目の座標をx+(y<<16)で返す - * - * 現状range=1でアイテムドロップ用途のみ - *------------------------------------------ - */ -static -int map_searchrandfreecell(int m, int x, int y, int range) +std::pair map_randfreecell(int m, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - int free_cell, i, j, c; - - for (free_cell = 0, i = -range; i <= range; i++) - { - if (i + y < 0 || i + y >= map[m].ys) - continue; - for (j = -range; j <= range; j++) - { - if (j + x < 0 || j + x >= map[m].xs) - continue; - if ((c = read_gat(m, j + x, i + y)) == 1 || c == 5) - continue; - free_cell++; - } - } - if (free_cell == 0) - return -1; - free_cell = MRAND(free_cell); - for (i = -range; i <= range; i++) + for (int itr : random_::iterator(w * h)) { - if (i + y < 0 || i + y >= map[m].ys) - continue; - for (j = -range; j <= range; j++) - { - if (j + x < 0 || j + x >= map[m].xs) - continue; - if ((c = read_gat(m, j + x, i + y)) == 1 || c == 5) - continue; - if (free_cell == 0) - { - x += j; - y += i; - i = range + 1; - break; - } - free_cell--; - } + int dx = itr % w; + int dy = itr / w; + if (read_gat(m, x + dx, y + dy) == 1) + return {static_cast(x + dx), static_cast(y + dy)}; } + return {static_cast(0), static_cast(0)}; +} - return x + (y << 16); +/// Return a randomly selected passable cell within a given range. +static +std::pair map_searchrandfreecell(int m, int x, int y, int range) +{ + int whole_range = 2 * range + 1; + return map_randfreecell(m, x - range, y - range, whole_range, whole_range); } /*========================================== @@ -831,21 +799,19 @@ int map_addflooritem_any(struct item *item_data, int amount, struct map_session_data **owners, interval_t *owner_protection, interval_t lifetime, int dispersal) { - int xy, r; struct flooritem_data *fitem = NULL; nullpo_ret(item_data); - - if ((xy = map_searchrandfreecell(m, x, y, dispersal)) < 0) + auto xy = map_searchrandfreecell(m, x, y, dispersal); + if (xy.first == 0 && xy.second == 0) return 0; - r = mt_random(); CREATE(fitem, struct flooritem_data, 1); fitem->bl.type = BL::ITEM; fitem->bl.prev = fitem->bl.next = NULL; fitem->bl.m = m; - fitem->bl.x = xy & 0xffff; - fitem->bl.y = (xy >> 16) & 0xffff; + fitem->bl.x = xy.first; + fitem->bl.y = xy.second; fitem->first_get_id = 0; fitem->first_get_tick = tick_t(); fitem->second_get_id = 0; @@ -876,8 +842,13 @@ int map_addflooritem_any(struct item *item_data, int amount, memcpy(&fitem->item_data, item_data, sizeof(*item_data)); fitem->item_data.amount = amount; - fitem->subx = (r & 3) * 3 + 3; - fitem->suby = ((r >> 2) & 3) * 3 + 3; + // TODO - talk to 4144 about maybe removing this. + // It has no effect on the server itself, it is visual only. + // If it is desirable to prevent items from visibly stacking + // on the ground, that can be done with client-side randomness. + // Currently, it yields the numbers {3 6 9 12}. + fitem->subx = random_::in(1, 4) * 3; + fitem->suby = random_::in(1, 4) * 3; fitem->cleartimer = add_timer(gettick() + lifetime, std::bind(map_clearflooritem_timer, ph::_1, ph::_2, fitem->bl.id)); @@ -892,18 +863,11 @@ int map_addflooritem(struct item *item_data, int amount, int m, int x, int y, struct map_session_data *first_sd, struct map_session_data *second_sd, - struct map_session_data *third_sd, bool type) + struct map_session_data *third_sd) { struct map_session_data *owners[3] = { first_sd, second_sd, third_sd }; interval_t owner_protection[3]; - if (type) - { - owner_protection[0] = static_cast(battle_config.mvp_item_first_get_time); - owner_protection[1] = owner_protection[0] + static_cast(battle_config.mvp_item_second_get_time); - owner_protection[2] = owner_protection[1] + static_cast(battle_config.mvp_item_third_get_time); - } - else { owner_protection[0] = static_cast(battle_config.item_first_get_time); owner_protection[1] = owner_protection[0] + static_cast(battle_config.item_second_get_time); diff --git a/src/map/map.hpp b/src/map/map.hpp index 2af7ec8..72ded63 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -419,7 +419,6 @@ struct map_data unsigned nopenalty:1; unsigned pvp:1; unsigned pvp_noparty:1; - unsigned pvp_nightmaredrop:1; unsigned pvp_nocalcrank:1; unsigned nozenypenalty:1; unsigned notrade:1; @@ -557,7 +556,7 @@ int map_addflooritem_any(struct item *, int amount, int m, int x, int y, interval_t lifetime, int dispersal); int map_addflooritem(struct item *, int, int, int, int, struct map_session_data *, struct map_session_data *, - struct map_session_data *, bool); + struct map_session_data *); // キャラid=>キャラ名 変換関連 void map_addchariddb(int charid, const char *name); @@ -594,6 +593,7 @@ DIR map_calc_dir(struct block_list *src, int x, int y); // path.cより int path_search(struct walkpath_data *, int, int, int, int, int, int); -int path_blownpos(int m, int x0, int y0, int dx, int dy, int count); + +std::pair map_randfreecell(int m, uint16_t x, uint16_t y, uint16_t w, uint16_t h); #endif // MAP_HPP diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 20bf1ec..80671c2 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -1,3 +1,4 @@ + #include "mob.hpp" #include @@ -8,7 +9,7 @@ #include #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" @@ -27,9 +28,9 @@ constexpr interval_t MIN_MOBTHINKTIME = std::chrono::milliseconds(100); // Move probability in the negligent mode MOB (rate of 1000 minute) -constexpr int MOB_LAZYMOVEPERC = 50; +constexpr random_::Fraction MOB_LAZYMOVEPERC {50, 1000}; // Warp probability in the negligent mode MOB (rate of 1000 minute) -constexpr int MOB_LAZYWARPPERC = 20; +constexpr random_::Fraction MOB_LAZYWARPPERC {20, 1000}; struct mob_db mob_db[2001]; @@ -326,19 +327,33 @@ void mob_init(struct mob_data *md) for (i = 0; i < mutations_nr; i++) { - mob_stat stat_nr = mob_stat(MRAND(unsigned(mob_stat::LAST))); - int strength; - - // double chance to modify hp - if (stat_nr == mob_stat::XP_BONUS) - stat_nr = mob_stat::MAX_HP; - - strength = - ((MRAND((mutation_power >> 1)) + - (MRAND((mutation_power >> 1))) + - 2) * mutation_scale[stat_nr]) / 100; - - strength = MRAND(2) ? strength : -strength; + mob_stat stat_nr = random_::choice({ + mob_stat::LV, + mob_stat::MAX_HP, + mob_stat::STR, + mob_stat::AGI, + mob_stat::VIT, + mob_stat::INT, + mob_stat::DEX, + mob_stat::LUK, + mob_stat::ATK1, + mob_stat::ATK2, + mob_stat::ADELAY, + mob_stat::DEF, + mob_stat::MDEF, + mob_stat::SPEED, + // double chance to modify hp + mob_stat::MAX_HP, + }); + // TODO: if I don't remove this entirely, look into + // normal distributions. + int strength = (random_::to(mutation_power / 2) + + random_::to(mutation_power / 2) + + 2) + * mutation_scale[stat_nr] / 100; + + if (random_::coin()) + strength = -strength; if (strength < -240) strength = -240; /* Don't go too close to zero */ @@ -356,10 +371,7 @@ int mob_once_spawn(struct map_session_data *sd, const char *mapname, const char *event) { struct mob_data *md = NULL; - int m, count, lv = 255, r = mob_class; - - if (sd) - lv = sd->status.base_level; + int m, count, r = mob_class; if (sd && strcmp(mapname, "this") == 0) m = sd->bl.m; @@ -369,35 +381,6 @@ int mob_once_spawn(struct map_session_data *sd, const char *mapname, if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // 値が異常なら召喚を止める return 0; - if (mob_class < 0) - { // ランダムに召喚 - int i = 0; - int j = -mob_class - 1; - int k; - if (j >= 0 && j < MAX_RANDOMMONSTER) - { - do - { - mob_class = MPRAND(1001, 1000); - k = MRAND(1000000); - } - while ((mob_db[mob_class].max_hp <= 0 - || mob_db[mob_class].summonper[j] <= k - || (lv < mob_db[mob_class].lv - && battle_config.random_monster_checklv == 1)) - && (i++) < 2000); - if (i >= 2000) - { - mob_class = mob_db[0].summonper[j]; - } - } - else - { - return 0; - } -// if(battle_config.etc_log==1) -// PRINTF("mobmob_class=%d try=%d\n",mob_class,i); - } if (sd) { if (x <= 0) @@ -472,8 +455,8 @@ int mob_once_spawn_area(struct map_session_data *sd, const char *mapname, int j = 0; do { - x = MPRAND(x0, (x1 - x0 + 1)); - y = MPRAND(y0, (y1 - y0 + 1)); + x = random_::in(x0, x1); + y = random_::in(y0, y1); } while (((c = map_getcell(m, x, y)) == 1 || c == 5) && (++j) < max); if (j >= max) @@ -493,65 +476,6 @@ int mob_once_spawn_area(struct map_session_data *sd, const char *mapname, return id; } -/*========================================== - * Summoning Guardians [Valaris] - *------------------------------------------ - */ -int mob_spawn_guardian(struct map_session_data *sd, const char *mapname, - int x, int y, const char *mobname, int mob_class, - int amount, const char *event, int) -{ - struct mob_data *md = NULL; - int m, count = 1; - - if (sd && strcmp(mapname, "this") == 0) - m = sd->bl.m; - else - m = map_mapname2mapid(mapname); - - if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // 値が異常なら召喚を止める - return 0; - - if (mob_class < 0) - return 0; - - if (sd) - { - if (x <= 0) - x = sd->bl.x; - if (y <= 0) - y = sd->bl.y; - } - - else if (x <= 0 || y <= 0) - PRINTF("mob_spawn_guardian: ??\n"); - - for (count = 0; count < amount; count++) - { - CREATE(md, struct mob_data, 1); - - mob_spawn_dataset(md, mobname, mob_class); - md->bl.m = m; - md->bl.x = x; - md->bl.y = y; - md->m = m; - md->x0 = x; - md->y0 = y; - md->xs = 0; - md->ys = 0; - md->spawndelay1 = static_cast(-1); // Only once is a flag. - md->spawndelay2 = static_cast(-1); // Only once is a flag. - - memcpy(md->npc_event, event, sizeof(md->npc_event)); - - md->bl.type = BL::MOB; - map_addiddb(&md->bl); - mob_spawn(md->bl.id); - } - - return (amount > 0) ? md->bl.id : 0; -} - // TODO: deprecate these int mob_get_sex(int mob_class) { @@ -1162,13 +1086,15 @@ int mob_spawn(int id) { if (md->x0 == 0 && md->y0 == 0) { - x = MPRAND(1, (map[md->bl.m].xs - 2)); - y = MPRAND(1, (map[md->bl.m].ys - 2)); + x = random_::in(1, map[md->bl.m].xs - 2); + y = random_::in(1, map[md->bl.m].ys - 2); } else { - x = MPRAND(md->x0, (md->xs + 1)) - md->xs / 2; - y = MPRAND(md->y0, (md->ys + 1)) - md->ys / 2; + // TODO: move this logic earlier - possibly all the way + // into the data files + x = md->x0 - md->xs / 2 + random_::in(0, md->xs); + y = md->y0 - md->ys / 2 + random_::in(0, md->ys); } i++; } @@ -1207,7 +1133,7 @@ int mob_spawn(int id) md->state.skillstate = MobSkillState::MSS_IDLE; md->timer = nullptr; md->last_thinktime = tick; - md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(MRAND(50)); + md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(random_::to(50)); md->attackabletime = tick; md->canmove_tick = tick; @@ -1412,7 +1338,8 @@ int mob_target(struct mob_data *md, struct block_list *bl, int dist) } // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending. if ((md->target_id > 0 && md->state.attackable) - && (!bool(mode & MobMode::AGGRESSIVE) || MRAND(100) > 25)) + && (!bool(mode & MobMode::AGGRESSIVE) + || !random_::chance({25 + 1, 100}))) return 0; // Coercion is exerted if it is MVPMOB. @@ -1494,10 +1421,13 @@ void mob_ai_sub_hard_activesearch(struct block_list *bl, || (!tsd->state.gangsterparadise || race == Race::_insect || race == Race::_demon)) - { // 妨害がないか判定 - if (mob_can_reach(smd, bl, 12) && // 到達可能性判定 - MRAND(1000) < 1000 / (++(*pcc))) - { // 範囲内PCで等確率にする + { + // 妨害がないか判定 + // 到達可能性判定 + if (mob_can_reach(smd, bl, 12) + && random_::chance({1, ++*pcc})) + { + // 範囲内PCで等確率にする smd->target_id = tsd->bl.id; smd->state.attackable = true; smd->min_chase = 13; @@ -1510,9 +1440,11 @@ void mob_ai_sub_hard_activesearch(struct block_list *bl, (dist = distance(smd->bl.x, smd->bl.y, tmd->bl.x, tmd->bl.y)) < 9) { - if (mob_can_reach(smd, bl, 12) && // 到達可能性判定 - MRAND(1000) < 1000 / (++(*pcc))) - { // 範囲内で等確率にする + // 到達可能性判定 + if (mob_can_reach(smd, bl, 12) + && random_::chance({1, ++*pcc})) + { + // 範囲内で等確率にする smd->target_id = bl->id; smd->state.attackable = true; smd->min_chase = 13; @@ -1551,9 +1483,11 @@ void mob_ai_sub_hard_lootsearch(struct block_list *bl, struct mob_data *md, int if (bl->m == md->bl.m && (dist = distance(md->bl.x, md->bl.y, bl->x, bl->y)) < 9) { - if (mob_can_reach(md, bl, 12) && // Reachability judging - MRAND(1000) < 1000 / (++(*itc))) - { // It is made a probability, such as within the limits PC. + // Reachability judging + if (mob_can_reach(md, bl, 12) + && random_::chance({1, ++*itc})) + { + // It is made a probability, such as within the limits PC. md->target_id = bl->id; md->state.attackable = false; md->min_chase = 13; @@ -1653,18 +1587,18 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, tick_t tick) dx = mmd->bl.x - md->bl.x; dy = mmd->bl.y - md->bl.y; if (dx < 0) - dx += (MPRAND(1, ((dx < -3) ? 3 : -dx))); + dx += random_::in(1, std::min(3, -dx)); else if (dx > 0) - dx -= (MPRAND(1, ((dx > 3) ? 3 : dx))); + dx -= random_::in(1, std::min(3, dx)); if (dy < 0) - dy += (MPRAND(1, ((dy < -3) ? 3 : -dy))); + dy += random_::in(1, std::min(3, -dy)); else if (dy > 0) - dy -= (MPRAND(1, ((dy > 3) ? 3 : dy))); + dy -= random_::in(1, std::min(3, dy)); } else { - dx = mmd->bl.x - md->bl.x + MRAND(7) - 3; - dy = mmd->bl.y - md->bl.y + MRAND(7) - 3; + dx = mmd->bl.x - md->bl.x + random_::in(-3, 3); + dy = mmd->bl.y - md->bl.y + random_::in(-3, 3); } ret = mob_walktoxy(md, md->bl.x + dx, md->bl.y + dy, 0); @@ -1676,12 +1610,14 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, tick_t tick) { do { - dx = MRAND(9) - 5; - dy = MRAND(9) - 5; + // changed to do what it was obviously supposed to do, + // instead of what it was doing ... + dx = random_::in(-4, 4); + dy = random_::in(-4, 4); if (dx == 0 && dy == 0) { - dx = (MRAND(1)) ? 1 : -1; - dy = (MRAND(1)) ? 1 : -1; + dx = random_::coin() ? 1 : -1; + dy = random_::coin() ? 1 : -1; } dx += mmd->bl.x; dy += mmd->bl.y; @@ -1736,7 +1672,7 @@ int mob_unlocktarget(struct mob_data *md, tick_t tick) md->target_id = 0; md->state.attackable = false; md->state.skillstate = MobSkillState::MSS_IDLE; - md->next_walktime = tick + std::chrono::seconds(3) + std::chrono::milliseconds(MRAND(3000)); + md->next_walktime = tick + std::chrono::seconds(3) + std::chrono::milliseconds(random_::to(3000)); return 0; } @@ -1760,9 +1696,8 @@ int mob_randomwalk(struct mob_data *md, tick_t tick) for (i = 0; i < retrycount; i++) { // Search of a movable place - int r = mt_random(); - x = md->bl.x + r % (d * 2 + 1) - d; - y = md->bl.y + r / (d * 2 + 1) % (d * 2 + 1) - d; + x = md->bl.x + random_::in(-d, d); + y = md->bl.y + random_::in(-d, d); uint8_t c = map_getcell(md->bl.m, x, y); if (c != 1 && c != 5 && mob_walktoxy(md, x, y, 1) == 0) @@ -1792,7 +1727,7 @@ int mob_randomwalk(struct mob_data *md, tick_t tick) else c += speed; } - md->next_walktime = tick + std::chrono::seconds(3) + std::chrono::milliseconds(MRAND(3000)) + c; + md->next_walktime = tick + std::chrono::seconds(3) + std::chrono::milliseconds(random_::to(3000)) + c; md->state.skillstate = MobSkillState::MSS_WALK; return 1; } @@ -1860,7 +1795,7 @@ void mob_ai_sub_hard(struct block_list *bl, tick_t tick) // It checks to see it was attacked first (if active, it is target change at 25% of probability). if (mode != MobMode::ZERO && md->attacked_id > 0 && (!md->target_id || !md->state.attackable - || (bool(mode & MobMode::AGGRESSIVE) && MRAND(100) < 25))) + || (bool(mode & MobMode::AGGRESSIVE) && random_::chance({25, 100})))) { struct block_list *abl = map_id2bl(md->attacked_id); struct map_session_data *asd = NULL; @@ -1971,7 +1906,8 @@ void mob_ai_sub_hard(struct block_list *bl, tick_t tick) do { if (i == 0) - { // 最初はAEGISと同じ方法で検索 + { + // 最初はAEGISと同じ方法で検索 dx = tbl->x - md->bl.x; dy = tbl->y - md->bl.y; if (dx < 0) @@ -1984,9 +1920,11 @@ void mob_ai_sub_hard(struct block_list *bl, tick_t tick) dy--; } else - { // だめならAthena式(ランダム) - dx = tbl->x - md->bl.x + MRAND(3) - 1; - dy = tbl->y - md->bl.y + MRAND(3) - 1; + { + // だめならAthena式(ランダム) + // {0 1 2} + dx = tbl->x - md->bl.x + random_::in(-1, 1); + dy = tbl->y - md->bl.y + random_::in(-1, 1); } ret = mob_walktoxy(md, md->bl.x + dx, md->bl.y + dy, 0); i++; @@ -2114,7 +2052,7 @@ void mob_ai_sub_hard(struct block_list *bl, tick_t tick) // yields 3000 * {0 3000 6000 9000 ... 5991000 5994000 5997000} // I have reverted to the original logic, but I don't understand. #warning "I don't understand this code! It is either wrong now or was wrong before." - md->next_walktime = tick + std::chrono::seconds(MRAND(2)); + md->next_walktime = tick + std::chrono::seconds(random_::to(2)); } // Random movement @@ -2190,13 +2128,14 @@ void mob_ai_sub_lazy(db_key_t, db_val_t data, tick_t tick) // Since PC is in the same map, somewhat better negligent processing is carried out. // It sometimes moves. - if (MRAND(1000) < MOB_LAZYMOVEPERC) + if (random_::chance(MOB_LAZYMOVEPERC)) mob_randomwalk(md, tick); // MOB which is not not the summons MOB but BOSS, either sometimes reboils. - else if (MRAND(1000) < MOB_LAZYWARPPERC && md->x0 <= 0 - && md->master_id != 0 && mob_db[md->mob_class].mexp <= 0 - && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) + else if (random_::chance(MOB_LAZYWARPPERC) + && md->x0 <= 0 + && md->master_id != 0 + && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) mob_spawn(md->bl.id); } @@ -2205,13 +2144,14 @@ void mob_ai_sub_lazy(db_key_t, db_val_t data, tick_t tick) // Since PC is not even in the same map, suitable processing is carried out even if it takes. // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping - if (MRAND(1000) < MOB_LAZYWARPPERC && md->x0 <= 0 - && md->master_id != 0 && mob_db[md->mob_class].mexp <= 0 + if (random_::chance(MOB_LAZYWARPPERC) + && md->x0 <= 0 + && md->master_id != 0 && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) mob_warp(md, -1, -1, -1, BeingRemoveWhy::NEGATIVE1); } - md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(MRAND(10 * 1000)); + md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(random_::to(10 * 1000)); } } @@ -2270,16 +2210,17 @@ void mob_delay_item_drop(TimerData *, tick_t, struct delay_item_drop *ditem) != PickupFail::OKAY) { clif_additem(ditem->first_sd, 0, 0, flag); - map_addflooritem(&temp_item, 1, ditem->m, ditem->x, ditem->y, - ditem->first_sd, ditem->second_sd, - ditem->third_sd, 0); + map_addflooritem(&temp_item, 1, + ditem->m, ditem->x, ditem->y, + ditem->first_sd, ditem->second_sd, ditem->third_sd); } free(ditem); return; } - map_addflooritem(&temp_item, 1, ditem->m, ditem->x, ditem->y, - ditem->first_sd, ditem->second_sd, ditem->third_sd, 0); + map_addflooritem(&temp_item, 1, + ditem->m, ditem->x, ditem->y, + ditem->first_sd, ditem->second_sd, ditem->third_sd); free(ditem); } @@ -2305,16 +2246,16 @@ void mob_delay_item_drop2(TimerData *, tick_t, struct delay_item_drop2 *ditem) { clif_additem(ditem->first_sd, 0, 0, flag); map_addflooritem(&ditem->item_data, ditem->item_data.amount, - ditem->m, ditem->x, ditem->y, ditem->first_sd, - ditem->second_sd, ditem->third_sd, 0); + ditem->m, ditem->x, ditem->y, + ditem->first_sd, ditem->second_sd, ditem->third_sd); } free(ditem); return; } - map_addflooritem(&ditem->item_data, ditem->item_data.amount, ditem->m, - ditem->x, ditem->y, ditem->first_sd, ditem->second_sd, - ditem->third_sd, 0); + map_addflooritem(&ditem->item_data, ditem->item_data.amount, + ditem->m, ditem->x, ditem->y, + ditem->first_sd, ditem->second_sd, ditem->third_sd); free(ditem); } @@ -2418,9 +2359,7 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, tick_t tick = gettick(); struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd = NULL; - double tdmg, temp; - struct item item; - PickupFail ret; + double tdmg; nullpo_ret(md); //srcはNULLで呼ばれる場合もあるので、他でチェック @@ -2701,22 +2640,19 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, for (int i = 0; i < 8; i++) { struct delay_item_drop *ditem; - int drop_rate; if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris] break; // End if (mob_db[md->mob_class].dropitem[i].nameid <= 0) continue; - drop_rate = mob_db[md->mob_class].dropitem[i].p; - if (drop_rate <= 0 && battle_config.drop_rate0item == 1) - drop_rate = 1; + random_::Fixed drop_rate = mob_db[md->mob_class].dropitem[i].p; if (battle_config.drops_by_luk > 0 && sd && md) - drop_rate += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris] + drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris] if (sd && md && battle_config.pk_mode == 1 && (mob_db[md->mob_class].lv - sd->status.base_level >= 20)) - drop_rate *= 1.25; // pk_mode increase drops if 20 level difference [Valaris] - if (drop_rate <= MRAND(10000)) + drop_rate.num *= 1.25; // pk_mode increase drops if 20 level difference [Valaris] + if (!random_::chance(drop_rate)) continue; ditem = (struct delay_item_drop *) @@ -2756,53 +2692,6 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, } } } - - // mvp処理 - if (mvp_sd && mob_db[md->mob_class].mexp > 0) - { - int j; - int mexp = battle_get_mexp(&md->bl); - temp = - ((double) mexp * (double) battle_config.mvp_exp_rate * - (9. + (double) count) / 1000.); - mexp = (temp > 2147483647.) ? 0x7fffffff : (int) temp; - if (mexp < 1) - mexp = 1; - clif_mvp_effect(mvp_sd); // エフェクト - pc_gainexp(mvp_sd, mexp, 0); - for (j = 0; j < 3; j++) - { - int i = MRAND(3); - if (mob_db[md->mob_class].mvpitem[i].nameid <= 0) - continue; - int drop_rate = mob_db[md->mob_class].mvpitem[i].p; - if (drop_rate <= 0 && battle_config.drop_rate0item == 1) - drop_rate = 1; - if (drop_rate < battle_config.item_drop_mvp_min) - drop_rate = battle_config.item_drop_mvp_min; - if (drop_rate > battle_config.item_drop_mvp_max) - drop_rate = battle_config.item_drop_mvp_max; - if (drop_rate <= MRAND(10000)) - continue; - memset(&item, 0, sizeof(item)); - item.nameid = mob_db[md->mob_class].mvpitem[i].nameid; - item.identify = !itemdb_isequip3(item.nameid); - if (mvp_sd->weight * 2 > mvp_sd->max_weight) - map_addflooritem(&item, 1, mvp_sd->bl.m, mvp_sd->bl.x, - mvp_sd->bl.y, mvp_sd, second_sd, - third_sd, 1); - else if ((ret = pc_additem(mvp_sd, &item, 1)) - != PickupFail::OKAY) - { - clif_additem(sd, 0, 0, ret); - map_addflooritem(&item, 1, mvp_sd->bl.m, mvp_sd->bl.x, - mvp_sd->bl.y, mvp_sd, second_sd, - third_sd, 1); - } - break; - } - } - } // [MouseJstr] // SCRIPT実行 @@ -2843,83 +2732,6 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage, return 0; } -/*========================================== - * - *------------------------------------------ - */ -int mob_class_change(struct mob_data *md, int *value) -{ - tick_t tick = gettick(); - int i, hp_rate, max_hp, mob_class, count = 0; - - nullpo_ret(md); - nullpo_ret(value); - - if (value[0] <= 1000 || value[0] > 2000) - return 0; - if (md->bl.prev == NULL) - return 0; - - while (count < 5 && value[count] > 1000 && value[count] <= 2000) - count++; - if (count < 1) - return 0; - - mob_class = value[MRAND(count)]; - if (mob_class <= 1000 || mob_class > 2000) - return 0; - - max_hp = battle_get_max_hp(&md->bl); - hp_rate = md->hp * 100 / max_hp; - md->mob_class = mob_class; - max_hp = battle_get_max_hp(&md->bl); - if (battle_config.monster_class_change_full_recover == 1) - { - md->hp = max_hp; - memset(md->dmglog, 0, sizeof(md->dmglog)); - } - else - md->hp = max_hp * hp_rate / 100; - if (md->hp > max_hp) - md->hp = max_hp; - else if (md->hp < 1) - md->hp = 1; - - memcpy(md->name, mob_db[mob_class].jname, 24); - memset(&md->state, 0, sizeof(md->state)); - md->attacked_id = 0; - md->target_id = 0; - md->move_fail_count = 0; - - md->stats[mob_stat::SPEED] = mob_db[md->mob_class].speed; - md->def_ele = mob_db[md->mob_class].element; - - mob_changestate(md, MS::IDLE, 0); - skill_castcancel(&md->bl, 0); - md->state.skillstate = MobSkillState::MSS_IDLE; - md->last_thinktime = tick; - md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(MRAND(50)); - md->attackabletime = tick; - md->canmove_tick = tick; - md->sg_count = 0; - - tick_t c = tick - std::chrono::hours(10); - for (i = 0; i < MAX_MOBSKILL; i++) - md->skilldelay[i] = c; - md->skillid = SkillID(); - md->skilllv = 0; - - if (md->lootitem == NULL - && bool(mob_db[mob_class].mode & MobMode::LOOTER)) - md->lootitem = (struct item *) - calloc(LOOTITEM_SIZE, sizeof(struct item)); - - clif_clearchar(&md->bl, BeingRemoveWhy::GONE); - clif_spawnmob(md); - - return 0; -} - /*========================================== * mob回復 *------------------------------------------ @@ -2999,14 +2811,16 @@ int mob_warp(struct mob_data *md, int m, int x, int y, BeingRemoveWhy type) && (i++) < 1000) { if (xs > 0 && ys > 0 && i < 250) - { // 指定位置付近の探索 - x = MPRAND(bx, xs) - xs / 2; - y = MPRAND(by, ys) - ys / 2; + { + // 指定位置付近の探索 + x = bx + random_::to(xs) - xs / 2; + y = by + random_::to(ys) - ys / 2; } else - { // 完全ランダム探索 - x = MPRAND(1, (map[m].xs - 2)); - y = MPRAND(1, (map[m].ys - 2)); + { + // 完全ランダム探索 + x = random_::in(1, map[m].xs - 2); + y = random_::in(1, map[m].ys - 2); } } md->dir = DIR::S; @@ -3121,8 +2935,8 @@ int mob_summonslave(struct mob_data *md2, int *value, int amount, int flag) while ((x <= 0 || y <= 0 || (c = map_getcell(m, x, y)) == 1 || c == 5) && (i++) < 100) { - x = MPRAND(bx, 9) - 4; - y = MPRAND(by, 9) - 4; + x = bx + random_::in(-4, 4); + y = by + random_::in(-4, 4); } if (i >= 100) { @@ -3530,7 +3344,7 @@ int mobskill_use(struct mob_data *md, tick_t tick, } // 確率判定 - if (flag && MRAND(10000) < ms[ii].permillage) + if (flag && random_::chance({ms[ii].permillage, 10000})) { if (skill_get_inf(ms[ii].skill_id) & 2) @@ -3636,23 +3450,11 @@ int mob_makedummymobdb(int mob_class) mob_db[mob_class].adelay = 1000; mob_db[mob_class].amotion = 500; mob_db[mob_class].dmotion = 500; - mob_db[mob_class].dropitem[0].nameid = 909; // Jellopy - mob_db[mob_class].dropitem[0].p = 1000; - for (i = 1; i < 8; i++) + for (i = 0; i < 8; i++) { mob_db[mob_class].dropitem[i].nameid = 0; - mob_db[mob_class].dropitem[i].p = 0; - } - // Item1,Item2 - mob_db[mob_class].mexp = 0; - mob_db[mob_class].mexpper = 0; - for (i = 0; i < 3; i++) - { - mob_db[mob_class].mvpitem[i].nameid = 0; - mob_db[mob_class].mvpitem[i].p = 0; + mob_db[mob_class].dropitem[i].p.num = 0; } - for (i = 0; i < MAX_RANDOMMONSTER; i++) - mob_db[mob_class].summonper[i] = 0; return 0; } @@ -3760,63 +3562,15 @@ int mob_readdb(void) for (int i = 0; i < 8; i++) { - int rate = 0, ratemin, ratemax; mob_db[mob_class].dropitem[i].nameid = atoi(str[29 + i * 2]); - ItemType type = itemdb_type(mob_db[mob_class].dropitem[i].nameid); - if (type == ItemType::USE) - { // Added [Valaris] - rate = battle_config.item_rate_heal; - ratemin = battle_config.item_drop_heal_min; - ratemax = battle_config.item_drop_heal_max; - } - else if (type == ItemType::_2) - { - rate = battle_config.item_rate_use; - ratemin = battle_config.item_drop_use_min; - ratemax = battle_config.item_drop_use_max; // End - } - else if (type == ItemType::WEAPON - || type == ItemType::ARMOR - || type == ItemType::_8) - { - rate = battle_config.item_rate_equip; - ratemin = battle_config.item_drop_equip_min; - ratemax = battle_config.item_drop_equip_max; - } - else if (type == ItemType::_6) - { - rate = battle_config.item_rate_card; - ratemin = battle_config.item_drop_card_min; - ratemax = battle_config.item_drop_card_max; - } - else - { - rate = battle_config.item_rate_common; - ratemin = battle_config.item_drop_common_min; - ratemax = battle_config.item_drop_common_max; - } - rate = (rate / 100) * atoi(str[30 + i * 2]); - rate = - (rate < ratemin) ? ratemin : (rate > - ratemax) ? ratemax : rate; - mob_db[mob_class].dropitem[i].p = rate; - } - // Item1,Item2 - mob_db[mob_class].mexp = - atoi(str[45]) * battle_config.mvp_exp_rate / 100; - mob_db[mob_class].mexpper = atoi(str[46]); - for (int i = 0; i < 3; i++) - { - mob_db[mob_class].mvpitem[i].nameid = atoi(str[47 + i * 2]); - mob_db[mob_class].mvpitem[i].p = - atoi(str[48 + i * 2]) * battle_config.mvp_item_rate / - 100; + int rate = atoi(str[30 + i * 2]); + if (rate < 1) rate = 1; + if (rate > 10000) rate = 10000; + mob_db[mob_class].dropitem[i].p.num = rate; } mob_db[mob_class].mutations_nr = atoi(str[55]); mob_db[mob_class].mutation_power = atoi(str[56]); - for (int i = 0; i < MAX_RANDOMMONSTER; i++) - mob_db[mob_class].summonper[i] = 0; mob_db[mob_class].maxskill = 0; mob_db[mob_class].sex = 0; @@ -3838,61 +3592,6 @@ int mob_readdb(void) return 0; } -/*========================================== - * Reading of random monster data - *------------------------------------------ - */ -static -int mob_read_randommonster(void) -{ - FILE *fp; - char line[1024]; - char *str[10], *p; - int i, j; - - const char *mobfile[] = { - "db/mob_branch.txt", - "db/mob_poring.txt", - "db/mob_boss.txt" - }; - - for (i = 0; i < MAX_RANDOMMONSTER; i++) - { - mob_db[0].summonper[i] = 1002; // 設定し忘れた場合はポリンが出るようにしておく - fp = fopen_(mobfile[i], "r"); - if (fp == NULL) - { - PRINTF("can't read %s\n", mobfile[i]); - return -1; - } - while (fgets(line, 1020, fp)) - { - int mob_class, per; - if (line[0] == '/' && line[1] == '/') - continue; - memset(str, 0, sizeof(str)); - for (j = 0, p = line; j < 3 && p; j++) - { - str[j] = p; - p = strchr(p, ','); - if (p) - *p++ = 0; - } - - if (str[0] == NULL || str[2] == NULL) - continue; - - mob_class = atoi(str[0]); - per = atoi(str[2]); - if ((mob_class > 1000 && mob_class <= 2000) || mob_class == 0) - mob_db[mob_class].summonper[i] = per; - } - fclose_(fp); - PRINTF("read %s done\n", mobfile[i]); - } - return 0; -} - /*========================================== * db/mob_skill_db.txt reading *------------------------------------------ @@ -4054,7 +3753,6 @@ int do_init_mob(void) { mob_readdb(); - mob_read_randommonster(); mob_readskilldb(); add_timer_interval(gettick() + MIN_MOBTHINKTIME, diff --git a/src/map/mob.hpp b/src/map/mob.hpp index 3a7ce3d..16715c4 100644 --- a/src/map/mob.hpp +++ b/src/map/mob.hpp @@ -5,13 +5,12 @@ #include "../common/mmo.hpp" #include "../common/timer.t.hpp" +#include "../common/random.t.hpp" #include "clif.t.hpp" #include "map.hpp" #include "skill.t.hpp" -constexpr int MAX_RANDOMMONSTER = 3; - struct mob_skill { MobSkillState state; @@ -22,7 +21,6 @@ struct mob_skill short cancel; MobSkillCondition cond1; int cond2i; - SkillID cond2sk() { return SkillID(cond2i); } MobSkillTarget target; int val[5]; short emotion; @@ -44,20 +42,15 @@ struct mob_db LevelElement element; MobMode mode; int speed, adelay, amotion, dmotion; - int mexp, mexpper; int mutations_nr, mutation_power; struct { - int nameid, p; + int nameid; + random_::Fixed p; } dropitem[8]; - struct - { - int nameid, p; - } mvpitem[3]; int sex; short hair, hair_color, weapon, shield, head_top, head_mid, head_buttom, option, clothes_color; // [Valaris] int equip; // [Valaris] - int summonper[MAX_RANDOMMONSTER]; int maxskill; struct mob_skill skill[MAX_MOBSKILL]; }; @@ -72,11 +65,6 @@ int mob_once_spawn_area(struct map_session_data *sd, const char *mapname, int x0, int y0, int x1, int y1, const char *mobname, int class_, int amount, const char *event); -int mob_spawn_guardian(struct map_session_data *sd, - const char *mapname, int x, int y, - const char *mobname, int class_, int amount, - const char *event, int guardian); // Spawning Guardians [Valaris] - int mob_target(struct mob_data *md, struct block_list *bl, int dist); int mob_stop_walking(struct mob_data *md, int type); int mob_stopattack(struct mob_data *); @@ -104,7 +92,6 @@ int mob_deleteslave(struct mob_data *md); int mob_counttargeted(struct mob_data *md, struct block_list *src, ATK target_lv); -int mob_class_change(struct mob_data *md, int *value); int mob_warp(struct mob_data *md, int m, int x, int y, BeingRemoveWhy type); int mobskill_use(struct mob_data *md, tick_t tick, MobSkillCondition event); diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 2aa9480..610a274 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -1674,8 +1674,6 @@ int npc_parse_mapflag(char *w1, char *, char *w3, char *w4) int m; char mapname[24], savemap[16]; int savex, savey; - char drop_arg1[16], drop_arg2[16]; - int drop_id = 0, drop_type = 0, drop_per = 0; // 引数の個数チェック // if ( sscanf(w1,"%[^,],%d,%d,%d",mapname,&x,&y,&dir) != 4 ) @@ -1743,39 +1741,6 @@ int npc_parse_mapflag(char *w1, char *, char *w3, char *w4) { map[m].flag.pvp_noparty = 1; } - else if (strcasecmp(w3, "pvp_nightmaredrop") == 0) - { - if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == - 3) - { - int i; - if (strcmp(drop_arg1, "random") == 0) - drop_id = -1; - else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL) - drop_id = 0; - if (strcmp(drop_arg2, "inventory") == 0) - drop_type = 1; - else if (strcmp(drop_arg2, "equip") == 0) - drop_type = 2; - else if (strcmp(drop_arg2, "all") == 0) - drop_type = 3; - - if (drop_id != 0) - { - for (i = 0; i < MAX_DROP_PER_MAP; i++) - { - if (map[m].drop_list[i].drop_id == 0) - { - map[m].drop_list[i].drop_id = drop_id; - map[m].drop_list[i].drop_type = drop_type; - map[m].drop_list[i].drop_per = drop_per; - break; - } - } - map[m].flag.pvp_nightmaredrop = 1; - } - } - } else if (strcasecmp(w3, "pvp_nocalcrank") == 0) { map[m].flag.pvp_nocalcrank = 1; diff --git a/src/map/path.cpp b/src/map/path.cpp index 1a4385b..9c6ea28 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -1,5 +1,5 @@ #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "battle.hpp" @@ -221,57 +221,6 @@ int can_move(struct map_data *m, int x0, int y0, int x1, int y1, int flag) return 1; } -/*========================================== - * (x0,y0)から(dx,dy)方向へcountセル分 - * 吹き飛ばしたあとの座標を所得 - *------------------------------------------ - */ -int path_blownpos(int m, int x0, int y0, int dx, int dy, int count) -{ - struct map_data *md; - - if (!map[m].gat) - return -1; - md = &map[m]; - - if (count > 15) - { // 最大10マスに制限 - if (battle_config.error_log) - PRINTF("path_blownpos: count too many %d !\n", count); - count = 15; - } - if (dx > 1 || dx < -1 || dy > 1 || dy < -1) - { - if (battle_config.error_log) - PRINTF("path_blownpos: illeagal dx=%d or dy=%d !\n", dx, dy); - dx = (dx >= 0) ? 1 : ((dx < 0) ? -1 : 0); - dy = (dy >= 0) ? 1 : ((dy < 0) ? -1 : 0); - } - - while ((count--) > 0 && (dx != 0 || dy != 0)) - { - if (!can_move(md, x0, y0, x0 + dx, y0 + dy, 0)) - { - int fx = (dx != 0 && can_move(md, x0, y0, x0 + dx, y0, 0)); - int fy = (dy != 0 && can_move(md, x0, y0, x0, y0 + dy, 0)); - if (fx && fy) - { - if (MRAND(2)) - dx = 0; - else - dy = 0; - } - if (!fx) - dx = 0; - if (!fy) - dy = 0; - } - x0 += dx; - y0 += dy; - } - return (x0 << 16) | y0; -} - /*========================================== * path探索 (x0,y0)->(x1,y1) *------------------------------------------ diff --git a/src/map/pc.cpp b/src/map/pc.cpp index bbd59aa..c5fa07c 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -5,7 +5,7 @@ #include #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" @@ -610,84 +610,6 @@ int pc_isequip(struct map_session_data *sd, int n) return 1; } -/*========================================== - * Weapon Breaking [Valaris] - *------------------------------------------ - */ -int pc_breakweapon(struct map_session_data *sd) -{ - struct item_data *item; - int i; - - if (sd == NULL) - return -1; - if (!MRAND(100)) - return 0; - - for (i = 0; i < MAX_INVENTORY; i++) - { - if (bool(sd->status.inventory[i].equip) - && bool(sd->status.inventory[i].equip & EPOS::WEAPON) - && !sd->status.inventory[i].broken) - { - item = sd->inventory_data[i]; - sd->status.inventory[i].broken = 1; - //pc_unequipitem(sd,i,CalcStatus::NOW); - if (bool(sd->status.inventory[i].equip) - && bool(sd->status.inventory[i].equip & EPOS::WEAPON) - && sd->status.inventory[i].broken == 1) - { - std::string output = STRPRINTF("%s has broken.", item->jname); - clif_emotion(&sd->bl, 23); - clif_displaymessage(sd->fd, output); - clif_equiplist(sd); - skill_status_change_start(&sd->bl, StatusChange::SC_BROKNWEAPON, 0, interval_t::zero()); - } - } - if (sd->status.inventory[i].broken == 1) - return 0; - } - - return 0; -} - -/*========================================== - * Armor Breaking [Valaris] - *------------------------------------------ - */ -int pc_breakarmor(struct map_session_data *sd) -{ - if (sd == NULL) - return -1; - if (!MRAND(100)) - return 0; - - for (int i = 0; i < MAX_INVENTORY; i++) - { - if (bool(sd->status.inventory[i].equip) - && bool(sd->status.inventory[i].equip & EPOS::MISC1) - && !sd->status.inventory[i].broken) - { - struct item_data *item = sd->inventory_data[i]; - sd->status.inventory[i].broken = 1; - if (bool(sd->status.inventory[i].equip) - && bool(sd->status.inventory[i].equip & EPOS::MISC1) - && sd->status.inventory[i].broken == 1) - { - std::string output = STRPRINTF("%s has broken.", - item->jname); - clif_emotion(&sd->bl, 23); - clif_displaymessage(sd->fd, output); - clif_equiplist(sd); - skill_status_change_start(&sd->bl, StatusChange::SC_BROKNARMOR, 0, interval_t::zero()); - } - } - if (sd->status.inventory[i].broken == 1) - return 0; - } - return 0; -} - /*========================================== * session idに問題無し * char鯖から送られてきたステータスを設定 @@ -2238,8 +2160,9 @@ int pc_dropitem(struct map_session_data *sd, int n, int amount) sd->status.inventory[n].amount < amount || sd->trade_partner != 0 || sd->status.inventory[n].amount <= 0) return 1; - map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, - sd->bl.y, NULL, NULL, NULL, 0); + map_addflooritem(&sd->status.inventory[n], amount, + sd->bl.m, sd->bl.x, sd->bl.y, + NULL, NULL, NULL); pc_delitem(sd, n, amount, 0); return 0; @@ -2432,131 +2355,6 @@ int pc_cart_delitem(struct map_session_data *sd, int n, int amount, int) return 0; } -/*========================================== - * スティル品公開 - *------------------------------------------ - */ -static -void pc_show_steal(struct block_list *bl, - struct map_session_data *sd, int itemid, int type) -{ - nullpo_retv(bl); - nullpo_retv(sd); - - std::string output; - if (!type) - { - struct item_data *item = itemdb_exists(itemid); - if (item == NULL) - output = STRPRINTF("%s stole an Unknown_Item.", - sd->status.name); - else - output = STRPRINTF("%s stole %s.", - sd->status.name, item->jname); - clif_displaymessage(((struct map_session_data *) bl)->fd, output); - } - else - { - output = STRPRINTF( - "%s has not stolen the item because of being overweight.", - sd->status.name); - clif_displaymessage(((struct map_session_data *) bl)->fd, output); - } -} - -/*========================================== - * - *------------------------------------------ - */ -//** pc.c: Small Steal Item fix by fritz -int pc_steal_item(struct map_session_data *sd, struct block_list *bl) -{ - if (sd != NULL && bl != NULL && bl->type == BL::MOB) - { - int i, skill, rate, itemid, count; - struct mob_data *md; - md = (struct mob_data *) bl; - if (!md->state.steal_flag - && mob_db[md->mob_class].mexp <= 0 - && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) - { - skill = sd->paramc[ATTR::DEX] - mob_db[md->mob_class].attrs[ATTR::DEX] + 10; - - if (0 < skill) - { - for (count = 8; count <= 8 && count != 0; count--) - { - i = MRAND(8); - itemid = mob_db[md->mob_class].dropitem[i].nameid; - - if (itemid > 0 && itemdb_type(itemid) != ItemType::_6) - { - rate = - (mob_db[md->mob_class].dropitem[i].p / - battle_config.item_rate_common * 100 * skill) / - 100; - - if (MRAND(10000) < rate) - { - struct item tmp_item; - memset(&tmp_item, 0, sizeof(tmp_item)); - tmp_item.nameid = itemid; - tmp_item.amount = 1; - tmp_item.identify = 1; - PickupFail flag = pc_additem(sd, &tmp_item, 1); - if (battle_config.show_steal_in_same_party) - { - party_foreachsamemap( - std::bind(pc_show_steal, ph::_1, sd, tmp_item.nameid, 0), sd, 1); - } - - if (flag != PickupFail::OKAY) - { - if (battle_config.show_steal_in_same_party) - { - party_foreachsamemap( - std::bind(pc_show_steal, ph::_1, sd, tmp_item.nameid, 1), sd, 1); - } - - clif_additem(sd, 0, 0, flag); - } - md->state.steal_flag = 1; - return 1; - } - } - } - } - } - } - return 0; -} - -/*========================================== - * - *------------------------------------------ - */ -int pc_steal_coin(struct map_session_data *sd, struct block_list *bl) -{ - if (sd != NULL && bl != NULL && bl->type == BL::MOB) - { - int rate; - struct mob_data *md = (struct mob_data *) bl; - if (md && !md->state.steal_coin_flag) - { - rate = (sd->status.base_level - mob_db[md->mob_class].lv) * 3 - + sd->paramc[ATTR::DEX] * 2 + sd->paramc[ATTR::LUK] * 2; - if (MRAND(1000) < rate) - { - pc_getzeny(sd, mob_db[md->mob_class].lv * 10 + MRAND(100)); - md->state.steal_coin_flag = 1; - return 1; - } - } - } - - return 0; -} - // // // @@ -2645,8 +2443,8 @@ int pc_setpos(struct map_session_data *sd, const char *mapname_org, int x, int y } do { - x = MRAND(map[m].xs - 2) + 1; - y = MRAND(map[m].ys - 2) + 1; + x = random_::in(1, map[m].xs - 2); + y = random_::in(1, map[m].ys - 2); } while ((c = read_gat(m, x, y)) == 1 || c == 5); } @@ -2693,8 +2491,8 @@ int pc_randomwarp(struct map_session_data *sd, BeingRemoveWhy type) do { - x = MRAND(map[m].xs - 2) + 1; - y = MRAND(map[m].ys - 2) + 1; + x = random_::in(1, map[m].xs - 2); + y = random_::in(1, map[m].ys - 2); } while (((c = read_gat(m, x, y)) == 1 || c == 5) && (i++) < 1000); @@ -3738,7 +3536,7 @@ int pc_resetskill(struct map_session_data *sd) int pc_damage(struct block_list *src, struct map_session_data *sd, int damage) { - int i = 0, j = 0; + int i = 0; nullpo_ret(sd); @@ -3876,70 +3674,7 @@ int pc_damage(struct block_list *src, struct map_session_data *sd, clif_updatestatus(sd, SP::JOBEXP); } } - //ナイトメアモードアイテムドロップ - if (map[sd->bl.m].flag.pvp_nightmaredrop) - { // Moved this outside so it works when PVP isnt enabled and during pk mode [Ancyker] - for (j = 0; j < MAX_DROP_PER_MAP; j++) - { - int id = map[sd->bl.m].drop_list[j].drop_id; - int type = map[sd->bl.m].drop_list[j].drop_type; - int per = map[sd->bl.m].drop_list[j].drop_per; - if (id == 0) - continue; - if (id == -1) - { //ランダムドロップ - int eq_num = 0, eq_n[MAX_INVENTORY]; - memset(eq_n, 0, sizeof(eq_n)); - //先ず装備しているアイテム数をカウント - for (i = 0; i < MAX_INVENTORY; i++) - { - int k; - if ((type == 1 && !bool(sd->status.inventory[i].equip)) - || (type == 2 && bool(sd->status.inventory[i].equip)) - || type == 3) - { - //InventoryIndexを格納 - for (k = 0; k < MAX_INVENTORY; k++) - { - if (eq_n[k] <= 0) - { - eq_n[k] = i; - break; - } - } - eq_num++; - } - } - if (eq_num > 0) - { - int n = eq_n[MRAND(eq_num)]; //該当アイテムの中からランダム - if (MRAND(10000) < per) - { - if (bool(sd->status.inventory[n].equip)) - pc_unequipitem(sd, n, CalcStatus::NOW); - pc_dropitem(sd, n, 1); - } - } - } - else if (id > 0) - { - for (i = 0; i < MAX_INVENTORY; i++) - { - if (sd->status.inventory[i].nameid == id //ItemIDが一致していて - && MRAND(10000) < per //ドロップ率判定もOKで - && ((type == 1 && !bool(sd->status.inventory[i].equip)) //タイプ判定もOKならドロップ - || (type == 2 && bool(sd->status.inventory[i].equip)) - || type == 3)) - { - if (bool(sd->status.inventory[i].equip)) - pc_unequipitem(sd, i, CalcStatus::NOW); - pc_dropitem(sd, i, 1); - break; - } - } - } - } - } + // pvp if (map[sd->bl.m].flag.pvp && !battle_config.pk_mode) { // disable certain pvp functions on pk_mode [Valaris] diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 18e72e9..12935b5 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -61,9 +61,6 @@ int pc_authfail(int); EPOS pc_equippoint(struct map_session_data *sd, int n); -int pc_breakweapon(struct map_session_data *sd); // weapon breaking [Valaris] -int pc_breakarmor(struct map_session_data *sd); // armor breaking [Valaris] - int pc_checkskill(struct map_session_data *sd, SkillID skill_id); int pc_checkequip(struct map_session_data *sd, EPOS pos); @@ -96,9 +93,6 @@ int pc_bonus(struct map_session_data *, SP, int); int pc_bonus2(struct map_session_data *sd, SP, int, int); int pc_skill(struct map_session_data *, SkillID, int, int); -int pc_steal_item(struct map_session_data *sd, struct block_list *bl); -int pc_steal_coin(struct map_session_data *sd, struct block_list *bl); - int pc_attack(struct map_session_data *, int, int); int pc_stopattack(struct map_session_data *); diff --git a/src/map/script.cpp b/src/map/script.cpp index 22e2f16..e7f957d 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -12,7 +12,7 @@ #include "../common/db.hpp" #include "../common/extract.hpp" #include "../common/lock.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/socket.hpp" #include "../common/utils.hpp" #include "../common/timer.hpp" @@ -1550,26 +1550,18 @@ void builtin_menu(ScriptState *st) static void builtin_rand(ScriptState *st) { - int range, min, max; - if (st->end > st->start + 3) { - min = conv_num(st, &(st->stack->stack_data[st->start + 2])); - max = conv_num(st, &(st->stack->stack_data[st->start + 3])); - if (max < min) - { - int tmp; - tmp = min; - min = max; - max = tmp; - } - range = max - min + 1; - push_val(st->stack, ScriptCode::INT, (range <= 0 ? 0 : MRAND(range)) + min); + int min = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int max = conv_num(st, &(st->stack->stack_data[st->start + 3])); + if (min > max) + std::swap(max, min); + push_val(st->stack, ScriptCode::INT, random_::in(min, max)); } else { - range = conv_num(st, &(st->stack->stack_data[st->start + 2])); - push_val(st->stack, ScriptCode::INT, range <= 0 ? 0 : MRAND(range)); + int range = conv_num(st, &(st->stack->stack_data[st->start + 2])); + push_val(st->stack, ScriptCode::INT, range <= 0 ? 0 : random_::to(range)); } } @@ -2111,22 +2103,12 @@ void builtin_getitem(ScriptState *st) { return; //return if amount <=0, skip the useles iteration } - bool flag1 = false; - //Violet Box, Blue Box, etc - random item pick - if (nameid < 0) - { // ランダム - nameid = itemdb_searchrandomid(-nameid); - flag1 = 1; - } if (nameid > 0) { memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = nameid; - if (!flag1) - item_tmp.identify = 1; - else - item_tmp.identify = !itemdb_isequip3(nameid); + item_tmp.identify = 1; if (st->end > st->start + 5) //アイテムを指定したIDに渡す sd = map_id2sd(conv_num(st, &(st->stack->stack_data[st->start + 5]))); if (sd == NULL) //アイテムを渡す相手がいなかったらお帰り @@ -2135,8 +2117,9 @@ void builtin_getitem(ScriptState *st) if ((flag = pc_additem(sd, &item_tmp, amount)) != PickupFail::OKAY) { clif_additem(sd, 0, 0, flag); - map_addflooritem(&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y, - NULL, NULL, NULL, 0); + map_addflooritem(&item_tmp, amount, + sd->bl.m, sd->bl.x, sd->bl.y, + NULL, NULL, NULL); } } @@ -2180,12 +2163,6 @@ void builtin_makeitem(ScriptState *st) else m = map_mapname2mapid(mapname); - if (nameid < 0) - { // ランダム - nameid = itemdb_searchrandomid(-nameid); - flag = 1; - } - if (nameid > 0) { memset(&item_tmp, 0, sizeof(item_tmp)); @@ -2195,8 +2172,7 @@ void builtin_makeitem(ScriptState *st) else item_tmp.identify = !itemdb_isequip3(nameid); -// clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp, amount, m, x, y, NULL, NULL, NULL, 0); + map_addflooritem(&item_tmp, amount, m, x, y, NULL, NULL, NULL); } } diff --git a/src/map/skill.cpp b/src/map/skill.cpp index d1d5c38..8a2deb2 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -6,7 +6,7 @@ #include #include "../common/cxxstdio.hpp" -#include "../common/mt_rand.hpp" +#include "../common/random.hpp" #include "../common/nullpo.hpp" #include "../common/socket.hpp" #include "../common/timer.hpp" @@ -210,7 +210,7 @@ int skill_additional_effect(struct block_list *src, struct block_list *bl, { case SkillID::NPC_POISON: // blame Fate for this - if (MRAND(100) < 50 - (sc_def_vit >> 2) - (sc_def_phys_shield_spell) + (skilllv >> 2)) + if (random_::chance({50 - (sc_def_vit >> 2) - (sc_def_phys_shield_spell) + (skilllv >> 2), 100})) skill_status_change_start(bl, StatusChange::SC_POISON, skilllv, static_cast(skilllv)); break; } @@ -327,22 +327,22 @@ int skill_attack(BF attack_type, struct block_list *src, int hp = 0, sp = 0; nullpo_ret(sd); if (sd->hp_drain_rate && dmg.damage > 0 - && MRAND(100) < sd->hp_drain_rate) + && random_::chance({sd->hp_drain_rate, 100})) { hp += (dmg.damage * sd->hp_drain_per) / 100; } if (sd->hp_drain_rate_ && dmg.damage2 > 0 - && MRAND(100) < sd->hp_drain_rate_) + && random_::chance({sd->hp_drain_rate_, 100})) { hp += (dmg.damage2 * sd->hp_drain_per_) / 100; } if (sd->sp_drain_rate > 0 && dmg.damage > 0 - && MRAND(100) < sd->sp_drain_rate) + && random_::chance({sd->sp_drain_rate, 100})) { sp += (dmg.damage * sd->sp_drain_per) / 100; } if (sd->sp_drain_rate_ > 0 && dmg.damage2 > 0 - && MRAND(100) < sd->sp_drain_rate_) + && random_::chance({sd->sp_drain_rate_, 100})) { sp += (dmg.damage2 * sd->sp_drain_per_) / 100; } @@ -917,7 +917,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange const int resist_poison = skill_power_bl(bl, SkillID::TMW_RESIST_POISON) >> 3; if (resist_poison) - sc_data[type].val1 -= MRAND(resist_poison + 1); + sc_data[type].val1 -= random_::in(0, resist_poison); if ((--sc_data[type].val1) > 0) { -- cgit v1.2.3-60-g2f50