diff --git a/packages/app/src/components/app/play/ui/stamina/index.jsx b/packages/app/src/components/app/play/ui/stamina/index.jsx
index 8211ec3..3441c8f 100644
--- a/packages/app/src/components/app/play/ui/stamina/index.jsx
+++ b/packages/app/src/components/app/play/ui/stamina/index.jsx
@@ -4,8 +4,8 @@ import {PropTypes, React} from '@flecks/react';
import styles from './index.module.scss';
function Stamina({selfEntity}) {
- const stamina = usePropertyChange(selfEntity, 'stamina') || 85;
- const maxStamina = usePropertyChange(selfEntity, 'maxStamina') || 100;
+ const stamina = usePropertyChange(selfEntity, 'stamina');
+ const maxStamina = usePropertyChange(selfEntity, 'maxStamina');
const filled = stamina / maxStamina;
return (
class Tool extends Trait {
}
}
+ consumeStamina() {
+ const {wielder} = this.entity;
+ if (wielder.stamina >= this.params.cost) {
+ wielder.stamina -= this.params.cost;
+ return true;
+ }
+ return false;
+ }
+
createTargetContext(target) {
const {wielder} = this.entity;
const {room} = wielder;
@@ -105,6 +114,7 @@ export default (flecks) => class Tool extends Trait {
static defaultParams() {
return {
+ cost: 3,
target: {
type: 'projection',
distance: 1,
@@ -165,6 +175,9 @@ export default (flecks) => class Tool extends Trait {
return {
useTool: () => {
+ if (!this.consumeStamina()) {
+ return undefined;
+ }
this.calculateTargets();
const promises = this.$$targets.map((target) => {
const {Script} = flecks.get('$avocado/resource.resources');
diff --git a/packages/inventory/src/packets/trait-update-wielder-stamina.js b/packages/inventory/src/packets/trait-update-wielder-stamina.js
new file mode 100644
index 0000000..32e10ff
--- /dev/null
+++ b/packages/inventory/src/packets/trait-update-wielder-stamina.js
@@ -0,0 +1,12 @@
+import {Packet} from '@flecks/socket';
+
+export default () => class TraitUpdateWielderStamina extends Packet {
+
+ static get data() {
+ return {
+ stamina: 'uint16',
+ maxStamina: 'uint16',
+ };
+ }
+
+};
diff --git a/packages/inventory/src/traits/wielder.js b/packages/inventory/src/traits/wielder.js
index 1f2bf3d..01d6a92 100644
--- a/packages/inventory/src/traits/wielder.js
+++ b/packages/inventory/src/traits/wielder.js
@@ -5,6 +5,12 @@ const decorate = compose(
StateProperty('activeSlotIndex', {
track: true,
}),
+ StateProperty('maxStamina', {
+ track: true,
+ }),
+ StateProperty('stamina', {
+ track: true,
+ }),
);
export default () => class Wielder extends decorate(Trait) {
@@ -18,9 +24,21 @@ export default () => class Wielder extends decorate(Trait) {
this.$$itemPromise = undefined;
}
+ acceptPacket(packet) {
+ switch (packet.constructor.type) {
+ case 'TraitUpdateWielderStamina':
+ this.entity.stamina = packet.data.stamina;
+ this.entity.maxStamina = packet.data.maxStamina;
+ break;
+ default:
+ }
+ }
+
static defaultState() {
return {
activeSlotIndex: 0,
+ maxStamina: 100,
+ stamina: 100,
};
}
@@ -99,6 +117,30 @@ export default () => class Wielder extends decorate(Trait) {
};
}
+ packetsFor() {
+ const packets = [];
+ const {stamina, maxStamina} = this.stateDifferences();
+ if (stamina || maxStamina) {
+ packets.push([
+ 'TraitUpdateWielderStamina',
+ {
+ stamina: this.state.stamina,
+ maxStamina: this.state.maxStamina,
+ },
+ ]);
+ }
+ return packets;
+ }
+
+ get stamina() {
+ return this.state.stamina;
+ }
+
+ set stamina(stamina) {
+ // Clamp stamina between 0 and max.
+ super.stamina = Math.min(Math.max(0, stamina), this.entity.maxStamina);
+ }
+
tick() {
if (-1 !== this.$$itemUseRequest && !this.$$itemPromise) {
const tickingPromise = this.entity.useItemInSlot(this.$$itemUseRequest);