fun: lootz!

This commit is contained in:
cha0s 2019-10-09 03:39:22 -05:00
parent 7a8c787261
commit 4b8c062b0f
9 changed files with 203 additions and 10 deletions

View File

@ -0,0 +1,29 @@
import msgpack from 'msgpack-lite';
import {Packet} from '@avocado/net';
export class TraitUpdateReceptacleItemFullPacket extends Packet {
static pack(packet) {
const data = packet.data[1];
data.json = msgpack.encode(data.json);
return super.pack(packet);
}
static get schema() {
return {
...super.schema,
data: {
slotIndex: 'uint16',
json: 'buffer',
},
};
}
static unpack(packet) {
const data = super.unpack(packet);
data.json = msgpack.decode(data.json);
return data;
}
}

View File

@ -0,0 +1,68 @@
import {compose, Property} from '@avocado/core';
import {StateProperty, Trait, Entity} from '@avocado/entity';
import {Rectangle, Vector} from '@avocado/math';
const decorate = compose(
StateProperty('lootable', {
track: true,
}),
);
export class Lootable extends decorate(Trait) {
static defaultParams() {
return {
table: [],
};
}
static defaultState() {
return {
lootable: true,
};
}
static type() {
return 'lootable';
}
constructor(entity, params, state) {
super(entity, params, state);
}
calculateLoot() {
const jsons = [];
const roll = Math.random() * 100;
for (const {perc, json} of this.params.table) {
if (perc > roll) {
jsons.push(json);
}
}
return jsons;
}
listeners() {
const listeners = {};
if (AVOCADO_SERVER) {
listeners['died'] = () => {
const jsons = this.calculateLoot();
const position = this.entity.position;
for (let i = 0; i < jsons.length; i++) {
const offset = Vector.sub(
[
Math.floor(Math.random() * 16),
Math.floor(Math.random() * 16)
],
[8, 8]
);
this.entity.spawnRawAt(
Vector.add(position, offset),
jsons[i]
);
}
};
}
return listeners;
}
}

View File

@ -7,6 +7,9 @@ import {
import {
TraitUpdateReceptacleItemSwapPacket,
} from '../packets/trait-update-receptacle-item-swap.packet';
import {
TraitUpdateReceptacleItemFullPacket,
} from '../packets/trait-update-receptacle-item-full.packet';
const decorate = compose(
StateProperty('slotCount', {
@ -79,6 +82,14 @@ export class Receptacle extends decorate(Trait) {
item.qty = packet.data.qty;
}
}
// Full item.
if (packet instanceof TraitUpdateReceptacleItemFullPacket) {
Entity.loadOrInstance(packet.data.json).then((item) => {
item.hydrate().then(() => {
this.entity.addItemToSlot(item, packet.data.slotIndex);
});
});
}
// Slot swap.
if (packet instanceof TraitUpdateReceptacleItemSwapPacket) {
// NULL destination slot === remove.
@ -105,7 +116,7 @@ export class Receptacle extends decorate(Trait) {
this.packetUpdates.push(new TraitUpdateReceptacleItemQtyPacket({
slotIndex,
qty: item.qty,
}, this.entity));
}));
}
// Item was used up.
else {
@ -197,6 +208,10 @@ export class Receptacle extends decorate(Trait) {
listeners.collisionStart = (other) => {
if (other.is('item')) {
this.entity.addItemToSlot(other);
const slotIndex = this.itemSlotIndex(other);
if (other.is('listed')) {
other.list.removeEntity(other);
}
}
};
}
@ -207,12 +222,20 @@ export class Receptacle extends decorate(Trait) {
return {
addItemToSlot: (item, slotIndex = AUTO_SLOT) => {
slotIndex = slotIndex >> 0;
if (AUTO_SLOT === slotIndex) {
return this.mergeItem(item);
}
else {
this.addListenersForItem(item);
this.slotItems[slotIndex] = item;
if (AVOCADO_SERVER) {
this.packetUpdates.push(new TraitUpdateReceptacleItemFullPacket({
slotIndex,
// CHEATING: assuming this entity is the informed
json: item.toNetwork(this.entity),
}));
}
}
this.entity.emit('inventoryChanged');
},
@ -228,7 +251,7 @@ export class Receptacle extends decorate(Trait) {
this.packetUpdates.push(new TraitUpdateReceptacleItemSwapPacket({
firstSlotIndex: slotIndex,
secondSlotIndex: NULL_SLOT,
}, this.entity));
}));
}
this.entity.emit('inventoryChanged');
return item;

BIN
resource/yarn-ball.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

View File

@ -40,6 +40,8 @@ import {wateringCanJSON} from './fixtures/watering-can.entity';
writeFixture('watering-can.entity.json', wateringCanJSON());
import {tomatoSeedsJSON} from './fixtures/tomato-seeds.entity';
writeFixture('tomato-seeds.entity.json', tomatoSeedsJSON());
import {yarnBallJSON} from './fixtures/yarn-ball.entity';
writeFixture('yarn-ball.entity.json', yarnBallJSON());
// Write rooms.
import {kittyFireJSON} from './fixtures/kitty-fire.room';
writeFixture('kitty-fire.room.json', kittyFireJSON());

View File

@ -64,15 +64,15 @@ export function kittyFireJSON() {
// for (let i = 0; i < 20; ++i) {
// addEntityWithRandomPosition('/rock.entity.json');
// }
for (let i = 0; i < 30; ++i) {
addEntityWithRandomPosition('/flower-barrel.entity.json');
}
// for (let i = 0; i < 30; ++i) {
// addEntityWithRandomPosition('/flower-barrel.entity.json');
// }
for (let i = 0; i < 5; ++i) {
addEntityWithRandomPosition('/mama-kitty-spawner.entity.json');
}
for (let i = 0; i < 50; ++i) {
addEntityWithRandomPosition('/fire.entity.json');
}
// for (let i = 0; i < 50; ++i) {
// addEntityWithRandomPosition('/fire.entity.json');
// }
for (let i = 0; i < 5; ++i) {
addEntityWithRandomPosition('/blue-fire.entity.json');
}

View File

@ -111,6 +111,24 @@ export function kittyJSON() {
},
layered: {},
listed: {},
lootable: {
params: {
table: [
{
perc: 20,
json: {
uri: '/rock.entity.json',
},
},
{
perc: 70,
json: {
uri: '/yarn-ball.entity.json',
},
},
],
},
},
mobile: {
state: {
speed: 40,
@ -128,6 +146,7 @@ export function kittyJSON() {
},
},
},
spawner: {},
vulnerable: {},
},
};

View File

@ -1,7 +1,5 @@
import {buildInvoke, buildTraversal} from '@avocado/behavior';
import {AFFINITY_NONE} from '../../common/combat/constants';
// Rock.
export function rockJSON() {
const spawnProjectile = buildInvoke(

View File

@ -0,0 +1,54 @@
import {buildInvoke, buildTraversal} from '@avocado/behavior';
// Yarn ball.
export function yarnBallJSON() {
return {
traits: {
collider: {
params: {
isSensor: true,
},
},
existent: {
state: {
name: 'Yarn Ball',
},
},
item: {
params: {
slotImageUris: {
default: '/yarn-ball.png',
},
},
},
layered: {},
listed: {},
magnetic: {},
mobile: {},
physical: {},
pictured: {
params: {
images: {
initial: {
offset: [0, 0],
size: [8, 8], // Derive?
uri: '/yarn-ball.png',
},
}
},
},
positioned: {},
roomed: {},
shaped: {
params: {
shape: {
type: 'rectangle',
position: [0, 0],
size: [16, 16],
},
},
},
visible: {},
},
};
}