@rpg-engine/long-bow 0.2.42 → 0.2.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
+ /// <reference types="react" />
1
2
  import { Meta } from '@storybook/react';
2
- import { ITradeComponentProps } from '../components/TradingMenu/TradingItemRow';
3
3
  declare const meta: Meta;
4
4
  export default meta;
5
- export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ITradeComponentProps>;
5
+ export declare const Default: () => JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.2.42",
3
+ "version": "0.2.44",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -10,12 +10,12 @@ import {
10
10
  import { observer } from 'mobx-react-lite';
11
11
  import React, { useEffect, useState } from 'react';
12
12
  import styled from 'styled-components';
13
+ import { v4 as uuidv4 } from 'uuid';
13
14
  import { RelativeListMenu } from '../../RelativeListMenu';
14
15
  import { SpriteFromAtlas } from '../../shared/SpriteFromAtlas';
15
16
  import { ItemTooltip } from '../Cards/ItemTooltip';
16
17
  import { ErrorBoundary } from './ErrorBoundary';
17
18
  import { generateContextMenu, IContextMenuItem } from './itemContainerHelper';
18
- import { v4 as uuidv4 } from 'uuid';
19
19
 
20
20
  const EquipmentSlotSpriteByType: any = {
21
21
  Neck: 'accessories/corruption-necklace.png',
@@ -77,7 +77,7 @@ export const ItemSlot: React.FC<IProps> = observer(
77
77
 
78
78
  useEffect(() => {
79
79
  if (item) {
80
- setContextActions(generateContextMenu(item.type, containerType));
80
+ setContextActions(generateContextMenu(item, containerType));
81
81
  }
82
82
  }, [item]);
83
83
 
@@ -3,6 +3,7 @@ import {
3
3
  ActionsForInventory,
4
4
  ActionsForLoot,
5
5
  ActionsForMapContainer,
6
+ IItem,
6
7
  ItemContainerType,
7
8
  ItemSocketEventsDisplayLabels,
8
9
  ItemType,
@@ -23,13 +24,13 @@ const generateContextMenuListOptions = (actionsByTypeList: any) => {
23
24
  };
24
25
 
25
26
  export const generateContextMenu = (
26
- itemType: ItemType,
27
+ item: IItem,
27
28
  itemContainerType: ItemContainerType | null
28
29
  ) => {
29
30
  let contextActionMenu: IContextMenuItem[] = [];
30
31
 
31
32
  if (itemContainerType === ItemContainerType.Inventory) {
32
- switch (itemType) {
33
+ switch (item.type) {
33
34
  case ItemType.Weapon:
34
35
  case ItemType.Armor:
35
36
  case ItemType.Accessory:
@@ -67,7 +68,7 @@ export const generateContextMenu = (
67
68
  }
68
69
  }
69
70
  if (itemContainerType === ItemContainerType.Equipment) {
70
- switch (itemType) {
71
+ switch (item.type) {
71
72
  case ItemType.Container:
72
73
  contextActionMenu = generateContextMenuListOptions(
73
74
  ActionsForEquipmentSet.Container
@@ -81,7 +82,7 @@ export const generateContextMenu = (
81
82
  }
82
83
  }
83
84
  if (itemContainerType === ItemContainerType.Loot) {
84
- switch (itemType) {
85
+ switch (item.type) {
85
86
  case ItemType.Weapon:
86
87
  case ItemType.Armor:
87
88
  case ItemType.Accessory:
@@ -111,7 +112,7 @@ export const generateContextMenu = (
111
112
  }
112
113
  }
113
114
  if (itemContainerType === ItemContainerType.MapContainer) {
114
- switch (itemType) {
115
+ switch (item.type) {
115
116
  case ItemType.Weapon:
116
117
  case ItemType.Armor:
117
118
  case ItemType.Accessory:
@@ -142,5 +143,10 @@ export const generateContextMenu = (
142
143
  break;
143
144
  }
144
145
  }
146
+
147
+ if (item.hasUseWith) {
148
+ contextActionMenu.push({ id: 'use-with', text: 'Use With...' });
149
+ }
150
+
145
151
  return contextActionMenu;
146
152
  };
@@ -1,6 +1,6 @@
1
1
  import { ITradeResponseItem } from '@rpg-engine/shared';
2
2
  import capitalize from 'lodash/capitalize';
3
- import React, { useState } from 'react';
3
+ import React from 'react';
4
4
  import styled from 'styled-components';
5
5
  import { uiColors } from '../../constants/uiColors';
6
6
  import { uiFonts } from '../../constants/uiFonts';
@@ -9,43 +9,32 @@ import { Ellipsis } from '../shared/Ellipsis';
9
9
  import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
10
10
  export interface ITradeComponentProps {
11
11
  traderItem: ITradeResponseItem;
12
- updateChartTotals: (traderItem: ITradeResponseItem) => void;
12
+ onQuantityChange: (
13
+ traderItem: ITradeResponseItem,
14
+ selectedQty: number
15
+ ) => void;
13
16
  atlasJSON: any;
14
17
  atlasIMG: any;
18
+ selectedQty: number;
15
19
  }
16
20
 
17
21
  export const TradingItemRow: React.FC<ITradeComponentProps> = ({
18
22
  atlasIMG,
19
23
  atlasJSON,
20
- updateChartTotals,
24
+ onQuantityChange,
21
25
  traderItem,
26
+ selectedQty,
22
27
  }) => {
23
- const [itemQuantity, setItemQuantity] = useState(0);
24
-
25
28
  const onLeftClick = () => {
26
- if (itemQuantity > 0) {
27
- const newQuantity = itemQuantity - 1;
28
- setItemQuantity(newQuantity);
29
- updateChartTotals({
30
- key: traderItem.key,
31
- qty: newQuantity,
32
- price: traderItem.price,
33
- texturePath: traderItem.texturePath,
34
- name: traderItem.name,
35
- });
29
+ if (selectedQty > 0) {
30
+ const newQuantity = selectedQty - 1;
31
+ onQuantityChange(traderItem, newQuantity);
36
32
  }
37
33
  };
38
34
  const onRightClick = () => {
39
- if (itemQuantity < 999) {
40
- const newQuantity = itemQuantity + 1;
41
- setItemQuantity(newQuantity);
42
- updateChartTotals({
43
- key: traderItem.key,
44
- qty: newQuantity,
45
- price: traderItem.price,
46
- texturePath: traderItem.texturePath,
47
- name: traderItem.name,
48
- });
35
+ if (selectedQty < (traderItem.qty ?? 999)) {
36
+ const newQuantity = selectedQty + 1;
37
+ onQuantityChange(traderItem, newQuantity);
49
38
  }
50
39
  };
51
40
 
@@ -80,7 +69,7 @@ export const TradingItemRow: React.FC<ITradeComponentProps> = ({
80
69
  ></SelectArrow>
81
70
  <QuantityDisplay>
82
71
  <TextOverlay>
83
- <Item>{itemQuantity}</Item>
72
+ <Item>{selectedQty}</Item>
84
73
  </TextOverlay>
85
74
  </QuantityDisplay>
86
75
  <SelectArrow
@@ -8,7 +8,7 @@ import { TradingItemRow } from './TradingItemRow';
8
8
  export interface ITrandingMenu {
9
9
  traderItems: ITradeResponseItem[];
10
10
  onClose: () => void;
11
- onConfirm: () => void;
11
+ onConfirm: (items: ITradeResponseItem[]) => void;
12
12
  type: TradeTransactionType;
13
13
  atlasJSON: any;
14
14
  atlasIMG: any;
@@ -25,23 +25,55 @@ export const TradingMenu: React.FC<ITrandingMenu> = ({
25
25
  onConfirm,
26
26
  }) => {
27
27
  const [sum, setSum] = useState(0);
28
- let newSumArray = 0;
29
- const updateChartTotals = (item: ITradeResponseItem) => {
30
- const itemIndex = traderItems.findIndex(
31
- itemArray => itemArray.key === item.key
32
- );
33
- traderItems[itemIndex] = item;
28
+ const [qtyMap, setQtyMap] = useState(new Map());
34
29
 
30
+ const onQuantityChange = (item: ITradeResponseItem, selectedQty: number) => {
31
+ setQtyMap(new Map(qtyMap.set(item.key, selectedQty)));
32
+
33
+ let newSum = 0;
35
34
  traderItems.forEach(item => {
36
- if (item.qty) newSumArray += item.qty * item.price;
37
- setSum(newSumArray);
35
+ const qty = qtyMap.get(item.key);
36
+ if (qty) newSum += qty * item.price;
37
+ setSum(newSum);
38
38
  });
39
39
  };
40
40
 
41
+ const isBuy = () => {
42
+ return type == 'buy';
43
+ };
44
+
45
+ const hasGoldForSale = () => {
46
+ if (isBuy()) {
47
+ return !(sum > characterAvailableGold);
48
+ }
49
+ return true;
50
+ };
51
+
52
+ const getFinalGold = () => {
53
+ if (isBuy()) {
54
+ return characterAvailableGold - sum;
55
+ } else {
56
+ return characterAvailableGold + sum;
57
+ }
58
+ };
59
+
41
60
  const Capitalize = (word: string) => {
42
61
  return word[0].toUpperCase() + word.substring(1);
43
62
  };
44
63
 
64
+ const onConfirmClick = () => {
65
+ const items: ITradeResponseItem[] = [];
66
+
67
+ traderItems.forEach(item => {
68
+ const qty = qtyMap.get(item.key);
69
+ if (qty) {
70
+ items.push(Object.assign({}, item, { qty: qty }));
71
+ }
72
+ });
73
+
74
+ onConfirm(items);
75
+ };
76
+
45
77
  return (
46
78
  <DraggableContainer
47
79
  type={RPGUIContainerTypes.Framed}
@@ -62,8 +94,9 @@ export const TradingMenu: React.FC<ITrandingMenu> = ({
62
94
  <TradingItemRow
63
95
  atlasIMG={atlasIMG}
64
96
  atlasJSON={atlasJSON}
65
- updateChartTotals={updateChartTotals}
97
+ onQuantityChange={onQuantityChange}
66
98
  traderItem={tradeItem}
99
+ selectedQty={qtyMap.get(tradeItem.key) ?? 0}
67
100
  />
68
101
  </ItemWrapper>
69
102
  ))}
@@ -76,22 +109,22 @@ export const TradingMenu: React.FC<ITrandingMenu> = ({
76
109
  <p>Total:</p>
77
110
  <p>${sum}</p>
78
111
  </TotalWrapper>
79
- {sum > characterAvailableGold ? (
112
+ {!hasGoldForSale() ? (
80
113
  <AlertWrapper>
81
114
  <p> Sorry, not enough money.</p>
82
115
  </AlertWrapper>
83
116
  ) : (
84
117
  <GoldWrapper>
85
118
  <p>Final Gold:</p>
86
- <p>${characterAvailableGold - sum}</p>
119
+ <p>${getFinalGold()}</p>
87
120
  </GoldWrapper>
88
121
  )}
89
122
 
90
123
  <ButtonWrapper>
91
124
  <Button
92
125
  buttonType={ButtonTypes.RPGUIButton}
93
- disabled={sum > characterAvailableGold}
94
- onClick={() => onConfirm()}
126
+ disabled={!hasGoldForSale()}
127
+ onClick={() => onConfirmClick()}
95
128
  >
96
129
  Confirm
97
130
  </Button>
@@ -141,7 +141,7 @@ export const items: IItem[] = [
141
141
  },
142
142
  {
143
143
  _id: '629acek4j7c8e8002fg60034',
144
- hasUseWith: false,
144
+ hasUseWith: true,
145
145
  type: ItemType.Consumable,
146
146
  subType: ItemSubType.Accessory,
147
147
  textureAtlas: 'items',
@@ -156,7 +156,7 @@ export const items: IItem[] = [
156
156
  layer: 1,
157
157
  isItemContainer: false,
158
158
  isSolid: false,
159
- key: 'board-sword-22',
159
+ key: 'silver-key',
160
160
  texturePath: 'others/silver-key.png',
161
161
  textureKey: 'silver-key',
162
162
  name: 'Key',
@@ -1,39 +1,35 @@
1
1
  import { ITradeResponseItem } from '@rpg-engine/shared';
2
- import { Meta, Story } from '@storybook/react';
3
- import React from 'react';
2
+ import { Meta } from '@storybook/react';
3
+ import React, { useState } from 'react';
4
4
  import { RPGUIRoot } from '../components/RPGUIRoot';
5
5
  import { itemMock } from '../components/TradingMenu/items.mock';
6
- import {
7
- ITradeComponentProps,
8
- TradingItemRow,
9
- } from '../components/TradingMenu/TradingItemRow';
6
+ import { TradingItemRow } from '../components/TradingMenu/TradingItemRow';
10
7
  import atlasJSON from '../mocks/atlas/items/items.json';
11
8
  import atlasIMG from '../mocks/atlas/items/items.png';
12
9
 
13
- const updateChartTotals = (itemInfo: ITradeResponseItem) => {
14
- console.log(itemInfo);
15
- // will be needed read all itens from chart list ignoring the current item (itemInfo) and recalculate the totals
16
- // with the amount updated set the total to a state to be shown to the player.
17
- // OBS: This list with Id, quantity and amount will be the one to send to API,
18
- // because the API need to know wichi Items and the quantity of it to make a purchese and set the itens to the player.
19
- };
20
-
21
10
  const meta: Meta = {
22
11
  title: 'Trading Item',
23
12
  component: TradingItemRow,
24
13
  };
25
14
  export default meta;
26
15
 
27
- const Template: Story<ITradeComponentProps> = args => (
28
- <RPGUIRoot>
29
- <TradingItemRow {...args} traderItem={itemMock[0]} />
30
- </RPGUIRoot>
31
- );
16
+ export const Default = () => {
17
+ const [selectedQty, setSelectedQty] = useState(0);
32
18
 
33
- export const Default = Template.bind({});
19
+ const handleOnChange = (item: ITradeResponseItem, qty: number) => {
20
+ console.log(item);
21
+ setSelectedQty(qty);
22
+ };
34
23
 
35
- Default.args = {
36
- atlasIMG: atlasIMG,
37
- atlasJSON: atlasJSON,
38
- updateChartTotals,
24
+ return (
25
+ <RPGUIRoot>
26
+ <TradingItemRow
27
+ atlasIMG={atlasIMG}
28
+ atlasJSON={atlasJSON}
29
+ onQuantityChange={handleOnChange}
30
+ selectedQty={selectedQty}
31
+ traderItem={itemMock[0]}
32
+ />
33
+ </RPGUIRoot>
34
+ );
39
35
  };
@@ -1,3 +1,4 @@
1
+ import { ITradeResponseItem } from '@rpg-engine/shared';
1
2
  import { Meta, Story } from '@storybook/react';
2
3
  import React from 'react';
3
4
  import { RPGUIRoot } from '../components/RPGUIRoot';
@@ -24,6 +25,11 @@ const Template: Story<ITrandingMenu> = args => (
24
25
 
25
26
  export const Default = Template.bind({});
26
27
 
28
+ const onConfirm = (items: ITradeResponseItem[]) => {
29
+ console.log('on confirm trading menu');
30
+ console.log(items);
31
+ };
32
+
27
33
  const onClose = () => {
28
34
  console.log('close');
29
35
  };
@@ -31,6 +37,7 @@ const onClose = () => {
31
37
  Default.args = {
32
38
  traderItems: itemMock,
33
39
  onClose: onClose,
40
+ onConfirm: onConfirm,
34
41
  type: 'buy',
35
42
  atlasJSON: atlasJSON,
36
43
  atlasIMG: atlasIMG,