diff --git a/CursorUserSetup-x64-3.6.21.exe b/CursorUserSetup-x64-3.6.21.exe
deleted file mode 100644
index fd33e58..0000000
Binary files a/CursorUserSetup-x64-3.6.21.exe and /dev/null differ
diff --git a/malebody.png b/malebody.png
deleted file mode 100644
index 0188a75..0000000
Binary files a/malebody.png and /dev/null differ
diff --git a/src/App.css b/src/App.css
index c6c5c0b..eeafedb 100644
--- a/src/App.css
+++ b/src/App.css
@@ -947,15 +947,86 @@ body {
cursor: not-allowed;
}
-.limb-cancel-btn {
- background: #1e1e30;
- color: #6b7280;
- border: 1px solid #2e303a;
- border-radius: 3px;
- padding: 14px 40px;
- cursor: pointer;
+.limb-select-panel {
+ width: 600px;
+ min-height: 0;
+}
+
+.limb-select-title {
+ margin-bottom: 16px;
font-size: 16px;
font-weight: bold;
+ color: #e0e0e0;
+}
+
+.limb-select-skills {
+ margin-bottom: 8px;
+}
+
+.limb-select-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.limb-target-btn {
+ text-align: center;
+ cursor: pointer;
+ border: 1px solid #5F71C5;
+ border-radius: 1px;
+ padding: 8px 14px;
+ font-weight: bold;
+ font-size: 13px;
+ background: none;
+ color: #5F71C5;
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
+}
+
+.limb-target-btn:hover {
+ background: #1e2642;
+ color: #5F71C5;
+}
+
+.limb-target-selected {
+ background: #1e2642;
+ border-color: #fbbf24;
+ color: #fbbf24;
+}
+
+.limb-target-selected:hover {
+ background: #1e2642;
+ border-color: #fcd34d;
+ color: #fcd34d;
+}
+
+.limb-confirm-btn {
+ border: 1px solid #22c55e;
+ border-radius: 1px;
+ padding: 10px 24px;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: bold;
+ background: #22c55e;
+ color: #000;
+ transition: background 0.15s;
+ white-space: nowrap;
+}
+
+.limb-confirm-btn:hover {
+ background: #16a34a;
+}
+
+.limb-cancel-btn {
+ text-align: center;
+ border: 1px solid #2e303a;
+ border-radius: 1px;
+ padding: 10px 0;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: bold;
+ background: #1e1e30;
+ color: #6b7280;
+ transition: color 0.15s, border-color 0.15s;
}
.limb-cancel-btn:hover {
@@ -1318,6 +1389,40 @@ body {
justify-content: center;
}
+.world-info-panel {
+ background: rgba(15, 15, 26, 0.75);
+ border: 2px solid #5F71C5;
+ border-radius: 3px;
+ padding: 24px 32px 32px;
+ min-width: 280px;
+ position: relative;
+}
+
+.world-info-grid {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.info-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 6px 0;
+ border-bottom: 1px solid #2e303a;
+}
+
+.info-label {
+ color: #6b7280;
+ font-size: 14px;
+}
+
+.info-value {
+ color: #e0e0e0;
+ font-size: 14px;
+ font-weight: bold;
+}
+
.inventory-panel {
background: rgba(15, 15, 26, 0.75);
border: 2px solid #5F71C5;
diff --git a/src/App.jsx b/src/App.jsx
index 2a962ff..deb13b3 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -196,6 +196,7 @@ function App() {
const [weaponConditions, setWeaponConditions] = useState({ rusty_sword: 65 })
const [buyArmChoice, setBuyArmChoice] = useState(null)
const [showInventory, setShowInventory] = useState(false)
+ const [showWorldInfo, setShowWorldInfo] = useState(false)
const [invTab, setInvTab] = useState('health')
const [gameTime, setGameTime] = useState({ day: 1, hour: 8 })
const [contextMenu, setContextMenu] = useState(null)
@@ -246,9 +247,12 @@ function App() {
const [selectedSkill, setSelectedSkill] = useState(null)
const [selectedEnemy, setSelectedEnemy] = useState(0)
const [targetEnemy, setTargetEnemy] = useState(null)
- const [showEnemyInv, setShowEnemyInv] = useState(false)
- const [enemyInvTab, setEnemyInvTab] = useState('health')
- const [charView, setCharView] = useState(null)
+ const [attackEnemy, setAttackEnemy] = useState(null)
+ const [panelTarget, setPanelTarget] = useState('player')
+ const [minimapView, setMinimapView] = useState({ x: 0, y: 0, scale: 1 })
+ const minimapPanRef = useRef(false)
+ const minimapPanStart = useRef({ x: 0, y: 0 })
+ const minimapMovedRef = useRef(false)
const liveCharacters = characters
@@ -364,6 +368,8 @@ function App() {
return {
id: npc.id,
name: npc.name,
+ age: Math.floor(Math.random() * 30) + 18,
+ location: npc.location ?? 'Unknown',
pos: { x: 120 + index * spread, y: 60 + index * spread },
integrity: freshBody(),
injuries: freshInjuries(),
@@ -708,15 +714,30 @@ function App() {
}, [combatTime, combat, bodyInjuries])
const handleItemClick = (itemId, i) => {
- setCharView('player')
+ setShowInventory(true); setPanelTarget('player')
}
- const confirmLimbAttack = (part) => {
- if (!limbSelect) return
- const partMap = { larm: 'leftArm', rarm: 'rightArm', lleg: 'leftLeg', rleg: 'rightLeg' }
+ const partMap = { larm: 'leftArm', rarm: 'rightArm', lleg: 'leftLeg', rleg: 'rightLeg' }
+
+ const selectLimbTarget = (part) => {
const fullPart = partMap[part] || part
- playerAttack(fullPart, limbSelect, null, selectedEnemy)
+ setSelectedTarget(fullPart)
+ }
+
+ const executeAttack = () => {
+ if (!limbSelect || !selectedTarget) return
+ playerAttack(selectedTarget, limbSelect, selectedSkill, attackEnemy)
setLimbSelect(null)
+ setSelectedSkill(null)
+ setSelectedTarget(null)
+ setAttackEnemy(null)
+ }
+
+ const cancelAttack = () => {
+ setLimbSelect(null)
+ setSelectedSkill(null)
+ setSelectedTarget(null)
+ setAttackEnemy(null)
}
return (
@@ -737,7 +758,7 @@ function App() {
setExpandedWeapon(expandedWeapon === 'ROOT' ? null : 'ROOT')}>
{expandedWeapon === 'ROOT' ? '▼' : '▶'}
- { e.stopPropagation(); setCharView('player') }}>Player
+ { e.stopPropagation(); setShowInventory(true); setPanelTarget('player') }}>Player
{expandedWeapon === 'ROOT' && (
@@ -856,26 +877,76 @@ function App() {
)}
-
-