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);