added inventory and stamina system

This commit is contained in:
2026-02-17 15:38:46 +00:00
parent 8b975163a0
commit 27f2931ce1
43 changed files with 2980 additions and 250 deletions

View File

@@ -0,0 +1,100 @@
using UnityEngine;
using UnityEditor;
using System.IO;
/// <summary>
/// OGG → Setup → Create Bunny Hop Boots
/// Creates the ItemDefinition and a world pickup for the bhop boots.
/// </summary>
public static class BhopBootsSetup
{
private const string ITEM_DEF_PATH = "Assets/Items/BhopBoots_Item.asset";
private const string PICKUP_PREFAB = "Assets/Prefabs/Pickups/BhopBoots_Pickup.prefab";
[MenuItem("OGG/Setup/Create Bunny Hop Boots")]
public static void Create()
{
EnsureFolder("Assets/Items");
EnsureFolder("Assets/Prefabs/Pickups");
// ── ItemDefinition ────────────────────────────────────────────
ItemDefinition item = AssetDatabase.LoadAssetAtPath<ItemDefinition>(ITEM_DEF_PATH);
bool isNew = item == null;
if (isNew) item = ScriptableObject.CreateInstance<ItemDefinition>();
item.itemName = "Bunny Hop Boots";
item.type = ItemDefinition.ItemType.Misc;
item.isEquippable = true;
item.description = "Illegal footwear. Gives 200 stamina while worn. Do not wear near cliffs.";
if (isNew)
AssetDatabase.CreateAsset(item, ITEM_DEF_PATH);
else
EditorUtility.SetDirty(item);
AssetDatabase.SaveAssets();
// ── Pickup prefab — procedural boot shape ─────────────────────
GameObject root = new GameObject("BhopBoots_Pickup");
// Simple visual: a squashed cube (boot-ish)
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Cube);
body.name = "Visual";
body.transform.SetParent(root.transform, false);
body.transform.localPosition = new Vector3(0f, 0f, 0f);
body.transform.localScale = new Vector3(0.4f, 0.2f, 0.7f);
Object.DestroyImmediate(body.GetComponent<Collider>());
// Bright accent colour so it stands out
var rend = body.GetComponent<Renderer>();
if (rend != null)
{
rend.material = new Material(Shader.Find("Universal Render Pipeline/Lit"));
rend.material.color = new Color(0.1f, 0.9f, 0.4f);
}
PickupItem pickup = root.AddComponent<PickupItem>();
pickup.definition = item;
pickup.spinSpeed = 140f;
pickup.bobHeight = 0.2f;
pickup.bobSpeed = 2.8f;
pickup.pickupRadius = 2.2f;
pickup.pickupKey = KeyCode.E;
StaminaBoostPickup boost = root.AddComponent<StaminaBoostPickup>();
boost.newMaxStamina = 200f;
if (File.Exists(Application.dataPath + "/../" + PICKUP_PREFAB))
AssetDatabase.DeleteAsset(PICKUP_PREFAB);
GameObject saved = PrefabUtility.SaveAsPrefabAsset(root, PICKUP_PREFAB);
Object.DestroyImmediate(root);
AssetDatabase.Refresh();
EditorUtility.DisplayDialog(
"Bunny Hop Boots ✓",
$"Created:\n• {ITEM_DEF_PATH}\n• {PICKUP_PREFAB}\n\n" +
"Drag BhopBoots_Pickup into the scene.\n" +
"Pick it up with [E] to unlock bunny hopping.\n\n" +
"Hold SPACE while landing to chain hops and build speed.\n" +
"Strafe left/right mid-air to steer.",
"Let's go");
EditorGUIUtility.PingObject(saved);
Selection.activeObject = saved;
}
static void EnsureFolder(string path)
{
string[] parts = path.Split('/');
string current = parts[0];
for (int i = 1; i < parts.Length; i++)
{
string next = current + "/" + parts[i];
if (!AssetDatabase.IsValidFolder(next))
AssetDatabase.CreateFolder(current, parts[i]);
current = next;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 92ff81f98e809934bab9c5b8f160276a

View File

@@ -0,0 +1,151 @@
using UnityEngine;
using UnityEditor;
using System.IO;
/// <summary>
/// OGG → Setup → Create Gun Splat Weapon
/// Builds:
/// • Assets/Prefabs/Weapons/GunSplat.prefab — the held weapon (SimpleGun)
/// • Assets/Prefabs/Pickups/GunSplat_Pickup.prefab — world pickup (spins/bobs, press E)
/// • Assets/Items/GunSplat_Item.asset — ItemDefinition (type = Weapon)
/// </summary>
public static class GunSplatSetup
{
private const string GLB_PATH = "Assets/Models/LidarScans/Gun Splat.glb";
private const string WEAPON_PREFAB = "Assets/Prefabs/Weapons/GunSplat.prefab";
private const string PICKUP_PREFAB = "Assets/Prefabs/Pickups/GunSplat_Pickup.prefab";
private const string ITEM_DEF_PATH = "Assets/Items/GunSplat_Item.asset";
[MenuItem("OGG/Setup/Create Gun Splat Weapon")]
public static void CreateGunSplat()
{
// ── 1. Ensure output folders exist ──────────────────────────
EnsureFolder("Assets/Prefabs/Weapons");
EnsureFolder("Assets/Prefabs/Pickups");
EnsureFolder("Assets/Items");
// ── 2. Load the GLB model ────────────────────────────────────
GameObject modelAsset = AssetDatabase.LoadAssetAtPath<GameObject>(GLB_PATH);
if (modelAsset == null)
{
Debug.LogError($"[GunSplatSetup] Could not find GLB at: {GLB_PATH}");
EditorUtility.DisplayDialog("Gun Splat Setup", $"Could not find model at:\n{GLB_PATH}", "OK");
return;
}
// ── 3. Build the held-weapon prefab ──────────────────────────
GameObject weaponRoot = new GameObject("GunSplat");
AttachVisual(weaponRoot, modelAsset);
SimpleGun gun = weaponRoot.AddComponent<SimpleGun>();
gun.damage = 30f;
gun.range = 120f;
gun.fireRate = 6f;
gun.maxAmmo = 24;
gun.isAutomatic = false;
if (File.Exists(DataRelative(WEAPON_PREFAB)))
AssetDatabase.DeleteAsset(WEAPON_PREFAB);
GameObject savedWeapon = PrefabUtility.SaveAsPrefabAsset(weaponRoot, WEAPON_PREFAB);
Object.DestroyImmediate(weaponRoot);
if (savedWeapon == null)
{
Debug.LogError("[GunSplatSetup] Failed to save weapon prefab.");
return;
}
Debug.Log($"[GunSplatSetup] Weapon prefab → {WEAPON_PREFAB}");
// ── 4. Create / update ItemDefinition ────────────────────────
ItemDefinition item = AssetDatabase.LoadAssetAtPath<ItemDefinition>(ITEM_DEF_PATH);
bool isNew = item == null;
if (isNew) item = ScriptableObject.CreateInstance<ItemDefinition>();
item.itemName = "Gun Splat";
item.type = ItemDefinition.ItemType.Weapon;
item.weaponPrefab = savedWeapon;
item.description = "A janky lidar-scanned sidearm. Shoots first, looks weird always.";
if (isNew)
AssetDatabase.CreateAsset(item, ITEM_DEF_PATH);
else
EditorUtility.SetDirty(item);
AssetDatabase.SaveAssets();
Debug.Log($"[GunSplatSetup] ItemDefinition → {ITEM_DEF_PATH}");
// ── 5. Build the world pickup prefab ─────────────────────────
GameObject pickupRoot = new GameObject("GunSplat_Pickup");
// Visual child — the GLB model
AttachVisual(pickupRoot, modelAsset);
// PickupItem component
PickupItem pickup = pickupRoot.AddComponent<PickupItem>();
pickup.definition = item;
pickup.spinSpeed = 90f;
pickup.bobHeight = 0.15f;
pickup.bobSpeed = 2.0f;
pickup.pickupRadius = 2.2f;
pickup.pickupKey = KeyCode.E;
if (File.Exists(DataRelative(PICKUP_PREFAB)))
AssetDatabase.DeleteAsset(PICKUP_PREFAB);
GameObject savedPickup = PrefabUtility.SaveAsPrefabAsset(pickupRoot, PICKUP_PREFAB);
Object.DestroyImmediate(pickupRoot);
if (savedPickup == null)
{
Debug.LogError("[GunSplatSetup] Failed to save pickup prefab.");
return;
}
Debug.Log($"[GunSplatSetup] Pickup prefab → {PICKUP_PREFAB}");
AssetDatabase.Refresh();
// ── 6. Done ──────────────────────────────────────────────────
EditorUtility.DisplayDialog(
"Gun Splat Setup ✓",
"Created:\n" +
$"• {WEAPON_PREFAB}\n" +
$"• {PICKUP_PREFAB}\n" +
$"• {ITEM_DEF_PATH}\n\n" +
"Drag GunSplat_Pickup into the scene wherever you want it to spawn.\n" +
"It will spin, bob, and show an [E] prompt when the player gets close.",
"Sick");
EditorGUIUtility.PingObject(savedPickup);
Selection.activeObject = savedPickup;
}
// ─── Helpers ─────────────────────────────────────────────────────
static void AttachVisual(GameObject parent, GameObject modelAsset)
{
GameObject visual = (GameObject)PrefabUtility.InstantiatePrefab(modelAsset);
if (visual == null) visual = Object.Instantiate(modelAsset);
visual.name = "Visual";
visual.transform.SetParent(parent.transform, false);
visual.transform.localPosition = Vector3.zero;
visual.transform.localRotation = Quaternion.identity;
visual.transform.localScale = Vector3.one;
}
static string DataRelative(string assetPath) =>
Application.dataPath + "/../" + assetPath;
static void EnsureFolder(string path)
{
string[] parts = path.Split('/');
string current = parts[0];
for (int i = 1; i < parts.Length; i++)
{
string next = current + "/" + parts[i];
if (!AssetDatabase.IsValidFolder(next))
AssetDatabase.CreateFolder(current, parts[i]);
current = next;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a0ceea0a64e3fa344b83004be51fe457

View File

@@ -0,0 +1,92 @@
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(WeaponManager))]
public class WeaponManagerEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
WeaponManager wm = (WeaponManager)target;
if (!Application.isPlaying) return;
EditorGUILayout.Space();
EditorGUILayout.LabelField("── Live Positioning ──", EditorStyles.boldLabel);
// Show what's active
string activeName = wm.ActiveWeaponName;
if (string.IsNullOrEmpty(activeName))
{
EditorGUILayout.HelpBox("No weapon currently equipped.", MessageType.Info);
return;
}
EditorGUILayout.HelpBox($"Active: {activeName}", MessageType.None);
// Select the live GO so you can drag gizmos in Scene view
if (GUILayout.Button("🎯 Select Active Weapon in Scene"))
{
var slot = wm.slots.Find(s => s.itemName == activeName);
if (slot != null)
{
Selection.activeGameObject = slot.instance;
SceneView.lastActiveSceneView?.Focus();
}
}
EditorGUILayout.Space();
// Sync the current transform back into the WeaponViewmodel (or fallback global offset)
if (GUILayout.Button("⬆ Sync Transform → Offset Fields"))
{
var slot = wm.slots.Find(s => s.itemName == activeName);
if (slot != null)
{
var vm = slot.instance.GetComponent<WeaponViewmodel>();
if (vm != null)
{
Undo.RecordObject(vm, "Sync Weapon Viewmodel");
vm.SyncFromTransform();
EditorUtility.SetDirty(vm);
// Also save back to the source prefab asset
var prefabAsset = PrefabUtility.GetCorrespondingObjectFromSource(slot.instance);
if (prefabAsset != null)
{
var prefabVm = prefabAsset.GetComponent<WeaponViewmodel>();
if (prefabVm != null)
{
Undo.RecordObject(prefabVm, "Sync Weapon Viewmodel Prefab");
prefabVm.positionOffset = vm.positionOffset;
prefabVm.rotationOffset = vm.rotationOffset;
prefabVm.scale = vm.scale;
EditorUtility.SetDirty(prefabVm);
AssetDatabase.SaveAssets();
}
}
Debug.Log($"[WeaponManager] Synced to WeaponViewmodel: pos={vm.positionOffset} rot={vm.rotationOffset} scale={vm.scale}");
}
else
{
// Fallback: no viewmodel, write to global offsets
Undo.RecordObject(wm, "Sync Weapon Offset");
wm.weaponPositionOffset = slot.instance.transform.localPosition;
wm.weaponRotationOffset = slot.instance.transform.localRotation.eulerAngles;
wm.weaponScale = slot.instance.transform.localScale;
EditorUtility.SetDirty(wm);
Debug.Log($"[WeaponManager] Synced to global offset: pos={wm.weaponPositionOffset}");
}
}
}
EditorGUILayout.HelpBox(
"1. Hit Play & equip the gun\n" +
"2. Click 'Select Active Weapon'\n" +
"3. Use Move/Rotate gizmos in Scene view\n" +
"4. Click 'Sync Transform → Offset Fields'\n" +
"5. Stop Play — values are saved",
MessageType.Info);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fe67de8a32d4bf5449ee8def34a1bb8a