The shop discount from Big Spender badges was incorrectly implemented:
intended behavior was for 2pp per badge. However, the values in
const.py were set as if a user could only have one Spender badge at
once, while user.py @ discount was implemented as if they were
additive. Since users factually do have multiple big spender badges,
the values in const were adjusted to reflect this fact.
Also, lootbox Roller badges now each offer a 1pp discount.
users.py @ discount was improved to check against the `discounts`
keys for appropriate badges, rather than a hardcoded list.
Double XP now has a constant for unixtime to start. Logic around
DXP is designed to only apply to votes made after DOUBLE_XP_ENABLED.
This prevents an exploit in the old implementation where spam voting/
unvoting a post made prior to the DXP start could farm 300 DC/hr/alt.
Also it's more maintainable and comports with the coin_delta changes
to prevent self-vote coin changes.
Re-enable lootboxes in const.py, and update their contents in
awards.py. Additionally, improve appearance in shop.
Upon purchasing a lootbox, users now receive a message informing
them of the contents thereof.
Lootbox backend now properly uses CARP_ID (and checks for the
existence thereof correctly).
Also, minor changes to how const.py whitelists awards.
Chose to split text into lines because Python regex supports neither
variable-width nor infinite-width negative lookbehinds. This precludes
a simple pure regex solution. Since all replacements are done at the
word level, this has no obvious ill effects.