ThePix / QuestJS

A major re-write of Quest that is written in JavaScript and will run in the browser.
MIT License
66 stars 12 forks source link

Template for limited-use items (guns, tanks, etc.) #62

Open Kln95130 opened 3 years ago

Kln95130 commented 3 years ago

Here is the template for limited-used items that I mentioned in the previous ticket. I tried to dissociate it from ranged weapons, so it might need a couple of tests before validating it, but I can at least get your feedback on that.

This template must work in tandem with a object extending countable.

In lang-en.js

  verbs:{
    //...
    reload: "Reload",
    recharge: "Recharge"
  },
cannot_recharge: "{pv:char:can't:true} recharge {ob:item}.",

In _commands.js

commands.push(
    new Cmd('Recharge', {
      npcCmd:true,
      regex:/^(?:recharge|reload) (.+)$/,
      attName: "recharge",
      rules:[cmdRules.canManipulate, cmdRules.isHere],
      objects:[
        {scope:parser.isPresent},
      ],
      defmsg:lang.cannot_recharge,
    })
)

In _templates.js

/**
 * This template applies to any item which has a number of charges, who deplete through interaction or time. These charges can be repleted with a predetermined item.
 * The item's predominently adds a specific recharge function (associated to the recharge command).
 * NOTE : if the item cannot be recharged, overwrite the recharge property with the value "false", in order to trigger the command's default message
 * @param {String} charger Name of the item(s) used to resplenish the charges. MUST ALWAYS BE A CHARGER ITEM, due to relying on COUNTABLE's functions.
 * @param {Number} charges Number of charges the item can have at maximum and starts with. Overwrite chargesMax or chargesCur in case you want a difference.
 * @param {Bolean} verb Is this item "reloaded" (true) or "recharged" (false) ?
 */
const LIMITED_USE = function(charger, charges, isLoaded=false) {
  const res = $.extend({});
  res.limitedUse = true;
  res.rechargeable = true;
  res.charger = charger;
  res.chargesMax = charges;
  res.chargesCur = charges;
  res.isLoaded = isLoaded;

  res.onCreation = function(o) {
    o.verbFunctions.push(function(o, verbList) {
      if (this.wearable) {
        if (!o.isAtLoc(game.player.name)) {
          verbList.push(lang.verbs.take)
        } else if (o.getWorn()) {
          if (!o.getWearRemoveBlocker(game.player, false)) verbList.push(lang.verbs.remove)
        } else {
          verbList.push(lang.verbs.drop)
          if (!o.getWearRemoveBlocker(game.player, true)) verbList.push(lang.verbs.wear)
        }
      } else {
        verbList.push(o.isAtLoc(game.player.name) ? lang.verbs.drop : lang.verbs.take)
      }
      (o.isLoaded) ? verbList.push(lang.verbs.reload) : verbList.push(lang.verbs.recharge)
    })
    o.nameModifierFunctions.push(function(o, list) {
      if (o.worn && o.isAtLoc(game.player.name)) list.push(lang.invModifiers.worn)
    })
  }

/**
 * This function recharges a limited use item, and does a certain number of checks
 * @returns the success state of the function
 */
 res.recharge = function() {
      let maxReload = this.chargesMax - this.chargesCur;
      if (maxReload === 0) {
        return failedmsg(this.reloadFullMsg);
      }

      let chargeCarried = w[this.charger].countAtLoc("me");
      let chargeNb = chargeCarried * w[this.charger].chargeNb;
      if (chargeCarried === 0) {
        return failedmsg("You do not have any " + this.charger.alias + " on you.");
      }

      if (maxReload >= chargeNb) {
        this.chargesCur += chargeNb;
        w[this.charger].countableLocs["me"] = false;
        printOrRun(game.player, this, "partialRecharge");
      } else {
        this.chargesCur = this.chargesMax;
        w[this.ammoName].countableLocs["me"] -= Math.ceil(chargeNb / maxReload);
        printOrRun(game.player, this, "fullRecharge");
      }
      return world.SUCCESS;
  }
  res.reload = function() {return this.recharge() };

  res.partialRecharge = "You partially recharge this item.";
  res.fullRecharge = "You completely recharge this item.";

  return res;
}

/**
 * This template is applied to an item that is used to recharge a limited item. It extends COUNTABLE
 * @param {Object} countableLocs a generic object with locations as keys and number at location as value
 * @param {Number} chargeNb indicates how many units of charge of the limited use item *this* item holds. Ex: bullets are "1" (bullet), a battery may be "100" (percents), a canister may be "3" (liters)
 * @param {String} unitName the name of the charge unit (for fluff)
 */
const CHARGER = function(countableLocs, chargeNb=1, unitName="") {
  const res = $.extend({}, COUNTABLE(countableLocs));

  this.chargeNb = chargeNb;
  this.unitName = unitName;

  return res;
}