Skip to content

Commit

Permalink
add attendants
Browse files Browse the repository at this point in the history
  • Loading branch information
AngryBeaver committed Nov 27, 2022
1 parent 793113b commit 7bdd5b4
Show file tree
Hide file tree
Showing 16 changed files with 207 additions and 38 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ Default is "Create New Item" obviously you need to adapt if you have a different
### Configure subtype Recipe
![img.png](pictures/configure.png)

#### tool: (0.5.x)
#### attendants: optional (0.7.x)
you may add an attendant the crafting process requires but is not consumed.
#### tool: optional (0.5.x)
you may add a tool the crafting process requires.
#### cost:
you may add costs to the crafting process
Expand Down Expand Up @@ -100,6 +102,8 @@ When you use a recipe with AnyOf you can customize it and by doing so define wha
- none customized AnyOf ingredients will consume a random fitting ingredient of your inventory.

### Settings
- You can enable or disable attendants for recipes feature 0.7.x default it is disabled.

![img.png](pictures/toolconfig.png)

- You can enable or disable tools for recipes feature 0.5.x default it is disabled.
Expand All @@ -108,17 +112,19 @@ When you use a recipe with AnyOf you can customize it and by doing so define wha

## latest features:
have a look at the changelog.md
### 0.7.x optional attendants
you now can customize recipes with anyOf Ingredients.
### 0.6.x customized AnyOf
you now can customize recipes with anyOf Ingredients.
### 0.5.x feature tool
### 0.5.x optional tool
you now can use tools, if you do not have the tool you dont get a check you simple fail and your ingredients won't vanish.
### 0.4.x feature compendiums,
### 0.4.x starter compendiums,
you now can use items directly from compendium,
module comes with 4 compendiums ingredients,rolltables,potions and recipes
### 0.3.x feature add initial anyOf ingredient
### 0.3.x initial anyOf ingredient
you now can have anyOf ingredients
breaking change 0.2.x -> 0.3.x
### 0.2.x feature add rollTable result
### 0.2.x rollTable result
you now can produce a random Potion.
breaking change 0.1.x -> 0.2.x

Expand Down
16 changes: 13 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
# Changelog
## 0.7.x Upcomming
### TODO
## 0.7.x attendants
### feature optional attendants
You now are able to create recipes with attendance that are items, features, tools or classes that are required in the craft process but not consumed.

![img.png](pictures/mining.png)

![img.png](pictures/gathering.png)

This enables completly diffrent kinds of recipes like e.g. mining or gathering
that requires certain items like sickle or backgrounds like Farmer etc...

### feature add abilities as skillCheck

![img.png](pictures/abilities.png)

### bug: "missing tools check whem ingredients are already insufficient" fixed
### bug: "consume costs on failed check with insufficient requirements" fixed
### bug: "roll skill with insufficient requirements" fixed

## 0.6.x
## 0.6.x customized AnyOf
### feature customized AnyOf ingredient
You now are able to customize recipes that uses anyOf Ingredients,
and by doing so define what specific ingredients you want to use for this recipe.
Expand Down
11 changes: 8 additions & 3 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"results": "Results",
"dropItem": "drop item",
"currency": "Cost",
"consumeOnFailedSaveHint": "Consumes Cost on failed Skill check"
"consumeOnFailedSaveHint": "Consumes Cost on failed Skill check",
"attendants": "Attendants"
},
"anyOf": {
"dropItem": "drop item",
Expand Down Expand Up @@ -47,8 +48,12 @@
"hint": "Show ItemSheet when clicking on ingredient items of a recipe."
},
"useTool": {
"name": "Recipes use tools",
"hint": "A Recipe can require to have a tool present on actor."
"name": "Recipes use tools (deprecated)",
"hint": "A Recipe can require to have a tool present on actor. Deprecated since 0.7.x in favour of attendants. It will get removed at somePoint in future, you should migrate to attendants."
},
"useAttendants": {
"name": "Recipes use attendants",
"hint": "A Recipe can require to have attendance present on actor. You can setUp anything you want feats, class, background, tools etc!"
},
"toolButton": {
"name": "Configure tools available",
Expand Down
2 changes: 1 addition & 1 deletion module.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"title": "Beaver's Crafting System",
"description": "A Crafting Module for DnD",
"id": "beavers-crafting",
"version": "0.6.0",
"version": "0.7.0",
"authors": [
{
"name": "angryBeaver",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "beavers-crafting",
"title": "Beaver's Crafting",
"version": "0.6.0",
"version": "0.7.0",
"description": "Crafting",
"devDir": "C:\\Users\\Riess\\AppData\\Local\\FoundryVTT\\Data\\modules",
"main": "src/main.js",
Expand Down
Binary file added pictures/gathering.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pictures/mining.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions src/Crafting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class Crafting {

async craft(): Promise<Result> {
const result = await this.checkTool();
await this.checkAttendants(result);
await this.evaluateAnyOf();
RecipeCompendium.validateRecipeToItemList(Object.values(this.recipe.ingredients), this.actor.items, result);
this.checkCurrency(result);
Expand Down Expand Up @@ -66,10 +67,14 @@ export class Crafting {

async checkTool(result?: Result): Promise<Result> {
if(!result) result = new DefaultResult();
if (result.hasErrors) return result;
return await RecipeCompendium.validateTool(this.recipe,this.actor.items,result);
}

async checkAttendants(result?: Result): Promise<Result> {
if(!result) result = new DefaultResult();
return await RecipeCompendium.validateAttendants(this.recipe,this.actor.items,result);
}

async evaluateAnyOf(){
const toDelete:string[] = [];
const toAdd:Component[] = [];
Expand Down Expand Up @@ -156,7 +161,8 @@ export class Crafting {
recipe: this.recipe,
result: result,
roll: this.roll,
displayTool: Settings.get(Settings.USE_TOOL)
useTool: Settings.get(Settings.USE_TOOL),
useAttendants: Settings.get(Settings.USE_ATTENDANTS)
})
content = TextEditor.enrichHTML(content);
await ChatMessage.create({
Expand Down
26 changes: 24 additions & 2 deletions src/Recipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ export class Recipe {
skill?:Skill;
currency?:Currency;
tool?:string;
attendants:Map<string,Component>;
_trash:Trash;

static fromItem(item):Recipe{
const flags = item.flags[Settings.NAMESPACE]?.recipe;
const data = mergeObject({ingredients:{},results:{}}, flags || {}, {inplace: false});
const data = mergeObject({attendants:{},ingredients:{},results:{}}, flags || {}, {inplace: false});
return new Recipe(item.id,item.name,item.img,data);
}

Expand All @@ -34,9 +35,11 @@ export class Recipe {
this.skill = data.skill;
this.currency = data.currency;
this.tool = data.tool;
this.attendants = data.attendants || {}
this._trash = {
ingredients:{},
results:{},
attendants:{}
};
}

Expand All @@ -47,6 +50,7 @@ export class Recipe {
results: this.serializeResults(),
currency: this.currency,
tool: this.tool,
attendants: this.serializeAttendants()
}
if(!this.tool){
serialized["-=tool"] = null;
Expand All @@ -60,13 +64,29 @@ export class Recipe {
return serialized;
}

serializeAttendants(){
return {...this.attendants,...this._trash.attendants}
}
serializeIngredients(){
return {...this.ingredients,...this._trash.ingredients}
}
serializeResults(){
return {...this.results,...this._trash.results}
}

addAttendant(entity,uuid,type) {
const uuidS = sanitizeUuid(uuid);
if(!this.attendants[uuidS]){
this.attendants[uuidS] = new DefaultComponent(entity,uuid,type);
}else{
DefaultComponent.inc(this.attendants[uuidS])
}
}
removeAttendant(uuidS){
delete this.attendants[uuidS];
this._trash.attendants["-="+uuidS] = null;
}

addIngredient(entity,uuid,type) {
const uuidS = sanitizeUuid(uuid);
if(!this.ingredients[uuidS]){
Expand All @@ -87,7 +107,7 @@ export class Recipe {
DefaultComponent.inc(this.results[uuidS])
}
}
removeResults(uuidS) {
removeResult(uuidS) {
delete this.results[uuidS];
this._trash.results["-=" + uuidS] = null;
}
Expand Down Expand Up @@ -115,6 +135,7 @@ export class Recipe {
interface Trash {
ingredients:{};
results:{};
attendants:{};
}

export class DefaultComponent implements Component {
Expand Down Expand Up @@ -157,4 +178,5 @@ interface RecipeStoreData {
skill?:Skill;
currency?:Currency;
tool?:string;
attendants: Map<string,Component>;
}
19 changes: 14 additions & 5 deletions src/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ export class Settings {
static DISPLAY_RESULTS = "displayResults";
static DISPLAY_INGREDIENTS = "displayIngredients";
static USE_TOOL = "useTool";
static USE_ATTENDANTS = "useAttendants";
static TOOL_CONFIG_BUTTON= "toolConfigButton";
static TOOL_CONFIG = "toolConfig;"
static RECIPE_SUBTYPE = "Recipe";
static ANYOF_SUBTYPE = "AnyOf";

static init() {
game.settings.register(this.NAMESPACE, this.CREATE_ITEM_TITLE, {
name: game.i18n.localize('beaversCrafting.settings.createItemTitle.name'),
hint: game.i18n.localize('beaversCrafting.settings.createItemTitle.hint'),
scope: "world",
config: true,
default: "Create New Item",
type: String,
});
game.settings.register(this.NAMESPACE, this.USE_TOOL, {
name: game.i18n.localize('beaversCrafting.settings.useTool.name'),
hint: game.i18n.localize('beaversCrafting.settings.useTool.hint'),
Expand All @@ -21,13 +30,13 @@ export class Settings {
default: false,
type: Boolean,
});
game.settings.register(this.NAMESPACE, this.CREATE_ITEM_TITLE, {
name: game.i18n.localize('beaversCrafting.settings.createItemTitle.name'),
hint: game.i18n.localize('beaversCrafting.settings.createItemTitle.hint'),
game.settings.register(this.NAMESPACE, this.USE_ATTENDANTS, {
name: game.i18n.localize('beaversCrafting.settings.useAttendants.name'),
hint: game.i18n.localize('beaversCrafting.settings.useAttendants.hint'),
scope: "world",
config: true,
default: "Create New Item",
type: String,
default: false,
type: Boolean,
});
game.settings.register(this.NAMESPACE, this.DISPLAY_RESULTS, {
name: game.i18n.localize('beaversCrafting.settings.displayResults.name'),
Expand Down
4 changes: 3 additions & 1 deletion src/apps/CraftingApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export class CraftingApp extends Application {
this.data.result = RecipeCompendium.validateRecipeToItemList(Object.values(this.data.recipe.ingredients), this.data.actor.items);
const crafting = await Crafting.from(this.data.actor.id, this.data.recipe.id);
this.data.result = await crafting.checkTool(this.data.result);
this.data.result = await crafting.checkAttendants(this.data.result);
this.data.content = await renderTemplate('modules/beavers-crafting/templates/recipe-sheet.hbs',
{
recipe: this.data.recipe,
Expand All @@ -78,7 +79,8 @@ export class CraftingApp extends Application {
displayResults:Settings.get(Settings.DISPLAY_RESULTS),
displayIngredients:Settings.get(Settings.DISPLAY_RESULTS),
tools: await getToolConfig(),
displayTool: Settings.get(Settings.USE_TOOL)
useTool: Settings.get(Settings.USE_TOOL),
useAttendants: Settings.get(Settings.USE_ATTENDANTS)
});
this._element.find(".sheet-body").empty();
this._element.find(".sheet-body").append(this.data.content);
Expand Down
31 changes: 29 additions & 2 deletions src/apps/RecipeCompendium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class RecipeCompendium {
const listOfIngredientsWithoutAnyOf = Object.values(recipe.ingredients).filter(component => component.type !== Settings.ANYOF_SUBTYPE);
const result = RecipeCompendium.validateRecipeToItemList(listOfIngredientsWithoutAnyOf, actor.items);
await RecipeCompendium.validateTool(recipe,actor.items,result);
await RecipeCompendium.validateAttendants(recipe,actor.items,result);
if ((filter == FilterType.usable && !result.hasErrors)
|| (filter == FilterType.available && result.isAvailable)) {
returnList.push(recipe);
Expand All @@ -81,6 +82,28 @@ export class RecipeCompendium {
return true;
}

static async validateAttendants(recipe:Recipe,listOfItems,result ?: Result): Promise<Result>{
if (!result) result = new DefaultResult();
if( Settings.get(Settings.USE_ATTENDANTS)) {
for(const attendant of Object.values(recipe.attendants)){
const key = sanitizeUuid(attendant.uuid);
const itemChange = RecipeCompendium.findComponentInList(listOfItems, attendant);
const remainingQuantity = itemChange.toUpdate["system.quantity"] - attendant.quantity;
const isAvailAble = itemChange.toUpdate["system.quantity"] > 0;
result.attendants[key] = {
component: attendant,
isAvailable: isAvailAble,
difference: remainingQuantity,
};
if (remainingQuantity < 0) {
result.hasErrors = true;
}
}
}
return result;
}


static async validateTool(recipe,listOfItems,result ?: Result): Promise<Result>{
if (!result) result = new DefaultResult();
if( recipe.tool && Settings.get(Settings.USE_TOOL)) {
Expand All @@ -101,7 +124,7 @@ export class RecipeCompendium {

static validateRecipeToItemList(listOfIngredients: Component[], listOfItems, result ?: Result): Result {
if (!result) result = new DefaultResult();
result.isAvailable = listOfIngredients.length === 0;
let anyIngredientIsAvailable = listOfIngredients.length === 0;
for (const component of listOfIngredients) {
const key = sanitizeUuid(component.uuid);
const itemChange = RecipeCompendium.findComponentInList(listOfItems, component);
Expand All @@ -113,7 +136,7 @@ export class RecipeCompendium {
difference: remainingQuantity,
};
if (isAvailAble) {
result.isAvailable = isAvailAble;
anyIngredientIsAvailable = isAvailAble;
}
if (remainingQuantity < 0) {
result.hasErrors = true;
Expand All @@ -127,6 +150,9 @@ export class RecipeCompendium {
result.changes.items.toDelete.push(...itemChange.toDelete);
}
}
if(result.isAvailable){
result.isAvailable = anyIngredientIsAvailable;
}
return result;
}

Expand Down Expand Up @@ -181,6 +207,7 @@ class DefaultItemChange implements ItemChange {
export class DefaultResult implements Result {
ingredients = {};
currencies = true;
attendants = {};
changes = {
items: {
toUpdate: [],
Expand Down
Loading

0 comments on commit 7bdd5b4

Please sign in to comment.