Quote:
Originally Posted by jarzseald
does that remove item drop restriction upon reaching certain level?
|
No. It just makes it so players are unable to remove the "Level Down" scroll on an equipped item. What you are looking for is going to be in CMover::DropItem.
Since this thread was already necro'd, I might as well say somethings.
The fix for "CDPSrvr::OnRemoveItemLevelDown" could be changed. You could check for player level being in range still and if not then un-equip the item if there is space, then remove the scroll. When it is equipped and the level is within range, you can still update the variable as it wouldn't cause another exploit.
You can also do other things like for the "Blessing" stat stack, you're able to just reset the equipped items stats on the player and then there is no need to unequip said cs item.
CPiercing::SetPiercingSize is another fix where you don't need to check if < 0 if you just change the function to accept an unsigned integer rather than a signed integer because the type casting and overflow would already happen and thus be greater than the maximum pierced size. Also, vector resize will trim. There is no requirement for the == 0 check.
Haven't looked into the guild house code enough to state whether it is useless or not; however, if it's best to check the whole system before throwing fixes around.
nTotalDays is working with time_t variables, rather int, using time_t (because you can get rid of 32bit time_t and will have to in like 10 years).
But, here is multiply overflow checking that's templated. Could be optimized, and shouldn't be used with floats (you could constexpr check to see if it is floating point to cast to double rather than ulonglong to avoid float > int > float math and possibility of truncation and then the requires will need to be updated to be a boolean statement of integral value or floating point value).
Code:
enum FlowFlag : unsigned char
{
ff_under = 1 << 0,
ff_over = 1 << 1,
ff_downcast = 1 << 2,
ff_NegUpcast = 1 << 3
};
template <typename Ret = unsigned long, typename A = Ret, typename B = Ret>
bool checkMul(A a, B b, const FlowFlag ft = static_cast<FlowFlag>(ff_over | ff_downcast | ff_NegUpcast)) requires std::is_integral_v<Ret>
{
static_assert((std::is_integral_v<A> || std::is_floating_point_v<A>) && (std::is_integral_v<B> || std::is_floating_point_v<B>) && std::is_integral_v<Ret>, "incorrect types");
if constexpr (!std::numeric_limits<Ret>::is_signed)
{
if (ft & ff_NegUpcast)
if (a < std::numeric_limits<Ret>::min() || b < std::numeric_limits<Ret>::min())
return false;
if (ft & ff_downcast)
if (static_cast<unsigned long long>(static_cast<Ret>(a)) != static_cast<unsigned long long>(a) || static_cast<unsigned long long>(static_cast<Ret>(b)) != static_cast<unsigned long long>(b))
return true;
if (a == 0 || b == 0)
return false;
return static_cast<Ret>(a) < std::numeric_limits<Ret>::max() / static_cast<Ret>(b);
}
if (ft & ff_NegUpcast)
if (a > std::numeric_limits<Ret>::max() || b > std::numeric_limits<Ret>::max())
return true;
if (ft & ff_downcast)
if (static_cast<long long>(static_cast<Ret>(a)) != static_cast<long long>(a) || static_cast<long long>(static_cast<Ret>(b)) != static_cast<long long>(b))
return true;
if (a == 0 || b == 0)
return false;
return static_cast<Ret>(a) < std::numeric_limits<Ret>::max() / static_cast<Ret>(b);
}
template <typename Ret = unsigned long, typename A, typename B>
std::optional<Ret> eMul(A a, B b, const FlowFlag ft = static_cast<FlowFlag>(ff_over | ff_downcast | ff_NegUpcast)) requires std::numeric_limits<Ret>::is_integer
{
return checkMul<Ret>(a, b, ft) ? std::optional<Ret>(static_cast<Ret>(a) * static_cast<Ret>(b)) : std::nullopt;
}
Code:
if (const auto opt = eMul<long>(INT_MAX, 2); !opt.has_value())
{
// overflow
}