lib/vhyl-rpg-expanded-traits.t

Reference index ยท View on GitHub

   1  /* Include after the expanded foundation. Source: full-2008, B101; B110; B121. */
   2  
   3  /** Pure signed percentage pricing, rounded toward positive infinity.
   4   * This validates arithmetic bounds, not modifier eligibility or effects. */
   5  rpgExpandedSignedModifiedCost(base, percentages)
   6  {
   7      rpgInteger(base, -1000000, 1000000);
   8      local percent = 100;
   9      foreach (local value in percentages) { rpgInteger(value, -1000, 1000); percent += value; }
  10      if (percent < 20) percent = 20;
  11      rpgInteger(percent, 20, 2000);
  12      if (base < 0) return -((-base * percent) / 100);
  13      return (base * percent + 99) / 100;
  14  }
  15  
  16  /** Pure percentage pricing for a positive-cost trait; ceiling, with an 80% floor.
  17   * Applicability and each modifier's actual effect require a separate definition. */
  18  rpgExpandedModifiedCost(base, percentages)
  19  {
  20      rpgInteger(base, 1, 1000000);
  21      return rpgExpandedSignedModifiedCost(base, percentages);
  22  }
  23  
  24  /** Pure self-control pricing for a negative base value; discard fractional magnitude.
  25   * The rating is independent of Will. This does not roll or resolve a trigger. */
  26  rpgExpandedSelfControlCost(base, rating)
  27  {
  28      rpgInteger(base, -1000000, -1);
  29      if (!holds([6, 9, 12, 15], rating)) rpgExpandedReject('self-control-rating');
  30      if (rating == 6) return base * 2;
  31      if (rating == 9) return -((-base * 3) / 2);
  32      if (rating == 15) return -((-base) / 2);
  33      return base;
  34  }
  35  
  36  /** An explicitly approved positive trait price specification.
  37   * This prices the trait; it does not implement modifier effects. */
  38  class RpgExpandedTrait: RpgLiteTrait
  39      percentages = []
  40      approved = nil
  41      creationCost()
  42      {
  43          if (!self.approved) rpgExpandedReject('unapproved-trait');
  44          rpgInteger(self.points, 1, 10000); rpgInteger(self.level, 1, 100);
  45          return rpgExpandedModifiedCost(self.points * self.level, self.percentages);
  46      }
  47  ;
  48  
  49  /** Approved negative price specification, using the shared character cost ledger.
  50   * Approval covers the authored price only, not completion of catalogue effects. */
  51  class RpgExpandedDisadvantage: RpgLiteTrait
  52      percentages = []
  53      approved = nil
  54      selfControlRating = nil
  55      creationCost()
  56      {
  57          if (!self.approved) rpgExpandedReject('unapproved-trait');
  58          rpgInteger(self.points, -10000, -1); rpgInteger(self.level, 1, 100);
  59          local base = self.points * self.level;
  60          if (self.selfControlRating != nil)
  61          {
  62              /* Resolve composition/rounding from source before supporting both. */
  63              if (self.percentages.length() != 0)
  64                  rpgExpandedReject('self-control-modifier-combination');
  65              return rpgExpandedSelfControlCost(base, self.selfControlRating);
  66          }
  67          return rpgExpandedSignedModifiedCost(base, self.percentages);
  68      }
  69  ;