Refactor tax counters into cast counts with separate ID space and user activated create/delete

This commit is contained in:
DawnFire42 2026-08-10 22:28:00 -04:00
parent 4354191918
commit f5e49a571e
No known key found for this signature in database
GPG key ID: 24BB855EE2911B33
50 changed files with 900 additions and 828 deletions

View file

@ -1,7 +1,10 @@
/**
* @file counter_ids.h
* @ingroup Core
* @brief Shared counter IDs and names for system counters (e.g. tax counters).
* @ingroup Utility
* @brief Counter ID ranges and cast count index utilities.
*
* Defines the boundary between built-in counters (life, mana colors, storm) and
* user-created counters, plus helpers for the cast count system used in Commander.
*/
#ifndef COCKATRICE_COUNTER_IDS_H
@ -11,95 +14,36 @@
/**
* @namespace CounterIds
* @brief Shared counter IDs used by both client and server.
*
* Single source of truth: included directly by both sides, so they cannot drift.
*
* Reserved counter IDs for system counters:
* IDs 0-7: Standard player counters (life, mana colors, storm)
* IDs 8-12: Tax counters (1st through 5th)
* IDs 13+: Available for user-created counters (FirstUserId)
*
* newCounterId() always returns >= FirstUserId to prevent user counters
* from colliding with reserved IDs, even in non-Commander games.
* @brief Reserved counter ID ranges.
*/
namespace CounterIds
{
constexpr int TaxCounter1 = 8; ///< 1st tax counter
constexpr int TaxCounter2 = 9; ///< 2nd tax counter
constexpr int TaxCounter3 = 10; ///< 3rd tax counter
constexpr int TaxCounter4 = 11; ///< 4th tax counter
constexpr int TaxCounter5 = 12; ///< 5th tax counter
constexpr int FirstUserId = 13; ///< First ID available for user-created counters
constexpr int FirstTaxCounterId = TaxCounter1;
constexpr int LastTaxCounterId = TaxCounter5;
constexpr int TaxCounterCount = LastTaxCounterId - FirstTaxCounterId + 1;
/** @brief Returns true if the given ID is a reserved tax counter. */
inline bool isTaxCounter(int id)
{
return id >= FirstTaxCounterId && id <= LastTaxCounterId;
}
/** @brief Returns the tax counter index (0-based) for display, or -1 if not a tax counter. */
inline int taxCounterIndex(int id)
{
if (!isTaxCounter(id)) {
return -1;
}
return id - FirstTaxCounterId;
}
/** @brief Returns the tax counter ID for the given 0-based index, or -1 if out of range. */
inline int taxCounterIdFromIndex(int index)
{
if (index < 0 || index >= TaxCounterCount) {
return -1;
}
return FirstTaxCounterId + index;
}
constexpr int FirstUserId = 8; ///< First ID available for user-created counters (0-7 are built-in)
} // namespace CounterIds
/**
* @namespace CounterNames
* @brief Reserved counter names for server-managed tax counters.
* @namespace CastCountIds
* @brief Cast count index range and utilities.
*
* Used to reject user-created counters that would spoof system counters.
* Cast counts use a separate 1-based index space (1-5), not sharing IDs with regular counters.
*/
namespace CounterNames
namespace CastCountIds
{
constexpr const char *TaxCounter1 = "1st_tax_counter";
constexpr const char *TaxCounter2 = "2nd_tax_counter";
constexpr const char *TaxCounter3 = "3rd_tax_counter";
constexpr const char *TaxCounter4 = "4th_tax_counter";
constexpr const char *TaxCounter5 = "5th_tax_counter";
constexpr int MinIndex = 1; ///< Minimum valid cast count index
constexpr int MaxIndex = 5; ///< Maximum valid cast count index
constexpr int Count = MaxIndex; ///< Total number of cast count slots
/** @brief Returns the name for the given tax counter ID, or nullptr if not a tax counter. */
inline const char *forId(int id)
/** @brief Returns true if the index is in the valid cast count range [1, 5]. */
inline bool isValidIndex(int index)
{
switch (id) {
case CounterIds::TaxCounter1:
return TaxCounter1;
case CounterIds::TaxCounter2:
return TaxCounter2;
case CounterIds::TaxCounter3:
return TaxCounter3;
case CounterIds::TaxCounter4:
return TaxCounter4;
case CounterIds::TaxCounter5:
return TaxCounter5;
default:
return nullptr;
}
return index >= MinIndex && index <= MaxIndex;
}
/** @brief Returns true if the given name is a reserved tax counter name. */
inline bool isTaxCounter(const QString &name)
/** @brief Returns the internal name for a cast count at the given index (e.g. "cast_count_1"). */
inline QString nameForIndex(int index)
{
return name == TaxCounter1 || name == TaxCounter2 || name == TaxCounter3 || name == TaxCounter4 ||
name == TaxCounter5;
return QString("cast_count_%1").arg(index);
}
} // namespace CounterNames
} // namespace CastCountIds
#endif // COCKATRICE_COUNTER_IDS_H

View file

@ -6,7 +6,7 @@
*
* Caps an individual counter's VALUE (e.g. a +1/+1 counter at 999), not how many counters
* something holds. Applies to counters that are constrained to a non-negative display range,
* such as card counters and commander tax. Unbounded counters (e.g. a player's life total)
* such as card counters and cast counts. Unbounded counters (e.g. a player's life total)
* do not use this limit and may go negative, saturating only at the int range.
*
* The max of 999 is a display constraint (3-digit rendering) and a reasonable gameplay limit.