Aray - record for inventory & equipment
This commit is contained in:
parent
561ffb1d7e
commit
cc8f4a562f
|
|
@ -34,7 +34,7 @@ interface SlotRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EquipmentState {
|
interface EquipmentState {
|
||||||
slots: SlotRecord[];
|
slots: Record<string, SlotRecord>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SlotInput =
|
export type SlotInput =
|
||||||
|
|
@ -46,17 +46,17 @@ export class Equipment extends Component<EquipmentState> {
|
||||||
#cachedVars: RPGVariables | null = null;
|
#cachedVars: RPGVariables | null = null;
|
||||||
|
|
||||||
constructor(slots: SlotInput[]) {
|
constructor(slots: SlotInput[]) {
|
||||||
super({
|
const record: Record<string, SlotRecord> = {};
|
||||||
slots: slots.map(s => {
|
for (const s of slots) {
|
||||||
const slotName = typeof s === 'string' ? s : s.slotName;
|
const slotName = typeof s === 'string' ? s : s.slotName;
|
||||||
const type = typeof s === 'object' && s.type ? s.type : null;
|
const type = typeof s === 'object' && s.type ? s.type : null;
|
||||||
return { slotName, type, itemId: null, appliedEffectKeys: [] };
|
record[slotName] = { slotName, type, itemId: null, appliedEffectKeys: [] };
|
||||||
}),
|
}
|
||||||
});
|
super({ slots: record });
|
||||||
}
|
}
|
||||||
|
|
||||||
#slot(slotName: string): SlotRecord | undefined {
|
#slot(slotName: string): SlotRecord | undefined {
|
||||||
return this.state.slots.find(s => s.slotName === slotName);
|
return this.state.slots[slotName];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ItemId in the named slot, or null if empty. */
|
/** ItemId in the named slot, or null if empty. */
|
||||||
|
|
@ -71,7 +71,7 @@ export class Equipment extends Component<EquipmentState> {
|
||||||
*/
|
*/
|
||||||
findCompatibleSlot(slotType: string): string | null {
|
findCompatibleSlot(slotType: string): string | null {
|
||||||
let genericFallback: string | null = null;
|
let genericFallback: string | null = null;
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.itemId !== null) continue;
|
if (slot.itemId !== null) continue;
|
||||||
if (slot.type === null) { genericFallback ??= slot.slotName; continue; }
|
if (slot.type === null) { genericFallback ??= slot.slotName; continue; }
|
||||||
if (slot.type === slotType) return slot.slotName;
|
if (slot.type === slotType) return slot.slotName;
|
||||||
|
|
@ -81,7 +81,7 @@ export class Equipment extends Component<EquipmentState> {
|
||||||
|
|
||||||
/** All currently equipped `{ slotName, itemId }` pairs. */
|
/** All currently equipped `{ slotName, itemId }` pairs. */
|
||||||
getEquipped(): { slotName: string; itemId: string }[] {
|
getEquipped(): { slotName: string; itemId: string }[] {
|
||||||
return this.state.slots
|
return Object.values(this.state.slots)
|
||||||
.filter((s): s is SlotRecord & { itemId: string } => s.itemId !== null)
|
.filter((s): s is SlotRecord & { itemId: string } => s.itemId !== null)
|
||||||
.map(({ slotName, itemId }) => ({ slotName, itemId }));
|
.map(({ slotName, itemId }) => ({ slotName, itemId }));
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +154,7 @@ export class Equipment extends Component<EquipmentState> {
|
||||||
if (this.#cachedVars) return this.#cachedVars;
|
if (this.#cachedVars) return this.#cachedVars;
|
||||||
|
|
||||||
const result: RPGVariables = {};
|
const result: RPGVariables = {};
|
||||||
for (const { slotName, itemId } of this.state.slots) {
|
for (const { slotName, itemId } of Object.values(this.state.slots)) {
|
||||||
result[slotName] = itemId ?? '';
|
result[slotName] = itemId ?? '';
|
||||||
}
|
}
|
||||||
this.#cachedVars = result;
|
this.#cachedVars = result;
|
||||||
|
|
|
||||||
|
|
@ -15,29 +15,25 @@ interface SlotRecord {
|
||||||
interface InventoryState {
|
interface InventoryState {
|
||||||
infinite: boolean;
|
infinite: boolean;
|
||||||
nextSlotId: number; // auto-increment counter for infinite mode
|
nextSlotId: number; // auto-increment counter for infinite mode
|
||||||
slots: SlotRecord[];
|
slots: Record<SlotId, SlotRecord>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildInventoryState(input?: number | InventorySlotInput[]): InventoryState {
|
function buildInventoryState(input?: number | InventorySlotInput[]): InventoryState {
|
||||||
if (input === undefined) {
|
if (input === undefined) {
|
||||||
return { infinite: true, nextSlotId: 0, slots: [] };
|
return { infinite: true, nextSlotId: 0, slots: {} as Record<SlotId, SlotRecord> };
|
||||||
}
|
}
|
||||||
if (typeof input === 'number') {
|
if (typeof input === 'number') {
|
||||||
return {
|
const slots = {} as Record<SlotId, SlotRecord>;
|
||||||
infinite: false,
|
for (let i = 0; i < input; i++) slots[i] = { slotId: i, limit: undefined, contents: null };
|
||||||
nextSlotId: 0,
|
return { infinite: false, nextSlotId: 0, slots };
|
||||||
slots: Array.from({ length: input }, (_, i) => ({ slotId: i, limit: undefined, contents: null })),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return {
|
const slots = {} as Record<SlotId, SlotRecord>;
|
||||||
infinite: false,
|
for (const def of input) {
|
||||||
nextSlotId: 0,
|
const slotId = typeof def === 'object' ? def.slotId : def;
|
||||||
slots: input.map(def => ({
|
const limit = typeof def === 'object' ? def.limit : undefined;
|
||||||
slotId: typeof def === 'object' ? def.slotId : def,
|
slots[slotId] = { slotId, limit, contents: null };
|
||||||
limit: typeof def === 'object' ? def.limit : undefined,
|
}
|
||||||
contents: null,
|
return { infinite: false, nextSlotId: 0, slots };
|
||||||
})),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@component
|
@component
|
||||||
|
|
@ -55,7 +51,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#slot(slotId: SlotId): SlotRecord | undefined {
|
#slot(slotId: SlotId): SlotRecord | undefined {
|
||||||
return this.state.slots.find(s => s.slotId === slotId);
|
return this.state.slots[slotId];
|
||||||
}
|
}
|
||||||
|
|
||||||
#capFor(slot: SlotRecord, itemId: string): number {
|
#capFor(slot: SlotRecord, itemId: string): number {
|
||||||
|
|
@ -94,7 +90,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
// ── Finite inventory: two-phase (check → apply) ───────────────────────
|
// ── Finite inventory: two-phase (check → apply) ───────────────────────
|
||||||
if (!this.state.infinite) {
|
if (!this.state.infinite) {
|
||||||
let canFit = 0;
|
let canFit = 0;
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents === null || slot.contents.itemId === itemId)
|
if (slot.contents === null || slot.contents.itemId === itemId)
|
||||||
canFit += this.#roomFor(slot, itemId);
|
canFit += this.#roomFor(slot, itemId);
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +98,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
|
|
||||||
let remaining = amount;
|
let remaining = amount;
|
||||||
const slotIds: SlotId[] = [];
|
const slotIds: SlotId[] = [];
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents?.itemId === itemId && remaining > 0) {
|
if (slot.contents?.itemId === itemId && remaining > 0) {
|
||||||
const take = Math.min(this.#roomFor(slot, itemId), remaining);
|
const take = Math.min(this.#roomFor(slot, itemId), remaining);
|
||||||
slot.contents!.amount += take;
|
slot.contents!.amount += take;
|
||||||
|
|
@ -110,7 +106,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
slotIds.push(slot.slotId);
|
slotIds.push(slot.slotId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents === null && remaining > 0) {
|
if (slot.contents === null && remaining > 0) {
|
||||||
const take = Math.min(this.#capFor(slot, itemId), remaining);
|
const take = Math.min(this.#capFor(slot, itemId), remaining);
|
||||||
slot.contents = { itemId, amount: take };
|
slot.contents = { itemId, amount: take };
|
||||||
|
|
@ -126,7 +122,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
let remaining = amount;
|
let remaining = amount;
|
||||||
const slotIds: SlotId[] = [];
|
const slotIds: SlotId[] = [];
|
||||||
|
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents?.itemId === itemId && remaining > 0) {
|
if (slot.contents?.itemId === itemId && remaining > 0) {
|
||||||
const take = Math.min(this.#roomFor(slot, itemId), remaining);
|
const take = Math.min(this.#roomFor(slot, itemId), remaining);
|
||||||
if (take > 0) {
|
if (take > 0) {
|
||||||
|
|
@ -136,7 +132,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents === null && remaining > 0) {
|
if (slot.contents === null && remaining > 0) {
|
||||||
const take = Math.min(this.#capFor(slot, itemId), remaining);
|
const take = Math.min(this.#capFor(slot, itemId), remaining);
|
||||||
slot.contents = { itemId, amount: take };
|
slot.contents = { itemId, amount: take };
|
||||||
|
|
@ -146,7 +142,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
}
|
}
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
const newSlot: SlotRecord = { slotId: this.state.nextSlotId++, limit: undefined, contents: null };
|
const newSlot: SlotRecord = { slotId: this.state.nextSlotId++, limit: undefined, contents: null };
|
||||||
this.state.slots.push(newSlot);
|
this.state.slots[newSlot.slotId] = newSlot;
|
||||||
const take = Math.min(this.#capFor(newSlot, itemId), remaining);
|
const take = Math.min(this.#capFor(newSlot, itemId), remaining);
|
||||||
newSlot.contents = { itemId, amount: take };
|
newSlot.contents = { itemId, amount: take };
|
||||||
remaining -= take;
|
remaining -= take;
|
||||||
|
|
@ -177,7 +173,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
|
|
||||||
let remaining = amount;
|
let remaining = amount;
|
||||||
const slotIds: SlotId[] = [];
|
const slotIds: SlotId[] = [];
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents?.itemId === itemId && remaining > 0) {
|
if (slot.contents?.itemId === itemId && remaining > 0) {
|
||||||
const take = Math.min(slot.contents.amount, remaining);
|
const take = Math.min(slot.contents.amount, remaining);
|
||||||
slot.contents.amount -= take;
|
slot.contents.amount -= take;
|
||||||
|
|
@ -290,7 +286,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
return slot?.contents?.itemId === itemId ? slot.contents.amount : 0;
|
return slot?.contents?.itemId === itemId ? slot.contents.amount : 0;
|
||||||
}
|
}
|
||||||
let total = 0;
|
let total = 0;
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents?.itemId === itemId) total += slot.contents.amount;
|
if (slot.contents?.itemId === itemId) total += slot.contents.amount;
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
|
|
@ -298,7 +294,7 @@ export class Inventory extends Component<InventoryState> {
|
||||||
|
|
||||||
getItems(): Map<string, number> {
|
getItems(): Map<string, number> {
|
||||||
const result = new Map<string, number>();
|
const result = new Map<string, number>();
|
||||||
for (const slot of this.state.slots) {
|
for (const slot of Object.values(this.state.slots)) {
|
||||||
if (slot.contents) {
|
if (slot.contents) {
|
||||||
const { itemId, amount } = slot.contents;
|
const { itemId, amount } = slot.contents;
|
||||||
result.set(itemId, (result.get(itemId) ?? 0) + amount);
|
result.set(itemId, (result.get(itemId) ?? 0) + amount);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue