Fix core RNG collapsing to ~0-1 on Linux due to integer overflow
CWorldServer::RandNumber (and three inlined copies of the same pattern in worldpackets.cpp's item-refine code) computed "range*rand()" in integer arithmetic before dividing by (RAND_MAX + 1.0). On Windows RAND_MAX is 32767 (15-bit), so this never overflowed. On Linux/glibc RAND_MAX is 2147483647 (2^31-1), so "range*rand()" overflows a 32-bit UINT for the vast majority of rand() outputs, wrapping to a small value -- the division by ~2^31 then collapses the result to ~0 or 1 almost always, regardless of the requested range. This made every percentage-based roll in the game (item drop selection, refine durability/stats, and anything else using RandNumber) behave as if called with range 1-2 instead of the real range, which is why item drops effectively never triggered post-port. Cast to double before the multiply so it can't overflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
560f6a968f
commit
f053a06920
2 files changed
+11
-7
No files matched your search
@@ -3162,18 +3162,18 @@ bool CWorldServer::pakCraft( CPlayer* thisclient, CPacket* P )
|
||||
int lowest = thisclient->Attr->Con/ 10 + 17;
|
||||
int highest = thisclient->Attr->Con / 10 + 70;
|
||||
int range = (highest - lowest) + 1;
|
||||
item.durability = lowest+int(range*rand()/(RAND_MAX + 1.0));
|
||||
item.durability = lowest+int((double)range*rand()/(RAND_MAX + 1.0));
|
||||
|
||||
// stats randomizer
|
||||
int changeofstatslow = thisclient->Attr->Sen / 13 + 10;
|
||||
int changeofstatshigh = thisclient->Attr->Sen / 13 + 50;
|
||||
int changeofstatsrange = (changeofstatshigh-changeofstatslow)+1;
|
||||
if (changeofstatslow+int(changeofstatsrange*rand()/(RAND_MAX + 1.0)) > 50)
|
||||
if (changeofstatslow+int((double)changeofstatsrange*rand()/(RAND_MAX + 1.0)) > 50)
|
||||
{
|
||||
int statslowget = 1;
|
||||
int statshighget = 256;
|
||||
int setstatrange=(statshighget-statslowget)+1;
|
||||
item.stats = statslowget + int(setstatrange*rand()/(RAND_MAX + 1.0));
|
||||
item.stats = statslowget + int((double)setstatrange*rand()/(RAND_MAX + 1.0));
|
||||
item.appraised = 1;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user