FoundryVTT-RestRecovery icon indicating copy to clipboard operation
FoundryVTT-RestRecovery copied to clipboard

[Request] Food and water resources purchased as a service by actors configured as merchants with the 'items piles' module function automatically as consumed resources in the total daily units of food and water needed."

Open Bzuk00 opened this issue 1 year ago • 3 comments

It would be great if the food and water resources purchased as a service through the "item's pile merchant sheet" were substracted from the total units of food and/or water that a player needs per day. This prevents players from being compelled to purchase individual food or water items that would simply be placed in their inventory, awaiting consumption.

For instance, if an innkeeper offers a particular dish that can only be consumed at his inn and cannot be placed in the player's inventory like a regular piece of bread, it would be beneficial if that dish, once purchased by a player, could count as a ration unit of food or water that the player needs to consume per day in order to meet their daily meal and water requirements.

Bzuk00 avatar Mar 28 '24 23:03 Bzuk00

Just a suggestion. I create "Inn Night Stays" as a consumable which pays for the night stay and counts as a full days food.

BenNelsonNeb avatar Apr 10 '24 21:04 BenNelsonNeb

Hi - could you please elaborate on the issue for me? If you purchase something from a merchant, it's an item, right? Could you not make it a consumable item providing however much food/water and tell your players it must be consumed on-the-spot? (If your player consumes it, it will be remembered that they consumed it when their next rest comes along).

roth-michael avatar May 13 '24 18:05 roth-michael

Revisiting this. The way services work are that you can write a macro associated with the purchase of the service. I've written a little (not so little) macro that should work as intended, so long as you've got the service set up in the item details tab with the appropriate Rest Recovery consumable info set. @Bzuk00 Let me know if assigning the following as a macro for one such service works. If so I may wrap it up as a macro and distribute it in Rest Recovery:

if (!game.settings.get('rest-recovery', 'enable-food-and-water')) return;

const consumable = foundry.utils.getProperty(item, 'flags.rest-recovery.data.consumable');

const actorUpdates = {};

const actorFoodSatedValue = foundry.utils.getProperty(buyer, 'flags.rest-recovery.data.sated.food') ?? 0;
const actorWaterSatedValue = foundry.utils.getProperty(buyer, 'flags.rest-recovery.data.sated.water') ?? 0;

const actorNeedsNoFoodWater = foundry.utils.getProperty(buyer, 'flags.dnd5e.noFoodWater');
const actorNeedsNoFood = foundry.utils.getProperty(buyer, 'flags.dae.rest-recovery.force.noFood');
const actorNeedsNoWater = foundry.utils.getProperty(buyer, 'flags.dae.rest-recovery.force.noWater');

const foodUnitsSetting = game.settings.get('rest-recovery', 'food-units-per-day');
const actorRequiredFoodUnits = foundry.utils.getProperty(buyer, 'flags.dae.rest-recovery.require.food')
?? foundry.utils.getProperty(buyer, 'flags.dnd5e.foodUnits');
let actorRequiredFood = !isNaN(actorRequiredFoodUnits) && (typeof actorRequiredFoodUnits === 'number') && isFinite(actorRequiredFoodUnits) && foodUnitsSetting !== 0
? actorRequiredFoodUnits
: foodUnitsSetting;

const waterUnitsSetting = game.settings.get('rest-recovery', 'water-units-per-day');
const actorRequiredWaterUnits = foundry.utils.getProperty(buyer, 'flags.dae.rest-recovery.require.water')
?? foundry.utils.getProperty(buyer, 'flags.dnd5e.waterUnits');
let actorRequiredWater = !isNaN(actorRequiredWaterUnits) && (typeof actorRequiredWaterUnits === 'number') && isFinite(actorRequireWaterUnits) && waterUnitsSetting !== 0
? actorRequiredWaterUnits
: waterUnitsSetting;

actorRequiredFood = actorNeedsNoFoodWater || actorNeedsNoFood ? 0 : actorRequiredFood;
actorRequiredWater = actorNeedsNoFoodWater || actorNeedsNoWater ? 0 : actorRequiredWater;

const chargesUsed = (foundry.utils.getProperty(item, "system.uses.value") ?? 1) * quantity;

let message;
console.log('hu');

if (consumable.type === "both") {

    actorUpdates['flags.rest-recovery.data.sated.food'] = consumable.dayWorth ? actorFoodSatedValue : actorFoodSatedValue + chargesUsed;
    actorUpdates['flags.rest-recovery.data.sated.water'] = consumable.dayWorth ? actorWaterSatedValue : actorWaterSatedValue + chargesUsed;

    const localize = "REST-RECOVERY.Chat.ConsumedBoth" + (consumable.dayWorth ? "DayWorth" : "")
    message = "<p>" + game.i18n.format(localize, {
    actorName: buyer.name,
    itemName: item.name,
    charges: chargesUsed
    }) + "</p>";

    if (!consumable.dayWorth) {
    message += actorUpdates['flags.rest-recovery.data.sated.food'] >= actorRequiredFood
        ? "<p>" + game.i18n.localize("REST-RECOVERY.Chat.SatedFood") + "</p>"
        : "<p>" + game.i18n.format("REST-RECOVERY.Chat.RequiredSatedFood", { units: actorRequiredFood - actorUpdates['flags.rest-recovery.data.sated.food'] }) + "</p>"
    message += actorUpdates['flags.rest-recovery.data.sated.water'] >= actorRequiredWater
        ? "<p>" + game.i18n.localize("REST-RECOVERY.Chat.SatedWater") + "</p>"
        : "<p>" + game.i18n.format("REST-RECOVERY.Chat.RequiredSatedWater", { units: actorRequiredWater - actorUpdates['flags.rest-recovery.data.sated.water'] }) + "</p>"
    }

} else if (consumable.type === "food") {

    actorUpdates['flags.rest-recovery.data.sated.food'] = consumable.dayWorth ? 100000000000 : actorFoodSatedValue + chargesUsed;

    const localize = "REST-RECOVERY.Chat.ConsumedFood" + (consumable.dayWorth ? "DayWorth" : "")
    message = "<p>" + game.i18n.format(localize, {
    actorName: buyer.name,
    itemName: item.name,
    charges: chargesUsed
    }) + "</p>";

    message += actorUpdates['flags.rest-recovery.data.sated.food'] >= actorRequiredFood
    ? "<p>" + game.i18n.localize("REST-RECOVERY.Chat.SatedFood") + "</p>"
    : "<p>" + game.i18n.format("REST-RECOVERY.Chat.RequiredSatedFood", { units: actorRequiredFood - actorUpdates['flags.rest-recovery.data.sated.food'] }) + "</p>"

} else if (consumable.type === "water") {

    actorUpdates['flags.rest-recovery.data.sated.water'] = consumable.dayWorth ? 100000000000 : actorWaterSatedValue + chargesUsed;

    const localize = "REST-RECOVERY.Chat.ConsumedWater" + (consumable.dayWorth ? "DayWorth" : "")
    message = "<p>" + game.i18n.format(localize, {
    actorName: buyer.name,
    itemName: item.name,
    charges: chargesUsed
    }) + "</p>";

    message += actorUpdates['flags.rest-recovery.data.sated.water'] >= actorRequiredWater
    ? "<p>" + game.i18n.localize("REST-RECOVERY.Chat.SatedWater") + "</p>"
    : "<p>" + game.i18n.format("REST-RECOVERY.Chat.RequiredSatedWater", { units: actorRequiredWater - actorUpdates['flags.rest-recovery.data.sated.water'] }) + "</p>"
}

if (!foundry.utils.isEmpty(actorUpdates)) {
    buyer.update(actorUpdates);
}

if (message) {
    setTimeout(() => {
    ChatMessage.create({
        flavor: "Rest Recovery",
        user: game.user.id,
        speaker: ChatMessage.getSpeaker({ actor: buyer }),
        content: message,
    });
    }, 1000)
}```

roth-michael avatar Jun 01 '24 17:06 roth-michael