Task 2: Equipment System - support 2-handed weapons, staves block offhand slot
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m40s

This commit is contained in:
Refactoring Agent
2026-04-25 19:24:23 +02:00
parent 7c05bea896
commit 5e0bee8820
3 changed files with 97 additions and 7 deletions
+45 -5
View File
@@ -103,8 +103,20 @@ export function EquipmentTab({ store }: EquipmentTabProps) {
return unequippedItems.filter((inst) => typeIds.has(inst.typeId));
};
// Check if a slot is blocked by a 2-handed weapon
const isSlotBlocked = (slot: EquipmentSlot): boolean => {
if (slot === 'offHand' && store.equippedInstances.mainHand) {
const mainHandType = EQUIPMENT_TYPES[store.equippedInstances.mainHand];
return mainHandType?.twoHanded === true;
}
return false;
};
// Get all items that can go in a slot (including accessories that can go in either accessory slot)
const getItemsForSlot = (slot: EquipmentSlot): EquipmentInstance[] => {
// Don't show items for blocked slots
if (isSlotBlocked(slot)) return [];
if (slot === 'accessory1' || slot === 'accessory2') {
// Accessories can go in either slot
const accessoryTypes = EQUIPMENT_TYPES;
@@ -114,6 +126,15 @@ export function EquipmentTab({ store }: EquipmentTabProps) {
return unequippedItems.filter((inst) => accessoryTypeIds.includes(inst.typeId));
}
// For offhand, don't show 2-handed weapons (they can only go in main hand)
if (slot === 'offHand') {
return getEquippableItems(slot).filter((inst) => {
const type = EQUIPMENT_TYPES[inst.typeId];
return !type?.twoHanded;
});
}
return getEquippableItems(slot);
};
@@ -132,24 +153,34 @@ export function EquipmentTab({ store }: EquipmentTabProps) {
const instanceId = store.equippedInstances[slot];
const instance = instanceId ? store.equipmentInstances[instanceId] : null;
const equipmentType = instance ? EQUIPMENT_TYPES[instance.typeId] : null;
const blocked = isSlotBlocked(slot);
return (
<div
key={slot}
className={`p-3 rounded border ${
instance
? RARITY_COLORS[instance.rarity]
: 'border-gray-700 bg-gray-800/30'
blocked
? 'border-red-900/50 bg-red-950/20'
: instance
? RARITY_COLORS[instance.rarity]
: 'border-gray-700 bg-gray-800/30'
}`}
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<span>{SLOT_ICONS[slot]}</span>
<span className="text-sm font-semibold text-gray-300">
<span className={`text-sm font-semibold ${
blocked ? 'text-red-400' : 'text-gray-300'
}`}>
{SLOT_NAMES[slot]}
</span>
{blocked && (
<Badge variant="outline" className="text-xs text-red-400 border-red-400">
Blocked
</Badge>
)}
</div>
{instance && (
{instance && !blocked && (
<Button
size="sm"
variant="ghost"
@@ -165,6 +196,11 @@ export function EquipmentTab({ store }: EquipmentTabProps) {
<div className="space-y-1">
<div className={`font-semibold text-sm ${RARITY_TEXT_COLORS[instance.rarity]}`}>
{instance.name}
{equipmentType?.twoHanded && (
<Badge variant="outline" className="ml-2 text-xs text-amber-400 border-amber-400">
2-Handed
</Badge>
)}
</div>
<div className="text-xs text-gray-400">
Capacity: {instance.usedCapacity}/{instance.totalCapacity}
@@ -198,6 +234,10 @@ export function EquipmentTab({ store }: EquipmentTabProps) {
</div>
)}
</div>
) : blocked ? (
<div className="text-sm text-red-400 italic">
Blocked by 2-handed weapon
</div>
) : (
<div className="text-sm text-gray-500 italic">
Empty