Skip to content

Commit

Permalink
initial anyOf
Browse files Browse the repository at this point in the history
  • Loading branch information
AngryBeaver committed Oct 17, 2022
1 parent 009a1b5 commit b34dd64
Show file tree
Hide file tree
Showing 18 changed files with 409 additions and 118 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
! Carefully structure will probably change until i finalize this module with version 1.0.0 !,
so do not start creating tones of recipes already ! The future upgrades might break them.

! breaking change release: 0.1.x -> 0.2.x !
! breaking change release: 0.2.x -> 0.3.x !

## Features
### Loot subtype Recipe
Expand Down Expand Up @@ -55,13 +55,22 @@ or throu recipe compendium
You will see a chat message with your result

## latest features:
### 0.3.x feature add initial anyOf ingredient
you now can have anyOf ingredients
breaking change 0.2.x -> 0.3.x
### 0.2.x feature add rollTable result
you now can produce a random Potion.
breaking change 0.1.x -> 0.2.x


## Upcoming Changes
### "any" of ingredient
### "any" of ingredient (initial 0.3.x)

I want to create recipes with "any" xxx e.g. (weapon,mushroom,etc) therefor i may need some new fields in recipe or a new subtype ingredient
---
currently it will only take randomly from avaiable items on actor in required quantity.
the precast is wrong it always shows that AnyOf is not available.

### results should include rollTables (done 0.2.x)
I want to create a random potion.
### macro
Expand Down
35 changes: 33 additions & 2 deletions css/crafting.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
padding-left:2px;
}

.beavers-crafting .recipe .left{
max-width:50%;
}

.beavers-crafting .recipe .right{
max-width:50%;
}
.beavers-crafting .recipe .attribute{
flex: 0 0 60px;
border-left: 1px solid #c9c7b8;
Expand Down Expand Up @@ -165,12 +172,12 @@
flex:0;
}

.beavers-crafting .crafting-app .drop-area .item{
.beavers-crafting .drop-area .item{
/* Center the content */
width:20px;
margin:2px;
}
.beavers-crafting .crafting-app .drop-area .item img{
.beavers-crafting .drop-area .item img{
/* Center the content */
border:0px;
}
Expand All @@ -195,4 +202,28 @@
border-radius: 0.25rem;
}

.beavers-crafting .anyOf textarea {
height: calc(100% - 30px);
resize: none;
padding:5px;
width: calc(100% - 20px);
margin:10px;
}

.sheet-body .beavers-crafting {
height:100%;
flex:1;
}
.beavers-crafting .anyOf{
height:100%;
}

.beavers-crafting .anyOf .drop-area{
margin:0px 5px;
height:34px;
}

.beavers-crafting .anyOf .bottom{
margin: 0px 5px 10px;
flex:0 0 30px;
}
Binary file added icons/anyOf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 8 additions & 11 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
"skills": "Skill",
"dc": "DC",
"results": "Results",
"dropitem": "drop item",
"dropItem": "drop item",
"currency": "Cost",
"consumeOnFailedSaveHint": "Consumes Cost on failed Skill check"
},
"anyOf": {
"dropItem": "drop item",
"button": "test item",
"error": "an 'anyOf' macro produced an error. See console (F12)"
},
"component": {
"warning": "Your controlled Actor does not have an item named "
},
Expand All @@ -28,17 +33,9 @@
}
},
"settings": {
"craftById": {
"name": "craftById",
"hint": "when crafting the actor item has to match in name and sourceId"
},
"createItemTitle": {
"name": "createItemTitle",
"hint": "Enter the title the create item window has so we can detect it and inject our recipe subtype"
},
"recipeSourceName":{
"name": "recipeSourceName",
"hint": "Enter the name the source of an item must have to switch to recipe"
"name": "Title of Item Creation Dialog",
"hint": "This Title is needed to detect the Item Creation Dialog to add 'Recipe' and 'AnyOf' Subtype"
}
}
}
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.2.1",
"version": "0.3.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.2.1",
"version": "0.3.0",
"description": "Crafting",
"devDir": "C:\\Users\\User\\AppData\\Local\\FoundryVTT\\Data\\modules",
"main": "src/main.js",
Expand Down
31 changes: 27 additions & 4 deletions src/Crafting.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {DefaultComponent, Recipe} from "./Recipe.js";
import {Exchange} from "./Exchange.js";
import {Settings} from "./Settings.js";
import {DefaultResult, RecipeCompendium} from "./RecipeCompendium.js";
import {rollTableToComponents} from "./helpers/RollTableToComponent.js";
import {DefaultResult, RecipeCompendium} from "./apps/RecipeCompendium.js";
import {rollTableToComponents} from "./helpers/Utility.js";
import {AnyOf} from "./apps/AnyOfSheet.js";

export class Crafting {
recipe: Recipe;
Expand All @@ -11,7 +12,7 @@ export class Crafting {
roll;

constructor(actor, item) {
this.recipe = new Recipe(item)
this.recipe = Recipe.fromItem(item)
this.actor = actor;
this.item = item;
}
Expand All @@ -28,7 +29,8 @@ export class Crafting {

async craft(): Promise<Result> {
const result = await this.checkSkill();
RecipeCompendium.validateRecipeToItemList(this.recipe, this.actor.items, result);
await this.evaluateAnyOf();
RecipeCompendium.validateRecipeToItemList(Object.values(this.recipe.ingredients), this.actor.items, result);
this.checkCurrency(result);
await this.addResults(result);
await this.updateActor(result);
Expand All @@ -53,6 +55,27 @@ export class Crafting {
return result;
}

async evaluateAnyOf(){
const toDelete:string[] = [];
const toAdd:Component[] = [];
for(const [key,component] of Object.entries(this.recipe.ingredients)){
if(component.type === Settings.ANYOF_SUBTYPE){
const item = await fromUuid(component.uuid);
const anyOf = new AnyOf(item);
let results = await anyOf.filter(this.actor.items);
results = results.filter(c=>c.quantity >= component.quantity);
if(results.length >= 0) {
const result = results[Math.floor(Math.random() * results.length)];
result.quantity = component.quantity;
toAdd.push(result);
toDelete.push(key);
}
}
}
toDelete.forEach(k=>this.recipe.removeIngredient(k));
toAdd.forEach(component=>{this.recipe.addIngredient(component,component.uuid,component.type)});
}

//simple stupid functional but not performant (yagni)
checkCurrency(result?: Result): Result {
if (!result) result = new DefaultResult();
Expand Down
54 changes: 28 additions & 26 deletions src/Recipe.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Settings} from "./Settings.js";
import {DefaultCurrency} from "./Exchange.js";
import {sanitizeUuid} from "./helpers/Utility.js";

export class Recipe implements RecipeStoreData{
id:string;
Expand All @@ -11,14 +12,19 @@ export class Recipe implements RecipeStoreData{
currency?:Currency;
_trash:Trash;

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


constructor(id,name,img,data:RecipeStoreData){
this.id = id;
this.name = name;
this.img = img;
this.ingredients = data.ingredients || {}
this.results = data.results || {}
this.skill = data.skill;
this.currency = data.currency;
this._trash = {
Expand All @@ -27,13 +33,7 @@ export class Recipe implements RecipeStoreData{
};
}

defaultData() {
return {
ingredients: {},
results: {},
}
}
serialize() {
serialize():RecipeStoreData {
const serialized = {
ingredients: this.serializeIngredients(),
skill: this.skill,
Expand All @@ -57,26 +57,28 @@ export class Recipe implements RecipeStoreData{
}

addIngredient(entity,uuid,type) {
if(!this.ingredients[uuid]){
this.ingredients[uuid] = new DefaultComponent(entity,uuid,type);
const uuidS = sanitizeUuid(uuid);
if(!this.ingredients[uuidS]){
this.ingredients[uuidS] = new DefaultComponent(entity,uuid,type);
}else{
DefaultComponent.inc(this.ingredients[uuid])
DefaultComponent.inc(this.ingredients[uuidS])
}
}
removeIngredient(uuid){
delete this.ingredients[uuid];
this._trash.ingredients["-="+uuid] = null;
removeIngredient(uuidS){
delete this.ingredients[uuidS];
this._trash.ingredients["-="+uuidS] = null;
}
addResult(entity,uuid,type) {
if(!this.results[uuid]){
this.results[uuid] = new DefaultComponent(entity,uuid,type);
const uuidS = sanitizeUuid(uuid);
if(!this.results[uuidS]){
this.results[uuidS] = new DefaultComponent(entity,uuid,type);
}else{
DefaultComponent.inc(this.results[uuid])
DefaultComponent.inc(this.results[uuidS])
}
}
removeResults(uuid) {
delete this.results[uuid];
this._trash.results["-=" + uuid] = null;
removeResults(uuidS) {
delete this.results[uuidS];
this._trash.results["-=" + uuidS] = null;
}
addSkill() {
this.skill = new DefaultSkill();
Expand Down
22 changes: 2 additions & 20 deletions src/Settings.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
export class Settings {

static NAMESPACE = "beavers-crafting";
static CRAFT_BY_ID = "craftById";
static CREATE_ITEM_TITLE = "createItemTitle";
static RECIPE_SOURCE_NAME = "recipeSourceName";
static RECIPE_SUBTYPE = "Recipe";
static ANYOF_SUBTYPE = "AnyOf";

static init() {
game.settings.register(this.NAMESPACE, this.RECIPE_SOURCE_NAME, {
name: game.i18n.localize('beaversCrafting.settings.recipeSourceName.name'),
hint: game.i18n.localize('beaversCrafting.settings.recipeSourceName.hint'),
scope: "world",
config: true,
default: "Recipe",
type: String,
});

game.settings.register(this.NAMESPACE, this.CRAFT_BY_ID, {
name: game.i18n.localize('beaversCrafting.settings.craftById.name'),
hint: game.i18n.localize('beaversCrafting.settings.craftById.hint'),
scope: "world",
config: true,
default: true,
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'),
Expand Down
Loading

0 comments on commit b34dd64

Please sign in to comment.