summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile8
-rw-r--r--src/common/core.cpp5
-rw-r--r--src/common/md5calc.cpp7
-rw-r--r--src/common/mt_rand.cpp123
-rw-r--r--src/common/mt_rand.hpp24
-rw-r--r--src/common/random.cpp8
-rw-r--r--src/common/random.hpp69
-rw-r--r--src/common/random.t.hpp23
-rw-r--r--src/common/random2.hpp74
-rw-r--r--src/login/login.cpp10
-rw-r--r--src/map/atcommand.cpp148
-rw-r--r--src/map/battle.cpp260
-rw-r--r--src/map/battle.hpp21
-rw-r--r--src/map/clif.cpp2
-rw-r--r--src/map/itemdb.cpp158
-rw-r--r--src/map/itemdb.hpp2
-rw-r--r--src/map/magic-expr.cpp47
-rw-r--r--src/map/magic-stmt.cpp30
-rw-r--r--src/map/map.cpp90
-rw-r--r--src/map/map.hpp6
-rw-r--r--src/map/mob.cpp556
-rw-r--r--src/map/mob.hpp19
-rw-r--r--src/map/npc.cpp35
-rw-r--r--src/map/path.cpp53
-rw-r--r--src/map/pc.cpp285
-rw-r--r--src/map/pc.hpp6
-rw-r--r--src/map/script.cpp50
-rw-r--r--src/map/skill.cpp14
28 files changed, 458 insertions, 1675 deletions
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 <cstdlib>
#include <ctime>
-#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 <cstring>
-#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 <http://www.math.keio.ac.jp/~matumoto/emt.html>
-// (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 <matumoto@math.keio.ac.jp> with
-// an appropriate reference to your work.
-//
-// It would be nice to CC: <Cokus@math.washington.edu> when you write.
-//
-*/
-
-#include "mt_rand.hpp"
-
-#include <ctime>
-
-#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 <random>
+
+// 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<int> 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<int> dist(low, high);
+ return dist(generate);
+ }
+
+ inline
+ bool coin()
+ {
+ // sigh, can't specify <bool> directly ...
+ std::uniform_int_distribution<int> 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<T>
+ // std::initializer_list<T>
+ // std::array<T, n>
+ template<class C>
+ auto choice(C&& c) -> decltype(*c.begin())
+ {
+ return *(c.begin() + random_::to(c.size()));
+ }
+
+ // allow bare braces
+ template<class T>
+ T choice(std::initializer_list<T>&& 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<class T, T den>
+ 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 <algorithm>
+
+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<detail::RandomIterator> 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<class C>
+ 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, "");
@@ -4867,125 +4864,6 @@ int atcommand_chardelitem(const int fd, struct map_session_data *sd,
}
/*==========================================
- * @jail <char_name> 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 <char_name>).");
- 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 <char_name> 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 <char_name>).");
- 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 <fstream>
#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<int>(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<int>(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<struct status_change, StatusChange> 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);
@@ -69,56 +56,6 @@ struct item_data *itemdb_searchname(const char *str)
}
/*==========================================
- * 箱系アイテム検索
- *------------------------------------------
- */
-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の存在確認
*------------------------------------------
*/
@@ -323,98 +260,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 <cmath>
#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 <cassert>
#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<uint16_t, uint16_t> 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<uint16_t>(x + dx), static_cast<uint16_t>(y + dy)};
}
+ return {static_cast<uint16_t>(0), static_cast<uint16_t>(0)};
+}
- return x + (y << 16);
+/// Return a randomly selected passable cell within a given range.
+static
+std::pair<uint16_t, uint16_t> 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<interval_t>(battle_config.mvp_item_first_get_time);
- owner_protection[1] = owner_protection[0] + static_cast<interval_t>(battle_config.mvp_item_second_get_time);
- owner_protection[2] = owner_protection[1] + static_cast<interval_t>(battle_config.mvp_item_third_get_time);
- }
- else
{
owner_protection[0] = static_cast<interval_t>(battle_config.item_first_get_time);
owner_protection[1] = owner_protection[0] + static_cast<interval_t>(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<uint16_t, uint16_t> 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 <cassert>
@@ -8,7 +9,7 @@
#include <algorithm>
#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<interval_t>(-1); // Only once is a flag.
- md->spawndelay2 = static_cast<interval_t>(-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<int, 10000> 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実行
@@ -2844,83 +2733,6 @@ int mob_damage(struct block_list *src, struct mob_data *md, int damage,
}
/*==========================================
- *
- *------------------------------------------
- */
-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;
@@ -3839,61 +3593,6 @@ int mob_readdb(void)
}
/*==========================================
- * 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<int, 10000> 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"
@@ -222,57 +222,6 @@ int can_move(struct map_data *m, int x0, int y0, int x1, int y1, int flag)
}
/*==========================================
- * (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 <cstring>
#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"
@@ -611,84 +611,6 @@ int pc_isequip(struct map_session_data *sd, int n)
}
/*==========================================
- * 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 <ctime>
#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<interval_t>(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)
{