ソースを参照

Combat event workarounds and UI complete

Axel Nordh 8 ヶ月 前
コミット
fb5c1518cd
42 ファイル変更7216 行追加3 行削除
  1. 42 0
      Assets/Resources/TravelEvents/SkeletonAmbush.asset
  2. 133 1
      Assets/Scenes/MapScene2.unity
  3. 191 0
      Assets/Scripts/Characters/Enemies/EnemyCharacterData.cs
  4. 55 0
      Assets/Scripts/Characters/Enemies/ForestTroll.asset
  5. 52 0
      Assets/Scripts/Characters/Enemies/GoblinScout.asset
  6. 52 0
      Assets/Scripts/Characters/Enemies/SkeletonWarrior.asset
  7. 113 0
      Assets/Scripts/Editor/CombatEventFixer.cs
  8. 260 0
      Assets/Scripts/Editor/EnemyCharacterCreator.cs
  9. 209 0
      Assets/Scripts/Editor/EnemyWeaponMigrationTool.cs
  10. 330 0
      Assets/Scripts/Events/CombatEventIntegration.cs
  11. 296 0
      Assets/Scripts/Events/EnhancedTravelEventSystem.cs
  12. 40 0
      Assets/Scripts/Events/HiddenTreasure.asset
  13. 40 0
      Assets/Scripts/Events/SkeletonAmbush.asset
  14. 48 0
      Assets/Scripts/Events/SkeletonAmbushEvent.cs
  15. 298 0
      Assets/Scripts/Events/SpecificTravelEvents.cs
  16. 231 0
      Assets/Scripts/Events/TravelEvent.cs
  17. 108 0
      Assets/Scripts/Events/TravelEventContext.cs
  18. 488 0
      Assets/Scripts/Events/TravelEventSystem.cs
  19. 249 0
      Assets/Scripts/Events/TravelEventSystemSetup.cs
  20. 410 0
      Assets/Scripts/Events/TravelEventTypes.cs
  21. 284 0
      Assets/Scripts/Events/TravelEventUI.cs
  22. 13 2
      Assets/Scripts/Map/TeamTravelSystem.cs
  23. 3 0
      Assets/Scripts/Objects/Items/WeaponItem.cs
  24. 33 0
      Assets/Scripts/Objects/Weapons/Club.asset
  25. 34 0
      Assets/Scripts/Objects/Weapons/Dagger.asset
  26. 32 0
      Assets/Scripts/Objects/Weapons/SimpleBow.asset
  27. 33 0
      Assets/Scripts/Objects/Weapons/SimpleSword.asset
  28. 510 0
      Assets/Scripts/UI/CombatEventPopup.cs
  29. 620 0
      Assets/Scripts/UI/CombatEventPopupUXML.cs
  30. 227 0
      Assets/UI/CombatEventPopup.uss
  31. 28 0
      Assets/UI/CombatEventPopup.uxml
  32. 108 0
      BACKWARD_COMPATIBILITY_REMOVAL.md
  33. 99 0
      COMBAT_EVENT_ASSET_REFERENCE_FIX.md
  34. 165 0
      COMBAT_EVENT_POPUP_GUIDE.md
  35. 248 0
      COMBAT_EVENT_POPUP_UXML_GUIDE.md
  36. 99 0
      COMBAT_POPUP_SETUP_GUIDE.md
  37. 163 0
      ENEMY_CHARACTER_CREATION_GUIDE.md
  38. 117 0
      ENEMY_WEAPON_SYSTEM_UPDATE.md
  39. 188 0
      SEPARATION_OF_CONCERNS_GUIDE.md
  40. 145 0
      SKELETON_AMBUSH_CREATION_GUIDE.md
  41. 247 0
      TRAVEL_EVENT_SYSTEM_GUIDE.md
  42. 175 0
      TYPE_SAFE_TRAVEL_EVENTS_GUIDE.md

+ 42 - 0
Assets/Resources/TravelEvents/SkeletonAmbush.asset

@@ -0,0 +1,42 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f460ab3f7cb3e5342a0c4d4cd2acb8a5, type: 3}
+  m_Name: SkeletonAmbush
+  eventName: Skeleton Ambush
+  eventDescription: Ancient skeletal warriors rise from the ground to attack your party!
+  eventType: 0
+  rarity: 0
+  plainsChance: 0.3
+  forestChance: 0.8
+  mountainChance: 0.6
+  roadChance: 0.2
+  riverChance: 0.4
+  lakeChance: 0.3
+  oceanChance: 0.1
+  townChance: 0.05
+  villageChance: 0.15
+  bridgeChance: 0.4
+  tunnelChance: 0.7
+  ferryChance: 0.2
+  canOccurMultipleTimes: 1
+  cooldownDays: 0.5
+  minEnemies: 1
+  maxEnemies: 3
+  possibleEnemyTypes:
+  - Skeleton Warrior
+  - Skeleton
+  encounterDescriptions:
+  - Bones clatter as skeletal warriors emerge from the earth!
+  - Ancient skeletons wielding rusty weapons block your path!
+  - The ground splits open as undead skeletons rise to attack!
+  - Skeletal archers take aim from the shadows ahead!
+  difficulty: 0

+ 133 - 1
Assets/Scenes/MapScene2.unity

@@ -215,6 +215,7 @@ GameObject:
   - component: {fileID: 591284419}
   - component: {fileID: 591284418}
   - component: {fileID: 591284417}
+  - component: {fileID: 591284420}
   m_Layer: 0
   m_Name: TravelUI
   m_TagString: Untagged
@@ -271,6 +272,35 @@ Transform:
   m_Children: []
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &591284420
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 591284416}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: b5e7ade45cb1c7b40914eba0eb0213e2, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  combatEventPopup: {fileID: 0}
+  combatEventPopupUXML: {fileID: 1319078988}
+  combatPopupPrefab: {fileID: 0}
+  allowRunningAway: 1
+  runAwaySuccessChance: 0.75
+  runAwayHealthPenalty: 5
+  successfulRunAwayMessages:
+  - Your party successfully escapes from the enemies!
+  - Quick thinking allows your party to avoid the confrontation!
+  - Your party slips away unnoticed by the enemies.
+  failedRunAwayMessages:
+  - The enemies catch up to your party! You take {damage} damage while trying to
+    escape.
+  - Your escape attempt fails! The enemies pursue and wound your party for {damage}
+    damage.
+  - The enemies block your escape route! Your party suffers {damage} damage in the
+    failed attempt.
 --- !u!1 &1243674619
 GameObject:
   m_ObjectHideFlags: 0
@@ -443,6 +473,55 @@ MonoBehaviour:
   m_LightCookieSize: {x: 1, y: 1}
   m_LightCookieOffset: {x: 0, y: 0}
   m_SoftShadowQuality: 0
+--- !u!1 &1319078984
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 1319078986}
+  - component: {fileID: 1319078988}
+  m_Layer: 0
+  m_Name: CombatEventUI
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &1319078986
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1319078984}
+  serializedVersion: 2
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 12.970818, y: 433.2704, z: 802.6817}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_ConstrainProportionsScale: 0
+  m_Children: []
+  m_Father: {fileID: 0}
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1319078988
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1319078984}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: caf20a4e9c141924eabbd10f4e254d11, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  uiDocument: {fileID: 591284417}
+  popupTemplate: {fileID: 9197481963319205126, guid: 8f2fc644fa775e045b9398ea420ce032, type: 3}
+  popupStyleSheet: {fileID: 7433441132597879392, guid: ec08bffc7fd7d4f4caf1ea5e3fdf50d8, type: 3}
+  animationDuration: 0.3
+  backgroundBlurIntensity: 0.5
 --- !u!1 &1581552013
 GameObject:
   m_ObjectHideFlags: 0
@@ -453,6 +532,8 @@ GameObject:
   m_Component:
   - component: {fileID: 1581552015}
   - component: {fileID: 1581552014}
+  - component: {fileID: 1581552016}
+  - component: {fileID: 1581552017}
   m_Layer: 0
   m_Name: TravelSystemSetup
   m_TagString: Untagged
@@ -493,7 +574,7 @@ MonoBehaviour:
   expensivePathColor: {r: 1, g: 0, b: 0, a: 1}
   alternativePathColor: {r: 1, g: 0.92156863, b: 0.015686275, a: 1}
   pathLineWidth: 0.2
-  pathLineZOffset: -1
+  pathLineHeight: 1
   showDebugLogs: 0
   showMovementCosts: 0
   timeMultiplier: 1
@@ -517,6 +598,55 @@ Transform:
   m_Children: []
   m_Father: {fileID: 0}
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1581552016
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1581552013}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3cc71511fb02ec944af7a35ffd641f13, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  enableEvents: 1
+  baseEventChance: 0.15
+  tilesPerEventCheck: 3
+  availableEvents:
+  - {fileID: 11400000, guid: de1e17a43d8889f4581856faed745ea2, type: 2}
+  - {fileID: 11400000, guid: 644048a8c9939c2408e9c8df1d68a170, type: 2}
+  showDebugLogs: 1
+  forceNextEvent: 0
+--- !u!114 &1581552017
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 1581552013}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: b5e7ade45cb1c7b40914eba0eb0213e2, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  combatEventPopup: {fileID: 0}
+  combatEventPopupUXML: {fileID: 1319078988}
+  combatPopupPrefab: {fileID: 0}
+  allowRunningAway: 1
+  runAwaySuccessChance: 0.75
+  runAwayHealthPenalty: 5
+  successfulRunAwayMessages:
+  - Your party successfully escapes from the enemies!
+  - Quick thinking allows your party to avoid the confrontation!
+  - Your party slips away unnoticed by the enemies.
+  failedRunAwayMessages:
+  - The enemies catch up to your party! You take {damage} damage while trying to
+    escape.
+  - Your escape attempt fails! The enemies pursue and wound your party for {damage}
+    damage.
+  - The enemies block your escape route! Your party suffers {damage} damage in the
+    failed attempt.
 --- !u!1 &1953346056
 GameObject:
   m_ObjectHideFlags: 0
@@ -631,6 +761,7 @@ MonoBehaviour:
   zoomToFullMapKey: 102
   focusZoomLevel: 10
   centeringSpeed: 2
+  teamMarkerZoomSize: 100
 --- !u!114 &1953346061
 MonoBehaviour:
   m_ObjectHideFlags: 0
@@ -685,3 +816,4 @@ SceneRoots:
   - {fileID: 1243674621}
   - {fileID: 1581552015}
   - {fileID: 591284419}
+  - {fileID: 1319078986}

+ 191 - 0
Assets/Scripts/Characters/Enemies/EnemyCharacterData.cs

@@ -0,0 +1,191 @@
+using UnityEngine;
+
+[CreateAssetMenu(fileName = "New Enemy", menuName = "RPG/Characters/Enemy")]
+[System.Serializable]
+public class EnemyCharacterData : ScriptableObject
+{
+    [Header("Basic Info")]
+    public string enemyName = "New Enemy";
+    [TextArea(2, 4)]
+    public string description = "A fearsome enemy";
+    public Sprite enemySprite;
+
+    [Header("Core Stats")]
+    [Range(1, 100)]
+    public int maxHealth = 10;
+    [Range(1, 30)]
+    public int attack = 8;
+    [Range(1, 30)]
+    public int constitution = 5;
+    [Range(1, 30)]
+    public int dexterity = 3;
+    [Range(1, 30)]
+    public int wisdom = 2;
+
+    [Header("Combat Modifiers")]
+    [Range(-10, 10)]
+    public int initModifier = -2;
+    [Range(-10, 10)]
+    public int damageModifier = 0;
+    [Range(-10, 10)]
+    public int spellModifier = 0;
+    [Range(1, 50)]
+    public int movementSpeed = 10;
+    [Range(1, 30)]
+    public int armorClass = 6;
+
+    [Header("Weapon Configuration")]
+    public WeaponItem preferredWeapon; // Assign a WeaponItem asset
+
+    [Header("AI Behavior")]
+    [Range(0f, 1f)]
+    public float aggressiveness = 0.7f; // How likely to attack vs defend
+    [Range(1, 10)]
+    public int threatLevel = 1; // Used for encounter balancing
+
+    [Header("Rewards")]
+    [Range(0, 1000)]
+    public int goldReward = 10;
+    [Range(0, 500)]
+    public int experienceReward = 25;
+    public DropTable dropTable; // For item drops
+
+    [Header("Visual Settings")]
+    public Material enemyMaterial;
+    public GameObject enemyModel; // 3D model prefab
+    [Range(0.5f, 3f)]
+    public float modelScale = 1f;
+
+    [Header("Special Abilities")]
+    public bool canCastSpells = false;
+    public bool hasRangedAttack = false;
+    public bool canFly = false;
+    public bool regeneratesHealth = false;
+    [Range(0, 10)]
+    public int healthRegenPerTurn = 0;
+
+    /// <summary>
+    /// Creates a complete enemy character script class from this data
+    /// </summary>
+    public string GenerateCharacterScript()
+    {
+        string className = enemyName.Replace(" ", "") + "Character";
+        string weaponCreationCode = GenerateWeaponCreationCode();
+
+        return $@"using UnityEngine;
+
+/// <summary>
+/// Auto-generated enemy character: {enemyName}
+/// {description}
+/// Generated from EnemyCharacterData
+/// </summary>
+public class {className} : Character
+{{
+    [Header(""{enemyName} Configuration"")]
+    public WeaponItem preferredWeapon; // Assign weapon item asset in inspector
+    
+    protected override void InitializeStats()
+    {{
+        // Basic Stats
+        MaxHealth = {maxHealth};
+        CurrentHealth = MaxHealth;
+        Attack = {attack};
+        Constitution = {constitution};
+        Dexterity = {dexterity};
+        Wisdom = {wisdom};
+        
+        // Combat Modifiers  
+        InitModifier = {initModifier};
+        DamageModifier = {damageModifier};
+        SpellModifier = {spellModifier};
+        MovementSpeed = {movementSpeed};
+        ArmorClass = {armorClass};
+        
+        // Special Abilities
+        // TODO: Implement special abilities based on data
+        // Can Cast Spells: {canCastSpells.ToString().ToLower()}
+        // Has Ranged Attack: {hasRangedAttack.ToString().ToLower()}
+        // Can Fly: {canFly.ToString().ToLower()}
+        // Regenerates Health: {regeneratesHealth.ToString().ToLower()}
+        // Health Regen Per Turn: {healthRegenPerTurn}
+    }}
+    
+    public override Character Spawn(int count)
+    {{
+        name = ""{enemyName}"";
+        CharacterName = ""{enemyName}"";
+        if (count > 1)
+        {{
+            name += "" "" + count;
+            CharacterName += "" "" + count;
+        }}
+        
+        return this;
+    }}
+    
+    public override Weapon GetWeapon()
+    {{
+        // Return null to trigger direct weapon creation from WeaponItem
+        return CreateDirectWeapon();
+    }}
+    
+    protected override Weapon CreateDirectWeapon()
+    {{
+{weaponCreationCode}
+    }}
+    
+    /// <summary>
+    /// Gets the reward data for defeating this enemy
+    /// </summary>
+    public (int gold, int experience) GetRewards()
+    {{
+        return ({goldReward}, {experienceReward});
+    }}
+    
+    /// <summary>
+    /// Gets the threat level for encounter balancing
+    /// </summary>
+    public int GetThreatLevel()
+    {{
+        return {threatLevel};
+    }}
+}}";
+    }
+
+    private string GenerateWeaponCreationCode()
+    {
+        return $@"        // Create weapon from WeaponItem asset
+        if (preferredWeapon != null)
+        {{
+            spawnedWeapon = preferredWeapon.CreateWeaponInstance(this.transform);
+            if (spawnedWeapon != null)
+            {{
+                spawnedWeapon.SetWielder(this);
+                return spawnedWeapon;
+            }}
+        }}
+        
+        // Fallback: Create basic sword if no weapon item assigned
+        GameObject weaponObject = new GameObject(""Basic Weapon"");
+        weaponObject.transform.SetParent(this.transform, false);
+        spawnedWeapon = weaponObject.AddComponent<SimpleSword>();
+        spawnedWeapon.SetWielder(this);
+        return spawnedWeapon;";
+    }
+}
+
+[System.Serializable]
+public class DropTable
+{
+    [System.Serializable]
+    public class DropItem
+    {
+        public string itemName;
+        [Range(0f, 1f)]
+        public float dropChance;
+        [Range(1, 10)]
+        public int maxQuantity = 1;
+    }
+
+    public DropItem[] possibleDrops;
+}

+ 55 - 0
Assets/Scripts/Characters/Enemies/ForestTroll.asset

@@ -0,0 +1,55 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 9aa8bb6c0a7055640acdd5f516858f41, type: 3}
+  m_Name: ForestTroll
+  m_EditorClassIdentifier: 
+  enemyName: Forest Troll
+  description: A massive, moss-covered troll that haunts ancient forests. Its regenerative
+    abilities make it a formidable opponent in prolonged battles.
+  enemySprite: {fileID: 0}
+  maxHealth: 35
+  attack: 12
+  constitution: 15
+  dexterity: 2
+  wisdom: 4
+  initModifier: -3
+  damageModifier: 3
+  spellModifier: 0
+  movementSpeed: 8
+  armorClass: 4
+  preferredWeapon: {fileID: 11400000, guid: ca900eb0c0ebd1c4f93304e12b7b5c82, type: 2}
+  aggressiveness: 0.5
+  threatLevel: 5
+  goldReward: 45
+  experienceReward: 100
+  dropTable:
+    possibleDrops:
+    - itemName: Troll Hide
+      dropChance: 0.9
+      maxQuantity: 3
+    - itemName: Regeneration Moss
+      dropChance: 0.4
+      maxQuantity: 2
+    - itemName: Giant Club
+      dropChance: 0.6
+      maxQuantity: 1
+    - itemName: Forest Essence
+      dropChance: 0.2
+      maxQuantity: 1
+  enemyMaterial: {fileID: 0}
+  enemyModel: {fileID: 1880288660700002030, guid: 99900445755b7ea45b9e778888a1023c, type: 3}
+  modelScale: 2.5
+  canCastSpells: 0
+  hasRangedAttack: 0
+  canFly: 0
+  regeneratesHealth: 1
+  healthRegenPerTurn: 3

+ 52 - 0
Assets/Scripts/Characters/Enemies/GoblinScout.asset

@@ -0,0 +1,52 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 9aa8bb6c0a7055640acdd5f516858f41, type: 3}
+  m_Name: GoblinScout
+  m_EditorClassIdentifier: 
+  enemyName: Goblin Scout
+  description: A cunning and nimble goblin scout. Fast and aggressive, they prefer
+    hit-and-run tactics and often travel in small packs.
+  enemySprite: {fileID: 0}
+  maxHealth: 8
+  attack: 6
+  constitution: 4
+  dexterity: 7
+  wisdom: 3
+  initModifier: 2
+  damageModifier: 1
+  spellModifier: -2
+  movementSpeed: 15
+  armorClass: 8
+  preferredWeapon: {fileID: 11400000, guid: 957092d704b5dae449a68fd38b0bb9da, type: 2}
+  aggressiveness: 0.9
+  threatLevel: 1
+  goldReward: 8
+  experienceReward: 15
+  dropTable:
+    possibleDrops:
+    - itemName: Copper Coins
+      dropChance: 0.8
+      maxQuantity: 5
+    - itemName: Goblin Dagger
+      dropChance: 0.3
+      maxQuantity: 1
+    - itemName: Leather Scraps
+      dropChance: 0.5
+      maxQuantity: 2
+  enemyMaterial: {fileID: 0}
+  enemyModel: {fileID: 1880288660700002030, guid: 99900445755b7ea45b9e778888a1023c, type: 3}
+  modelScale: 0.8
+  canCastSpells: 0
+  hasRangedAttack: 0
+  canFly: 0
+  regeneratesHealth: 0
+  healthRegenPerTurn: 0

+ 52 - 0
Assets/Scripts/Characters/Enemies/SkeletonWarrior.asset

@@ -0,0 +1,52 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 9aa8bb6c0a7055640acdd5f516858f41, type: 3}
+  m_Name: SkeletonWarrior
+  m_EditorClassIdentifier: 
+  enemyName: Skeleton Warrior
+  description: A reanimated skeleton warrior, wielding ancient weapons with deadly
+    precision. Common in dark forests and abandoned ruins.
+  enemySprite: {fileID: 0}
+  maxHealth: 10
+  attack: 8
+  constitution: 5
+  dexterity: 3
+  wisdom: 2
+  initModifier: -2
+  damageModifier: 0
+  spellModifier: 0
+  movementSpeed: 10
+  armorClass: 6
+  preferredWeapon: {fileID: 11400000, guid: 25e42433d13b95f43b3cbb7849987b5c, type: 2}
+  aggressiveness: 0.7
+  threatLevel: 2
+  goldReward: 15
+  experienceReward: 25
+  dropTable:
+    possibleDrops:
+    - itemName: Bone
+      dropChance: 0.6
+      maxQuantity: 2
+    - itemName: Rusty Sword
+      dropChance: 0.2
+      maxQuantity: 1
+    - itemName: Tattered Cloth
+      dropChance: 0.4
+      maxQuantity: 1
+  enemyMaterial: {fileID: 0}
+  enemyModel: {fileID: 1880288660700002030, guid: 99900445755b7ea45b9e778888a1023c, type: 3}
+  modelScale: 1
+  canCastSpells: 0
+  hasRangedAttack: 1
+  canFly: 0
+  regeneratesHealth: 0
+  healthRegenPerTurn: 0

+ 113 - 0
Assets/Scripts/Editor/CombatEventFixer.cs

@@ -0,0 +1,113 @@
+using UnityEngine;
+using UnityEditor;
+
+/// <summary>
+/// Utility to fix combat events that are still using old string-based enemy types
+/// </summary>
+public class CombatEventFixer : EditorWindow
+{
+    [MenuItem("RPG/Utilities/Fix Combat Events")]
+    public static void ShowWindow()
+    {
+        GetWindow<CombatEventFixer>("Combat Event Fixer");
+    }
+
+    void OnGUI()
+    {
+        GUILayout.Label("Combat Event Asset Fixer", EditorStyles.boldLabel);
+        EditorGUILayout.Space();
+
+        EditorGUILayout.HelpBox(
+            "This tool fixes combat events and forces Unity to refresh the inspector to show EnemyCharacterData asset references.",
+            MessageType.Info);
+
+        EditorGUILayout.Space();
+
+        if (GUILayout.Button("Find and Fix All Combat Events", GUILayout.Height(30)))
+        {
+            FixAllCombatEvents();
+        }
+
+        EditorGUILayout.Space();
+
+        if (GUILayout.Button("Force Reimport TravelEventTypes.cs"))
+        {
+            ForceReimportTravelEventTypes();
+        }
+
+        if (GUILayout.Button("Refresh Asset Database"))
+        {
+            AssetDatabase.Refresh();
+            Debug.Log("✅ Asset database refreshed");
+        }
+    }
+
+    private void FixAllCombatEvents()
+    {
+        // Find all CombatTravelEvent assets
+        string[] guids = AssetDatabase.FindAssets("t:CombatTravelEvent");
+        int fixedCount = 0;
+
+        foreach (string guid in guids)
+        {
+            string path = AssetDatabase.GUIDToAssetPath(guid);
+            CombatTravelEvent combatEvent = AssetDatabase.LoadAssetAtPath<CombatTravelEvent>(path);
+
+            if (combatEvent != null)
+            {
+                // Mark as dirty to force Unity to update the inspector
+                EditorUtility.SetDirty(combatEvent);
+                fixedCount++;
+                Debug.Log($"🔧 Fixed combat event: {combatEvent.name}");
+            }
+        }
+
+        if (fixedCount > 0)
+        {
+            AssetDatabase.SaveAssets();
+            AssetDatabase.Refresh();
+            Debug.Log($"✅ Fixed {fixedCount} combat event(s). Please check the Inspector.");
+        }
+        else
+        {
+            Debug.Log("ℹ️ No combat events found to fix. Try creating a new one.");
+        }
+    }
+
+    private void ForceReimportTravelEventTypes()
+    {
+        string[] paths = {
+            "Assets/Scripts/Events/TravelEventTypes.cs",
+            "Assets/Scripts/Events/TravelEvent.cs"
+        };
+
+        foreach (string path in paths)
+        {
+            if (System.IO.File.Exists(path))
+            {
+                AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
+                Debug.Log($"🔄 Reimported: {path}");
+            }
+        }
+
+        AssetDatabase.Refresh();
+        Debug.Log("✅ Force reimport complete");
+    }
+
+    [MenuItem("Assets/RPG/Fix Combat Event Inspector", true)]
+    public static bool ValidateFixCombatEvent()
+    {
+        return Selection.activeObject is CombatTravelEvent;
+    }
+
+    [MenuItem("Assets/RPG/Fix Combat Event Inspector")]
+    public static void FixSelectedCombatEvent()
+    {
+        if (Selection.activeObject is CombatTravelEvent combatEvent)
+        {
+            EditorUtility.SetDirty(combatEvent);
+            AssetDatabase.SaveAssets();
+            Debug.Log($"🔧 Fixed inspector for: {combatEvent.name}");
+        }
+    }
+}

+ 260 - 0
Assets/Scripts/Editor/EnemyCharacterCreator.cs

@@ -0,0 +1,260 @@
+using UnityEngine;
+using UnityEditor;
+using System.IO;
+
+/// <summary>
+/// Editor utility for creating enemy characters from EnemyCharacterData
+/// Adds menu items under "RPG/Characters" for enemy creation workflow
+/// </summary>
+public class EnemyCharacterCreator : EditorWindow
+{
+    private EnemyCharacterData selectedEnemyData;
+    private string outputPath = "Assets/Scripts/Characters/Enemies/Generated/";
+    private Vector2 scrollPosition;
+
+    [MenuItem("RPG/Characters/Enemy Creator Window")]
+    public static void ShowWindow()
+    {
+        GetWindow<EnemyCharacterCreator>("Enemy Character Creator");
+    }
+
+    [MenuItem("Assets/RPG/Generate Enemy Character Script", true)]
+    public static bool ValidateGenerateEnemyScript()
+    {
+        return Selection.activeObject is EnemyCharacterData;
+    }
+
+    [MenuItem("Assets/RPG/Generate Enemy Character Script")]
+    public static void GenerateEnemyScriptFromSelected()
+    {
+        if (Selection.activeObject is EnemyCharacterData enemyData)
+        {
+            GenerateEnemyCharacterScript(enemyData);
+        }
+    }
+
+    void OnGUI()
+    {
+        GUILayout.Label("Enemy Character Creator", EditorStyles.boldLabel);
+        EditorGUILayout.Space();
+
+        // Enemy data selection
+        EditorGUILayout.LabelField("Select Enemy Data:", EditorStyles.boldLabel);
+        selectedEnemyData = (EnemyCharacterData)EditorGUILayout.ObjectField(
+            "Enemy Data", selectedEnemyData, typeof(EnemyCharacterData), false);
+
+        EditorGUILayout.Space();
+
+        // Output path
+        EditorGUILayout.LabelField("Output Settings:", EditorStyles.boldLabel);
+        outputPath = EditorGUILayout.TextField("Output Path:", outputPath);
+
+        if (GUILayout.Button("Browse Output Folder"))
+        {
+            string selectedPath = EditorUtility.OpenFolderPanel("Select Output Folder", Application.dataPath, "");
+            if (!string.IsNullOrEmpty(selectedPath))
+            {
+                outputPath = "Assets" + selectedPath.Substring(Application.dataPath.Length) + "/";
+            }
+        }
+
+        EditorGUILayout.Space();
+
+        // Preview
+        if (selectedEnemyData != null)
+        {
+            EditorGUILayout.LabelField("Preview:", EditorStyles.boldLabel);
+
+            using (var scrollScope = new EditorGUILayout.ScrollViewScope(scrollPosition, GUILayout.Height(200)))
+            {
+                scrollPosition = scrollScope.scrollPosition;
+
+                EditorGUILayout.LabelField("Generated Class Name:",
+                    selectedEnemyData.enemyName.Replace(" ", "") + "Character");
+                EditorGUILayout.LabelField("Health:", selectedEnemyData.maxHealth.ToString());
+                EditorGUILayout.LabelField("Attack:", selectedEnemyData.attack.ToString());
+                EditorGUILayout.LabelField("Armor Class:", selectedEnemyData.armorClass.ToString());
+                EditorGUILayout.LabelField("Weapon Type:", selectedEnemyData.preferredWeapon.weaponType.ToString());
+                EditorGUILayout.LabelField("Threat Level:", selectedEnemyData.threatLevel.ToString());
+
+                EditorGUILayout.Space();
+                EditorGUILayout.LabelField("Special Abilities:");
+                if (selectedEnemyData.canCastSpells) EditorGUILayout.LabelField("• Can Cast Spells");
+                if (selectedEnemyData.hasRangedAttack) EditorGUILayout.LabelField("• Has Ranged Attack");
+                if (selectedEnemyData.canFly) EditorGUILayout.LabelField("• Can Fly");
+                if (selectedEnemyData.regeneratesHealth) EditorGUILayout.LabelField($"• Regenerates {selectedEnemyData.healthRegenPerTurn} HP per turn");
+            }
+
+            EditorGUILayout.Space();
+
+            // Generate button
+            GUI.enabled = selectedEnemyData != null;
+            if (GUILayout.Button("Generate Enemy Character Script", GUILayout.Height(30)))
+            {
+                GenerateEnemyCharacterScript(selectedEnemyData);
+            }
+            GUI.enabled = true;
+        }
+        else
+        {
+            EditorGUILayout.HelpBox("Select an EnemyCharacterData asset to generate a character script.", MessageType.Info);
+        }
+
+        EditorGUILayout.Space();
+
+        // Quick actions
+        EditorGUILayout.LabelField("Quick Actions:", EditorStyles.boldLabel);
+
+        if (GUILayout.Button("Create New Enemy Data Asset"))
+        {
+            CreateNewEnemyData();
+        }
+
+        if (GUILayout.Button("Open Generated Scripts Folder"))
+        {
+            EditorUtility.RevealInFinder(Path.Combine(Application.dataPath, "Scripts/Characters/Enemies/Generated"));
+        }
+    }
+
+    public static void GenerateEnemyCharacterScript(EnemyCharacterData enemyData)
+    {
+        if (enemyData == null)
+        {
+            Debug.LogError("Enemy data is null!");
+            return;
+        }
+
+        // Ensure output directory exists
+        string fullOutputPath = Path.Combine(Application.dataPath, "Scripts/Characters/Enemies/Generated");
+        if (!Directory.Exists(fullOutputPath))
+        {
+            Directory.CreateDirectory(fullOutputPath);
+        }
+
+        // Generate script content
+        string scriptContent = enemyData.GenerateCharacterScript();
+        string className = enemyData.enemyName.Replace(" ", "") + "Character";
+        string fileName = className + ".cs";
+        string fullPath = Path.Combine(fullOutputPath, fileName);
+
+        // Write the file
+        try
+        {
+            File.WriteAllText(fullPath, scriptContent);
+
+            // Refresh asset database to show the new file
+            AssetDatabase.Refresh();
+
+            Debug.Log($"✅ Generated enemy character script: {fileName}");
+            Debug.Log($"📁 Location: {fullPath}");
+
+            // Select the generated file in the project window
+            string assetPath = "Assets/Scripts/Characters/Enemies/Generated/" + fileName;
+            Object asset = AssetDatabase.LoadAssetAtPath<Object>(assetPath);
+            if (asset != null)
+            {
+                Selection.activeObject = asset;
+                EditorGUIUtility.PingObject(asset);
+            }
+
+            EditorUtility.DisplayDialog("Success",
+                $"Generated enemy character script: {className}\n\nThe script has been created at:\n{assetPath}",
+                "OK");
+        }
+        catch (System.Exception e)
+        {
+            Debug.LogError($"Failed to generate enemy character script: {e.Message}");
+            EditorUtility.DisplayDialog("Error",
+                $"Failed to generate enemy character script:\n{e.Message}",
+                "OK");
+        }
+    }
+
+    private void CreateNewEnemyData()
+    {
+        string path = EditorUtility.SaveFilePanelInProject(
+            "Create New Enemy Data",
+            "NewEnemy",
+            "asset",
+            "Choose where to save the new enemy data asset");
+
+        if (!string.IsNullOrEmpty(path))
+        {
+            EnemyCharacterData newEnemy = CreateInstance<EnemyCharacterData>();
+            AssetDatabase.CreateAsset(newEnemy, path);
+            AssetDatabase.SaveAssets();
+            AssetDatabase.Refresh();
+
+            Selection.activeObject = newEnemy;
+            selectedEnemyData = newEnemy;
+
+            Debug.Log($"✅ Created new enemy data asset: {path}");
+        }
+    }
+}
+
+/// <summary>
+/// Additional menu items for RPG character creation
+/// </summary>
+public class RPGCharacterMenuItems
+{
+    [MenuItem("RPG/Characters/Create Enemy Data Asset")]
+    public static void CreateEnemyDataAsset()
+    {
+        string path = EditorUtility.SaveFilePanelInProject(
+            "Create Enemy Data Asset",
+            "NewEnemy",
+            "asset",
+            "Choose location for the enemy data asset",
+            "Assets/Scripts/Characters/Enemies");
+
+        if (!string.IsNullOrEmpty(path))
+        {
+            EnemyCharacterData enemyData = ScriptableObject.CreateInstance<EnemyCharacterData>();
+            AssetDatabase.CreateAsset(enemyData, path);
+            AssetDatabase.SaveAssets();
+            AssetDatabase.Refresh();
+
+            Selection.activeObject = enemyData;
+            EditorGUIUtility.PingObject(enemyData);
+
+            Debug.Log($"✅ Created enemy data asset: {path}");
+        }
+    }
+
+    [MenuItem("RPG/Characters/Batch Generate All Enemy Scripts")]
+    public static void BatchGenerateEnemyScripts()
+    {
+        string[] guids = AssetDatabase.FindAssets("t:EnemyCharacterData");
+        int count = 0;
+
+        foreach (string guid in guids)
+        {
+            string path = AssetDatabase.GUIDToAssetPath(guid);
+            EnemyCharacterData enemyData = AssetDatabase.LoadAssetAtPath<EnemyCharacterData>(path);
+
+            if (enemyData != null)
+            {
+                EnemyCharacterCreator.GenerateEnemyCharacterScript(enemyData);
+                count++;
+            }
+        }
+
+        EditorUtility.DisplayDialog("Batch Generation Complete",
+            $"Generated {count} enemy character scripts.", "OK");
+    }
+
+    [MenuItem("RPG/Characters/Open Enemy Scripts Folder")]
+    public static void OpenEnemyScriptsFolder()
+    {
+        string folderPath = Path.Combine(Application.dataPath, "Scripts/Characters/Enemies");
+        if (Directory.Exists(folderPath))
+        {
+            EditorUtility.RevealInFinder(folderPath);
+        }
+        else
+        {
+            Debug.LogWarning("Enemy scripts folder does not exist: " + folderPath);
+        }
+    }
+}

+ 209 - 0
Assets/Scripts/Editor/EnemyWeaponMigrationTool.cs

@@ -0,0 +1,209 @@
+using UnityEngine;
+using UnityEditor;
+using System.IO;
+
+/// <summary>
+/// Editor utility to help migrate EnemyCharacterData assets to use WeaponItem references
+/// instead of WeaponType enums
+/// </summary>
+public class EnemyWeaponMigrationTool : EditorWindow
+{
+    private bool showInstructions = true;
+    private Vector2 scrollPosition;
+
+    [MenuItem("RPG Tools/Enemy Weapon Migration Tool")]
+    static void Init()
+    {
+        EnemyWeaponMigrationTool window = (EnemyWeaponMigrationTool)EditorWindow.GetWindow(typeof(EnemyWeaponMigrationTool));
+        window.titleContent = new GUIContent("Enemy Weapon Migration");
+        window.Show();
+    }
+
+    void OnGUI()
+    {
+        GUILayout.Label("Enemy Weapon Migration Tool", EditorStyles.boldLabel);
+        GUILayout.Space(10);
+
+        showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions");
+        if (showInstructions)
+        {
+            EditorGUILayout.HelpBox(
+                "This tool helps migrate existing EnemyCharacterData assets to use WeaponItem references instead of WeaponType enums.\n\n" +
+                "BEFORE MIGRATION:\n" +
+                "1. Create WeaponItem assets for your desired weapons\n" +
+                "2. Configure weapon stats, prefabs, and class names\n" +
+                "3. Save the WeaponItem assets in your project\n\n" +
+                "MIGRATION PROCESS:\n" +
+                "1. Click 'Find Enemy Assets' to scan for EnemyCharacterData assets\n" +
+                "2. Review the list of enemies found\n" +
+                "3. For each enemy, drag the appropriate WeaponItem into the field\n" +
+                "4. Click 'Apply Changes' to update the assets\n\n" +
+                "NOTE: This migration is manual to ensure you assign the correct weapons.",
+                MessageType.Info);
+        }
+
+        GUILayout.Space(10);
+
+        if (GUILayout.Button("Create Sample WeaponItem Assets"))
+        {
+            CreateSampleWeaponItems();
+        }
+
+        GUILayout.Space(10);
+
+        if (GUILayout.Button("Find EnemyCharacterData Assets"))
+        {
+            FindEnemyAssets();
+        }
+
+        GUILayout.Space(10);
+
+        // Display found assets
+        if (enemyAssets != null && enemyAssets.Length > 0)
+        {
+            GUILayout.Label($"Found {enemyAssets.Length} Enemy Assets:", EditorStyles.boldLabel);
+
+            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
+
+            for (int i = 0; i < enemyAssets.Length; i++)
+            {
+                var enemy = enemyAssets[i];
+                if (enemy != null)
+                {
+                    EditorGUILayout.BeginHorizontal("box");
+
+                    EditorGUILayout.LabelField(enemy.enemyName, GUILayout.Width(120));
+                    EditorGUILayout.LabelField($"Health: {enemy.maxHealth}", GUILayout.Width(80));
+
+                    // Show current weapon assignment
+                    enemy.preferredWeapon = (WeaponItem)EditorGUILayout.ObjectField(
+                        "Weapon:",
+                        enemy.preferredWeapon,
+                        typeof(WeaponItem),
+                        false,
+                        GUILayout.Width(200));
+
+                    if (GUILayout.Button("Select Asset", GUILayout.Width(100)))
+                    {
+                        Selection.activeObject = enemy;
+                        EditorGUIUtility.PingObject(enemy);
+                    }
+
+                    EditorGUILayout.EndHorizontal();
+                }
+            }
+
+            EditorGUILayout.EndScrollView();
+
+            GUILayout.Space(10);
+
+            if (GUILayout.Button("Save All Changes"))
+            {
+                SaveAllChanges();
+            }
+        }
+    }
+
+    private EnemyCharacterData[] enemyAssets;
+
+    void FindEnemyAssets()
+    {
+        string[] guids = AssetDatabase.FindAssets("t:EnemyCharacterData");
+        enemyAssets = new EnemyCharacterData[guids.Length];
+
+        for (int i = 0; i < guids.Length; i++)
+        {
+            string path = AssetDatabase.GUIDToAssetPath(guids[i]);
+            enemyAssets[i] = AssetDatabase.LoadAssetAtPath<EnemyCharacterData>(path);
+        }
+
+        Debug.Log($"Found {enemyAssets.Length} EnemyCharacterData assets");
+    }
+
+    void CreateSampleWeaponItems()
+    {
+        // Create a folder for sample weapons if it doesn't exist
+        string folderPath = "Assets/Resources/SampleWeapons";
+        if (!AssetDatabase.IsValidFolder(folderPath))
+        {
+            AssetDatabase.CreateFolder("Assets/Resources", "SampleWeapons");
+        }
+
+        // Create sample sword
+        var sword = ScriptableObject.CreateInstance<WeaponItem>();
+        sword.itemName = "Enemy Sword";
+        sword.description = "A basic sword for enemy characters";
+        sword.minDamage = 2;
+        sword.maxDamage = 6;
+        sword.range = 2;
+        sword.weaponModifier = 0;
+        sword.attackSpeed = 1.0f;
+        sword.weaponType = WeaponType.Sword;
+        sword.weaponClassName = "SimpleSword";
+        sword.goldCost = 10;
+
+        AssetDatabase.CreateAsset(sword, $"{folderPath}/EnemySword.asset");
+
+        // Create sample bow
+        var bow = ScriptableObject.CreateInstance<WeaponItem>();
+        bow.itemName = "Enemy Bow";
+        bow.description = "A basic bow for enemy archers";
+        bow.minDamage = 1;
+        bow.maxDamage = 6;
+        bow.range = 100;
+        bow.weaponModifier = 0;
+        bow.attackSpeed = 2.0f;
+        bow.weaponType = WeaponType.Bow;
+        bow.weaponClassName = "SimpleBow";
+        bow.goldCost = 15;
+
+        AssetDatabase.CreateAsset(bow, $"{folderPath}/EnemyBow.asset");
+
+        // Create sample dagger
+        var dagger = ScriptableObject.CreateInstance<WeaponItem>();
+        dagger.itemName = "Enemy Dagger";
+        dagger.description = "A fast dagger for quick enemies";
+        dagger.minDamage = 1;
+        dagger.maxDamage = 4;
+        dagger.range = 1;
+        dagger.weaponModifier = 1;
+        dagger.attackSpeed = 0.8f;
+        dagger.weaponType = WeaponType.Dagger;
+        dagger.weaponClassName = "SimpleSword"; // Using sword class as base
+        dagger.goldCost = 8;
+
+        AssetDatabase.CreateAsset(dagger, $"{folderPath}/EnemyDagger.asset");
+
+        AssetDatabase.SaveAssets();
+        AssetDatabase.Refresh();
+
+        Debug.Log("Created sample WeaponItem assets in " + folderPath);
+        EditorUtility.DisplayDialog("Sample Weapons Created",
+            $"Created sample weapon assets:\n• Enemy Sword\n• Enemy Bow\n• Enemy Dagger\n\nLocation: {folderPath}",
+            "OK");
+    }
+
+    void SaveAllChanges()
+    {
+        if (enemyAssets == null) return;
+
+        int updatedCount = 0;
+
+        foreach (var enemy in enemyAssets)
+        {
+            if (enemy != null)
+            {
+                EditorUtility.SetDirty(enemy);
+                updatedCount++;
+            }
+        }
+
+        AssetDatabase.SaveAssets();
+        AssetDatabase.Refresh();
+
+        Debug.Log($"Updated {updatedCount} enemy assets");
+        EditorUtility.DisplayDialog("Migration Complete",
+            $"Successfully updated {updatedCount} enemy assets.\n\nAll changes have been saved.",
+            "OK");
+    }
+}

+ 330 - 0
Assets/Scripts/Events/CombatEventIntegration.cs

@@ -0,0 +1,330 @@
+using UnityEngine;
+
+/// <summary>
+/// Integration manager that connects TravelEventSystem with CombatEventPopup
+/// Handles the choice between battle and escape when combat events occur
+/// </summary>
+public class CombatEventIntegration : MonoBehaviour
+{
+    [Header("Combat Popup Integration")]
+    [Tooltip("Use either the original CombatEventPopup or the new CombatEventPopupUXML")]
+    public CombatEventPopup combatEventPopup; // Original popup (legacy)
+    public CombatEventPopupUXML combatEventPopupUXML; // New UXML-based popup
+    public GameObject combatPopupPrefab; // Optional: if popup component not already in scene
+
+    // Component references
+    private TravelEventSystem travelEventSystem;
+    private TravelEventUI eventUI;
+    private TeamTravelSystem teamTravelSystem;
+
+    // Current combat state
+    private bool isHandlingCombat = false;
+    private CombatTravelEvent currentCombatEvent; // Store reference to the current combat event
+
+    void Start()
+    {
+        Debug.Log("🔧 Combat Event Integration starting...");
+
+        // Find required components - try same GameObject first, then search scene
+        travelEventSystem = GetComponent<TravelEventSystem>();
+        if (travelEventSystem == null)
+            travelEventSystem = FindFirstObjectByType<TravelEventSystem>();
+
+        eventUI = FindFirstObjectByType<TravelEventUI>();
+        teamTravelSystem = FindFirstObjectByType<TeamTravelSystem>();
+
+        if (travelEventSystem == null)
+        {
+            Debug.LogError("❌ Combat Event Integration requires TravelEventSystem in the scene!");
+            Debug.LogError("   Please ensure you have a GameObject with TravelEventSystem component.");
+            enabled = false;
+            return;
+        }
+        else if (GetComponent<TravelEventSystem>() == null)
+        {
+            Debug.LogWarning("⚠️ CombatEventIntegration is not on the same GameObject as TravelEventSystem.");
+            Debug.LogWarning("   Consider moving it to the TravelEventSystem GameObject for better organization.");
+        }
+
+        // Try to find existing popup components first
+        if (combatEventPopup == null)
+            combatEventPopup = FindFirstObjectByType<CombatEventPopup>();
+
+        if (combatEventPopupUXML == null)
+            combatEventPopupUXML = FindFirstObjectByType<CombatEventPopupUXML>();
+
+        // If no popup component found and we have a prefab, instantiate it
+        if (combatEventPopup == null && combatEventPopupUXML == null && combatPopupPrefab != null)
+        {
+            Debug.Log("📦 Instantiating combat popup from prefab...");
+            GameObject popupInstance = Instantiate(combatPopupPrefab);
+            combatEventPopup = popupInstance.GetComponent<CombatEventPopup>();
+            combatEventPopupUXML = popupInstance.GetComponent<CombatEventPopupUXML>();
+
+            if (combatEventPopup == null && combatEventPopupUXML == null)
+            {
+                Debug.LogError("❌ Combat popup prefab does not contain CombatEventPopup or CombatEventPopupUXML component!");
+                enabled = false;
+                return;
+            }
+        }
+
+        if (combatEventPopup == null && combatEventPopupUXML == null)
+        {
+            Debug.LogError("❌ Combat Event Integration requires a CombatEventPopup or CombatEventPopupUXML component!");
+            Debug.LogError("   Either add one of these components to a GameObject in the scene,");
+            Debug.LogError("   or assign a prefab with one of these components to combatPopupPrefab field.");
+            enabled = false;
+            return;
+        }
+
+        // Setup combat popup callbacks
+        if (combatEventPopup != null)
+            combatEventPopup.OnCombatDecision += HandleCombatDecision;
+
+        if (combatEventPopupUXML != null)
+            combatEventPopupUXML.OnCombatDecision += HandleCombatDecision;
+
+        Debug.Log("✅ Combat Event Integration initialized successfully");
+    }
+
+    void OnDestroy()
+    {
+        if (combatEventPopup != null)
+            combatEventPopup.OnCombatDecision -= HandleCombatDecision;
+
+        if (combatEventPopupUXML != null)
+            combatEventPopupUXML.OnCombatDecision -= HandleCombatDecision;
+    }
+
+    /// <summary>
+    /// Call this method when a combat event occurs to show the popup
+    /// This should be called from TravelEventTypes.cs in the ExecuteEvent method
+    /// </summary>
+    public void ShowCombatChoicePopup(BattleEventData battleData, TravelEventContext context, string eventDescription, CombatTravelEvent combatEvent = null)
+    {
+        if (isHandlingCombat || battleData == null)
+            return;
+
+        Debug.Log($"🎭 Showing combat choice popup: {eventDescription}");
+
+        isHandlingCombat = true;
+        currentCombatEvent = combatEvent; // Store reference to the original combat event
+
+        // Store battle data for later use
+        currentBattleData = battleData;
+        currentContext = context;
+
+        // Show combat popup - try UXML version first, then fallback to original
+        if (combatEventPopupUXML != null)
+        {
+            Debug.Log("Using UXML-based combat popup");
+            combatEventPopupUXML.OnCombatDecision = HandleCombatDecision;
+            combatEventPopupUXML.ShowCombatEncounter(battleData, context, eventDescription);
+        }
+        else if (combatEventPopup != null)
+        {
+            Debug.Log("Using original combat popup");
+            combatEventPopup.OnCombatDecision = HandleCombatDecision;
+            combatEventPopup.ShowCombatEncounter(battleData, context, eventDescription);
+        }
+        else
+        {
+            Debug.LogError("No combat popup component assigned! Please assign either CombatEventPopup or CombatEventPopupUXML.");
+            isHandlingCombat = false;
+        }
+    }
+
+    // Store current battle data
+    private BattleEventData currentBattleData;
+    private TravelEventContext currentContext;
+
+    /// <summary>
+    /// Handle the player's combat decision from the popup
+    /// </summary>
+    private void HandleCombatDecision(bool chooseToAttack)
+    {
+        if (!isHandlingCombat || currentBattleData == null)
+            return;
+
+        isHandlingCombat = false;
+
+        if (chooseToAttack)
+        {
+            HandleAttackChoice();
+        }
+        else
+        {
+            HandleRunAwayChoice();
+        }
+
+        // Clear stored data
+        currentBattleData = null;
+        currentContext = null;
+    }
+
+    /// <summary>
+    /// Handle when player chooses to attack
+    /// </summary>
+    private void HandleAttackChoice()
+    {
+        Debug.Log("⚔️ Player chose to fight! Setting up battle...");
+
+        // Create and return the battle result that will start the battle
+        var battleResult = EventResult.SimpleBattle(
+            $"Your party prepares for battle against {currentBattleData.enemyCount} {currentBattleData.enemyType}!",
+            currentBattleData.enemyCount,
+            currentBattleData.enemyType
+        );
+
+        // Copy over the enemy character data
+        battleResult.battleData.enemyCharacterData = currentBattleData.enemyCharacterData;
+
+        // Apply the battle result through the travel event system
+        ApplyBattleResult(battleResult);
+    }
+
+    /// <summary>
+    /// Handle when player chooses to run away
+    /// </summary>
+    private void HandleRunAwayChoice()
+    {
+        Debug.Log("🏃 Player chose to run away!");
+
+        EventResult escapeResult = null;
+
+        // Use the combat event's escape handling if available
+        if (currentCombatEvent != null)
+        {
+            Debug.Log($"🎯 Using escape configuration from {currentCombatEvent.eventName}");
+            escapeResult = currentCombatEvent.HandleEscapeAttempt(currentContext);
+        }
+        else
+        {
+            Debug.LogWarning("⚠️ No combat event reference - using hardcoded fallback escape handling");
+
+            // Hardcoded fallback values when no combat event is available
+            const float fallbackSuccessChance = 0.75f;
+            bool escapeSuccessful = Random.value <= fallbackSuccessChance;
+
+            if (escapeSuccessful)
+            {
+                escapeResult = CreateFallbackSuccessfulEscape();
+            }
+            else
+            {
+                escapeResult = CreateFallbackFailedEscape();
+            }
+        }
+
+        // Apply the escape result
+        if (escapeResult != null)
+        {
+            ApplyBattleResult(escapeResult);
+        }
+        else
+        {
+            Debug.LogWarning("⚠️ Escape not allowed by combat event - forcing battle");
+            HandleAttackChoice();
+        }
+    }
+
+    /// <summary>
+    /// Create fallback successful escape result when no combat event is available
+    /// </summary>
+    private EventResult CreateFallbackSuccessfulEscape()
+    {
+        string message = "Your party successfully escapes from the enemies!";
+        Debug.Log($"✅ Fallback escape successful: {message}");
+
+        return new EventResult(message)
+        {
+            shouldStopTravel = false,
+            startBattle = false,
+            eventOccurred = true,
+            healthChange = 0
+        };
+    }
+
+    /// <summary>
+    /// Create fallback failed escape result when no combat event is available
+    /// </summary>
+    private EventResult CreateFallbackFailedEscape()
+    {
+        const int fallbackHealthPenalty = 5; // Hardcoded fallback value
+        string message = $"The enemies catch up to your party! You take {fallbackHealthPenalty} damage while trying to escape.";
+
+        Debug.Log($"❌ Fallback escape failed: {message}");
+
+        return new EventResult(message)
+        {
+            shouldStopTravel = true,
+            startBattle = false,
+            eventOccurred = true,
+            healthChange = -fallbackHealthPenalty
+        };
+    }    /// <summary>
+         /// Apply battle result through the travel event system
+         /// </summary>
+    private void ApplyBattleResult(EventResult result)
+    {
+        // Apply resource changes
+        if (result.healthChange != 0)
+        {
+            Debug.Log($"❤️ Health changed by {result.healthChange}");
+            // TODO: Actually apply health changes to party
+        }
+
+        if (result.goldChange != 0)
+        {
+            Debug.Log($"💰 Gold changed by {result.goldChange}");
+            // TODO: Actually apply gold changes to party
+        }
+
+        // Handle travel stopping
+        if (result.shouldStopTravel && teamTravelSystem != null)
+        {
+            teamTravelSystem.CancelJourney();
+            Debug.Log("🛑 Travel stopped due to event");
+        }
+
+        // Handle battle start
+        if (result.startBattle)
+        {
+            Debug.Log($"⚔️ Starting battle: {result.battleData.enemyCount} {result.battleData.enemyType}(s)");
+
+            // TODO: Integrate with your battle system
+            // This is where you would transition to the battle scene
+            // or set up the battle data for your existing battle system
+
+            if (result.battleData.enemyCharacterData != null)
+            {
+                Debug.Log($"🎯 Using enemy data: {result.battleData.enemyCharacterData.enemyName}");
+                Debug.Log($"📊 Enemy stats: HP={result.battleData.enemyCharacterData.maxHealth}, " +
+                         $"AC={result.battleData.enemyCharacterData.armorClass}, " +
+                         $"Threat={result.battleData.enemyCharacterData.threatLevel}");
+            }
+        }
+    }
+
+    /// <summary>
+    /// Check if the system is currently handling a combat choice
+    /// </summary>
+    public bool IsHandlingCombat => isHandlingCombat;
+
+    /// <summary>
+    /// Cancel current combat handling (for cleanup)
+    /// </summary>
+    public void CancelCombatHandling()
+    {
+        if (isHandlingCombat)
+        {
+            isHandlingCombat = false;
+            currentBattleData = null;
+            currentContext = null;
+
+            if (combatEventPopup != null)
+                combatEventPopup.ForceClose();
+        }
+    }
+}

+ 296 - 0
Assets/Scripts/Events/EnhancedTravelEventSystem.cs

@@ -0,0 +1,296 @@
+using UnityEngine;
+using System.Collections;
+
+/// <summary>
+/// Enhanced Travel Event System that provides player choice for combat encounters
+/// Integrates CombatEventPopup for better user experience
+/// </summary>
+public class EnhancedTravelEventSystem : MonoBehaviour
+{
+    [Header("Enhanced Event System")]
+    public CombatEventPopup combatEventPopup;
+    public bool allowRunningAway = true;
+    [Range(0f, 1f)]
+    public float runAwaySuccessChance = 0.75f;
+    public int runAwayHealthPenalty = 5;
+
+    [Header("Run Away Messages")]
+    [TextArea(2, 4)]
+    public string[] successfulRunAwayMessages = {
+        "Your party successfully escapes from the enemies!",
+        "Quick thinking allows your party to avoid the confrontation!",
+        "Your party slips away unnoticed by the enemies."
+    };
+
+    [TextArea(2, 4)]
+    public string[] failedRunAwayMessages = {
+        "The enemies catch up to your party! You take {damage} damage while trying to escape.",
+        "Your escape attempt fails! The enemies pursue and wound your party for {damage} damage.",
+        "The enemies block your escape route! Your party suffers {damage} damage in the failed attempt."
+    };
+
+    // Component references
+    private TravelEventSystem originalEventSystem;
+    private TravelEventUI eventUI;
+
+    // Current combat state
+    private BattleEventData pendingBattleData;
+    private TravelEventContext pendingContext;
+    private bool waitingForCombatDecision = false;
+
+    void Start()
+    {
+        // Find required components
+        originalEventSystem = FindFirstObjectByType<TravelEventSystem>();
+        eventUI = FindFirstObjectByType<TravelEventUI>();
+
+        if (combatEventPopup == null)
+            combatEventPopup = FindFirstObjectByType<CombatEventPopup>();
+
+        if (originalEventSystem == null)
+        {
+            Debug.LogError("❌ Enhanced Travel Event System requires a TravelEventSystem component!");
+            enabled = false;
+            return;
+        }
+
+        if (combatEventPopup == null)
+        {
+            Debug.LogError("❌ Enhanced Travel Event System requires a CombatEventPopup component!");
+            enabled = false;
+            return;
+        }
+
+        // Setup combat popup callback
+        combatEventPopup.OnCombatDecision += HandleCombatDecision;
+
+        Debug.Log("✅ Enhanced Travel Event System initialized");
+    }
+
+    void OnDestroy()
+    {
+        if (combatEventPopup != null)
+            combatEventPopup.OnCombatDecision -= HandleCombatDecision;
+    }
+
+    /// <summary>
+    /// Enhanced combat event handler that shows popup before battle
+    /// Call this instead of the original HandleBattleEvent
+    /// </summary>
+    public void HandleEnhancedBattleEvent(BattleEventData battleData, TravelEventContext context, string eventDescription)
+    {
+        if (battleData == null || waitingForCombatDecision)
+            return;
+
+        Debug.Log($"🎭 Enhanced battle event triggered: {eventDescription}");
+
+        // Store pending battle data
+        pendingBattleData = battleData;
+        pendingContext = context;
+        waitingForCombatDecision = true;
+
+        // Show combat popup
+        combatEventPopup.ShowCombatEncounter(battleData, context, eventDescription);
+    }
+
+    /// <summary>
+    /// Handle the player's combat decision from the popup
+    /// </summary>
+    private void HandleCombatDecision(bool chooseToAttack)
+    {
+        if (!waitingForCombatDecision || pendingBattleData == null)
+            return;
+
+        waitingForCombatDecision = false;
+
+        if (chooseToAttack)
+        {
+            HandleAttackChoice();
+        }
+        else
+        {
+            HandleRunAwayChoice();
+        }
+
+        // Clear pending data
+        pendingBattleData = null;
+        pendingContext = null;
+    }
+
+    /// <summary>
+    /// Handle when player chooses to attack
+    /// </summary>
+    private void HandleAttackChoice()
+    {
+        Debug.Log("⚔️ Player chose to fight! Setting up battle...");
+
+        // Call the original battle setup logic
+        if (originalEventSystem != null)
+        {
+            // Use reflection to call the private HandleBattleEvent method
+            var method = originalEventSystem.GetType().GetMethod("HandleBattleEvent",
+                System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+
+            if (method != null)
+            {
+                method.Invoke(originalEventSystem, new object[] { pendingBattleData, pendingContext });
+            }
+            else
+            {
+                Debug.LogError("❌ Could not find HandleBattleEvent method in TravelEventSystem");
+                // Fallback: just log the battle setup
+                LogBattleSetup(pendingBattleData);
+            }
+        }
+    }
+
+    /// <summary>
+    /// Handle when player chooses to run away
+    /// </summary>
+    private void HandleRunAwayChoice()
+    {
+        Debug.Log("🏃 Player chose to run away! Rolling for escape...");
+
+        if (!allowRunningAway)
+        {
+            Debug.Log("❌ Running away is not allowed! Forcing combat...");
+            HandleAttackChoice();
+            return;
+        }
+
+        bool escapeSuccessful = Random.value <= runAwaySuccessChance;
+
+        if (escapeSuccessful)
+        {
+            HandleSuccessfulEscape();
+        }
+        else
+        {
+            HandleFailedEscape();
+        }
+    }
+
+    /// <summary>
+    /// Handle successful escape attempt
+    /// </summary>
+    private void HandleSuccessfulEscape()
+    {
+        string message = successfulRunAwayMessages[Random.Range(0, successfulRunAwayMessages.Length)];
+
+        Debug.Log($"✅ Escape successful: {message}");
+
+        // Show escape message
+        if (eventUI != null)
+        {
+            eventUI.ShowEventMessage(message, EventType.Discovery, false);
+        }
+        else
+        {
+            Debug.Log($"📜 ESCAPE: {message}");
+        }
+
+        // Continue travel (no resource penalties for successful escape)
+        ResumeTravelAfterEvent();
+    }
+
+    /// <summary>
+    /// Handle failed escape attempt
+    /// </summary>
+    private void HandleFailedEscape()
+    {
+        string message = failedRunAwayMessages[Random.Range(0, failedRunAwayMessages.Length)];
+        message = message.Replace("{damage}", runAwayHealthPenalty.ToString());
+
+        Debug.Log($"❌ Escape failed: {message}");
+
+        // Apply health penalty
+        ApplyRunAwayPenalty();
+
+        // Show failure message
+        if (eventUI != null)
+        {
+            eventUI.ShowEventMessage(message, EventType.Hazard, false);
+        }
+        else
+        {
+            Debug.Log($"📜 ESCAPE FAILED: {message}");
+        }
+
+        // Start combat anyway
+        StartCoroutine(DelayedCombatStart());
+    }
+
+    /// <summary>
+    /// Apply penalties for failed escape attempt
+    /// </summary>
+    private void ApplyRunAwayPenalty()
+    {
+        // This would integrate with your character health system
+        Debug.Log($"❤️ Party takes {runAwayHealthPenalty} damage from failed escape attempt");
+
+        // TODO: Actually apply health damage to party members
+        // Example: TeamHealthManager.ApplyDamageToParty(runAwayHealthPenalty);
+    }
+
+    /// <summary>
+    /// Resume travel after successful escape
+    /// </summary>
+    private void ResumeTravelAfterEvent()
+    {
+        // The travel system should continue normally
+        Debug.Log("🚗 Resuming travel after event...");
+
+        // No need to stop travel for successful escapes
+    }
+
+    /// <summary>
+    /// Start combat after a delay (for failed escape)
+    /// </summary>
+    private IEnumerator DelayedCombatStart()
+    {
+        yield return new WaitForSeconds(3f); // Wait for escape message to be read
+
+        Debug.Log("⚔️ Starting combat after failed escape...");
+        HandleAttackChoice();
+    }
+
+    /// <summary>
+    /// Fallback battle setup logging
+    /// </summary>
+    private void LogBattleSetup(BattleEventData battleData)
+    {
+        Debug.Log($"⚔️ Setting up battle: {battleData.enemyCount} {battleData.enemyType}(s)");
+
+        if (battleData.enemyCharacterData != null)
+        {
+            Debug.Log($"🎯 Using enemy data: {battleData.enemyCharacterData.enemyName}");
+            Debug.Log($"📊 Enemy stats: HP={battleData.enemyCharacterData.maxHealth}, " +
+                     $"AC={battleData.enemyCharacterData.armorClass}, " +
+                     $"Threat={battleData.enemyCharacterData.threatLevel}");
+        }
+
+        // TODO: Actually set up battle scene transition
+        Debug.Log("🎬 Transitioning to battle scene...");
+    }
+
+    /// <summary>
+    /// Check if the system is currently waiting for player input
+    /// </summary>
+    public bool IsWaitingForCombatDecision => waitingForCombatDecision;
+
+    /// <summary>
+    /// Cancel pending combat (for cleanup)
+    /// </summary>
+    public void CancelPendingCombat()
+    {
+        if (waitingForCombatDecision)
+        {
+            waitingForCombatDecision = false;
+            pendingBattleData = null;
+            pendingContext = null;
+
+            if (combatEventPopup != null)
+                combatEventPopup.ForceClose();
+        }
+    }
+}

+ 40 - 0
Assets/Scripts/Events/HiddenTreasure.asset

@@ -0,0 +1,40 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 0}
+  m_Name: HiddenTreasure
+  m_EditorClassIdentifier: Assembly-CSharp::DiscoveryTravelEvent
+  eventName: Hidden treasure
+  eventDescription: A chest is hidden at this location, spend {time} hours to dig
+    it out
+  eventType: 2
+  rarity: 2
+  plainsChance: 0.4
+  forestChance: 0.7
+  mountainChance: 0.8
+  roadChance: 0.3
+  riverChance: 0.033
+  lakeChance: 0.059
+  oceanChance: 0.197
+  townChance: 0.1
+  villageChance: 0.01
+  bridgeChance: 0
+  tunnelChance: 0
+  ferryChance: 0
+  canOccurMultipleTimes: 0
+  cooldownDays: 0
+  minGoldFound: 10
+  maxGoldFound: 100
+  canFindItems: 1
+  discoveryDescriptions:
+  - Your party discovers a hidden cache containing {amount} gold!
+  - While exploring, you find an abandoned stash with {amount} gold pieces.
+  - A keen-eyed party member spots something valuable - {amount} gold!

+ 40 - 0
Assets/Scripts/Events/SkeletonAmbush.asset

@@ -0,0 +1,40 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f460ab3f7cb3e5342a0c4d4cd2acb8a5, type: 3}
+  m_Name: SkeletonAmbush
+  m_EditorClassIdentifier: 
+  eventName: Skeletons attack!
+  eventDescription: A group of skeletons are attacking
+  eventType: 0
+  rarity: 1
+  plainsChance: 0.4
+  forestChance: 0.8
+  mountainChance: 0.9
+  roadChance: 0.2
+  riverChance: 0.5
+  lakeChance: 0.5
+  oceanChance: 0.5
+  townChance: 0.1
+  villageChance: 0.3
+  bridgeChance: 0.5
+  tunnelChance: 0.5
+  ferryChance: 0.5
+  canOccurMultipleTimes: 1
+  cooldownDays: 0
+  minEnemies: 1
+  maxEnemies: 3
+  possibleEnemies:
+  - {fileID: 11400000, guid: a0c1cb52b0bf42c4299acc5827d0d6e2, type: 2}
+  encounterDescriptions:
+  - Your party is ambushed by {enemyType}s!
+  - A group of {enemyType}s blocks your path!
+  - You stumble upon a {enemyType} camp!

+ 48 - 0
Assets/Scripts/Events/SkeletonAmbushEvent.cs

@@ -0,0 +1,48 @@
+using UnityEngine;
+
+/// <summary>
+/// Skeleton Ambush - Undead warriors rising from the earth
+/// Uses EnemyCharacterData for type-safe enemy references
+/// </summary>
+[CreateAssetMenu(fileName = "Skeleton Ambush", menuName = "RPG/Travel Events/Specific/Skeleton Ambush")]
+public class SkeletonAmbushEvent : CombatTravelEvent
+{
+    void OnEnable()
+    {
+        eventName = "Skeleton Ambush";
+        eventDescription = "Ancient skeletal warriors rise from the ground to attack your party!";
+        eventType = EventType.Combat;
+        rarity = EventRarity.Common;
+
+        // Terrain preferences - high in dangerous/abandoned areas
+        forestChance = 0.8f;        // Common in dark forests
+        mountainChance = 0.6f;      // Moderate in mountains
+        plainsChance = 0.3f;        // Less common in open plains
+        roadChance = 0.2f;          // Much safer on roads
+        townChance = 0.05f;         // Very rare near civilization
+        villageChance = 0.15f;      // Uncommon near villages
+        bridgeChance = 0.4f;        // Moderate at crossings
+        tunnelChance = 0.9f;        // Very common in dark tunnels/caves
+
+        // Combat settings
+        minEnemies = 1;
+        maxEnemies = 3;
+        
+        // NOTE: In the Inspector, drag your EnemyCharacterData assets here:
+        // - SkeletonWarrior.asset
+        // - Any other skeleton variants you create
+        // This replaces the old string-based possibleEnemyTypes
+        
+        encounterDescriptions = new string[]
+        {
+            "Bones clatter as skeletal warriors emerge from the earth!",
+            "Ancient skeletons wielding rusty weapons block your path!",
+            "The ground splits open as undead skeletons rise to attack!",
+            "Skeletal archers take aim from the shadows ahead!",
+            "Weathered bones reassemble into hostile warriors!"
+        };
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 0.5f; // Can happen again after half a day
+    }
+}

+ 298 - 0
Assets/Scripts/Events/SpecificTravelEvents.cs

@@ -0,0 +1,298 @@
+using UnityEngine;
+
+/// <summary>
+/// Forest Ambush - Bandits attacking from the woods
+/// High probability in forests, lower on roads
+/// </summary>
+[CreateAssetMenu(fileName = "Forest Ambush", menuName = "RPG/Travel Events/Specific/Forest Ambush")]
+public class ForestAmbushEvent : CombatTravelEvent
+{
+    void OnEnable()
+    {
+        eventName = "Forest Ambush";
+        eventDescription = "Bandits leap from the undergrowth to ambush your party!";
+        eventType = EventType.Combat;
+        rarity = EventRarity.Common;
+
+        // Very likely in forests, unlikely on roads
+        forestChance = 0.95f;
+        plainsChance = 0.3f;
+        mountainChance = 0.6f;
+        roadChance = 0.15f; // Much safer on roads
+        townChance = 0.05f;
+        villageChance = 0.2f;
+
+        minEnemies = 2;
+        maxEnemies = 4;
+        // TODO: Assign possibleEnemies array with EnemyCharacterData assets
+        // Example: possibleEnemies = new EnemyCharacterData[] { forestBanditAsset, brigandAsset, outlawAsset };
+
+        encounterDescriptions = new string[]
+        {
+            "Bandits emerge from behind the trees to surround your party!",
+            "Your party walks into a carefully planned ambush by forest brigands!",
+            "Outlaws drop from the canopy above, weapons drawn!",
+            "A group of bandits blocks the forest path ahead!"
+        };
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 0.5f; // Can happen again after half a day
+    }
+}
+
+/// <summary>
+/// Mountain Ambush - More dangerous encounter in treacherous terrain
+/// </summary>
+[CreateAssetMenu(fileName = "Mountain Ambush", menuName = "RPG/Travel Events/Specific/Mountain Ambush")]
+public class MountainAmbushEvent : CombatTravelEvent
+{
+    void OnEnable()
+    {
+        eventName = "Mountain Ambush";
+        eventDescription = "Mountain bandits use the rocky terrain to their advantage!";
+        eventType = EventType.Combat;
+        rarity = EventRarity.Common;
+
+        // Most likely in mountains
+        mountainChance = 0.9f;
+        forestChance = 0.4f;
+        plainsChance = 0.2f;
+        roadChance = 0.1f;
+        townChance = 0.02f;
+        villageChance = 0.1f;
+
+        minEnemies = 1;
+        maxEnemies = 3;
+        // TODO: Assign possibleEnemies array with EnemyCharacterData assets
+        // Example: possibleEnemies = new EnemyCharacterData[] { mountainBanditAsset, highwaymanAsset, raiderAsset };
+
+        encounterDescriptions = new string[]
+        {
+            "Mountain bandits rain arrows down from the cliffs above!",
+            "Your party is caught in a narrow pass by armed raiders!",
+            "Highwaymen emerge from rocky crevices to block your path!",
+            "A rockslide reveals it was a trap - bandits attack!"
+        };
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 1f;
+    }
+}
+
+/// <summary>
+/// Traveling Merchant - Friendly trader offering goods
+/// Much more likely on roads and near settlements
+/// </summary>
+[CreateAssetMenu(fileName = "Traveling Merchant", menuName = "RPG/Travel Events/Specific/Traveling Merchant")]
+public class TravelingMerchantEvent : TradingTravelEvent
+{
+    void OnEnable()
+    {
+        eventName = "Traveling Merchant";
+        eventDescription = "A friendly merchant offers to trade goods with your party.";
+        eventType = EventType.Trading;
+        rarity = EventRarity.Common;
+
+        // Very likely on roads and near settlements
+        roadChance = 0.85f;
+        townChance = 0.6f;
+        villageChance = 0.75f;
+        bridgeChance = 0.7f; // Common at crossings
+        ferryChance = 0.6f;
+
+        // Less likely in wilderness
+        forestChance = 0.25f;
+        mountainChance = 0.15f;
+        plainsChance = 0.4f;
+        lakeChance = 0.3f;
+        riverChance = 0.3f;
+
+        merchantTypes = new string[] {
+            "Traveling Merchant",
+            "Caravan Trader",
+            "Wandering Peddler",
+            "Road Merchant"
+        };
+
+        canHaveRareItems = true;
+        rareItemChance = 0.25f;
+        priceModifier = 1.1f; // Slightly more expensive than town shops
+
+        encounterDescriptions = new string[]
+        {
+            "A {merchantType} with a pack full of goods approaches your party.",
+            "Your party encounters a {merchantType} resting beside the road.",
+            "A {merchantType} calls out, offering to show you their wares.",
+            "You come across a {merchantType} leading a pack animal loaded with goods."
+        };
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 0.25f; // Multiple merchants can be encountered
+    }
+}
+
+/// <summary>
+/// Road Patrol - Guards or soldiers patrolling main roads
+/// Only occurs on roads, provides safety information
+/// </summary>
+[CreateAssetMenu(fileName = "Road Patrol", menuName = "RPG/Travel Events/Specific/Road Patrol")]
+public class RoadPatrolEvent : TravelEvent
+{
+    [Header("Patrol Event Settings")]
+    public string[] patrolTypes = { "City Guard Patrol", "Royal Guard", "Local Militia" };
+    public bool providesInformation = true;
+    public bool canRestoreHealth = true;
+    public int healthRestored = 15;
+
+    void OnEnable()
+    {
+        eventName = "Road Patrol";
+        eventDescription = "A patrol of guards maintains order on the roads.";
+        eventType = EventType.Social;
+        rarity = EventRarity.Common;
+
+        // Only on roads and near settlements
+        roadChance = 0.9f;
+        townChance = 0.8f;
+        villageChance = 0.6f;
+        bridgeChance = 0.5f;
+
+        // Never in wilderness
+        forestChance = 0f;
+        mountainChance = 0f;
+        plainsChance = 0.1f;
+        lakeChance = 0f;
+        riverChance = 0f;
+        oceanChance = 0f;
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 1f;
+    }
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        string patrolType = patrolTypes[Random.Range(0, patrolTypes.Length)];
+        string message = $"Your party encounters a {patrolType} maintaining security on the road.";
+
+        if (canRestoreHealth && Random.value < 0.4f)
+        {
+            message += $" They provide aid, restoring {healthRestored} health to your party.";
+            return new EventResult(message) { healthChange = healthRestored };
+        }
+        else if (providesInformation)
+        {
+            string[] infoMessages = {
+                " They warn you about bandit activity ahead.",
+                " They share information about safe camping spots nearby.",
+                " They mention a trading post further down the road.",
+                " They advise taking the main road for safer travel."
+            };
+            message += infoMessages[Random.Range(0, infoMessages.Length)];
+        }
+
+        return new EventResult(message);
+    }
+}
+
+/// <summary>
+/// Hidden Cache - Discovery of abandoned supplies
+/// More likely off main roads in remote areas
+/// </summary>
+[CreateAssetMenu(fileName = "Hidden Cache", menuName = "RPG/Travel Events/Specific/Hidden Cache")]
+public class HiddenCacheEvent : DiscoveryTravelEvent
+{
+    void OnEnable()
+    {
+        eventName = "Hidden Cache";
+        eventDescription = "Your party discovers a hidden stash of supplies.";
+        eventType = EventType.Discovery;
+        rarity = EventRarity.Uncommon;
+
+        // More likely in remote areas
+        forestChance = 0.8f;
+        mountainChance = 0.9f;
+        plainsChance = 0.5f;
+        riverChance = 0.6f;
+
+        // Less likely on main routes
+        roadChance = 0.2f;
+        townChance = 0.05f;
+        villageChance = 0.1f;
+
+        minGoldFound = 25;
+        maxGoldFound = 150;
+        canFindItems = true;
+
+        discoveryDescriptions = new string[]
+        {
+            "Your party discovers a carefully hidden cache containing {amount} gold!",
+            "While exploring off the beaten path, you find an old smuggler's stash with {amount} gold pieces.",
+            "A party member notices disturbed earth that reveals a buried cache worth {amount} gold!",
+            "Behind some rocks, your party uncovers an abandoned supply cache with {amount} gold."
+        };
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 2f; // Takes time for new caches to be found
+    }
+}
+
+/// <summary>
+/// Wild Animal Encounter - Non-aggressive animal encounter
+/// Can be peaceful or turn into combat based on party actions
+/// </summary>
+[CreateAssetMenu(fileName = "Wild Animal Encounter", menuName = "RPG/Travel Events/Specific/Wild Animal Encounter")]
+public class WildAnimalEvent : TravelEvent
+{
+    [Header("Animal Encounter Settings")]
+    public string[] animalTypes = { "Wolf Pack", "Brown Bear", "Wild Boar", "Mountain Lion" };
+    public float aggressionChance = 0.3f; // Chance the animal attacks
+
+    void OnEnable()
+    {
+        eventName = "Wild Animal Encounter";
+        eventDescription = "Your party encounters wild animals.";
+        eventType = EventType.Mystery;
+        rarity = EventRarity.Common;
+
+        // More likely in natural areas
+        forestChance = 0.9f;
+        mountainChance = 0.8f;
+        plainsChance = 0.6f;
+        riverChance = 0.5f;
+        lakeChance = 0.4f;
+
+        // Very unlikely near civilization
+        roadChance = 0.2f;
+        townChance = 0.02f;
+        villageChance = 0.1f;
+
+        canOccurMultipleTimes = true;
+        cooldownDays = 0.5f;
+    }
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        string animalType = animalTypes[Random.Range(0, animalTypes.Length)];
+
+        if (Random.value < aggressionChance)
+        {
+            // Animal attacks
+            return EventResult.SimpleBattle(
+                $"A {animalType} attacks your party!",
+                1,
+                animalType
+            );
+        }
+        else
+        {
+            // Peaceful encounter
+            string[] peacefulMessages = {
+                $"Your party spots a {animalType} in the distance. It notices you but moves away peacefully.",
+                $"A {animalType} crosses your path but shows no aggression toward your party.",
+                $"Your party carefully observes a {animalType} before it disappears into the wilderness."
+            };
+
+            return new EventResult(peacefulMessages[Random.Range(0, peacefulMessages.Length)]);
+        }
+    }
+}

+ 231 - 0
Assets/Scripts/Events/TravelEvent.cs

@@ -0,0 +1,231 @@
+using UnityEngine;
+using System;
+
+/// <summary>
+/// Base class for all travel events that can occur during journeys
+/// </summary>
+[Serializable]
+public abstract class TravelEvent : ScriptableObject
+{
+    [Header("Basic Event Info")]
+    public string eventName;
+    [TextArea(3, 6)]
+    public string eventDescription;
+    public EventType eventType;
+    public EventRarity rarity = EventRarity.Common;
+
+    [Header("Terrain Preferences")]
+    [Range(0f, 1f)]
+    public float plainsChance = 0.5f;
+    [Range(0f, 1f)]
+    public float forestChance = 0.5f;
+    [Range(0f, 1f)]
+    public float mountainChance = 0.5f;
+    [Range(0f, 1f)]
+    public float roadChance = 0.5f;
+    [Range(0f, 1f)]
+    public float riverChance = 0.5f;
+    [Range(0f, 1f)]
+    public float lakeChance = 0.5f;
+    [Range(0f, 1f)]
+    public float oceanChance = 0.5f;
+
+    [Header("Feature Preferences")]
+    [Range(0f, 1f)]
+    public float townChance = 0.5f;
+    [Range(0f, 1f)]
+    public float villageChance = 0.5f;
+    [Range(0f, 1f)]
+    public float bridgeChance = 0.5f;
+    [Range(0f, 1f)]
+    public float tunnelChance = 0.5f;
+    [Range(0f, 1f)]
+    public float ferryChance = 0.5f;
+
+    [Header("Timing")]
+    public bool canOccurMultipleTimes = true;
+    public float cooldownDays = 0f; // Days before this event can occur again
+
+    /// <summary>
+    /// Calculate the chance of this event occurring on a specific tile
+    /// </summary>
+    public virtual float GetEventChance(MapTile tile)
+    {
+        float baseChance = GetBaseChanceForRarity();
+        float terrainModifier = GetTerrainModifier(tile.terrainType);
+        float featureModifier = GetFeatureModifier(tile.featureType);
+
+        return baseChance * terrainModifier * featureModifier;
+    }
+
+    /// <summary>
+    /// Execute the event - must be implemented by derived classes
+    /// </summary>
+    public abstract EventResult ExecuteEvent(TravelEventContext context);
+
+    /// <summary>
+    /// Check if this event can occur given the current context
+    /// </summary>
+    public virtual bool CanOccur(TravelEventContext context)
+    {
+        // Check cooldown
+        if (!canOccurMultipleTimes && context.eventHistory.HasOccurred(this))
+        {
+            return false;
+        }
+
+        if (cooldownDays > 0f && context.eventHistory.GetTimeSinceLastOccurrence(this) < cooldownDays)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    private float GetBaseChanceForRarity()
+    {
+        return rarity switch
+        {
+            EventRarity.VeryCommon => 0.25f,
+            EventRarity.Common => 0.15f,
+            EventRarity.Uncommon => 0.08f,
+            EventRarity.Rare => 0.04f,
+            EventRarity.VeryRare => 0.02f,
+            EventRarity.Legendary => 0.005f,
+            _ => 0.1f
+        };
+    }
+
+    private float GetTerrainModifier(TerrainType terrain)
+    {
+        return terrain switch
+        {
+            TerrainType.Plains => plainsChance,
+            TerrainType.Forest => forestChance,
+            TerrainType.Mountain => mountainChance,
+            TerrainType.River => riverChance,
+            TerrainType.Lake => lakeChance,
+            TerrainType.Ocean => oceanChance,
+            TerrainType.ForestRiver => forestChance * riverChance, // Hybrid terrain
+            _ => 0.5f
+        };
+    }
+
+    private float GetFeatureModifier(FeatureType feature)
+    {
+        return feature switch
+        {
+            FeatureType.Road => roadChance,
+            FeatureType.Town => townChance,
+            FeatureType.Village => villageChance,
+            FeatureType.Bridge => bridgeChance,
+            FeatureType.Tunnel => tunnelChance,
+            FeatureType.Ferry => ferryChance,
+            FeatureType.None => 1f, // No modifier for no feature
+            _ => 0.5f
+        };
+    }
+}
+
+[Serializable]
+public enum EventType
+{
+    Combat,     // Battle encounters
+    Trading,    // Merchant encounters
+    Discovery,  // Finding items/resources
+    Social,     // Meeting NPCs, getting information
+    Hazard,     // Environmental dangers
+    Rest,       // Camping, healing opportunities
+    Mystery     // Strange occurrences, puzzles
+}
+
+[Serializable]
+public enum EventRarity
+{
+    VeryCommon,  // 25% base chance
+    Common,      // 15% base chance
+    Uncommon,    // 8% base chance
+    Rare,        // 4% base chance
+    VeryRare,    // 2% base chance
+    Legendary    // 0.5% base chance
+}
+
+/// <summary>
+/// Result of executing a travel event
+/// </summary>
+[Serializable]
+public class EventResult
+{
+    public bool eventOccurred = true;
+    public bool shouldStopTravel = false;
+    public bool startBattle = false;
+    public bool openTrading = false;
+    public string resultMessage = "";
+
+    // Resource changes
+    public int goldChange = 0;
+    public int foodChange = 0;
+    public int healthChange = 0;
+
+    // Battle setup (if startBattle is true)
+    public BattleEventData battleData;
+
+    // Trading setup (if openTrading is true)
+    public TradingEventData tradingData;
+
+    public EventResult(string message)
+    {
+        resultMessage = message;
+    }
+
+    public static EventResult NoEvent()
+    {
+        return new EventResult("") { eventOccurred = false };
+    }
+
+    public static EventResult SimpleBattle(string message, int enemyCount, string enemyType = "Bandit")
+    {
+        return new EventResult(message)
+        {
+            shouldStopTravel = true,
+            startBattle = true,
+            battleData = new BattleEventData
+            {
+                enemyCount = enemyCount,
+                enemyType = enemyType
+            }
+        };
+    }
+
+    public static EventResult SimpleTrading(string message, string merchantType = "Traveling Merchant")
+    {
+        return new EventResult(message)
+        {
+            shouldStopTravel = true,
+            openTrading = true,
+            tradingData = new TradingEventData
+            {
+                merchantType = merchantType,
+                hasRareItems = UnityEngine.Random.value < 0.3f
+            }
+        };
+    }
+}
+
+[Serializable]
+public class BattleEventData
+{
+    public int enemyCount = 1;
+    public string enemyType = "Bandit";
+    public string battleDescription = "";
+    [Tooltip("Reference to the actual enemy data asset (safer than string names)")]
+    public EnemyCharacterData enemyCharacterData = null;
+}
+
+[Serializable]
+public class TradingEventData
+{
+    public string merchantType = "Traveling Merchant";
+    public bool hasRareItems = false;
+    public float priceModifier = 1f; // 1f = normal prices, 0.8f = 20% discount, etc.
+}

+ 108 - 0
Assets/Scripts/Events/TravelEventContext.cs

@@ -0,0 +1,108 @@
+using UnityEngine;
+using System.Collections.Generic;
+using System;
+
+/// <summary>
+/// Context information passed to travel events for decision making
+/// </summary>
+[Serializable]
+public class TravelEventContext
+{
+    public Vector2Int currentPosition;
+    public MapTile currentTile;
+    public TravelRoute currentRoute;
+    public int dayOfJourney;
+    public float timeOfDay; // 0-24 hours
+    public Weather currentWeather = Weather.Clear;
+
+    // Team state
+    public List<TeamCharacter> teamMembers;
+    public int teamGold;
+    public int teamFood;
+    public float teamMorale = 1f;
+
+    // Event tracking
+    public TravelEventHistory eventHistory;
+
+    // Travel context
+    public Vector2Int destination;
+    public bool isOnMainRoad;
+    public float distanceToDestination;
+
+    public TravelEventContext(Vector2Int position, MapTile tile, TravelRoute route)
+    {
+        currentPosition = position;
+        currentTile = tile;
+        currentRoute = route;
+        eventHistory = new TravelEventHistory();
+        teamMembers = new List<TeamCharacter>();
+
+        // Initialize with current team data
+        var teamPlacement = UnityEngine.Object.FindFirstObjectByType<SimpleTeamPlacement>();
+        if (teamPlacement != null)
+        {
+            // Get team data from the game
+            // This would need to be implemented based on your team system
+        }
+    }
+}
+
+/// <summary>
+/// Tracks which events have occurred and when
+/// </summary>
+[Serializable]
+public class TravelEventHistory
+{
+    [Serializable]
+    public class EventOccurrence
+    {
+        public string eventName;
+        public float dayOccurred;
+        public Vector2Int location;
+    }
+
+    public List<EventOccurrence> pastEvents = new List<EventOccurrence>();
+
+    public bool HasOccurred(TravelEvent travelEvent)
+    {
+        return pastEvents.Exists(e => e.eventName == travelEvent.eventName);
+    }
+
+    public float GetTimeSinceLastOccurrence(TravelEvent travelEvent)
+    {
+        var lastOccurrence = pastEvents.FindLast(e => e.eventName == travelEvent.eventName);
+        if (lastOccurrence == null) return float.MaxValue;
+
+        // This would need to be implemented with actual game time
+        return Time.time - lastOccurrence.dayOccurred;
+    }
+
+    public void RecordEvent(TravelEvent travelEvent, TravelEventContext context)
+    {
+        pastEvents.Add(new EventOccurrence
+        {
+            eventName = travelEvent.eventName,
+            dayOccurred = context.dayOfJourney,
+            location = context.currentPosition
+        });
+    }
+}
+
+[Serializable]
+public enum Weather
+{
+    Clear,
+    Cloudy,
+    Rain,
+    Storm,
+    Fog,
+    Snow
+}
+
+/// <summary>
+/// Interface for objects that can handle travel event results
+/// </summary>
+public interface ITravelEventHandler
+{
+    void HandleEventResult(EventResult result, TravelEventContext context);
+}

+ 488 - 0
Assets/Scripts/Events/TravelEventSystem.cs

@@ -0,0 +1,488 @@
+using UnityEngine;
+using System.Collections.Generic;
+using System.Linq;
+
+/// <summary>
+/// Main travel event system that manages when and where events occur during travel
+/// Integrates with the existing TeamTravelSystem
+/// </summary>
+public class TravelEventSystem : MonoBehaviour
+{
+    [Header("Event System Settings")]
+    public bool enableEvents = true;
+    [Range(0f, 1f)]
+    public float baseEventChance = 0.15f; // 15% chance per tile by default
+    [Range(1, 10)]
+    public int tilesPerEventCheck = 3; // Check for events every N tiles
+
+    [Header("Event Collections")]
+    public List<TravelEvent> availableEvents = new List<TravelEvent>();
+
+    [Header("Debug")]
+    public bool showDebugLogs = true;
+    public bool forceNextEvent = false; // For testing
+
+    // Event tracking
+    private TravelEventHistory globalEventHistory;
+    private int tilesTraveledSinceLastCheck = 0;
+    private TravelEventContext currentContext;
+
+    // Component references
+    private TeamTravelSystem travelSystem;
+    private MapMaker2 mapMaker;
+    private SimpleTeamPlacement teamPlacement;
+    private TravelEventUI eventUI;
+    // Enhanced system will be linked after compilation
+    private object enhancedEventSystem;
+
+    void Start()
+    {
+        // Find required components
+        travelSystem = FindFirstObjectByType<TeamTravelSystem>();
+        mapMaker = FindFirstObjectByType<MapMaker2>();
+        teamPlacement = FindFirstObjectByType<SimpleTeamPlacement>();
+        eventUI = FindFirstObjectByType<TravelEventUI>();
+        // Enhanced system will be found after compilation
+        // enhancedEventSystem = FindFirstObjectByType<EnhancedTravelEventSystem>();
+
+        globalEventHistory = new TravelEventHistory();
+
+        if (showDebugLogs)
+        {
+            Debug.Log($"🎲 Travel Event System initialized with {availableEvents.Count} events");
+            if (eventUI == null)
+                Debug.LogWarning("⚠️ TravelEventUI not found. Event messages will only appear in console.");
+            LogEventDistribution();
+        }
+
+        // Load default events if none are assigned
+        if (availableEvents.Count == 0)
+        {
+            LoadDefaultEvents();
+        }
+    }
+
+    void Update()
+    {
+        if (!enableEvents || travelSystem == null || !travelSystem.IsTraveling()) return;
+
+        // Check if we should evaluate for events
+        tilesTraveledSinceLastCheck++;
+        if (tilesTraveledSinceLastCheck >= tilesPerEventCheck)
+        {
+            CheckForTravelEvent();
+            tilesTraveledSinceLastCheck = 0;
+        }
+    }
+
+    /// <summary>
+    /// Main method to check if a travel event should occur
+    /// </summary>
+    public void CheckForTravelEvent()
+    {
+        if (!enableEvents) return;
+
+        // Get current travel context
+        currentContext = CreateCurrentContext();
+        if (currentContext == null) return;
+
+        // Calculate if an event should occur
+        float eventRoll = Random.value;
+        float eventThreshold = CalculateEventThreshold(currentContext);
+
+        // Force event for testing
+        if (forceNextEvent)
+        {
+            forceNextEvent = false;
+            eventRoll = 0f; // Guarantee event
+            eventThreshold = 1f;
+        }
+
+        if (eventRoll <= eventThreshold)
+        {
+            TriggerRandomEvent(currentContext);
+        }
+    }
+
+    /// <summary>
+    /// Force a specific event to occur (for testing or story purposes)
+    /// </summary>
+    public void TriggerSpecificEvent(TravelEvent eventToTrigger)
+    {
+        if (eventToTrigger == null) return;
+
+        currentContext = CreateCurrentContext();
+        if (currentContext == null) return;
+
+        ExecuteEvent(eventToTrigger, currentContext);
+    }
+
+    /// <summary>
+    /// Trigger a random event based on current context
+    /// </summary>
+    private void TriggerRandomEvent(TravelEventContext context)
+    {
+        var possibleEvents = GetPossibleEvents(context);
+        if (possibleEvents.Count == 0)
+        {
+            if (showDebugLogs)
+                Debug.Log("🎲 No valid events found for current context");
+            return;
+        }
+
+        // Select event based on weighted chances
+        TravelEvent selectedEvent = SelectWeightedEvent(possibleEvents, context);
+        if (selectedEvent != null)
+        {
+            ExecuteEvent(selectedEvent, context);
+        }
+    }
+
+    /// <summary>
+    /// Execute a travel event and handle its results
+    /// </summary>
+    private void ExecuteEvent(TravelEvent travelEvent, TravelEventContext context)
+    {
+        if (showDebugLogs)
+        {
+            Debug.Log($"🎭 Executing event: {travelEvent.eventName} at {context.currentPosition}");
+        }
+
+        // Execute the event
+        EventResult result = travelEvent.ExecuteEvent(context);
+
+        if (!result.eventOccurred)
+        {
+            if (showDebugLogs)
+                Debug.Log($"🎭 Event {travelEvent.eventName} chose not to occur");
+            return;
+        }
+
+        // Record the event
+        globalEventHistory.RecordEvent(travelEvent, context);
+
+        // Display event message
+        if (eventUI != null)
+        {
+            eventUI.ShowEventResult(result);
+        }
+        else
+        {
+            ShowEventMessage(result.resultMessage);
+        }
+
+        // Handle the event result
+        HandleEventResult(result, context);
+    }
+
+    /// <summary>
+    /// Handle the results of a travel event
+    /// </summary>
+    private void HandleEventResult(EventResult result, TravelEventContext context)
+    {
+        // Apply resource changes
+        ApplyResourceChanges(result);
+
+        // Handle special event types
+        if (result.shouldStopTravel)
+        {
+            if (travelSystem != null)
+            {
+                // Stop current travel using the existing cancellation system
+                travelSystem.CancelJourney();
+                Debug.Log("🛑 Travel stopped due to event");
+            }
+        }
+
+        if (result.startBattle)
+        {
+            HandleBattleEvent(result.battleData, context);
+        }
+
+        if (result.openTrading)
+        {
+            HandleTradingEvent(result.tradingData, context);
+        }
+    }
+
+    /// <summary>
+    /// Create travel event context from current game state
+    /// </summary>
+    private TravelEventContext CreateCurrentContext()
+    {
+        if (teamPlacement == null || mapMaker == null || travelSystem == null)
+            return null;
+
+        Vector2Int currentPos = teamPlacement.GetCurrentTeamPosition();
+        var mapData = mapMaker.GetMapData();
+        var currentTile = mapData.GetTile(currentPos.x, currentPos.y);
+        var currentRoute = travelSystem.GetCurrentRoute();
+
+        var context = new TravelEventContext(currentPos, currentTile, currentRoute)
+        {
+            dayOfJourney = 1, // This could be tracked elsewhere
+            timeOfDay = 12f, // This could be from a day/night system
+            teamGold = 100, // This should come from actual team resources
+            teamFood = 50,
+            eventHistory = globalEventHistory
+        };
+
+        // Set travel context
+        if (currentRoute != null)
+        {
+            context.destination = travelSystem.GetPlannedDestination() ?? currentPos;
+            context.isOnMainRoad = currentTile.featureType == FeatureType.Road;
+        }
+
+        return context;
+    }
+
+    /// <summary>
+    /// Calculate the threshold for events to occur based on context
+    /// </summary>
+    private float CalculateEventThreshold(TravelEventContext context)
+    {
+        float threshold = baseEventChance;
+
+        // Modify based on terrain (some areas are more eventful)
+        switch (context.currentTile.terrainType)
+        {
+            case TerrainType.Forest:
+                threshold *= 1.3f; // More events in forests
+                break;
+            case TerrainType.Mountain:
+                threshold *= 1.4f; // Even more in mountains
+                break;
+            case TerrainType.Plains:
+                threshold *= 0.8f; // Fewer in plains
+                break;
+        }
+
+        // Modify based on features
+        switch (context.currentTile.featureType)
+        {
+            case FeatureType.Road:
+                threshold *= 0.7f; // Fewer events on roads (safer travel)
+                break;
+            case FeatureType.Town:
+            case FeatureType.Village:
+                threshold *= 0.5f; // Much fewer in settlements
+                break;
+        }
+
+        return Mathf.Clamp01(threshold);
+    }
+
+    /// <summary>
+    /// Get all events that can occur in the current context
+    /// </summary>
+    private List<TravelEvent> GetPossibleEvents(TravelEventContext context)
+    {
+        return availableEvents.Where(e => e != null && e.CanOccur(context)).ToList();
+    }
+
+    /// <summary>
+    /// Select an event based on weighted probabilities
+    /// </summary>
+    private TravelEvent SelectWeightedEvent(List<TravelEvent> events, TravelEventContext context)
+    {
+        if (events.Count == 0) return null;
+        if (events.Count == 1) return events[0];
+
+        // Calculate weights
+        var weights = events.Select(e => e.GetEventChance(context.currentTile)).ToList();
+        float totalWeight = weights.Sum();
+
+        if (totalWeight <= 0) return null;
+
+        // Select based on weight
+        float randomValue = Random.value * totalWeight;
+        float currentWeight = 0f;
+
+        for (int i = 0; i < events.Count; i++)
+        {
+            currentWeight += weights[i];
+            if (randomValue <= currentWeight)
+            {
+                return events[i];
+            }
+        }
+
+        return events.Last(); // Fallback
+    }
+
+    /// <summary>
+    /// Apply resource changes from event results
+    /// </summary>
+    private void ApplyResourceChanges(EventResult result)
+    {
+        if (result.goldChange != 0)
+        {
+            // Apply gold change to team resources
+            // This would integrate with your resource system
+            Debug.Log($"💰 Gold changed by {result.goldChange}");
+        }
+
+        if (result.healthChange != 0)
+        {
+            // Apply health change to team
+            // This would integrate with your character health system
+            Debug.Log($"❤️ Health changed by {result.healthChange}");
+        }
+
+        if (result.foodChange != 0)
+        {
+            // Apply food change
+            Debug.Log($"🍖 Food changed by {result.foodChange}");
+        }
+    }
+
+    /// <summary>
+    /// Handle battle events by setting up battle data
+    /// </summary>
+    private void HandleBattleEvent(BattleEventData battleData, TravelEventContext context)
+    {
+        if (battleData == null) return;
+
+        // Try to use enhanced event system for player choice popup
+        var enhancedSystem = FindFirstObjectByType(System.Type.GetType("EnhancedTravelEventSystem"));
+        if (enhancedSystem != null)
+        {
+            Debug.Log("🎭 Using Enhanced Travel Event System for combat popup");
+
+            // Use reflection to call the enhanced handler
+            var method = enhancedSystem.GetType().GetMethod("HandleEnhancedBattleEvent");
+            if (method != null)
+            {
+                string eventDescription = $"Your party encounters {battleData.enemyCount} {battleData.enemyType}!";
+                method.Invoke(enhancedSystem, new object[] { battleData, context, eventDescription });
+                return;
+            }
+        }
+
+        // Fallback to original battle handling
+        Debug.Log($"⚔️ Setting up battle: {battleData.enemyCount} {battleData.enemyType}(s)");
+
+        // Enhanced battle setup using EnemyCharacterData if available
+        if (battleData.enemyCharacterData != null)
+        {
+            Debug.Log($"🎯 Using enemy data: {battleData.enemyCharacterData.enemyName}");
+            Debug.Log($"📊 Enemy stats: HP={battleData.enemyCharacterData.maxHealth}, " +
+                     $"AC={battleData.enemyCharacterData.armorClass}, " +
+                     $"Threat={battleData.enemyCharacterData.threatLevel}");
+
+            // TODO: Enhanced battle setup with actual enemy data
+            /*
+            BattleSetupData.enemySelections.Clear();
+            for (int i = 0; i < battleData.enemyCount; i++)
+            {
+                var enemyData = battleData.enemyCharacterData;
+                BattleSetupData.enemySelections.Add(new CharacterSelection
+                {
+                    characterName = $"{enemyData.enemyName}_{i+1}",
+                    weaponType = enemyData.preferredWeapon != null ? enemyData.preferredWeapon.weaponType.ToString() : "Sword",
+                    // Could also include:
+                    // health = enemyData.maxHealth,
+                    // armorClass = enemyData.armorClass,
+                    // threatLevel = enemyData.threatLevel
+                });
+            }
+            */
+        }
+        else
+        {
+            // Fallback to string-based system
+            Debug.Log("⚠️ No EnemyCharacterData found, using legacy string-based setup");
+            /*
+            BattleSetupData.enemySelections.Clear();
+            for (int i = 0; i < battleData.enemyCount; i++)
+            {
+                BattleSetupData.enemySelections.Add(new CharacterSelection
+                {
+                    characterName = $"{battleData.enemyType}_{i+1}",
+                    weaponType = "Sword" // Could be randomized
+                });
+            }
+            */
+        }
+    }
+
+    /// <summary>
+    /// Handle trading events by opening shop interface
+    /// </summary>
+    private void HandleTradingEvent(TradingEventData tradingData, TravelEventContext context)
+    {
+        if (tradingData == null) return;
+
+        Debug.Log($"🛒 Opening trading with {tradingData.merchantType}");
+
+        // This would open your shop system
+        // You could modify shop inventory based on merchantType and hasRareItems
+    }
+
+    /// <summary>
+    /// Display event message to player
+    /// </summary>
+    private void ShowEventMessage(string message)
+    {
+        if (string.IsNullOrEmpty(message)) return;
+
+        Debug.Log($"📜 EVENT: {message}");
+
+        // Use UI system if available
+        if (eventUI != null)
+        {
+            eventUI.ShowEventMessage(message);
+        }
+    }
+
+    /// <summary>
+    /// Load default events if none are assigned in inspector
+    /// </summary>
+    private void LoadDefaultEvents()
+    {
+        // Load default events from Resources folder
+        TravelEvent[] defaultEvents = Resources.LoadAll<TravelEvent>("TravelEvents");
+        availableEvents.AddRange(defaultEvents);
+
+        if (showDebugLogs)
+        {
+            Debug.Log($"🔄 Loaded {defaultEvents.Length} default events from Resources");
+        }
+    }
+
+    /// <summary>
+    /// Debug method to show event distribution
+    /// </summary>
+    private void LogEventDistribution()
+    {
+        if (!showDebugLogs) return;
+
+        var eventsByType = availableEvents.GroupBy(e => e.eventType);
+        foreach (var group in eventsByType)
+        {
+            Debug.Log($"📊 {group.Key}: {group.Count()} events");
+        }
+    }
+
+    /// <summary>
+    /// Public method to trigger event check manually (for testing)
+    /// </summary>
+    [ContextMenu("Trigger Event Check")]
+    public void TriggerEventCheck()
+    {
+        forceNextEvent = true;
+        CheckForTravelEvent();
+    }
+
+    /// <summary>
+    /// Reset event history (useful for testing)
+    /// </summary>
+    [ContextMenu("Reset Event History")]
+    public void ResetEventHistory()
+    {
+        globalEventHistory = new TravelEventHistory();
+        tilesTraveledSinceLastCheck = 0;
+        Debug.Log("🔄 Event history reset");
+    }
+}

+ 249 - 0
Assets/Scripts/Events/TravelEventSystemSetup.cs

@@ -0,0 +1,249 @@
+using UnityEngine;
+
+/// <summary>
+/// Setup script to easily add the Travel Event System to your existing travel setup
+/// This component should be added to the same GameObject as TeamTravelSystem
+/// </summary>
+public class TravelEventSystemSetup : MonoBehaviour
+{
+    [Header("Event System Setup")]
+    [Tooltip("Automatically create and configure the travel event system")]
+    public bool autoSetupEventSystem = true;
+
+    [Header("Event Configuration")]
+    [Range(0f, 1f)]
+    [Tooltip("Base chance for events to occur (15% recommended)")]
+    public float eventChance = 0.15f;
+
+    [Range(1, 10)]
+    [Tooltip("Check for events every N tiles traveled")]
+    public int tilesPerCheck = 3;
+
+    [Tooltip("Enable debug logging for events")]
+    public bool enableDebugLogs = true;
+
+    [Header("Default Events")]
+    [Tooltip("Create default ScriptableObject events automatically")]
+    public bool createDefaultEvents = true;
+
+    void Start()
+    {
+        if (autoSetupEventSystem)
+        {
+            SetupEventSystem();
+        }
+    }
+
+    [ContextMenu("Setup Event System")]
+    public void SetupEventSystem()
+    {
+        // Check if TravelEventSystem already exists
+        TravelEventSystem existingSystem = GetComponent<TravelEventSystem>();
+        if (existingSystem != null)
+        {
+            Debug.Log("✅ TravelEventSystem already exists on this GameObject");
+            ConfigureExistingSystem(existingSystem);
+            return;
+        }
+
+        // Add TravelEventSystem component
+        TravelEventSystem eventSystem = gameObject.AddComponent<TravelEventSystem>();
+
+        // Configure the system
+        eventSystem.enableEvents = true;
+        eventSystem.baseEventChance = eventChance;
+        eventSystem.tilesPerEventCheck = tilesPerCheck;
+        eventSystem.showDebugLogs = enableDebugLogs;
+
+        Debug.Log("✅ TravelEventSystem added and configured");
+
+        // Create default events if requested
+        if (createDefaultEvents)
+        {
+            CreateDefaultEventAssets();
+        }
+
+        // Verify integration
+        VerifyIntegration();
+    }
+
+    private void ConfigureExistingSystem(TravelEventSystem eventSystem)
+    {
+        eventSystem.baseEventChance = eventChance;
+        eventSystem.tilesPerEventCheck = tilesPerCheck;
+        eventSystem.showDebugLogs = enableDebugLogs;
+
+        Debug.Log("🔧 Updated existing TravelEventSystem configuration");
+    }
+
+    [ContextMenu("Create Default Events")]
+    public void CreateDefaultEventAssets()
+    {
+        // This would create ScriptableObject assets in the Resources folder
+        // For now, we'll just log what would be created
+
+        string[] defaultEvents = {
+            "Forest Ambush Event",
+            "Mountain Ambush Event",
+            "Traveling Merchant Event",
+            "Road Patrol Event",
+            "Hidden Cache Event",
+            "Wild Animal Event",
+            "Rest Site Event",
+            "Weather Hazard Event"
+        };
+
+        Debug.Log("📦 Default events that should be created:");
+        foreach (string eventName in defaultEvents)
+        {
+            Debug.Log($"   - {eventName}");
+        }
+
+        Debug.Log("💡 To create these events:");
+        Debug.Log("   1. Right-click in Project window");
+        Debug.Log("   2. Go to Create > RPG > Travel Events");
+        Debug.Log("   3. Choose the event type you want");
+        Debug.Log("   4. Configure the event settings");
+        Debug.Log("   5. Add to the Available Events list in TravelEventSystem");
+    }
+
+    private void VerifyIntegration()
+    {
+        Debug.Log("🔍 Verifying Travel Event System Integration...");
+
+        // Check for required components
+        TeamTravelSystem travelSystem = GetComponent<TeamTravelSystem>();
+        if (travelSystem == null)
+        {
+            Debug.LogError("❌ TeamTravelSystem not found! TravelEventSystem requires TeamTravelSystem on the same GameObject.");
+            return;
+        }
+
+        SimpleTeamPlacement teamPlacement = FindFirstObjectByType<SimpleTeamPlacement>();
+        if (teamPlacement == null)
+        {
+            Debug.LogWarning("⚠️ SimpleTeamPlacement not found in scene. Events may not work properly.");
+        }
+
+        MapMaker2 mapMaker = FindFirstObjectByType<MapMaker2>();
+        if (mapMaker == null)
+        {
+            Debug.LogWarning("⚠️ MapMaker2 not found in scene. Events may not work properly.");
+        }
+
+        TravelEventSystem eventSystem = GetComponent<TravelEventSystem>();
+        if (eventSystem != null && eventSystem.availableEvents.Count == 0)
+        {
+            Debug.LogWarning("⚠️ No events assigned to TravelEventSystem. Create and assign travel events for the system to work.");
+        }
+
+        Debug.Log("✅ Integration verification complete");
+    }
+
+    [ContextMenu("Test Event System")]
+    public void TestEventSystem()
+    {
+        TravelEventSystem eventSystem = GetComponent<TravelEventSystem>();
+        if (eventSystem == null)
+        {
+            Debug.LogError("❌ No TravelEventSystem found. Run Setup Event System first.");
+            return;
+        }
+
+        Debug.Log("🎲 Testing travel event system...");
+        eventSystem.TriggerEventCheck();
+    }
+
+    void OnValidate()
+    {
+        // Clamp values
+        eventChance = Mathf.Clamp01(eventChance);
+        tilesPerCheck = Mathf.Clamp(tilesPerCheck, 1, 10);
+    }
+}
+
+/// <summary>
+/// Helper script to create example travel events for testing
+/// Add this to any GameObject to quickly create test events
+/// </summary>
+public class TravelEventExampleCreator : MonoBehaviour
+{
+    [ContextMenu("Create Example Events")]
+    public void CreateExampleEvents()
+    {
+        Debug.Log("🎭 Creating example travel events...");
+
+        // This demonstrates how to create events at runtime for testing
+        CreateExampleAmbushEvent();
+        CreateExampleMerchantEvent();
+        CreateExampleDiscoveryEvent();
+
+        Debug.Log("✅ Example events created. Check the TravelEventSystem component.");
+    }
+
+    private void CreateExampleAmbushEvent()
+    {
+        var ambushEvent = ScriptableObject.CreateInstance<CombatTravelEvent>();
+        ambushEvent.eventName = "Test Forest Ambush";
+        ambushEvent.eventDescription = "A test ambush event for debugging";
+        ambushEvent.eventType = EventType.Combat;
+        ambushEvent.rarity = EventRarity.Common;
+
+        // Set terrain preferences
+        ambushEvent.forestChance = 0.9f;
+        ambushEvent.roadChance = 0.2f;
+        ambushEvent.townChance = 0.1f;
+
+        // Add to event system if available
+        TravelEventSystem eventSystem = FindFirstObjectByType<TravelEventSystem>();
+        if (eventSystem != null)
+        {
+            eventSystem.availableEvents.Add(ambushEvent);
+            Debug.Log("➕ Added test ambush event");
+        }
+    }
+
+    private void CreateExampleMerchantEvent()
+    {
+        var merchantEvent = ScriptableObject.CreateInstance<TradingTravelEvent>();
+        merchantEvent.eventName = "Test Traveling Merchant";
+        merchantEvent.eventDescription = "A test merchant event for debugging";
+        merchantEvent.eventType = EventType.Trading;
+        merchantEvent.rarity = EventRarity.Common;
+
+        // Set terrain preferences
+        merchantEvent.roadChance = 0.8f;
+        merchantEvent.townChance = 0.7f;
+        merchantEvent.forestChance = 0.3f;
+
+        // Add to event system if available
+        TravelEventSystem eventSystem = FindFirstObjectByType<TravelEventSystem>();
+        if (eventSystem != null)
+        {
+            eventSystem.availableEvents.Add(merchantEvent);
+            Debug.Log("➕ Added test merchant event");
+        }
+    }
+
+    private void CreateExampleDiscoveryEvent()
+    {
+        var discoveryEvent = ScriptableObject.CreateInstance<DiscoveryTravelEvent>();
+        discoveryEvent.eventName = "Test Hidden Treasure";
+        discoveryEvent.eventDescription = "A test discovery event for debugging";
+        discoveryEvent.eventType = EventType.Discovery;
+        discoveryEvent.rarity = EventRarity.Uncommon;
+
+        // Set terrain preferences
+        discoveryEvent.forestChance = 0.7f;
+        discoveryEvent.mountainChance = 0.8f;
+        discoveryEvent.roadChance = 0.2f;
+
+        // Add to event system if available
+        TravelEventSystem eventSystem = FindFirstObjectByType<TravelEventSystem>();
+        if (eventSystem != null)
+        {
+            eventSystem.availableEvents.Add(discoveryEvent);
+            Debug.Log("➕ Added test discovery event");
+        }
+    }
+}

+ 410 - 0
Assets/Scripts/Events/TravelEventTypes.cs

@@ -0,0 +1,410 @@
+using UnityEngine;
+
+/// <summary>
+/// Combat encounter events - ambushes, bandits, wild animals, etc.
+/// More likely in forests and mountains, less likely on roads
+/// </summary>
+[CreateAssetMenu(fileName = "New Combat Event", menuName = "RPG/Travel Events/Combat Event")]
+public class CombatTravelEvent : TravelEvent
+{
+    [Header("Combat Event Settings")]
+    public int minEnemies = 1;
+    public int maxEnemies = 3;
+    [Tooltip("Drag EnemyCharacterData assets here")]
+    public EnemyCharacterData[] possibleEnemies = new EnemyCharacterData[0];
+
+    [Header("Escape Configuration")]
+    public bool allowRunningAway = true;
+    [Range(0f, 1f)]
+    public float runAwaySuccessChance = 0.75f;
+    public int runAwayHealthPenalty = 5;
+
+    [Header("Run Away Messages")]
+    [TextArea(2, 4)]
+    public string[] successfulRunAwayMessages = {
+        "Your party successfully escapes from the enemies!",
+        "Quick thinking allows your party to avoid the confrontation!",
+        "Your party slips away unnoticed by the enemies."
+    };
+
+    [TextArea(2, 4)]
+    public string[] failedRunAwayMessages = {
+        "The enemies catch up to your party! You take {damage} damage while trying to escape.",
+        "Your escape attempt fails! The enemies pursue and wound your party for {damage} damage.",
+        "The enemies block your escape route! Your party suffers {damage} damage in the failed attempt."
+    };
+
+    [Header("Combat Event Descriptions")]
+    [TextArea(2, 4)]
+    public string[] encounterDescriptions = {
+        "Your party is ambushed by {enemyType}s!",
+        "A group of {enemyType}s blocks your path!",
+        "You stumble upon a {enemyType} camp!"
+    };
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        int enemyCount = Random.Range(minEnemies, maxEnemies + 1);
+
+        // Ensure we have valid enemies configured
+        if (possibleEnemies == null || possibleEnemies.Length == 0)
+        {
+            Debug.LogError($"No enemies configured for combat event: {eventName}");
+            return EventResult.NoEvent();
+        }
+
+        // Filter out null entries
+        var validEnemies = System.Array.FindAll(possibleEnemies, e => e != null);
+        if (validEnemies.Length == 0)
+        {
+            Debug.LogError($"All enemy references are null for combat event: {eventName}");
+            return EventResult.NoEvent();
+        }
+
+        // Select random enemy
+        EnemyCharacterData selectedEnemy = validEnemies[Random.Range(0, validEnemies.Length)];
+        string enemyType = selectedEnemy.enemyName;
+
+        // Generate description
+        string description = encounterDescriptions[Random.Range(0, encounterDescriptions.Length)];
+        description = description.Replace("{enemyType}", enemyType);
+
+        // Try to use combat event integration for popup choice
+        Debug.Log("🔍 Looking for CombatEventIntegration component...");
+
+        // First try to find it by component type
+        var integrationComponents = FindObjectsByType<MonoBehaviour>(FindObjectsSortMode.None);
+        var combatIntegration = System.Array.Find(integrationComponents,
+            comp => comp.GetType().Name == "CombatEventIntegration");
+
+        if (combatIntegration == null)
+        {
+            // Try the reflection approach as fallback
+            var type = System.Type.GetType("CombatEventIntegration");
+            if (type != null)
+            {
+                combatIntegration = FindFirstObjectByType(type) as MonoBehaviour;
+            }
+        }
+
+        if (combatIntegration != null)
+        {
+            Debug.Log($"✅ Found CombatEventIntegration: {combatIntegration.name}");
+
+            // Create battle data for the popup
+            var battleData = new BattleEventData
+            {
+                enemyCount = enemyCount,
+                enemyType = enemyType,
+                enemyCharacterData = selectedEnemy
+            };
+
+            // Use reflection to call ShowCombatChoicePopup with the new signature
+            var method = combatIntegration.GetType().GetMethod("ShowCombatChoicePopup");
+            if (method != null)
+            {
+                Debug.Log($"🎭 Calling ShowCombatChoicePopup with {enemyCount} {enemyType}(s) and combat event reference");
+                method.Invoke(combatIntegration, new object[] { battleData, context, description, this });
+
+                // Return a special result that indicates popup is handling the choice
+                return new EventResult("Combat encounter detected...")
+                {
+                    shouldStopTravel = true, // Stop travel while popup is showing
+                    startBattle = false, // Don't start battle yet - popup will handle it
+                    eventOccurred = true
+                };
+            }
+            else
+            {
+                Debug.LogError("❌ ShowCombatChoicePopup method not found on CombatEventIntegration");
+            }
+        }
+        else
+        {
+            Debug.LogWarning("⚠️ No CombatEventIntegration component found in scene");
+        }
+
+        // Fallback to immediate battle if no integration found
+        Debug.LogWarning("⚠️ No CombatEventIntegration found, proceeding with immediate battle");
+        var result = EventResult.SimpleBattle(description, enemyCount, enemyType);
+        result.battleData.enemyCharacterData = selectedEnemy;
+
+        return result;
+    }
+
+    /// <summary>
+    /// Handle escape attempt for this specific combat event
+    /// </summary>
+    public EventResult HandleEscapeAttempt(TravelEventContext context)
+    {
+        if (!allowRunningAway)
+        {
+            Debug.LogWarning($"🚫 Running away is not allowed for this combat event: {eventName}");
+            return null; // Force battle
+        }
+
+        Debug.Log($"🏃 Processing escape attempt for {eventName} (success chance: {runAwaySuccessChance:P})");
+
+        // Roll for escape success
+        bool escapeSuccessful = Random.value <= runAwaySuccessChance;
+
+        if (escapeSuccessful)
+        {
+            return CreateSuccessfulEscapeResult();
+        }
+        else
+        {
+            return CreateFailedEscapeResult(context);
+        }
+    }
+
+    /// <summary>
+    /// Create result for successful escape
+    /// </summary>
+    private EventResult CreateSuccessfulEscapeResult()
+    {
+        string message = successfulRunAwayMessages[Random.Range(0, successfulRunAwayMessages.Length)];
+        Debug.Log($"✅ Escape successful: {message}");
+
+        return new EventResult(message)
+        {
+            shouldStopTravel = false, // Don't stop travel for successful escape
+            startBattle = false,
+            eventOccurred = true
+        };
+    }
+
+    /// <summary>
+    /// Create result for failed escape
+    /// </summary>
+    private EventResult CreateFailedEscapeResult(TravelEventContext context)
+    {
+        string message = failedRunAwayMessages[Random.Range(0, failedRunAwayMessages.Length)];
+        message = message.Replace("{damage}", runAwayHealthPenalty.ToString());
+
+        Debug.Log($"❌ Escape failed: {message}");
+
+        var result = new EventResult(message)
+        {
+            shouldStopTravel = true, // Stop travel for failed escape
+            startBattle = false, // Don't start battle, just apply penalty
+            eventOccurred = true,
+            healthChange = -runAwayHealthPenalty // Apply health penalty through EventResult system
+        };
+
+        return result;
+    }
+
+    void OnEnable()
+    {
+        // Set default values for combat events
+        eventType = EventType.Combat;
+        rarity = EventRarity.Common;
+
+        // Combat events are more likely in dangerous terrain
+        forestChance = 0.8f;
+        mountainChance = 0.9f;
+        plainsChance = 0.4f;
+        roadChance = 0.2f; // Much less likely on roads
+        townChance = 0.1f; // Very unlikely in towns
+        villageChance = 0.3f;
+    }
+}
+
+/// <summary>
+/// Trading encounter events - merchants, traders, caravans
+/// More likely on roads and near settlements
+/// </summary>
+[CreateAssetMenu(fileName = "New Trading Event", menuName = "RPG/Travel Events/Trading Event")]
+public class TradingTravelEvent : TravelEvent
+{
+    [Header("Trading Event Settings")]
+    public string[] merchantTypes = { "Traveling Merchant", "Caravan Trader", "Wandering Peddler" };
+    public bool canHaveRareItems = true;
+    [Range(0f, 1f)]
+    public float rareItemChance = 0.3f;
+    [Range(0.5f, 1.5f)]
+    public float priceModifier = 1f;
+
+    [Header("Trading Event Descriptions")]
+    [TextArea(2, 4)]
+    public string[] encounterDescriptions = {
+        "You encounter a {merchantType} on the road.",
+        "A {merchantType} approaches your party with goods to sell.",
+        "You come across a {merchantType} resting by the roadside."
+    };
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        string merchantType = merchantTypes[Random.Range(0, merchantTypes.Length)];
+        string description = encounterDescriptions[Random.Range(0, encounterDescriptions.Length)];
+        description = description.Replace("{merchantType}", merchantType);
+
+        var result = EventResult.SimpleTrading(description, merchantType);
+        result.tradingData.hasRareItems = canHaveRareItems && Random.value < rareItemChance;
+        result.tradingData.priceModifier = priceModifier;
+
+        return result;
+    }
+
+    void OnEnable()
+    {
+        // Set default values for trading events
+        eventType = EventType.Trading;
+        rarity = EventRarity.Common;
+
+        // Trading events are more likely on roads and near settlements
+        roadChance = 0.9f;
+        townChance = 0.7f;
+        villageChance = 0.8f;
+        bridgeChance = 0.6f; // Common crossing points
+        ferryChance = 0.5f;
+
+        // Less likely in wilderness
+        forestChance = 0.3f;
+        mountainChance = 0.2f;
+        plainsChance = 0.5f;
+    }
+}
+
+/// <summary>
+/// Discovery events - finding treasures, resources, or hidden locations
+/// </summary>
+[CreateAssetMenu(fileName = "New Discovery Event", menuName = "RPG/Travel Events/Discovery Event")]
+public class DiscoveryTravelEvent : TravelEvent
+{
+    [Header("Discovery Settings")]
+    public int minGoldFound = 10;
+    public int maxGoldFound = 100;
+    public bool canFindItems = true;
+
+    [Header("Discovery Descriptions")]
+    [TextArea(2, 4)]
+    public string[] discoveryDescriptions = {
+        "Your party discovers a hidden cache containing {amount} gold!",
+        "While exploring, you find an abandoned stash with {amount} gold pieces.",
+        "A keen-eyed party member spots something valuable - {amount} gold!"
+    };
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        int goldFound = Random.Range(minGoldFound, maxGoldFound + 1);
+        string description = discoveryDescriptions[Random.Range(0, discoveryDescriptions.Length)];
+        description = description.Replace("{amount}", goldFound.ToString());
+
+        return new EventResult(description)
+        {
+            goldChange = goldFound
+        };
+    }
+
+    void OnEnable()
+    {
+        eventType = EventType.Discovery;
+        rarity = EventRarity.Uncommon;
+
+        // More likely in remote areas
+        forestChance = 0.7f;
+        mountainChance = 0.8f;
+        plainsChance = 0.4f;
+        roadChance = 0.3f;
+        townChance = 0.1f;
+    }
+}
+
+/// <summary>
+/// Rest events - safe camping spots, inns, healing springs
+/// </summary>
+[CreateAssetMenu(fileName = "New Rest Event", menuName = "RPG/Travel Events/Rest Event")]
+public class RestTravelEvent : TravelEvent
+{
+    [Header("Rest Settings")]
+    public int healthRestored = 25;
+    public bool restoresAllHealth = false;
+
+    [Header("Rest Descriptions")]
+    [TextArea(2, 4)]
+    public string[] restDescriptions = {
+        "Your party finds a peaceful grove perfect for resting and recovers {health} health.",
+        "A natural spring provides refreshing water, restoring {health} health to your party.",
+        "Your party discovers a safe camping spot and takes time to tend wounds, recovering {health} health."
+    };
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        int actualHealing = restoresAllHealth ? 100 : healthRestored;
+        string description = restDescriptions[Random.Range(0, restDescriptions.Length)];
+        description = description.Replace("{health}", actualHealing.ToString());
+
+        return new EventResult(description)
+        {
+            healthChange = actualHealing
+        };
+    }
+
+    void OnEnable()
+    {
+        eventType = EventType.Rest;
+        rarity = EventRarity.Common;
+
+        // More likely in natural areas
+        forestChance = 0.8f;
+        riverChance = 0.9f;
+        lakeChance = 0.9f;
+        plainsChance = 0.6f;
+        mountainChance = 0.5f;
+        roadChance = 0.4f;
+        townChance = 0.2f;
+    }
+}
+
+/// <summary>
+/// Hazard events - natural dangers, traps, environmental challenges
+/// </summary>
+[CreateAssetMenu(fileName = "New Hazard Event", menuName = "RPG/Travel Events/Hazard Event")]
+public class HazardTravelEvent : TravelEvent
+{
+    [Header("Hazard Settings")]
+    public int minHealthLoss = 5;
+    public int maxHealthLoss = 20;
+    public int goldCost = 0; // Cost to avoid the hazard
+
+    [Header("Hazard Descriptions")]
+    [TextArea(2, 4)]
+    public string[] hazardDescriptions = {
+        "Your party gets caught in a sudden rockslide, losing {damage} health.",
+        "Treacherous terrain causes injuries to your party members, resulting in {damage} health loss.",
+        "A hidden pit trap catches one of your party members, causing {damage} damage."
+    };
+
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        int damage = Random.Range(minHealthLoss, maxHealthLoss + 1);
+        string description = hazardDescriptions[Random.Range(0, hazardDescriptions.Length)];
+        description = description.Replace("{damage}", damage.ToString());
+
+        return new EventResult(description)
+        {
+            healthChange = -damage,
+            goldChange = -goldCost
+        };
+    }
+
+    void OnEnable()
+    {
+        eventType = EventType.Hazard;
+        rarity = EventRarity.Common;
+
+        // More likely in dangerous terrain
+        mountainChance = 0.9f;
+        forestChance = 0.6f;
+        riverChance = 0.7f;
+        oceanChance = 0.8f;
+
+        // Less likely in safe areas
+        roadChance = 0.2f;
+        townChance = 0.1f;
+        villageChance = 0.2f;
+        plainsChance = 0.4f;
+    }
+}

+ 284 - 0
Assets/Scripts/Events/TravelEventUI.cs

@@ -0,0 +1,284 @@
+using UnityEngine;
+using System.Collections;
+
+/// <summary>
+/// Simple UI manager for displaying travel event messages
+/// Integrates with your existing UI system to show event popups
+/// </summary>
+public class TravelEventUI : MonoBehaviour
+{
+    [Header("Event UI Settings")]
+    public bool useDebugUI = true; // Use simple debug UI for now
+    public float messageDisplayTime = 4f;
+    public KeyCode dismissKey = KeyCode.Space;
+
+    [Header("Event Message Queue")]
+    public int maxQueuedMessages = 5;
+
+    // Internal state
+    private System.Collections.Generic.Queue<EventMessage> messageQueue = new System.Collections.Generic.Queue<EventMessage>();
+    private bool isShowingMessage = false;
+    private EventMessage currentMessage;
+    private float messageTimer = 0f;
+
+    // UI Elements (for future implementation)
+    private Canvas eventCanvas;
+    private UnityEngine.UI.Text eventText;
+    private UnityEngine.UI.Button dismissButton;
+
+    [System.Serializable]
+    private class EventMessage
+    {
+        public string message;
+        public EventType eventType;
+        public float displayTime;
+        public bool requiresPlayerInput;
+
+        public EventMessage(string msg, EventType type, float time = 4f, bool requiresInput = false)
+        {
+            message = msg;
+            eventType = type;
+            displayTime = time;
+            requiresPlayerInput = requiresInput;
+        }
+    }
+
+    void Start()
+    {
+        SetupEventUI();
+    }
+
+    void Update()
+    {
+        HandleEventDisplay();
+        HandleInput();
+    }
+
+    /// <summary>
+    /// Show a travel event message to the player
+    /// </summary>
+    public void ShowEventMessage(string message, EventType eventType = EventType.Discovery, bool requiresInput = false)
+    {
+        if (string.IsNullOrEmpty(message)) return;
+
+        var eventMessage = new EventMessage(message, eventType, messageDisplayTime, requiresInput);
+
+        if (messageQueue.Count >= maxQueuedMessages)
+        {
+            Debug.LogWarning("⚠️ Event message queue full, discarding oldest message");
+            messageQueue.Dequeue();
+        }
+
+        messageQueue.Enqueue(eventMessage);
+
+        Debug.Log($"📜 Queued event message: {message}");
+    }
+
+    /// <summary>
+    /// Show an event result with appropriate formatting
+    /// </summary>
+    public void ShowEventResult(EventResult result)
+    {
+        if (result == null || !result.eventOccurred) return;
+
+        string message = result.resultMessage;
+
+        // Add resource change information to the message
+        if (result.goldChange != 0 || result.healthChange != 0 || result.foodChange != 0)
+        {
+            message += "\n\nEffects:";
+            if (result.goldChange > 0) message += $"\n💰 +{result.goldChange} Gold";
+            if (result.goldChange < 0) message += $"\n💰 {result.goldChange} Gold";
+            if (result.healthChange > 0) message += $"\n❤️ +{result.healthChange} Health";
+            if (result.healthChange < 0) message += $"\n❤️ {result.healthChange} Health";
+            if (result.foodChange > 0) message += $"\n🍖 +{result.foodChange} Food";
+            if (result.foodChange < 0) message += $"\n🍖 {result.foodChange} Food";
+        }
+
+        // Determine event type based on result
+        EventType eventType = EventType.Discovery;
+        if (result.startBattle) eventType = EventType.Combat;
+        else if (result.openTrading) eventType = EventType.Trading;
+        else if (result.healthChange < 0) eventType = EventType.Hazard;
+        else if (result.healthChange > 0) eventType = EventType.Rest;
+
+        bool requiresInput = result.shouldStopTravel || result.startBattle || result.openTrading;
+
+        ShowEventMessage(message, eventType, requiresInput);
+    }
+
+    private void SetupEventUI()
+    {
+        if (useDebugUI)
+        {
+            // For now, we'll use the debug console
+            Debug.Log("🖥️ Travel Event UI initialized (Debug Mode)");
+            return;
+        }
+
+        // TODO: Set up proper UI elements
+        // This would create or find UI canvas, text elements, buttons, etc.
+        // For integration with your existing UI system
+    }
+
+    private void HandleEventDisplay()
+    {
+        // Start showing next message if not currently showing one
+        if (!isShowingMessage && messageQueue.Count > 0)
+        {
+            currentMessage = messageQueue.Dequeue();
+            isShowingMessage = true;
+            messageTimer = 0f;
+            DisplayCurrentMessage();
+        }
+
+        // Handle message timing
+        if (isShowingMessage && currentMessage != null)
+        {
+            messageTimer += Time.deltaTime;
+
+            // Auto-dismiss if time expires and no input required
+            if (!currentMessage.requiresPlayerInput && messageTimer >= currentMessage.displayTime)
+            {
+                DismissCurrentMessage();
+            }
+        }
+    }
+
+    private void HandleInput()
+    {
+        if (!isShowingMessage || currentMessage == null) return;
+
+        // Handle dismiss input
+        if (Input.GetKeyDown(dismissKey))
+        {
+            DismissCurrentMessage();
+        }
+
+        // Handle other event-specific inputs
+        if (currentMessage.requiresPlayerInput)
+        {
+            // TODO: Handle specific event choices (Accept/Decline trade, etc.)
+        }
+    }
+
+    private void DisplayCurrentMessage()
+    {
+        if (currentMessage == null) return;
+
+        if (useDebugUI)
+        {
+            string prefix = GetEventTypePrefix(currentMessage.eventType);
+            Debug.Log($"{prefix} {currentMessage.message}");
+
+            if (currentMessage.requiresPlayerInput)
+            {
+                Debug.Log($"💡 Press {dismissKey} to continue...");
+            }
+        }
+        else
+        {
+            // TODO: Display in proper UI
+            // Set text content, show panel, animate, etc.
+        }
+    }
+
+    private void DismissCurrentMessage()
+    {
+        if (currentMessage == null) return;
+
+        Debug.Log($"✅ Event message dismissed: {currentMessage.eventType}");
+
+        currentMessage = null;
+        isShowingMessage = false;
+        messageTimer = 0f;
+
+        if (!useDebugUI)
+        {
+            // TODO: Hide UI elements, animate out, etc.
+        }
+    }
+
+    private string GetEventTypePrefix(EventType eventType)
+    {
+        return eventType switch
+        {
+            EventType.Combat => "⚔️ COMBAT:",
+            EventType.Trading => "🛒 TRADING:",
+            EventType.Discovery => "💎 DISCOVERY:",
+            EventType.Social => "👥 ENCOUNTER:",
+            EventType.Hazard => "⚠️ HAZARD:",
+            EventType.Rest => "🏕️ REST:",
+            EventType.Mystery => "❓ MYSTERY:",
+            _ => "📜 EVENT:"
+        };
+    }
+
+    /// <summary>
+    /// Clear all queued messages
+    /// </summary>
+    public void ClearMessages()
+    {
+        messageQueue.Clear();
+        if (isShowingMessage)
+        {
+            DismissCurrentMessage();
+        }
+        Debug.Log("🧹 Event message queue cleared");
+    }
+
+    /// <summary>
+    /// Check if the UI is currently showing a message that requires input
+    /// </summary>
+    public bool IsWaitingForInput()
+    {
+        return isShowingMessage && currentMessage != null && currentMessage.requiresPlayerInput;
+    }
+
+    /// <summary>
+    /// Get the number of queued messages
+    /// </summary>
+    public int GetQueuedMessageCount()
+    {
+        return messageQueue.Count;
+    }
+
+    void OnGUI()
+    {
+        if (!useDebugUI || !isShowingMessage || currentMessage == null) return;
+
+        // Simple on-screen display for debugging
+        GUIStyle style = new GUIStyle(GUI.skin.box);
+        style.fontSize = 16;
+        style.wordWrap = true;
+        style.alignment = TextAnchor.MiddleCenter;
+
+        // Background box
+        float boxWidth = Screen.width * 0.6f;
+        float boxHeight = Screen.height * 0.3f;
+        float boxX = (Screen.width - boxWidth) * 0.5f;
+        float boxY = (Screen.height - boxHeight) * 0.5f;
+
+        GUI.Box(new Rect(boxX, boxY, boxWidth, boxHeight), "", style);
+
+        // Event message
+        GUIStyle textStyle = new GUIStyle(GUI.skin.label);
+        textStyle.fontSize = 14;
+        textStyle.wordWrap = true;
+        textStyle.alignment = TextAnchor.MiddleCenter;
+        textStyle.normal.textColor = Color.white;
+
+        string displayText = currentMessage.message;
+        if (currentMessage.requiresPlayerInput)
+        {
+            displayText += $"\n\n[Press {dismissKey} to continue]";
+        }
+        else
+        {
+            float timeLeft = currentMessage.displayTime - messageTimer;
+            displayText += $"\n\n(Auto-dismiss in {timeLeft:F1}s)";
+        }
+
+        GUI.Label(new Rect(boxX + 10, boxY + 10, boxWidth - 20, boxHeight - 20), displayText, textStyle);
+    }
+}

+ 13 - 2
Assets/Scripts/Map/TeamTravelSystem.cs

@@ -66,6 +66,7 @@ public class TeamTravelSystem : MonoBehaviour
     private MapMaker2 mapMaker;
     private Camera mapCamera;
     private TravelUI travelUI;
+    private CombatEventPopupUXML combatEventPopup;
 
     // Travel state
     private Vector2Int? plannedDestination;
@@ -109,6 +110,7 @@ public class TeamTravelSystem : MonoBehaviour
         mapMaker = FindFirstObjectByType<MapMaker2>();
         mapCamera = Camera.main;
         travelUI = FindFirstObjectByType<TravelUI>();
+        combatEventPopup = FindFirstObjectByType<CombatEventPopupUXML>();
 
         // Initialize pathLineMaterial if not assigned
         if (pathLineMaterial == null)
@@ -169,6 +171,12 @@ public class TeamTravelSystem : MonoBehaviour
                 return; // Block map interaction if clicking within UI panel
             }
 
+            // Check if click is within the combat popup bounds
+            if (combatEventPopup != null && combatEventPopup.IsVisible && combatEventPopup.IsPointWithinUI(Input.mousePosition))
+            {
+                return; // Block map interaction if clicking within combat popup
+            }
+
             Vector3 mouseWorldPos = GetMouseWorldPosition();
 
             if (mouseWorldPos != Vector3.zero)
@@ -1715,8 +1723,11 @@ public class TeamTravelSystem : MonoBehaviour
     /// </summary>
     private bool IsTravelUIBlocking()
     {
-        // Direct check instead of reflection since TravelUI is now available
-        return travelUI != null && travelUI.IsUIBlocking();
+        // Check both travel UI and combat popup for blocking input
+        bool travelUIBlocking = travelUI != null && travelUI.IsUIBlocking();
+        bool combatPopupBlocking = combatEventPopup != null && combatEventPopup.IsVisible;
+
+        return travelUIBlocking || combatPopupBlocking;
     }
 
     private void ShowTravelUIIfAvailable(Vector2Int destination, List<TravelRoute> routes)

+ 3 - 0
Assets/Scripts/Objects/Items/WeaponItem.cs

@@ -14,6 +14,9 @@ public class WeaponItem : Item
 
     [Header("Weapon Behavior")]
     public string weaponClassName; // The class name to instantiate (e.g., "SimpleSword", "SimpleBow")
+
+    [Header("Weapon Prefabs")]
+    public GameObject weaponPrefab; // 3D model prefab for the weapon
     public GameObject arrowPrefab; // For ranged weapons
 
     public WeaponItem()

+ 33 - 0
Assets/Scripts/Objects/Weapons/Club.asset

@@ -0,0 +1,33 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3f3fc2d34ad47104ea60fdf8fa56b9e6, type: 3}
+  m_Name: Club
+  m_EditorClassIdentifier: 
+  itemName: Wooden club
+  description: A Basic wooden club, heavy and crushing
+  icon: {fileID: 0}
+  model3D: {fileID: 0}
+  itemType: 0
+  rarity: 0
+  goldCost: 5
+  silverCost: 0
+  copperCost: 0
+  searchTags: []
+  minDamage: 1
+  maxDamage: 6
+  range: 0
+  weaponModifier: 0
+  attackSpeed: 2
+  weaponType: 0
+  weaponClassName: 
+  weaponPrefab: {fileID: 0}
+  arrowPrefab: {fileID: 0}

+ 34 - 0
Assets/Scripts/Objects/Weapons/Dagger.asset

@@ -0,0 +1,34 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3f3fc2d34ad47104ea60fdf8fa56b9e6, type: 3}
+  m_Name: Dagger
+  m_EditorClassIdentifier: 
+  itemName: Dagger
+  description: Simple dagger
+  icon: {fileID: 0}
+  model3D: {fileID: 0}
+  itemType: 0
+  rarity: 0
+  goldCost: 5
+  silverCost: 0
+  copperCost: 0
+  searchTags:
+  - dagger
+  minDamage: 1
+  maxDamage: 4
+  range: 0
+  weaponModifier: 0
+  attackSpeed: 0.5
+  weaponType: 3
+  weaponClassName: 
+  weaponPrefab: {fileID: 0}
+  arrowPrefab: {fileID: 0}

+ 32 - 0
Assets/Scripts/Objects/Weapons/SimpleBow.asset

@@ -0,0 +1,32 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3f3fc2d34ad47104ea60fdf8fa56b9e6, type: 3}
+  m_Name: SimpleBow
+  m_EditorClassIdentifier: 
+  itemName: Basic Bow
+  description: A Simple wooden bow
+  icon: {fileID: 0}
+  model3D: {fileID: 5410050047777400374, guid: e0447dc7b412ede4b9090f9a3cf4fdd4, type: 3}
+  itemType: 0
+  rarity: 0
+  goldCost: 15
+  silverCost: 0
+  copperCost: 0
+  searchTags: []
+  minDamage: 1
+  maxDamage: 6
+  range: 100
+  weaponModifier: 0
+  attackSpeed: 2
+  weaponType: 0
+  weaponClassName: 
+  arrowPrefab: {fileID: 6456274890147168025, guid: 74d688b6c70543e46a9b3ea3c4c8e787, type: 3}

+ 33 - 0
Assets/Scripts/Objects/Weapons/SimpleSword.asset

@@ -0,0 +1,33 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 3f3fc2d34ad47104ea60fdf8fa56b9e6, type: 3}
+  m_Name: SimpleSword
+  m_EditorClassIdentifier: 
+  itemName: Basic Sword
+  description: A common simple sword
+  icon: {fileID: 0}
+  model3D: {fileID: 5410050047777400374, guid: 2e07955f8c531dc4ea65c9d6a521f306, type: 3}
+  itemType: 0
+  rarity: 0
+  goldCost: 10
+  silverCost: 0
+  copperCost: 0
+  searchTags:
+  - sword
+  minDamage: 1
+  maxDamage: 6
+  range: 0
+  weaponModifier: 0
+  attackSpeed: 1
+  weaponType: 0
+  weaponClassName: 
+  arrowPrefab: {fileID: 0}

+ 510 - 0
Assets/Scripts/UI/CombatEventPopup.cs

@@ -0,0 +1,510 @@
+using UnityEngine;
+using UnityEngine.UIElements;
+using System.Collections.Generic;
+using System.Linq;
+
+/// <summary>
+/// Beautiful UI popup for combat event encounters
+/// Shows enemy details and provides options to attack or run away
+/// </summary>
+public class CombatEventPopup : MonoBehaviour
+{
+    [Header("UI References")]
+    public UIDocument uiDocument;
+    public VisualTreeAsset popupTemplate;
+
+    [Header("Popup Settings")]
+    public float animationDuration = 0.3f;
+    public float backgroundBlurIntensity = 0.5f;
+
+    // Events
+    public System.Action<bool> OnCombatDecision; // true = attack, false = run away
+
+    // UI Elements
+    private VisualElement popupContainer;
+    private VisualElement backgroundOverlay;
+    private VisualElement popupPanel;
+    private Label eventTitleLabel;
+    private Label eventDescriptionLabel;
+    private VisualElement enemyListContainer;
+    private Button attackButton;
+    private Button runAwayButton;
+    private VisualElement popupContent;
+
+    // Current combat data
+    private BattleEventData currentBattleData;
+    private TravelEventContext currentContext;
+    private bool isPopupActive = false;
+
+    void Awake()
+    {
+        // Find UI Document if not assigned
+        if (uiDocument == null)
+            uiDocument = GetComponent<UIDocument>();
+
+        if (uiDocument == null)
+        {
+            Debug.LogError("CombatEventPopup: No UIDocument found! Please assign one.");
+            return;
+        }
+
+        SetupUI();
+    }
+
+    void SetupUI()
+    {
+        var root = uiDocument.rootVisualElement;
+
+        // Create main popup container
+        popupContainer = new VisualElement();
+        popupContainer.name = "combat-event-popup";
+        popupContainer.AddToClassList("combat-popup-container");
+        popupContainer.style.display = DisplayStyle.None;
+        popupContainer.style.position = Position.Absolute;
+        popupContainer.style.top = 0;
+        popupContainer.style.left = 0;
+        popupContainer.style.right = 0;
+        popupContainer.style.bottom = 0;
+        popupContainer.style.justifyContent = Justify.Center;
+        popupContainer.style.alignItems = Align.Center;
+
+        // Background overlay
+        backgroundOverlay = new VisualElement();
+        backgroundOverlay.name = "background-overlay";
+        backgroundOverlay.AddToClassList("combat-popup-overlay");
+        backgroundOverlay.style.position = Position.Absolute;
+        backgroundOverlay.style.top = 0;
+        backgroundOverlay.style.left = 0;
+        backgroundOverlay.style.right = 0;
+        backgroundOverlay.style.bottom = 0;
+        backgroundOverlay.style.backgroundColor = new Color(0, 0, 0, 0.7f);
+
+        // Main popup panel
+        popupPanel = new VisualElement();
+        popupPanel.name = "popup-panel";
+        popupPanel.AddToClassList("combat-popup-panel");
+        popupPanel.style.backgroundColor = new Color(0.15f, 0.15f, 0.2f, 0.95f);
+        popupPanel.style.borderLeftColor = new Color(0.8f, 0.2f, 0.2f, 1f);
+        popupPanel.style.borderRightColor = new Color(0.8f, 0.2f, 0.2f, 1f);
+        popupPanel.style.borderTopColor = new Color(0.8f, 0.2f, 0.2f, 1f);
+        popupPanel.style.borderBottomColor = new Color(0.8f, 0.2f, 0.2f, 1f);
+        popupPanel.style.borderLeftWidth = 3;
+        popupPanel.style.borderRightWidth = 3;
+        popupPanel.style.borderTopWidth = 3;
+        popupPanel.style.borderBottomWidth = 3;
+        popupPanel.style.borderTopLeftRadius = 10;
+        popupPanel.style.borderTopRightRadius = 10;
+        popupPanel.style.borderBottomLeftRadius = 10;
+        popupPanel.style.borderBottomRightRadius = 10;
+        popupPanel.style.minWidth = 400;
+        popupPanel.style.maxWidth = 600;
+        popupPanel.style.paddingTop = 20;
+        popupPanel.style.paddingBottom = 20;
+        popupPanel.style.paddingLeft = 20;
+        popupPanel.style.paddingRight = 20;
+
+        CreatePopupContent();
+
+        popupContainer.Add(backgroundOverlay);
+        popupContainer.Add(popupPanel);
+        root.Add(popupContainer);
+
+        // Setup event handlers
+        backgroundOverlay.RegisterCallback<ClickEvent>(OnBackgroundClick);
+        attackButton.clicked += OnAttackClicked;
+        runAwayButton.clicked += OnRunAwayClicked;
+    }
+
+    void CreatePopupContent()
+    {
+        // Title
+        eventTitleLabel = new Label("⚔️ COMBAT ENCOUNTER!");
+        eventTitleLabel.AddToClassList("combat-title");
+        eventTitleLabel.style.fontSize = 24;
+        eventTitleLabel.style.color = new Color(1f, 0.3f, 0.3f, 1f);
+        eventTitleLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
+        eventTitleLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
+        eventTitleLabel.style.marginBottom = 15;
+        popupPanel.Add(eventTitleLabel);
+
+        // Description
+        eventDescriptionLabel = new Label("Your party encounters hostile enemies!");
+        eventDescriptionLabel.AddToClassList("combat-description");
+        eventDescriptionLabel.style.fontSize = 16;
+        eventDescriptionLabel.style.color = Color.white;
+        eventDescriptionLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
+        eventDescriptionLabel.style.whiteSpace = WhiteSpace.Normal;
+        eventDescriptionLabel.style.marginBottom = 20;
+        popupPanel.Add(eventDescriptionLabel);
+
+        // Enemy list container
+        var enemySection = new VisualElement();
+        enemySection.AddToClassList("enemy-section");
+        enemySection.style.marginBottom = 25;
+
+        var enemyHeader = new Label("🛡️ ENEMIES");
+        enemyHeader.AddToClassList("enemy-header");
+        enemyHeader.style.fontSize = 18;
+        enemyHeader.style.color = new Color(1f, 0.8f, 0.2f, 1f);
+        enemyHeader.style.unityFontStyleAndWeight = FontStyle.Bold;
+        enemyHeader.style.unityTextAlign = TextAnchor.MiddleCenter;
+        enemyHeader.style.marginBottom = 10;
+        enemySection.Add(enemyHeader);
+
+        enemyListContainer = new VisualElement();
+        enemyListContainer.AddToClassList("enemy-list");
+        enemyListContainer.style.backgroundColor = new Color(0.1f, 0.1f, 0.15f, 0.8f);
+        enemyListContainer.style.borderTopLeftRadius = 5;
+        enemyListContainer.style.borderTopRightRadius = 5;
+        enemyListContainer.style.borderBottomLeftRadius = 5;
+        enemyListContainer.style.borderBottomRightRadius = 5;
+        enemyListContainer.style.paddingTop = 10;
+        enemyListContainer.style.paddingBottom = 10;
+        enemyListContainer.style.paddingLeft = 15;
+        enemyListContainer.style.paddingRight = 15;
+        enemySection.Add(enemyListContainer);
+
+        popupPanel.Add(enemySection);
+
+        // Button container
+        var buttonContainer = new VisualElement();
+        buttonContainer.AddToClassList("button-container");
+        buttonContainer.style.flexDirection = FlexDirection.Row;
+        buttonContainer.style.justifyContent = Justify.SpaceAround;
+        buttonContainer.style.marginTop = 20;
+
+        // Run Away button
+        runAwayButton = new Button();
+        runAwayButton.text = "🏃 RUN AWAY";
+        runAwayButton.AddToClassList("run-button");
+        runAwayButton.style.fontSize = 16;
+        runAwayButton.style.backgroundColor = new Color(0.6f, 0.6f, 0.1f, 1f);
+        runAwayButton.style.color = Color.white;
+        runAwayButton.style.borderTopLeftRadius = 8;
+        runAwayButton.style.borderTopRightRadius = 8;
+        runAwayButton.style.borderBottomLeftRadius = 8;
+        runAwayButton.style.borderBottomRightRadius = 8;
+        runAwayButton.style.paddingTop = 12;
+        runAwayButton.style.paddingBottom = 12;
+        runAwayButton.style.paddingLeft = 20;
+        runAwayButton.style.paddingRight = 20;
+        runAwayButton.style.minWidth = 120;
+
+        // Attack button
+        attackButton = new Button();
+        attackButton.text = "⚔️ ATTACK!";
+        attackButton.AddToClassList("attack-button");
+        attackButton.style.fontSize = 16;
+        attackButton.style.backgroundColor = new Color(0.8f, 0.2f, 0.2f, 1f);
+        attackButton.style.color = Color.white;
+        attackButton.style.borderTopLeftRadius = 8;
+        attackButton.style.borderTopRightRadius = 8;
+        attackButton.style.borderBottomLeftRadius = 8;
+        attackButton.style.borderBottomRightRadius = 8;
+        attackButton.style.paddingTop = 12;
+        attackButton.style.paddingBottom = 12;
+        attackButton.style.paddingLeft = 20;
+        attackButton.style.paddingRight = 20;
+        attackButton.style.minWidth = 120;
+
+        buttonContainer.Add(runAwayButton);
+        buttonContainer.Add(attackButton);
+        popupPanel.Add(buttonContainer);
+
+        // Add hover effects
+        SetupButtonHoverEffects();
+    }
+
+    void SetupButtonHoverEffects()
+    {
+        // Attack button hover effects
+        attackButton.RegisterCallback<MouseEnterEvent>(evt =>
+        {
+            attackButton.style.backgroundColor = new Color(1f, 0.3f, 0.3f, 1f);
+            attackButton.style.scale = new Vector2(1.05f, 1.05f);
+        });
+
+        attackButton.RegisterCallback<MouseLeaveEvent>(evt =>
+        {
+            attackButton.style.backgroundColor = new Color(0.8f, 0.2f, 0.2f, 1f);
+            attackButton.style.scale = new Vector2(1f, 1f);
+        });
+
+        // Run away button hover effects
+        runAwayButton.RegisterCallback<MouseEnterEvent>(evt =>
+        {
+            runAwayButton.style.backgroundColor = new Color(0.7f, 0.7f, 0.2f, 1f);
+            runAwayButton.style.scale = new Vector2(1.05f, 1.05f);
+        });
+
+        runAwayButton.RegisterCallback<MouseLeaveEvent>(evt =>
+        {
+            runAwayButton.style.backgroundColor = new Color(0.6f, 0.6f, 0.1f, 1f);
+            runAwayButton.style.scale = new Vector2(1f, 1f);
+        });
+    }
+
+    /// <summary>
+    /// Show the combat popup with enemy details
+    /// </summary>
+    public void ShowCombatEncounter(BattleEventData battleData, TravelEventContext context, string eventDescription)
+    {
+        if (isPopupActive || battleData == null) return;
+
+        currentBattleData = battleData;
+        currentContext = context;
+        isPopupActive = true;
+
+        // Update content
+        eventDescriptionLabel.text = eventDescription;
+        UpdateEnemyList(battleData);
+
+        // Show popup with animation
+        popupContainer.style.display = DisplayStyle.Flex;
+        AnimatePopupIn();
+
+        Debug.Log($"🎭 Combat popup shown: {battleData.enemyCount} enemies");
+    }
+
+    void UpdateEnemyList(BattleEventData battleData)
+    {
+        enemyListContainer.Clear();
+
+        if (battleData.enemyCharacterData != null)
+        {
+            // Group enemies by type and count
+            var enemyGroups = new Dictionary<string, int>();
+            for (int i = 0; i < battleData.enemyCount; i++)
+            {
+                string enemyName = battleData.enemyCharacterData.enemyName;
+                if (enemyGroups.ContainsKey(enemyName))
+                    enemyGroups[enemyName]++;
+                else
+                    enemyGroups[enemyName] = 1;
+            }
+
+            // Create enemy display elements
+            foreach (var group in enemyGroups)
+            {
+                var enemyElement = CreateEnemyElement(group.Key, group.Value, battleData.enemyCharacterData);
+                enemyListContainer.Add(enemyElement);
+            }
+        }
+        else
+        {
+            // Fallback for legacy string-based enemies
+            var enemyElement = CreateFallbackEnemyElement(battleData.enemyType, battleData.enemyCount);
+            enemyListContainer.Add(enemyElement);
+        }
+    }
+
+    VisualElement CreateEnemyElement(string enemyName, int count, EnemyCharacterData enemyData)
+    {
+        var enemyContainer = new VisualElement();
+        enemyContainer.style.flexDirection = FlexDirection.Row;
+        enemyContainer.style.justifyContent = Justify.SpaceBetween;
+        enemyContainer.style.alignItems = Align.Center;
+        enemyContainer.style.marginBottom = 8;
+        enemyContainer.style.paddingTop = 8;
+        enemyContainer.style.paddingBottom = 8;
+        enemyContainer.style.paddingLeft = 10;
+        enemyContainer.style.paddingRight = 10;
+        enemyContainer.style.backgroundColor = new Color(0.2f, 0.2f, 0.25f, 0.6f);
+        enemyContainer.style.borderTopLeftRadius = 4;
+        enemyContainer.style.borderTopRightRadius = 4;
+        enemyContainer.style.borderBottomLeftRadius = 4;
+        enemyContainer.style.borderBottomRightRadius = 4;
+
+        // Enemy info section
+        var enemyInfo = new VisualElement();
+        enemyInfo.style.flexDirection = FlexDirection.Column;
+        enemyInfo.style.flexGrow = 1;
+
+        // Enemy name and count
+        var nameLabel = new Label($"{count}x {enemyName}");
+        nameLabel.style.fontSize = 16;
+        nameLabel.style.color = new Color(1f, 0.9f, 0.7f, 1f);
+        nameLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
+        enemyInfo.Add(nameLabel);
+
+        // Enemy stats
+        var statsLabel = new Label($"HP: {enemyData.maxHealth} | AC: {enemyData.armorClass} | Threat: {enemyData.threatLevel}");
+        statsLabel.style.fontSize = 12;
+        statsLabel.style.color = new Color(0.8f, 0.8f, 0.8f, 1f);
+        enemyInfo.Add(statsLabel);
+
+        // Weapon info
+        if (enemyData.preferredWeapon != null)
+        {
+            var weaponLabel = new Label($"⚔️ {enemyData.preferredWeapon.itemName}");
+            weaponLabel.style.fontSize = 11;
+            weaponLabel.style.color = new Color(0.7f, 0.7f, 1f, 1f);
+            enemyInfo.Add(weaponLabel);
+        }
+
+        enemyContainer.Add(enemyInfo);
+
+        // Threat level indicator
+        var threatIndicator = new VisualElement();
+        threatIndicator.style.width = 60;
+        threatIndicator.style.height = 20;
+        threatIndicator.style.borderTopLeftRadius = 10;
+        threatIndicator.style.borderTopRightRadius = 10;
+        threatIndicator.style.borderBottomLeftRadius = 10;
+        threatIndicator.style.borderBottomRightRadius = 10;
+        threatIndicator.style.justifyContent = Justify.Center;
+        threatIndicator.style.alignItems = Align.Center;
+
+        // Color based on threat level
+        Color threatColor = enemyData.threatLevel switch
+        {
+            <= 2 => new Color(0.3f, 0.8f, 0.3f, 1f), // Green - Easy
+            <= 4 => new Color(0.8f, 0.8f, 0.3f, 1f), // Yellow - Medium
+            <= 6 => new Color(0.9f, 0.5f, 0.2f, 1f), // Orange - Hard
+            _ => new Color(0.9f, 0.2f, 0.2f, 1f)      // Red - Very Hard
+        };
+
+        threatIndicator.style.backgroundColor = threatColor;
+
+        var threatLabel = new Label($"T{enemyData.threatLevel}");
+        threatLabel.style.fontSize = 11;
+        threatLabel.style.color = Color.white;
+        threatLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
+        threatIndicator.Add(threatLabel);
+
+        enemyContainer.Add(threatIndicator);
+
+        return enemyContainer;
+    }
+
+    VisualElement CreateFallbackEnemyElement(string enemyType, int count)
+    {
+        var enemyContainer = new VisualElement();
+        enemyContainer.style.flexDirection = FlexDirection.Row;
+        enemyContainer.style.justifyContent = Justify.SpaceBetween;
+        enemyContainer.style.alignItems = Align.Center;
+        enemyContainer.style.marginBottom = 8;
+        enemyContainer.style.paddingTop = 8;
+        enemyContainer.style.paddingBottom = 8;
+        enemyContainer.style.paddingLeft = 10;
+        enemyContainer.style.paddingRight = 10;
+        enemyContainer.style.backgroundColor = new Color(0.2f, 0.2f, 0.25f, 0.6f);
+        enemyContainer.style.borderTopLeftRadius = 4;
+        enemyContainer.style.borderTopRightRadius = 4;
+        enemyContainer.style.borderBottomLeftRadius = 4;
+        enemyContainer.style.borderBottomRightRadius = 4;
+
+        var nameLabel = new Label($"{count}x {enemyType}");
+        nameLabel.style.fontSize = 16;
+        nameLabel.style.color = new Color(1f, 0.9f, 0.7f, 1f);
+        nameLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
+
+        var unknownLabel = new Label("Unknown Threat");
+        unknownLabel.style.fontSize = 12;
+        unknownLabel.style.color = new Color(0.6f, 0.6f, 0.6f, 1f);
+
+        enemyContainer.Add(nameLabel);
+        enemyContainer.Add(unknownLabel);
+
+        return enemyContainer;
+    }
+
+    void AnimatePopupIn()
+    {
+        // Simple scale animation
+        popupPanel.style.scale = new Vector2(0.7f, 0.7f);
+        popupPanel.style.opacity = 0f;
+
+        // Use coroutine for smooth animation
+        StartCoroutine(AnimateScale(0.7f, 1f, 0f, 1f, animationDuration));
+    }
+
+    void AnimatePopupOut(System.Action onComplete = null)
+    {
+        StartCoroutine(AnimateScale(1f, 0.7f, 1f, 0f, animationDuration, () =>
+        {
+            popupContainer.style.display = DisplayStyle.None;
+            onComplete?.Invoke();
+        }));
+    }
+
+    System.Collections.IEnumerator AnimateScale(float fromScale, float toScale, float fromOpacity, float toOpacity, float duration, System.Action onComplete = null)
+    {
+        float elapsed = 0f;
+
+        while (elapsed < duration)
+        {
+            elapsed += Time.deltaTime;
+            float t = elapsed / duration;
+
+            // Smooth easing
+            t = t * t * (3f - 2f * t); // Smoothstep
+
+            float currentScale = Mathf.Lerp(fromScale, toScale, t);
+            float currentOpacity = Mathf.Lerp(fromOpacity, toOpacity, t);
+
+            popupPanel.style.scale = new Vector2(currentScale, currentScale);
+            popupPanel.style.opacity = currentOpacity;
+
+            yield return null;
+        }
+
+        popupPanel.style.scale = new Vector2(toScale, toScale);
+        popupPanel.style.opacity = toOpacity;
+
+        onComplete?.Invoke();
+    }
+
+    void OnBackgroundClick(ClickEvent evt)
+    {
+        // Optionally close popup when clicking background
+        // For now, we'll require explicit choice
+    }
+
+    void OnAttackClicked()
+    {
+        if (!isPopupActive) return;
+
+        Debug.Log("⚔️ Player chose to ATTACK!");
+        HidePopup(() =>
+        {
+            OnCombatDecision?.Invoke(true); // true = attack
+        });
+    }
+
+    void OnRunAwayClicked()
+    {
+        if (!isPopupActive) return;
+
+        Debug.Log("🏃 Player chose to RUN AWAY!");
+        HidePopup(() =>
+        {
+            OnCombatDecision?.Invoke(false); // false = run away
+        });
+    }
+
+    void HidePopup(System.Action onComplete = null)
+    {
+        if (!isPopupActive) return;
+
+        isPopupActive = false;
+        AnimatePopupOut(onComplete);
+    }
+
+    /// <summary>
+    /// Check if the popup is currently active
+    /// </summary>
+    public bool IsActive => isPopupActive;
+
+    /// <summary>
+    /// Force close the popup (for cleanup)
+    /// </summary>
+    public void ForceClose()
+    {
+        if (isPopupActive)
+        {
+            isPopupActive = false;
+            popupContainer.style.display = DisplayStyle.None;
+        }
+    }
+}

+ 620 - 0
Assets/Scripts/UI/CombatEventPopupUXML.cs

@@ -0,0 +1,620 @@
+using UnityEngine;
+using UnityEngine.UIElements;
+using System.Collections.Generic;
+using System.Linq;
+
+/// <summary>
+/// Beautiful UI popup for combat event encounters
+/// Shows enemy details and provides options to attack or run away
+/// Uses UXML template for cleaner UI structure
+/// </summary>
+public class CombatEventPopupUXML : MonoBehaviour
+{
+    [Header("UI References")]
+    public UIDocument uiDocument;
+    public VisualTreeAsset popupTemplate; // UXML template
+    public StyleSheet popupStyleSheet; // USS styles
+
+    [Header("Popup Settings")]
+    public float animationDuration = 0.3f;
+    public float backgroundBlurIntensity = 0.5f;
+
+    // Events
+    public System.Action<bool> OnCombatDecision; // true = attack, false = run away
+
+    // UI Elements (from UXML)
+    private VisualElement popupContainer;
+    private VisualElement backgroundOverlay;
+    private VisualElement popupPanel;
+    private Label eventTitleLabel;
+    private Label eventDescriptionLabel;
+    private VisualElement enemyListContainer;
+    private VisualElement enemyItemTemplate;
+    private Button attackButton;
+    private Button runAwayButton;
+
+    // Current combat data
+    private BattleEventData currentBattleData;
+    private TravelEventContext currentContext;
+    private bool isPopupActive = false;
+
+    void Awake()
+    {
+        // Find UI Document if not assigned
+        if (uiDocument == null)
+            uiDocument = GetComponent<UIDocument>();
+
+        if (uiDocument == null)
+        {
+            Debug.LogError("CombatEventPopupUXML: No UIDocument found! Please assign one.");
+            return;
+        }
+
+        SetupUI();
+    }
+
+    void SetupUI()
+    {
+        var root = uiDocument.rootVisualElement;
+        Debug.Log($"🔧 SetupUI: Root element size: {root.resolvedStyle.width}x{root.resolvedStyle.height}");
+
+        // Load and instantiate UXML template
+        if (popupTemplate != null)
+        {
+            // Clone the template
+            var template = popupTemplate.Instantiate();
+            root.Add(template);
+            Debug.Log($"✅ UXML template instantiated and added to root");
+
+            // Apply style sheet
+            if (popupStyleSheet != null)
+            {
+                root.styleSheets.Add(popupStyleSheet);
+                Debug.Log($"✅ USS stylesheet applied");
+            }
+            else
+            {
+                Debug.LogWarning("⚠️ No USS stylesheet assigned");
+            }
+        }
+        else
+        {
+            Debug.LogWarning("No UXML template assigned, creating UI programmatically as fallback");
+            CreateUIFallback(root);
+        }
+
+        // Cache UI element references
+        CacheUIElements(root);
+
+        // Setup event handlers
+        if (backgroundOverlay != null)
+        {
+            // Block all mouse events from reaching the map below
+            backgroundOverlay.RegisterCallback<ClickEvent>(OnBackgroundClick);
+            backgroundOverlay.RegisterCallback<MouseDownEvent>(OnBackgroundMouseDown);
+            backgroundOverlay.RegisterCallback<MouseUpEvent>(OnBackgroundMouseUp);
+            backgroundOverlay.RegisterCallback<MouseMoveEvent>(OnBackgroundMouseMove);
+            backgroundOverlay.RegisterCallback<WheelEvent>(OnBackgroundWheelEvent);
+        }
+
+        if (attackButton != null)
+            attackButton.clicked += OnAttackClicked;
+
+        if (runAwayButton != null)
+            runAwayButton.clicked += OnRunAwayClicked;
+
+        // Initially hide the popup
+        HidePopup();
+    }
+
+    void CacheUIElements(VisualElement root)
+    {
+        // Cache references to UI elements by name/class
+        popupContainer = root.Q<VisualElement>("combat-event-popup");
+        backgroundOverlay = root.Q<VisualElement>("background-overlay");
+        popupPanel = root.Q<VisualElement>("popup-panel");
+        eventTitleLabel = root.Q<Label>("event-title");
+        eventDescriptionLabel = root.Q<Label>("event-description");
+        enemyListContainer = root.Q<VisualElement>("enemy-list");
+        enemyItemTemplate = root.Q<VisualElement>("enemy-item-template");
+        attackButton = root.Q<Button>("attack-button");
+        runAwayButton = root.Q<Button>("run-away-button");
+
+        // Debug what we found
+        Debug.Log($"🔍 UI Elements found:");
+        Debug.Log($"   popupContainer: {(popupContainer != null ? "✅" : "❌")}");
+        Debug.Log($"   backgroundOverlay: {(backgroundOverlay != null ? "✅" : "❌")}");
+        Debug.Log($"   popupPanel: {(popupPanel != null ? "✅" : "❌")}");
+        Debug.Log($"   eventTitleLabel: {(eventTitleLabel != null ? "✅" : "❌")}");
+        Debug.Log($"   attackButton: {(attackButton != null ? "✅" : "❌")}");
+        Debug.Log($"   runAwayButton: {(runAwayButton != null ? "✅" : "❌")}");
+
+        // Hide the template
+        if (enemyItemTemplate != null)
+            enemyItemTemplate.style.display = DisplayStyle.None;
+
+        // Debug missing elements
+        if (popupContainer == null) Debug.LogError("Could not find 'combat-event-popup' element");
+        if (attackButton == null) Debug.LogError("Could not find 'attack-button' element");
+        if (runAwayButton == null) Debug.LogError("Could not find 'run-away-button' element");
+    }
+
+    /// <summary>
+    /// Fallback UI creation if UXML template is not available
+    /// </summary>
+    void CreateUIFallback(VisualElement root)
+    {
+        // Create basic popup structure programmatically
+        popupContainer = new VisualElement();
+        popupContainer.name = "combat-event-popup";
+        popupContainer.style.position = Position.Absolute;
+        popupContainer.style.top = 0;
+        popupContainer.style.left = 0;
+        popupContainer.style.right = 0;
+        popupContainer.style.bottom = 0;
+        popupContainer.style.justifyContent = Justify.Center;
+        popupContainer.style.alignItems = Align.Center;
+
+        backgroundOverlay = new VisualElement();
+        backgroundOverlay.name = "background-overlay";
+        backgroundOverlay.style.position = Position.Absolute;
+        backgroundOverlay.style.top = 0;
+        backgroundOverlay.style.left = 0;
+        backgroundOverlay.style.right = 0;
+        backgroundOverlay.style.bottom = 0;
+        backgroundOverlay.style.backgroundColor = new Color(0, 0, 0, 0.7f);
+
+        popupPanel = new VisualElement();
+        popupPanel.name = "popup-panel";
+        popupPanel.style.backgroundColor = new Color(0.15f, 0.15f, 0.2f, 0.95f);
+        popupPanel.style.borderTopLeftRadius = 10;
+        popupPanel.style.borderTopRightRadius = 10;
+        popupPanel.style.borderBottomLeftRadius = 10;
+        popupPanel.style.borderBottomRightRadius = 10;
+        popupPanel.style.minWidth = 400;
+        popupPanel.style.paddingTop = 20;
+        popupPanel.style.paddingBottom = 20;
+        popupPanel.style.paddingLeft = 20;
+        popupPanel.style.paddingRight = 20;
+
+        eventTitleLabel = new Label("*** COMBAT ENCOUNTER! ***");
+        eventTitleLabel.name = "event-title";
+        eventTitleLabel.style.fontSize = 24;
+        eventTitleLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
+
+        eventDescriptionLabel = new Label();
+        eventDescriptionLabel.name = "event-description";
+
+        enemyListContainer = new VisualElement();
+        enemyListContainer.name = "enemy-list";
+
+        var buttonContainer = new VisualElement();
+        buttonContainer.style.flexDirection = FlexDirection.Row;
+        buttonContainer.style.justifyContent = Justify.SpaceAround;
+        buttonContainer.style.marginTop = 20;
+
+        runAwayButton = new Button();
+        runAwayButton.name = "run-away-button";
+        runAwayButton.text = "[FLEE] RUN AWAY";
+
+        attackButton = new Button();
+        attackButton.name = "attack-button";
+        attackButton.text = "[FIGHT] ATTACK!";
+
+        // Assemble the UI
+        buttonContainer.Add(runAwayButton);
+        buttonContainer.Add(attackButton);
+
+        popupPanel.Add(eventTitleLabel);
+        popupPanel.Add(eventDescriptionLabel);
+        popupPanel.Add(enemyListContainer);
+        popupPanel.Add(buttonContainer);
+
+        popupContainer.Add(backgroundOverlay);
+        popupContainer.Add(popupPanel);
+        root.Add(popupContainer);
+    }
+
+    /// <summary>
+    /// Show the combat encounter popup with battle data
+    /// </summary>
+    public void ShowCombatEncounter(BattleEventData battleData, TravelEventContext context, string description)
+    {
+        if (isPopupActive)
+        {
+            Debug.LogWarning("Combat popup is already active!");
+            return;
+        }
+
+        currentBattleData = battleData;
+        currentContext = context;
+        isPopupActive = true;
+
+        Debug.Log($"🎭 Showing combat popup with {battleData.enemyCount} {battleData.enemyType}(s)");
+
+        // Update UI content
+        UpdatePopupContent(battleData, description);
+
+        // Show popup with animation
+        ShowPopup();
+    }
+
+    void UpdatePopupContent(BattleEventData battleData, string description)
+    {
+        // Update description
+        if (eventDescriptionLabel != null)
+            eventDescriptionLabel.text = description;
+
+        // Clear existing enemy items
+        if (enemyListContainer != null)
+        {
+            var existingItems = enemyListContainer.Children().Where(child =>
+                child.name != "enemy-item-template").ToList();
+
+            foreach (var item in existingItems)
+            {
+                enemyListContainer.Remove(item);
+            }
+
+            // Create enemy display items
+            CreateEnemyDisplays(battleData);
+        }
+    }
+
+    void CreateEnemyDisplays(BattleEventData battleData)
+    {
+        if (battleData.enemyCharacterData == null)
+        {
+            Debug.LogWarning("No enemy character data available for display");
+            return;
+        }
+
+        var enemyData = battleData.enemyCharacterData;
+
+        // Create enemy item element
+        VisualElement enemyItem;
+
+        if (enemyItemTemplate != null)
+        {
+            // Clone the template by creating a new instance from the UXML
+            enemyItem = CreateEnemyItemFromTemplate();
+        }
+        else
+        {
+            // Create manually if no template
+            enemyItem = CreateEnemyItemFallback();
+        }
+
+        // Update enemy information
+        var nameLabel = enemyItem.Q<Label>("enemy-name");
+        var statsLabel = enemyItem.Q<Label>("enemy-stats");
+        var weaponLabel = enemyItem.Q<Label>("enemy-weapon");
+        var threatIndicator = enemyItem.Q<VisualElement>("threat-indicator");
+        var threatLabel = enemyItem.Q<Label>("threat-label");
+
+        if (nameLabel != null)
+            nameLabel.text = $"{battleData.enemyCount}x {enemyData.enemyName}";
+
+        if (statsLabel != null)
+            statsLabel.text = $"HP: {enemyData.maxHealth} | AC: {enemyData.armorClass} | Threat: {enemyData.threatLevel}";
+
+        if (weaponLabel != null && enemyData.preferredWeapon != null)
+            weaponLabel.text = $"[WEAPON] {enemyData.preferredWeapon.itemName}";
+
+        // Update threat indicator
+        if (threatIndicator != null && threatLabel != null)
+        {
+            threatLabel.text = $"T{enemyData.threatLevel}";
+
+            // Remove existing threat classes
+            threatIndicator.RemoveFromClassList("threat-low");
+            threatIndicator.RemoveFromClassList("threat-medium");
+            threatIndicator.RemoveFromClassList("threat-high");
+            threatIndicator.RemoveFromClassList("threat-extreme");
+
+            // Add appropriate threat class
+            if (enemyData.threatLevel <= 2)
+                threatIndicator.AddToClassList("threat-low");
+            else if (enemyData.threatLevel <= 4)
+                threatIndicator.AddToClassList("threat-medium");
+            else if (enemyData.threatLevel <= 6)
+                threatIndicator.AddToClassList("threat-high");
+            else
+                threatIndicator.AddToClassList("threat-extreme");
+        }
+
+        // Add hover effect
+        enemyItem.RegisterCallback<MouseEnterEvent>(evt =>
+        {
+            enemyItem.AddToClassList("enemy-item-hover");
+        });
+
+        enemyItem.RegisterCallback<MouseLeaveEvent>(evt =>
+        {
+            enemyItem.RemoveFromClassList("enemy-item-hover");
+        });
+
+        enemyListContainer.Add(enemyItem);
+    }
+
+    VisualElement CreateEnemyItemFromTemplate()
+    {
+        // Create a new enemy item based on the template structure
+        var item = new VisualElement();
+        item.style.flexDirection = FlexDirection.Row;
+        item.style.justifyContent = Justify.SpaceBetween;
+        item.style.alignItems = Align.Center;
+        item.style.marginBottom = 8;
+        item.style.paddingTop = 8;
+        item.style.paddingBottom = 8;
+        item.style.paddingLeft = 10;
+        item.style.paddingRight = 10;
+        item.style.backgroundColor = new Color(0.2f, 0.2f, 0.25f, 0.6f);
+        item.style.borderTopLeftRadius = 4;
+        item.style.borderTopRightRadius = 4;
+        item.style.borderBottomLeftRadius = 4;
+        item.style.borderBottomRightRadius = 4;
+        item.AddToClassList("enemy-item");
+
+        // Enemy info container
+        var infoContainer = new VisualElement();
+        infoContainer.name = "enemy-info";
+        infoContainer.AddToClassList("enemy-info");
+        infoContainer.style.flexDirection = FlexDirection.Column;
+        infoContainer.style.flexGrow = 1;
+
+        // Enemy name label
+        var nameLabel = new Label();
+        nameLabel.name = "enemy-name";
+        nameLabel.AddToClassList("enemy-name");
+        nameLabel.style.fontSize = 16;
+        nameLabel.style.color = new Color(1f, 0.9f, 0.7f, 1f);
+
+        // Enemy stats label
+        var statsLabel = new Label();
+        statsLabel.name = "enemy-stats";
+        statsLabel.AddToClassList("enemy-stats");
+        statsLabel.style.fontSize = 12;
+        statsLabel.style.color = new Color(0.8f, 0.8f, 0.8f, 1f);
+
+        // Enemy weapon label
+        var weaponLabel = new Label();
+        weaponLabel.name = "enemy-weapon";
+        weaponLabel.AddToClassList("enemy-weapon");
+        weaponLabel.style.fontSize = 11;
+        weaponLabel.style.color = new Color(0.7f, 0.7f, 1f, 1f);
+
+        // Threat indicator
+        var threatIndicator = new VisualElement();
+        threatIndicator.name = "threat-indicator";
+        threatIndicator.AddToClassList("threat-indicator");
+        threatIndicator.style.width = 60;
+        threatIndicator.style.height = 20;
+        threatIndicator.style.borderTopLeftRadius = 10;
+        threatIndicator.style.borderTopRightRadius = 10;
+        threatIndicator.style.borderBottomLeftRadius = 10;
+        threatIndicator.style.borderBottomRightRadius = 10;
+        threatIndicator.style.justifyContent = Justify.Center;
+        threatIndicator.style.alignItems = Align.Center;
+        threatIndicator.style.backgroundColor = new Color(0.3f, 0.8f, 0.3f, 1f);
+
+        // Threat label
+        var threatLabel = new Label();
+        threatLabel.name = "threat-label";
+        threatLabel.AddToClassList("threat-label");
+        threatLabel.style.fontSize = 11;
+        threatLabel.style.color = Color.white;
+
+        // Assemble the structure
+        threatIndicator.Add(threatLabel);
+        infoContainer.Add(nameLabel);
+        infoContainer.Add(statsLabel);
+        infoContainer.Add(weaponLabel);
+        item.Add(infoContainer);
+        item.Add(threatIndicator);
+
+        return item;
+    }
+
+    VisualElement CreateEnemyItemFallback()
+    {
+        var item = new VisualElement();
+        item.style.flexDirection = FlexDirection.Row;
+        item.style.justifyContent = Justify.SpaceBetween;
+        item.style.alignItems = Align.Center;
+        item.style.marginBottom = 8;
+        item.style.paddingTop = 8;
+        item.style.paddingBottom = 8;
+        item.style.paddingLeft = 10;
+        item.style.paddingRight = 10;
+        item.style.backgroundColor = new Color(0.2f, 0.2f, 0.25f, 0.6f);
+        item.style.borderTopLeftRadius = 4;
+        item.style.borderTopRightRadius = 4;
+        item.style.borderBottomLeftRadius = 4;
+        item.style.borderBottomRightRadius = 4;
+
+        var infoContainer = new VisualElement();
+        infoContainer.name = "enemy-info";
+        infoContainer.style.flexDirection = FlexDirection.Column;
+        infoContainer.style.flexGrow = 1;
+
+        var nameLabel = new Label();
+        nameLabel.name = "enemy-name";
+        nameLabel.style.fontSize = 16;
+        nameLabel.style.color = new Color(1f, 0.9f, 0.7f, 1f);
+
+        var statsLabel = new Label();
+        statsLabel.name = "enemy-stats";
+        statsLabel.style.fontSize = 12;
+        statsLabel.style.color = new Color(0.8f, 0.8f, 0.8f, 1f);
+
+        var weaponLabel = new Label();
+        weaponLabel.name = "enemy-weapon";
+        weaponLabel.style.fontSize = 11;
+        weaponLabel.style.color = new Color(0.7f, 0.7f, 1f, 1f);
+
+        var threatIndicator = new VisualElement();
+        threatIndicator.name = "threat-indicator";
+        threatIndicator.style.width = 60;
+        threatIndicator.style.height = 20;
+        threatIndicator.style.borderTopLeftRadius = 10;
+        threatIndicator.style.borderTopRightRadius = 10;
+        threatIndicator.style.borderBottomLeftRadius = 10;
+        threatIndicator.style.borderBottomRightRadius = 10;
+        threatIndicator.style.justifyContent = Justify.Center;
+        threatIndicator.style.alignItems = Align.Center;
+        threatIndicator.style.backgroundColor = new Color(0.3f, 0.8f, 0.3f, 1f);
+
+        var threatLabel = new Label();
+        threatLabel.name = "threat-label";
+        threatLabel.style.fontSize = 11;
+        threatLabel.style.color = Color.white;
+
+        threatIndicator.Add(threatLabel);
+        infoContainer.Add(nameLabel);
+        infoContainer.Add(statsLabel);
+        infoContainer.Add(weaponLabel);
+        item.Add(infoContainer);
+        item.Add(threatIndicator);
+
+        return item;
+    }
+
+    void ShowPopup()
+    {
+        if (popupContainer != null)
+        {
+            Debug.Log($"🎭 ShowPopup: Setting display to Flex, current display: {popupContainer.style.display}");
+            popupContainer.style.display = DisplayStyle.Flex;
+
+            // Add animation classes
+            popupContainer.RemoveFromClassList("popup-hidden");
+            popupContainer.RemoveFromClassList("popup-exit");
+            popupContainer.AddToClassList("popup-enter");
+
+            // Check if UI Document is active and panel settings are configured
+            if (uiDocument != null && uiDocument.panelSettings != null)
+            {
+                Debug.Log($"✅ UIDocument active: {uiDocument.enabled}, Panel Settings: {uiDocument.panelSettings.name}");
+            }
+            else
+            {
+                Debug.LogError("❌ UIDocument or Panel Settings not configured properly!");
+            }
+
+            Debug.Log("✅ Combat popup displayed");
+        }
+        else
+        {
+            Debug.LogError("❌ Cannot show popup - popupContainer is null!");
+        }
+    }
+    public void HidePopup()
+    {
+        if (popupContainer != null)
+        {
+            // Add exit animation
+            popupContainer.RemoveFromClassList("popup-enter");
+            popupContainer.AddToClassList("popup-exit");
+
+            // Hide after animation
+            this.ExecuteAfterDelay(() =>
+            {
+                popupContainer.style.display = DisplayStyle.None;
+                popupContainer.AddToClassList("popup-hidden");
+            }, animationDuration);
+
+            isPopupActive = false;
+            Debug.Log("✅ Combat popup hidden");
+        }
+    }
+
+    void OnBackgroundClick(ClickEvent evt)
+    {
+        // Block the click event from reaching elements below
+        evt.StopPropagation();
+
+        // Optionally allow closing popup by clicking background
+        // Uncomment if you want this behavior:
+        // OnRunAwayClicked();
+    }
+
+    void OnBackgroundMouseDown(MouseDownEvent evt)
+    {
+        // Block mouse down events from reaching the map below
+        evt.StopPropagation();
+    }
+
+    void OnBackgroundMouseUp(MouseUpEvent evt)
+    {
+        // Block mouse up events from reaching the map below
+        evt.StopPropagation();
+    }
+
+    void OnBackgroundMouseMove(MouseMoveEvent evt)
+    {
+        // Block mouse move events from reaching the map below
+        evt.StopPropagation();
+    }
+
+    void OnBackgroundWheelEvent(WheelEvent evt)
+    {
+        // Block wheel/scroll events from reaching the map below
+        evt.StopPropagation();
+    }
+
+    void OnAttackClicked()
+    {
+        Debug.Log("🗡️ Player chose to ATTACK!");
+        HidePopup();
+        OnCombatDecision?.Invoke(true);
+    }
+
+    void OnRunAwayClicked()
+    {
+        Debug.Log("🏃 Player chose to RUN AWAY!");
+        HidePopup();
+        OnCombatDecision?.Invoke(false);
+    }
+
+    /// <summary>
+    /// Check if a screen position is within the UI bounds to block map interaction
+    /// </summary>
+    public bool IsPointWithinUI(Vector2 screenPosition)
+    {
+        if (!isPopupActive || popupContainer == null || uiDocument == null)
+        {
+            return false;
+        }
+
+        // Convert screen position to panel-relative position
+        Vector2 panelPosition = RuntimePanelUtils.ScreenToPanel(uiDocument.rootVisualElement.panel, screenPosition);
+
+        // Check if the position is within the popup container bounds
+        bool withinBounds = popupContainer.worldBound.Contains(panelPosition);
+
+        return withinBounds;
+    }
+
+    /// <summary>
+    /// Public getters for external access
+    /// </summary>
+    public bool IsVisible => isPopupActive;
+}
+
+/// <summary>
+/// Extension method for delayed execution
+/// </summary>
+public static class MonoBehaviourExtensions
+{
+    public static void ExecuteAfterDelay(this MonoBehaviour mono, System.Action action, float delay)
+    {
+        mono.StartCoroutine(ExecuteAfterDelayCoroutine(action, delay));
+    }
+
+    private static System.Collections.IEnumerator ExecuteAfterDelayCoroutine(System.Action action, float delay)
+    {
+        yield return new WaitForSeconds(delay);
+        action?.Invoke();
+    }
+}

+ 227 - 0
Assets/UI/CombatEventPopup.uss

@@ -0,0 +1,227 @@
+/* Combat Event Popup Styles */
+
+/* Main Container */
+.combat-popup-container {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    justify-content: center;
+    align-items: center;
+    transition-property: opacity;
+    transition-duration: 0.3s;
+}
+
+/* Background Overlay */
+.combat-popup-overlay {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: rgba(0, 0, 0, 0.7);
+    /* Ensure the overlay captures all mouse events */
+    -unity-slice-left: 0;
+    -unity-slice-top: 0;
+    -unity-slice-right: 0;
+    -unity-slice-bottom: 0;
+}
+
+/* Main Panel */
+.combat-popup-panel {
+    background-color: rgba(38, 38, 51, 0.95);
+    border-color: rgba(204, 51, 51, 1);
+    border-width: 3px;
+    border-radius: 10px;
+    min-width: 400px;
+    max-width: 600px;
+    padding: 20px;
+    transition-property: scale, opacity;
+    transition-duration: 0.3s;
+    transition-timing-function: ease-out-back;
+}
+
+/* Title Styles */
+.combat-title {
+    font-size: 24px;
+    color: rgba(255, 77, 77, 1);
+    -unity-font-style: bold;
+    -unity-text-align: middle-center;
+    margin-bottom: 15px;
+    text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
+}
+
+/* Description */
+.combat-description {
+    font-size: 16px;
+    color: rgba(255, 255, 255, 1);
+    -unity-text-align: middle-center;
+    white-space: normal;
+    margin-bottom: 20px;
+}
+
+/* Enemy Section */
+.enemy-section {
+    margin-bottom: 25px;
+}
+
+.enemy-header {
+    font-size: 18px;
+    color: rgba(255, 204, 51, 1);
+    -unity-font-style: bold;
+    -unity-text-align: middle-center;
+    margin-bottom: 10px;
+}
+
+.enemy-list {
+    background-color: rgba(26, 26, 38, 0.8);
+    border-radius: 5px;
+    padding: 10px 15px;
+}
+
+/* Enemy Item */
+.enemy-item {
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 8px;
+    padding: 8px 10px;
+    background-color: rgba(51, 51, 64, 0.6);
+    border-radius: 4px;
+    transition-property: background-color, scale;
+    transition-duration: 0.2s;
+}
+
+.enemy-item:hover {
+    background-color: rgba(77, 77, 92, 0.8);
+    scale: 1.02;
+}
+
+.enemy-info {
+    flex-direction: column;
+    flex-grow: 1;
+}
+
+.enemy-name {
+    font-size: 16px;
+    color: rgba(255, 230, 179, 1);
+    -unity-font-style: bold;
+}
+
+.enemy-stats {
+    font-size: 12px;
+    color: rgba(204, 204, 204, 1);
+}
+
+.enemy-weapon {
+    font-size: 11px;
+    color: rgba(179, 179, 255, 1);
+}
+
+/* Threat Indicator */
+.threat-indicator {
+    width: 60px;
+    height: 20px;
+    border-radius: 10px;
+    justify-content: center;
+    align-items: center;
+}
+
+.threat-low {
+    background-color: rgba(77, 204, 77, 1); /* Green */
+}
+
+.threat-medium {
+    background-color: rgba(255, 204, 51, 1); /* Yellow */
+}
+
+.threat-high {
+    background-color: rgba(255, 102, 51, 1); /* Orange */
+}
+
+.threat-extreme {
+    background-color: rgba(204, 51, 51, 1); /* Red */
+}
+
+.threat-label {
+    font-size: 11px;
+    color: rgba(255, 255, 255, 1);
+    -unity-font-style: bold;
+}
+
+/* Button Container */
+.button-container {
+    flex-direction: row;
+    justify-content: space-around;
+    margin-top: 20px;
+}
+
+/* Button Base Style */
+.combat-button {
+    font-size: 16px;
+    color: rgba(255, 255, 255, 1);
+    border-radius: 8px;
+    padding: 12px 20px;
+    min-width: 120px;
+    transition-property: background-color, scale, border-color;
+    transition-duration: 0.2s;
+    border-width: 2px;
+    border-color: transparent;
+}
+
+.combat-button:hover {
+    scale: 1.05;
+    border-color: rgba(255, 255, 255, 0.3);
+}
+
+.combat-button:active {
+    scale: 0.98;
+}
+
+/* Run Away Button */
+.run-button {
+    background-color: rgba(153, 153, 26, 1);
+}
+
+.run-button:hover {
+    background-color: rgba(179, 179, 51, 1);
+}
+
+/* Attack Button */
+.attack-button {
+    background-color: rgba(204, 51, 51, 1);
+}
+
+.attack-button:hover {
+    background-color: rgba(230, 77, 77, 1);
+}
+
+/* Animation Classes */
+.popup-enter {
+    opacity: 1;
+    scale: 1;
+}
+
+.popup-exit {
+    opacity: 0;
+    scale: 0.8;
+}
+
+.popup-hidden {
+    display: none;
+}
+
+/* Pulse Animation for Threat Indicators */
+@keyframes threat-pulse {
+    0% { scale: 1; }
+    50% { scale: 1.1; }
+    100% { scale: 1; }
+}
+
+.threat-extreme .threat-label {
+    animation-name: threat-pulse;
+    animation-duration: 1.5s;
+    animation-iteration-count: infinite;
+    animation-timing-function: ease-in-out;
+}

+ 28 - 0
Assets/UI/CombatEventPopup.uxml

@@ -0,0 +1,28 @@
+<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
+    <engine:VisualElement name="combat-event-popup" class="combat-popup-container" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; justify-content: center; align-items: center; display: none;">
+        <engine:VisualElement name="background-overlay" class="combat-popup-overlay" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.7);" />
+        <engine:VisualElement name="popup-panel" class="combat-popup-panel" style="background-color: rgba(38, 38, 51, 0.95); border-left-color: rgb(204, 51, 51); border-right-color: rgb(204, 51, 51); border-top-color: rgb(204, 51, 51); border-bottom-color: rgb(204, 51, 51); border-left-width: 3px; border-right-width: 3px; border-top-width: 3px; border-bottom-width: 3px; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; min-width: 400px; max-width: 600px; padding-top: 20px; padding-bottom: 20px; padding-left: 20px; padding-right: 20px;">
+            <engine:Label name="event-title" text="*** COMBAT ENCOUNTER! ***" class="combat-title" style="font-size: 24px; color: rgb(255, 77, 77); -unity-font-style: bold; -unity-text-align: middle-center; margin-bottom: 15px;" />
+            <engine:Label name="event-description" text="Your party encounters hostile enemies!" class="combat-description" style="font-size: 16px; color: rgb(255, 255, 255); -unity-text-align: middle-center; white-space: normal; margin-bottom: 20px;" />
+            <engine:VisualElement name="enemy-section" class="enemy-section" style="margin-bottom: 25px;">
+                <engine:Label name="enemy-header" text="[ENEMIES]" class="enemy-header" style="font-size: 18px; color: rgb(255, 204, 51); -unity-font-style: bold; -unity-text-align: middle-center; margin-bottom: 10px;" />
+                <engine:VisualElement name="enemy-list" class="enemy-list" style="background-color: rgba(26, 26, 38, 0.8); border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; padding-top: 10px; padding-bottom: 10px; padding-left: 15px; padding-right: 15px;">
+                    <engine:VisualElement name="enemy-item-template" class="enemy-item" style="flex-direction: row; justify-content: space-between; align-items: center; margin-bottom: 8px; padding-top: 8px; padding-bottom: 8px; padding-left: 10px; padding-right: 10px; background-color: rgba(51, 51, 64, 0.6); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; display: none;">
+                        <engine:VisualElement name="enemy-info" class="enemy-info" style="flex-direction: column; flex-grow: 1;">
+                            <engine:Label name="enemy-name" text="1x Skeleton Warrior" class="enemy-name" style="font-size: 16px; color: rgb(255, 230, 179); -unity-font-style: bold;" />
+                            <engine:Label name="enemy-stats" text="HP: 25 | AC: 14 | Threat: 3" class="enemy-stats" style="font-size: 12px; color: rgb(204, 204, 204);" />
+                            <engine:Label name="enemy-weapon" text="[WEAPON] Iron Sword" class="enemy-weapon" style="font-size: 11px; color: rgb(179, 179, 255);" />
+                        </engine:VisualElement>
+                        <engine:VisualElement name="threat-indicator" class="threat-indicator" style="width: 60px; height: 20px; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; justify-content: center; align-items: center; background-color: rgb(77, 204, 77);">
+                            <engine:Label name="threat-label" text="T3" class="threat-label" style="font-size: 11px; color: rgb(255, 255, 255); -unity-font-style: bold;" />
+                        </engine:VisualElement>
+                    </engine:VisualElement>
+                </engine:VisualElement>
+            </engine:VisualElement>
+            <engine:VisualElement name="button-container" class="button-container" style="flex-direction: row; justify-content: space-around; margin-top: 20px;">
+                <engine:Button name="run-away-button" text="[FLEE] RUN AWAY" class="run-button" style="font-size: 16px; background-color: rgb(153, 153, 26); color: rgb(255, 255, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; padding-top: 12px; padding-bottom: 12px; padding-left: 20px; padding-right: 20px; min-width: 120px;" />
+                <engine:Button name="attack-button" text="[FIGHT] ATTACK!" class="attack-button" style="font-size: 16px; background-color: rgb(204, 51, 51); color: rgb(255, 255, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; padding-top: 12px; padding-bottom: 12px; padding-left: 20px; padding-right: 20px; min-width: 120px;" />
+            </engine:VisualElement>
+        </engine:VisualElement>
+    </engine:VisualElement>
+</engine:UXML>

+ 108 - 0
BACKWARD_COMPATIBILITY_REMOVAL.md

@@ -0,0 +1,108 @@
+# Backward Compatibility Removal - Clean System
+
+## Changes Made
+
+### ✅ Removed from CombatTravelEvent:
+- ❌ `public string[] possibleEnemyTypes` field
+- ❌ `[Header("Backward Compatibility")]` section
+- ❌ Fallback logic to string-based enemy types
+- ❌ Complex conditional logic in ExecuteEvent()
+
+### ✅ Simplified ExecuteEvent Method:
+```csharp
+// Before: Complex fallback logic
+if (possibleEnemies != null && possibleEnemies.Length > 0) {
+    // Use EnemyCharacterData
+} else {
+    // Fall back to strings
+}
+
+// After: Clean, type-safe only
+EnemyCharacterData selectedEnemy = validEnemies[Random.Range(0, validEnemies.Length)];
+var result = EventResult.SimpleBattle(description, enemyCount, enemyType);
+result.battleData.enemyCharacterData = selectedEnemy;
+```
+
+### ✅ Enhanced Error Handling:
+- Clear error messages when no enemies are configured
+- Validation of asset references
+- Graceful handling of null references
+
+### ✅ Updated Example Events:
+- `ForestAmbushEvent`: Now has TODO comments for asset assignment
+- `MountainAmbushEvent`: Now has TODO comments for asset assignment
+
+## Benefits
+
+### 🎯 **Cleaner Code:**
+- No more complex conditional logic
+- Single responsibility: EnemyCharacterData assets only
+- Easier to understand and maintain
+
+### 🛡️ **Type Safety:**
+- Impossible to misspell enemy names
+- Compile-time checking of asset references
+- Clear error messages for missing configuration
+
+### 🎮 **Better User Experience:**
+- Drag-and-drop asset assignment
+- Visual feedback in Inspector
+- No more text input confusion
+
+## How It Works Now
+
+### 1. Combat Event Creation:
+```
+Create → RPG → Travel Events → Combat Event
+```
+
+### 2. Asset Configuration:
+```
+Combat Event Settings
+├─ Min Enemies: 1
+├─ Max Enemies: 3
+└─ Possible Enemies: [Array]
+   ├─ Size: 2
+   ├─ Element 0: [Drag SkeletonWarrior.asset]
+   └─ Element 1: [Drag GoblinScout.asset]
+```
+
+### 3. Error Prevention:
+- ✅ Empty array → Clear error message
+- ✅ Null references → Filtered out automatically
+- ✅ No assets → Event doesn't execute
+
+## Migration Notes
+
+### For New Users:
+- 🎯 **Simple**: Just drag enemy assets into combat events
+- 🎮 **Intuitive**: Visual asset picker interface
+- 🛡️ **Safe**: No way to create invalid references
+
+### For Existing Events:
+- Any old combat events with string arrays will need to be reconfigured
+- Use the `CombatEventFixer` tool if needed
+- Create new events with proper asset references
+
+## Example: Skeleton Ambush
+
+```csharp
+// Clean configuration:
+eventName = "Skeleton Ambush";
+minEnemies = 1;
+maxEnemies = 3;
+possibleEnemies = new EnemyCharacterData[] { 
+    skeletonWarriorAsset // ← Actual asset reference!
+};
+```
+
+### Battle Integration:
+```csharp
+// HandleBattleEvent gets full enemy data:
+Debug.Log($"⚔️ Enemy: {battleData.enemyCharacterData.enemyName}");
+Debug.Log($"📊 Stats: HP={battleData.enemyCharacterData.maxHealth}");
+Debug.Log($"💰 Rewards: {battleData.enemyCharacterData.goldReward} gold");
+Debug.Log($"⚔️ Weapon: {battleData.enemyCharacterData.preferredWeaponType}");
+```
+
+The system is now much cleaner and forces proper asset-based configuration! 🎯

+ 99 - 0
COMBAT_EVENT_ASSET_REFERENCE_FIX.md

@@ -0,0 +1,99 @@
+# Fix: Combat Event Using Asset References Instead of Strings
+
+## Problem
+The combat event inspector is still showing "Possible Enemy Types" (string input) instead of "Possible Enemies" (asset drag-drop).
+
+## Quick Fix Steps
+
+### Step 1: Use the Fixer Tool
+1. Go to **RPG → Utilities → Fix Combat Events**
+2. Click **"Force Reimport TravelEventTypes.cs"**
+3. Click **"Refresh Asset Database"**
+
+### Step 2: Create New Combat Event (Clean Slate)
+1. **Delete any existing combat event assets** that show string inputs
+2. Right-click in Project → **Create → RPG → Travel Events → Combat Event**
+3. Name it `SkeletonAmbush`
+
+### Step 3: Configure with Asset References
+Open the `SkeletonAmbush` asset and you should now see:
+
+#### ✅ Correct Inspector Layout:
+```
+Combat Event Settings
+├─ Min Enemies: 1
+├─ Max Enemies: 3
+└─ Possible Enemies: [Drag assets here] 
+   ├─ Size: 1
+   └─ Element 0: [Drag SkeletonWarrior.asset here]
+
+Backward Compatibility  
+└─ Possible Enemy Types: (empty - ignore this)
+```
+
+#### ❌ Wrong Inspector Layout:
+```
+Combat Event Settings
+├─ Min Enemies: 1
+├─ Max Enemies: 3
+└─ Possible Enemy Types: [Text input] ← WRONG!
+```
+
+### Step 4: Drag Your Enemy Assets
+1. **Expand "Possible Enemies"** section
+2. **Set Size to 1** (or however many enemy types you want)
+3. **Drag `SkeletonWarrior.asset`** from Project window into `Element 0`
+4. The field should show the asset icon and name
+
+### Step 5: Verify It's Working
+```csharp
+✅ Field shows: SkeletonWarrior (EnemyCharacterData)
+❌ Field shows: "Skeleton Warrior" (string)
+```
+
+## Alternative: Right-Click Fix
+If you already have a combat event asset:
+1. **Right-click the asset** in Project window
+2. Select **RPG → Fix Combat Event Inspector**
+3. **Refresh** the Inspector by clicking elsewhere and back
+
+## Create Skeleton Ambush Example
+
+### Complete Configuration:
+```yaml
+Event Name: Skeleton Ambush
+Event Description: Ancient skeletal warriors rise to attack!
+Event Type: Combat
+Rarity: Common
+
+# Terrain (where skeletons appear)
+Forest Chance: 0.8
+Mountain Chance: 0.6  
+Road Chance: 0.2
+Town Chance: 0.1
+
+# Combat Settings
+Min Enemies: 1
+Max Enemies: 3
+Possible Enemies:
+  - SkeletonWarrior.asset  ← Drag this asset here!
+
+# Descriptions
+Encounter Descriptions:
+  - "Bones clatter as skeletal warriors emerge from the earth!"
+  - "Ancient skeletons wielding rusty weapons block your path!"
+```
+
+## Why This Happens
+- **Unity Inspector Caching**: Unity sometimes caches old inspector layouts
+- **Script Compilation**: Changes to class fields require Unity to recompile
+- **Asset Serialization**: Old assets may still have old field data
+
+## Verification
+After fixing, you should see:
+- 🎯 **Drag-drop asset fields** instead of text input
+- 🔗 **Direct references** to your enemy data assets  
+- ✅ **Type safety** - no more typos possible
+- 🎮 **Full enemy data access** in battle setup
+
+The new system is much safer and more powerful! 🎯

+ 165 - 0
COMBAT_EVENT_POPUP_GUIDE.md

@@ -0,0 +1,165 @@
+# Combat Event Popup System - Setup Guide
+
+## Overview
+This system provides a beautiful popup UI for combat encounters that allows players to choose between "Attack" or "Run Away" when encountering enemies during travel.
+
+## Components Created
+
+### 1. CombatEventPopup.cs
+- **Purpose**: Beautiful UI popup showing enemy details and choice buttons
+- **Features**: 
+  - Displays enemy count, names, stats, and threat levels
+  - Animated popup with smooth transitions
+  - Hover effects on buttons
+  - Enemy threat level color coding
+
+### 2. CombatEventIntegration.cs
+- **Purpose**: Connects the popup with the travel event system
+- **Features**:
+  - Handles player choices (attack/run away)
+  - Manages escape success/failure logic
+  - Applies health penalties for failed escapes
+  - Configurable escape chance and messages
+
+### 3. Enhanced TravelEventTypes.cs
+- **Purpose**: Updated combat events to use the popup system
+- **Features**:
+  - Automatically detects if popup system is available
+  - Falls back to immediate battle if no popup found
+  - Integrates with existing enemy character data
+
+## Setup Instructions
+
+### Step 1: Create UI Document
+1. In your scene, create a UI Document GameObject
+2. Add a UI Document component
+3. Create or assign a Panel Settings asset
+4. Leave the Visual Tree Asset blank (popup creates its own UI)
+
+### Step 2: Setup Combat Event Popup
+1. Create an empty GameObject named "CombatEventPopup"
+2. Add the `CombatEventPopup` component
+3. Assign the UI Document from step 1 to the `uiDocument` field
+4. Adjust animation settings if desired
+
+### Step 3: Setup Combat Event Integration
+1. Find your existing TravelEventSystem GameObject
+2. Add the `CombatEventIntegration` component to the same GameObject
+3. Assign the CombatEventPopup from step 2 to the `combatEventPopup` field
+4. Configure settings:
+   - **Allow Running Away**: Enable/disable run away option
+   - **Run Away Success Chance**: Probability of successful escape (0.0 - 1.0)
+   - **Run Away Health Penalty**: Damage taken on failed escape
+   - **Messages**: Customize success/failure messages
+
+### Step 4: Test the System
+1. Create or find a CombatTravelEvent asset
+2. Assign EnemyCharacterData assets to the `possibleEnemies` array
+3. Add the combat event to your TravelEventSystem's `availableEvents` list
+4. Start travel and trigger the event (use "Force Next Event" for testing)
+
+## Configuration Options
+
+### Combat Event Integration Settings
+```csharp
+[Header("Combat Popup Integration")]
+public bool allowRunningAway = true;            // Can players run away?
+public float runAwaySuccessChance = 0.75f;      // 75% success chance
+public int runAwayHealthPenalty = 5;            // Damage on failed escape
+
+[Header("Run Away Messages")]
+public string[] successfulRunAwayMessages;      // Success messages
+public string[] failedRunAwayMessages;          // Failure messages (use {damage} placeholder)
+```
+
+### Popup Animation Settings
+```csharp
+[Header("Popup Settings")]
+public float animationDuration = 0.3f;          // Animation speed
+public float backgroundBlurIntensity = 0.5f;    // Background overlay opacity
+```
+
+## Enemy Display Features
+
+### Threat Level Color Coding
+- **Green (1-2)**: Easy enemies
+- **Yellow (3-4)**: Medium enemies  
+- **Orange (5-6)**: Hard enemies
+- **Red (7+)**: Very hard enemies
+
+### Enemy Information Shown
+- Enemy count and name
+- Health points, armor class, threat level
+- Preferred weapon (if assigned)
+- Visual threat level indicator
+
+## Integration Flow
+
+### 1. Combat Event Triggered
+```
+Travel Event System → Combat Travel Event → Combat Integration → Popup UI
+```
+
+### 2. Player Makes Choice
+```
+Popup UI → Combat Integration → Apply Result → Continue/Battle
+```
+
+### 3. Escape Outcomes
+**Successful Escape:**
+- Show success message
+- No penalties applied
+- Travel continues normally
+
+**Failed Escape:**
+- Show failure message with damage
+- Apply health penalty to party
+- Force combat to start
+
+### 4. Attack Choice
+- Show battle preparation message
+- Stop travel
+- Set up battle with enemy data
+- Transition to battle system
+
+## Troubleshooting
+
+### Popup Not Appearing
+1. Check that UI Document is properly assigned
+2. Verify CombatEventIntegration is on the same GameObject as TravelEventSystem
+3. Ensure combat events have valid EnemyCharacterData assigned
+
+### Escape Always Fails/Succeeds
+1. Check `runAwaySuccessChance` setting (0.0 = always fail, 1.0 = always succeed)
+2. Verify `allowRunningAway` is enabled
+
+### UI Layout Issues
+1. Check that Panel Settings asset is properly configured
+2. Verify screen resolution compatibility
+3. Adjust popup container sizing in CombatEventPopup.cs
+
+### Events Go Straight to Battle
+1. Verify CombatEventIntegration component is present and enabled
+2. Check console for "No CombatEventIntegration found" warnings
+3. Ensure all components are on active GameObjects
+
+## Customization Tips
+
+### Custom Enemy Display
+Modify `CreateEnemyElement()` in CombatEventPopup.cs to show additional enemy information like special abilities or lore.
+
+### Custom Button Styles
+Update `SetupButtonHoverEffects()` and button creation code to match your game's visual style.
+
+### Different Escape Mechanics
+Modify `HandleRunAwayChoice()` in CombatEventIntegration.cs to implement different escape mechanics based on party stats, terrain, or enemy types.
+
+### Battle System Integration
+Update `ApplyBattleResult()` in CombatEventIntegration.cs to properly integrate with your existing battle scene transition system.
+
+## File Locations
+- `/Assets/Scripts/UI/CombatEventPopup.cs`
+- `/Assets/Scripts/Events/CombatEventIntegration.cs`  
+- `/Assets/Scripts/Events/TravelEventTypes.cs` (modified)
+
+This system provides a rich, interactive combat encounter experience while maintaining compatibility with your existing travel and battle systems!

+ 248 - 0
COMBAT_EVENT_POPUP_UXML_GUIDE.md

@@ -0,0 +1,248 @@
+# Combat Event Popup UXML Setup Guide
+
+This guide explains how to set up and use the new UXML-based combat event popup system.
+
+## 📁 Files Created
+
+### UI Assets:
+- **`Assets/UI/CombatEventPopup.uxml`** - UXML template defining the popup structure
+- **`Assets/UI/CombatEventPopup.uss`** - USS stylesheet with animations and styling
+- **`Assets/Scripts/UI/CombatEventPopupUXML.cs`** - Script that uses UXML template
+
+### Key Features:
+- ✅ **UXML Template-based** - Easier to edit UI structure
+- ✅ **USS Styling** - Professional animations and hover effects
+- ✅ **Fallback Support** - Works even without UXML template
+- ✅ **Threat Level Indicators** - Color-coded enemy danger levels
+- ✅ **Enemy Details** - Shows HP, AC, weapons, and threat levels
+- ✅ **Smooth Animations** - Enter/exit transitions and hover effects
+- ✅ **Mouse Input Blocking** - Prevents map clicks while popup is open
+
+## 🎯 Per-Event Escape Configuration
+
+**NEW**: Each `CombatTravelEvent` asset now has its own escape configuration! This allows for much more varied and interesting combat encounters:
+
+### Individual Combat Event Setup:
+1. **Create/Edit Combat Event Assets**: Go to `Create -> RPG -> Travel Events -> Combat Event`
+2. **Configure Escape Settings**:
+   - **Allow Running Away**: Uncheck for boss fights or special encounters where escape isn't allowed
+   - **Run Away Success Chance**: Set different values per encounter type
+     - **Weak enemies** (bandits): 0.9 (90% success)
+     - **Normal enemies** (wolves): 0.75 (75% success) 
+     - **Strong enemies** (bears): 0.5 (50% success)
+     - **Boss encounters**: 0.1 (10% success) or disable entirely
+   - **Run Away Health Penalty**: Adjust damage based on enemy danger
+   - **Custom Messages**: Write encounter-specific escape descriptions
+
+### Examples:
+- **Bandit Ambush**: High escape chance (0.9), low penalty (3 damage), messages like "You slip away while the bandits argue over loot"
+- **Dragon Encounter**: Low escape chance (0.2), high penalty (15 damage), messages like "The dragon's flames sear your party as you flee"
+- **Town Guard Pursuit**: Escape disabled (legal consequences), forces combat
+
+## 🔄 System Priority:
+1. **Combat Event Configuration** (only option) - Uses the specific event's settings
+2. **Hardcoded Fallback** - Simple defaults (75% success, 5 damage) if no combat event is available
+3. **Error Handling** - Graceful degradation with basic escape mechanics
+
+## 🛠️ Setup Instructions
+
+### Step 1: Create UI Document
+1. Create a new GameObject in your scene
+2. Name it "CombatEventUI"
+3. Add a **UIDocument** component
+4. Create a **Panel Settings** asset (Create -> UI Toolkit -> Panel Settings)
+5. Assign the Panel Settings to the UIDocument
+
+### Step 2: Setup the Popup Component
+1. Add the **CombatEventPopupUXML** component to the same GameObject
+2. In the inspector, assign these references:
+   - **UI Document**: The UIDocument component you just added
+   - **Popup Template**: Drag `Assets/UI/CombatEventPopup.uxml`
+   - **Popup Style Sheet**: Drag `Assets/UI/CombatEventPopup.uss`
+
+### Step 3: Setup Combat Integration
+**Option A (Recommended): Add to TravelEventSystem GameObject**
+1. Find the GameObject that has the **TravelEventSystem** component
+2. Add the **CombatEventIntegration** component to that GameObject
+3. In the inspector, assign:
+   - **Combat Event Popup UXML**: Drag your "CombatEventUI" GameObject's CombatEventPopupUXML component here
+   - Leave **Combat Event Popup** empty (this is for the legacy system)
+   - Leave **Combat Popup Prefab** empty (only needed if you're using prefabs)
+
+**Option B: Add to UI GameObject (Also works)**
+1. Add the **CombatEventIntegration** component to the same GameObject as your popup (CombatEventUI)
+2. The system will automatically find the TravelEventSystem in the scene
+3. In the inspector, assign:
+   - **Combat Event Popup UXML**: The CombatEventPopupUXML component on the same GameObject
+   - Leave other fields empty
+
+### Step 4: Configure Panel Settings
+In your Panel Settings asset, configure:
+- **Scale Mode**: Scale With Screen Size
+- **Screen Match Mode**: Match Width Or Height
+- **Reference Resolution**: 1920x1080 (or your preferred resolution)
+
+## 🎮 Usage
+
+The system will automatically work with your travel events! When a combat event is triggered:
+
+1. **Automatic Detection**: The system finds CombatEventIntegration in the scene
+2. **Beautiful Popup**: Shows enemy details with:
+   - Enemy count and names
+   - Health, Armor Class, and threat levels
+   - Weapon information
+   - Color-coded threat indicators
+3. **Player Choice**: Two options with hover effects:
+   - **[FLEE] RUN AWAY** - Attempt to escape (configurable success rate)
+   - **[FIGHT] ATTACK!** - Enter battle
+4. **Input Blocking**: Prevents mouse clicks from reaching the map while popup is open
+
+## 🎨 Customization Options
+
+### Visual Customization:
+Edit `CombatEventPopup.uss` to change:
+- Colors and themes
+- Animation speeds and effects
+- Button styles and hover effects
+- Threat level color coding
+
+### UXML Structure:
+Edit `CombatEventPopup.uxml` to:
+- Rearrange UI elements
+- Add new information displays
+- Change button layouts
+- Modify popup structure
+
+### Script Configuration:
+In `CombatEventPopupUXML.cs` inspector:
+- **Animation Duration**: How long show/hide animations take
+- **Background Blur Intensity**: Overlay darkness level
+
+### Integration Settings:
+In **individual CombatTravelEvent assets** (Required):
+- **Allow Running Away**: Enable/disable escape option for this specific combat
+- **Run Away Success Chance**: Probability of successful escape (0.0 = never, 1.0 = always)
+- **Run Away Health Penalty**: Damage taken on failed escape attempts
+- **Successful Run Away Messages**: Custom success messages for this combat type
+- **Failed Run Away Messages**: Custom failure messages for this combat type
+
+**Note**: `CombatEventIntegration` no longer has escape configuration fields. All escape behavior is now configured per combat event asset for maximum flexibility and narrative control.
+
+## 🔧 Advanced Features
+
+### Threat Level System:
+- **T1-T2**: Green (Low threat)
+- **T3-T4**: Yellow (Medium threat) 
+- **T5-T6**: Orange (High threat)
+- **T7+**: Red with pulse animation (Extreme threat)
+
+### Fallback Support:
+If UXML template is missing, the system automatically creates UI programmatically.
+
+### Animation Classes:
+- `.popup-enter` - Fade in and scale up
+- `.popup-exit` - Fade out and scale down
+- `.enemy-item:hover` - Hover effects on enemy items
+- `.threat-extreme` - Pulsing animation for dangerous enemies
+
+## 🐛 Troubleshooting
+
+### Common Issues:
+
+**Popup not showing but debug logs say "✅ Combat popup displayed"**
+This usually means the UI is created but not visible. Check:
+1. **Panel Settings Configuration**:
+   - Ensure Panel Settings asset is assigned to UIDocument
+   - Set Scale Mode to "Scale With Screen Size"
+   - Set Screen Match Mode to "Match Width Or Height"
+   - Set Reference Resolution (e.g., 1920x1080)
+
+2. **UIDocument Setup**:
+   - GameObject with UIDocument must be active
+   - UIDocument component must be enabled
+   - Sort Order should be higher than other UI (try 1000)
+
+3. **Camera Setup**:
+   - If using Multiple Displays, ensure correct target display
+   - Check if UI is behind other UI elements
+
+4. **UXML/USS Assets**:
+   - Verify UXML and USS files are properly assigned in inspector
+   - Check Console for "Could not find [element] element" errors
+
+**"Could not find [element] element"**
+- Ensure UXML template is properly assigned
+- Check element names match between UXML and script
+- Verify Panel Settings are configured
+
+**"No UIDocument found"**
+- Add UIDocument component to GameObject
+- Assign Panel Settings to UIDocument
+
+**"No CombatEventIntegration found in scene"**
+- Add CombatEventIntegration component to scene
+- Assign CombatEventPopupUXML reference
+
+### Quick Diagnostic Steps:
+
+1. **Check Console Logs**: Look for these debug messages:
+   - `🔧 SetupUI: Root element size: [width]x[height]`
+   - `✅ UXML template instantiated and added to root`
+   - `🔍 UI Elements found:` (should show ✅ for all elements)
+
+2. **Verify Panel Settings**:
+   - Select your UIDocument GameObject
+   - Check if Panel Settings is assigned
+   - Open Panel Settings asset and verify configuration
+
+3. **Test with Fallback UI**:
+   - Temporarily remove UXML template assignment
+   - System should create UI programmatically as fallback
+   - If this works, issue is with UXML/USS setup
+
+4. **Check GameObject Hierarchy**:
+   - Ensure CombatEventUI GameObject is active
+   - Verify no parent objects are disabled
+   - Check if GameObject is in correct scene
+
+### Debug Logs:
+The system provides detailed debug information:
+- `🔍 Looking for CombatEventIntegration component...`
+- `✅ Found CombatEventIntegration: [name]`
+- `🎭 Calling ShowCombatChoicePopup with X enemies`
+- `🗡️ Player chose to ATTACK!`
+- `🏃 Player chose to RUN AWAY!`
+
+## 🚀 Comparison: UXML vs Programmatic
+
+### UXML Benefits:
+- ✅ **Visual Editor**: Edit UI structure in Unity Inspector
+- ✅ **Separation of Concerns**: UI structure separate from logic
+- ✅ **Easier Styling**: CSS-like USS styling
+- ✅ **Performance**: More efficient element creation
+- ✅ **Maintainability**: Easier to modify and update
+
+### Programmatic Benefits:
+- ✅ **Dynamic Creation**: Runtime element generation
+- ✅ **No Asset Dependencies**: Fully self-contained
+- ✅ **Procedural UI**: Complex dynamic layouts
+
+## 📋 File Dependencies
+
+```
+CombatEventPopupUXML.cs
+├── CombatEventPopup.uxml (optional - has fallback)
+├── CombatEventPopup.uss (optional - inline styles as fallback)
+├── UIDocument component
+└── Panel Settings asset
+
+CombatEventIntegration.cs
+├── CombatEventPopupUXML reference
+└── TravelEventSystem integration
+
+Travel Events
+├── CombatTravelEvent.cs (uses reflection to find integration)
+└── BattleEventData (enemy information structure)
+```
+
+The new UXML-based system provides a much cleaner, more maintainable approach to creating beautiful combat event popups while maintaining full backwards compatibility!

+ 99 - 0
COMBAT_POPUP_SETUP_GUIDE.md

@@ -0,0 +1,99 @@
+# Combat Event Popup Setup Guide
+
+## Overview
+The combat event popup system has been enhanced to support two setup methods. The popup now includes comprehensive debugging to help identify any setup issues.
+
+## Setup Options
+
+### Option 1: Direct Component Setup (Recommended for Testing)
+1. Find your **TravelEventSystem** GameObject in the scene
+2. Add the **CombatEventIntegration** component to it
+3. Add the **CombatEventPopup** component to the same GameObject
+4. The system will automatically detect and connect the components
+
+### Option 2: Prefab-Based Setup (Production Ready)
+1. Create a prefab containing the **CombatEventPopup** component
+2. Add **CombatEventIntegration** to your **TravelEventSystem** GameObject
+3. Assign your popup prefab to the **Combat Popup Prefab** field
+4. The system will instantiate the popup when needed
+
+## Verification Steps
+
+### 1. Check Console for Initialization Messages
+When the scene starts, you should see:
+```
+🔧 Combat Event Integration starting...
+📦 Instantiating combat popup from prefab... (if using prefab)
+✅ Combat Event Integration initialized successfully
+```
+
+### 2. Test Combat Event Triggering
+When a combat event occurs, you should see debug messages like:
+```
+🔍 Attempting to find CombatEventIntegration component...
+🎯 Found CombatEventIntegration via FindObjectsByType
+📞 Calling ShowCombatChoicePopup method...
+🎭 Showing combat choice popup: A group of bandits blocks your path!
+```
+
+### 3. Verify Component Attachment
+In the Inspector, ensure:
+- **TravelEventSystem** GameObject has **CombatEventIntegration** component
+- **CombatEventIntegration** component has either:
+  - **Combat Event Popup** field assigned (Option 1), OR
+  - **Combat Popup Prefab** field assigned (Option 2)
+
+## Troubleshooting
+
+### No Popup Appears
+1. **Check Console**: Look for initialization error messages
+2. **Verify Components**: Ensure CombatEventIntegration is on TravelEventSystem GameObject
+3. **Check References**: Ensure either popup component or prefab is assigned
+4. **Test in Play Mode**: The system only works when the scene is playing
+
+### Error Messages
+- `❌ Combat Event Integration requires TravelEventSystem on the same GameObject!`
+  - Solution: Add CombatEventIntegration to the same GameObject as TravelEventSystem
+
+- `❌ Combat popup prefab does not contain CombatEventPopup component!`
+  - Solution: Ensure your prefab has the CombatEventPopup component
+
+- `❌ Combat Event Integration requires a CombatEventPopup component or prefab!`
+  - Solution: Either add CombatEventPopup component to scene or assign a prefab
+
+### Component Not Found During Events
+If you see `⚠️ CombatEventIntegration component not found via FindObjectsByType`:
+1. Ensure CombatEventIntegration is actually added to a GameObject in the scene
+2. Check that the GameObject is active
+3. Verify the component is enabled
+
+## Testing the System
+
+### Manual Test Steps
+1. Start the game in Play mode
+2. Initiate travel between locations
+3. If combat events don't trigger naturally, you can:
+   - Modify travel event probabilities in the Inspector
+   - Add multiple enemy types to locations
+   - Test with shorter travel distances
+
+### Debug Information
+The system now provides extensive debugging:
+- Component discovery process
+- Method invocation attempts
+- Popup display calls
+- Event handling flow
+
+## Quick Setup Checklist
+- [ ] TravelEventSystem GameObject exists in scene
+- [ ] CombatEventIntegration component added to TravelEventSystem
+- [ ] Either CombatEventPopup component OR prefab assigned
+- [ ] EnemyCharacterData assets created and assigned to locations
+- [ ] Console shows successful initialization message
+- [ ] Test travel triggers combat events with popup
+
+## Recent Enhancements
+- **Flexible Setup**: Support for both direct component and prefab-based setup
+- **Enhanced Debugging**: Comprehensive logging throughout the integration process
+- **Better Error Handling**: Clear error messages with solutions
+- **Automatic Detection**: System automatically finds and connects components when possible

+ 163 - 0
ENEMY_CHARACTER_CREATION_GUIDE.md

@@ -0,0 +1,163 @@
+# Enemy Character Creation System
+
+This system provides a streamlined workflow for creating new enemy characters in your RPG game, similar to the weapon creation system but specifically designed for enemies.
+
+## Overview
+
+The enemy creation system consists of:
+- **EnemyCharacterData**: ScriptableObject assets that define enemy stats and behavior
+- **Enemy Creator Window**: Unity Editor window for managing enemy creation
+- **Auto-Generated Scripts**: Character classes automatically generated from the data
+
+## How to Use
+
+### Method 1: Unity Menu (Recommended)
+1. Right-click in Project window
+2. Go to **Create > RPG > Characters > Enemy**
+3. Name your enemy data asset (e.g., "SkeletonWarrior")
+4. Configure the enemy in the Inspector
+5. Right-click the asset and select **RPG > Generate Enemy Character Script**
+
+### Method 2: Enemy Creator Window
+1. Go to **RPG > Characters > Enemy Creator Window**
+2. Click "Create New Enemy Data Asset" or select existing one
+3. Configure settings in the Inspector
+4. Click "Generate Enemy Character Script" in the window
+
+### Method 3: Batch Generation
+1. Create multiple enemy data assets
+2. Go to **RPG > Characters > Batch Generate All Enemy Scripts**
+3. All enemy scripts will be generated at once
+
+## Configuration Options
+
+### Basic Info
+- **Enemy Name**: Display name (e.g., "Skeleton Warrior")
+- **Description**: Flavor text for the enemy
+- **Enemy Sprite**: 2D sprite representation
+
+### Core Stats (Based on SkeletonCharacter.cs)
+- **Max Health**: Hit points (1-100)
+- **Attack**: Base attack value (1-30)
+- **Constitution**: Physical resilience (1-30)
+- **Dexterity**: Speed and agility (1-30)
+- **Wisdom**: Mental acuity (1-30)
+
+### Combat Modifiers
+- **Init Modifier**: Initiative bonus/penalty (-10 to +10)
+- **Damage Modifier**: Damage bonus/penalty (-10 to +10)
+- **Spell Modifier**: Spell casting bonus/penalty (-10 to +10)
+- **Movement Speed**: Movement range (1-50)
+- **Armor Class**: Defense rating (1-30)
+
+### Weapon Configuration
+- **Preferred Weapon Type**: Sword, Bow, Staff, Dagger, Axe, Mace
+- **Weapon Prefab**: Optional specific weapon prefab
+- **Arrow Prefab**: For ranged enemies
+
+### AI & Behavior
+- **Aggressiveness**: How likely to attack vs defend (0-1)
+- **Threat Level**: For encounter balancing (1-10)
+
+### Rewards
+- **Gold Reward**: Gold dropped when defeated
+- **Experience Reward**: XP awarded to player
+- **Drop Table**: Items that can be dropped
+
+### Special Abilities
+- **Can Cast Spells**: Enable spell casting
+- **Has Ranged Attack**: Enable ranged attacks
+- **Can Fly**: Enable flight movement
+- **Regenerates Health**: Enable health regeneration
+- **Health Regen Per Turn**: Amount healed per turn
+
+## Generated Scripts
+
+Generated enemy scripts include:
+- Complete character class inheriting from `Character`
+- Proper stat initialization based on your configuration
+- Weapon creation logic based on preferred weapon type
+- Reward and threat level methods
+- Comments indicating special abilities
+
+### Example Generated Class
+```csharp
+public class SkeletonWarriorCharacter : Character
+{
+    protected override void InitializeStats()
+    {
+        MaxHealth = 10;
+        CurrentHealth = MaxHealth;
+        Attack = 8;
+        // ... all other stats
+    }
+    
+    public override Character Spawn(int count)
+    {
+        name = "Skeleton Warrior";
+        CharacterName = "Skeleton Warrior";
+        // Handle multiple spawns
+        return this;
+    }
+    
+    // Weapon creation and other methods...
+}
+```
+
+## Integration with Travel Events
+
+The **spawn settings** (group size, biome preferences, encounter frequency) are now handled by the **Travel Event system** instead of individual enemy data. This provides better separation of concerns:
+
+- **Enemy Data**: Focuses on individual enemy stats, abilities, and rewards
+- **Travel Events**: Handles when, where, and how many enemies spawn
+
+### Travel Event Configuration
+```csharp
+// In your travel events
+public int minEnemies = 1;           // Group size controlled here
+public int maxEnemies = 3;
+public float forestChance = 0.8f;    // Biome preferences here
+public EnemyCharacterData[] possibleEnemies; // Reference to enemy data
+```
+
+Generated enemies can be easily used with the travel event system:
+
+```csharp
+// In your travel events
+battleData.enemyType = "SkeletonWarrior";
+battleData.enemyCount = 2;
+```
+
+## File Locations
+
+- **Enemy Data Assets**: `Assets/Scripts/Characters/Enemies/`
+- **Generated Scripts**: `Assets/Scripts/Characters/Enemies/Generated/`
+- **Editor Scripts**: `Assets/Scripts/Editor/`
+
+## Tips
+
+1. **Start with Examples**: Use the provided SkeletonWarrior, GoblinScout, and ForestTroll as templates
+2. **Consistent Naming**: Use clear, descriptive names for easy identification
+3. **Balance Stats**: Consider threat level when setting stats and rewards
+4. **Test Generated Scripts**: Always test generated enemies in battle scenarios
+5. **Backup Data**: Keep your enemy data assets in version control
+
+## Extending the System
+
+To add new features:
+1. Add fields to `EnemyCharacterData.cs`
+2. Update the `GenerateCharacterScript()` method
+3. Modify the editor window if needed
+4. Test with existing enemies
+
+## Troubleshooting
+
+**Script won't generate**: Check that output folder exists and is writable
+**Compilation errors**: Ensure all referenced types (WeaponType, BiomeType) exist
+**Missing menu items**: Confirm editor scripts are in an Editor folder
+
+## Examples Included
+
+- **SkeletonWarrior**: Ranged archer with moderate stats
+- **GoblinScout**: Fast, aggressive melee fighter
+- **ForestTroll**: Tanky regenerating boss-type enemy

+ 117 - 0
ENEMY_WEAPON_SYSTEM_UPDATE.md

@@ -0,0 +1,117 @@
+# Enemy Character Weapon System Update
+
+## Overview
+Updated the EnemyCharacterData system to use WeaponItem assets instead of WeaponType enums, providing better integration with the existing weapon system and centralizing weapon configuration.
+
+## Key Changes
+
+### EnemyCharacterData.cs
+**BEFORE:**
+- Used `WeaponType preferredWeaponType` enum field
+- Had separate `Weapon weaponPrefab` and `GameObject arrowPrefab` fields
+- Generated hardcoded weapon creation logic based on weapon type
+
+**AFTER:**
+- Uses `WeaponItem preferredWeapon` asset reference
+- Removed redundant prefab fields (moved to WeaponItem)
+- Simplified weapon creation using `preferredWeapon.CreateWeaponInstance()`
+
+### WeaponItem.cs
+**ENHANCED:**
+- Added `GameObject weaponPrefab` field for 3D weapon models
+- Already had `GameObject arrowPrefab` field for ranged weapons
+- Centralized all weapon configuration in one asset
+
+## Benefits
+
+### 1. Type Safety
+- Enemies can only use weapons that exist as assets
+- No more hardcoded weapon types in enemy data
+- Inspector shows drag-drop fields for weapon selection
+
+### 2. Centralized Configuration
+- All weapon properties (damage, range, speed, prefabs) in WeaponItem
+- No duplication of weapon data across different systems
+- Easy to create new weapons and assign to enemies
+
+### 3. Better Integration
+- Uses same weapon system as player characters
+- Consistent weapon creation across all character types
+- Leverages existing WeaponItem.CreateWeaponInstance() method
+
+### 4. Simplified Maintenance
+- Adding new weapon types only requires creating WeaponItem assets
+- No need to update enemy creation code for new weapons
+- Weapon prefabs managed in one place
+
+## Usage Workflow
+
+### Creating Enemy Weapons
+1. Create WeaponItem asset: `Create → RPG → Items → Weapon`
+2. Configure weapon stats (damage, range, speed, etc.)
+3. Set `weaponClassName` (e.g., "SimpleSword", "SimpleBow")
+4. Assign `weaponPrefab` for 3D model (optional)
+5. Assign `arrowPrefab` for ranged weapons (if applicable)
+
+### Assigning to Enemies
+1. Open existing EnemyCharacterData asset
+2. Drag WeaponItem asset into `Preferred Weapon` field
+3. Generated enemy characters will use this weapon automatically
+
+### Fallback Behavior
+- If no WeaponItem assigned, enemies get basic sword
+- Ensures all enemies have functional weapons
+- Prevents null reference errors
+
+## Generated Character Code
+The updated system generates cleaner character classes:
+
+```csharp
+protected override Weapon CreateDirectWeapon()
+{
+    // Create weapon from WeaponItem asset
+    if (preferredWeapon != null)
+    {
+        spawnedWeapon = preferredWeapon.CreateWeaponInstance(this.transform);
+        if (spawnedWeapon != null)
+        {
+            spawnedWeapon.SetWielder(this);
+            return spawnedWeapon;
+        }
+    }
+    
+    // Fallback: Create basic sword if no weapon item assigned
+    GameObject weaponObject = new GameObject("Basic Weapon");
+    weaponObject.transform.SetParent(this.transform, false);
+    spawnedWeapon = weaponObject.AddComponent<SimpleSword>();
+    spawnedWeapon.SetWielder(this);
+    return spawnedWeapon;
+}
+```
+
+## Migration Guide
+
+### For Existing Enemy Assets
+1. Open each EnemyCharacterData asset
+2. Create appropriate WeaponItem for the current `preferredWeaponType`
+3. Assign the WeaponItem to `preferredWeapon` field
+4. The old WeaponType field will be automatically removed
+
+### For New Enemies
+1. Create WeaponItem assets first
+2. Then create EnemyCharacterData and assign weapons
+3. Use the enhanced enemy creation workflow
+
+## Technical Integration
+
+### With Travel Events
+- CombatTravelEvent continues to use EnemyCharacterData assets
+- Weapons are automatically configured when enemies spawn
+- No changes needed to travel event system
+
+### With Battle System
+- Generated enemy characters work seamlessly with existing battle system
+- Weapon creation happens during character initialization
+- All weapon types supported through WeaponItem system
+
+This update provides a much cleaner, more maintainable approach to enemy weapon configuration while maintaining full backward compatibility through the fallback system.

+ 188 - 0
SEPARATION_OF_CONCERNS_GUIDE.md

@@ -0,0 +1,188 @@
+# Improved Enemy System: Separation of Concerns
+
+## Overview
+
+The enemy character system has been refactored to provide better separation of concerns between **individual enemy data** and **spawning/encounter logic**.
+
+## What Changed
+
+### Before: Mixed Responsibilities ❌
+```csharp
+// EnemyCharacterData.cs (BAD)
+public class EnemyCharacterData : ScriptableObject
+{
+    // Individual enemy stats
+    public int maxHealth = 10;
+    public int attack = 8;
+    
+    // Spawning logic (WRONG PLACE!)
+    public int minGroupSize = 1;
+    public int maxGroupSize = 3;
+    public BiomeType[] preferredBiomes;
+}
+```
+
+### After: Clean Separation ✅
+```csharp
+// EnemyCharacterData.cs (GOOD)
+public class EnemyCharacterData : ScriptableObject
+{
+    // ONLY individual enemy data
+    public int maxHealth = 10;
+    public int attack = 8;
+    public WeaponType preferredWeaponType;
+    public bool regeneratesHealth;
+    // etc...
+}
+
+// CombatTravelEvent.cs (GOOD)
+public class CombatTravelEvent : TravelEvent
+{
+    // ONLY spawning/encounter logic
+    public int minEnemies = 1;
+    public int maxEnemies = 3;
+    public float forestChance = 0.8f;
+    public EnemyCharacterData[] possibleEnemies;
+}
+```
+
+## Benefits
+
+### 🎯 **Single Responsibility Principle**
+- **EnemyCharacterData**: Individual enemy stats, abilities, and rewards
+- **Travel Events**: When, where, and how many enemies spawn
+
+### 🔄 **Reusability**
+- Same enemy can be used in different encounters with different group sizes
+- Forest Troll can appear solo in "Boss Encounter" or in groups in "Troll Pack"
+
+### 🛠️ **Maintainability**
+- Change spawn behavior without touching enemy stats
+- Modify enemy stats without affecting encounter design
+
+### 🎮 **Game Design Flexibility**
+```csharp
+// Same Skeleton Warrior in different contexts:
+
+// Solo boss fight
+var bossFight = new CombatTravelEvent {
+    minEnemies = 1,
+    maxEnemies = 1,
+    possibleEnemies = { skeletonWarrior }
+};
+
+// Small patrol
+var patrol = new CombatTravelEvent {
+    minEnemies = 2,
+    maxEnemies = 4,
+    possibleEnemies = { skeletonWarrior, goblinScout }
+};
+
+// Large army encounter
+var army = new CombatTravelEvent {
+    minEnemies = 5,
+    maxEnemies = 8,
+    possibleEnemies = { skeletonWarrior, goblinScout, forestTroll }
+};
+```
+
+## File Structure
+
+### Enemy Data (Individual Stats)
+```
+Assets/Scripts/Characters/Enemies/
+├── EnemyCharacterData.cs        (Base class for enemy stats)
+├── SkeletonWarrior.asset        (Individual skeleton data)
+├── GoblinScout.asset           (Individual goblin data)
+└── ForestTroll.asset           (Individual troll data)
+```
+
+### Travel Events (Encounter Logic)
+```
+Assets/Scripts/Events/
+├── TravelEventTypes.cs         (CombatTravelEvent class)
+├── SpecificTravelEvents.cs     (Specific encounter types)
+└── TravelEventSystem.cs        (Main event manager)
+
+Assets/Resources/TravelEvents/
+├── SkeletonAmbush.asset        (1-3 skeletons in forests)
+├── GoblinRaid.asset            (2-5 goblins on roads)
+└── TrollEncounter.asset        (1 troll in deep forests)
+```
+
+## Migration Guide
+
+### For Existing Enemy Assets
+- ✅ **Automatically cleaned**: Spawn settings removed from all enemy assets
+- ✅ **No code changes needed**: Generated enemy scripts still work
+- ✅ **Backward compatible**: Existing functionality preserved
+
+### For New Travel Events
+```csharp
+// Create travel events that reference enemy data:
+[CreateAssetMenu(fileName = "Skeleton Ambush", menuName = "RPG/Travel Events/Specific/Skeleton Ambush")]
+public class SkeletonAmbushEvent : CombatTravelEvent
+{
+    void OnEnable()
+    {
+        eventName = "Skeleton Ambush";
+        
+        // Encounter-specific settings
+        minEnemies = 1;
+        maxEnemies = 3;
+        forestChance = 0.8f;
+        roadChance = 0.2f;
+        
+        // Reference to enemy data (drag from Project window)
+        possibleEnemies = new EnemyCharacterData[] { 
+            /* Drag SkeletonWarrior.asset here */ 
+        };
+    }
+}
+```
+
+## Best Practices
+
+### ✅ Do This:
+- Put **individual stats** in EnemyCharacterData
+- Put **encounter rules** in Travel Events
+- Reference enemy data assets in travel events
+- Use multiple travel events for the same enemy in different contexts
+
+### ❌ Don't Do This:
+- Put spawn logic in enemy data
+- Put individual stats in travel events
+- Hardcode encounter parameters in enemy scripts
+- Mix individual and group behaviors
+
+## Example Scenarios
+
+### Scenario 1: Bandit Encounters
+```csharp
+// BanditLeader.asset (Individual)
+maxHealth = 25, attack = 10, goldReward = 50
+
+// BanditSoldier.asset (Individual)  
+maxHealth = 15, attack = 8, goldReward = 20
+
+// BanditAmbush.asset (Encounter)
+minEnemies = 3, maxEnemies = 5
+possibleEnemies = [BanditSoldier, BanditLeader]
+forestChance = 0.9f, roadChance = 0.3f
+```
+
+### Scenario 2: Dynamic Difficulty
+```csharp
+// Same enemies, different encounter intensity:
+
+// Easy Encounter
+minEnemies = 1, maxEnemies = 2
+
+// Normal Encounter  
+minEnemies = 2, maxEnemies = 4
+
+// Hard Encounter
+minEnemies = 3, maxEnemies = 6
+```
+
+This separation makes the system much more flexible and maintainable! 🎯

+ 145 - 0
SKELETON_AMBUSH_CREATION_GUIDE.md

@@ -0,0 +1,145 @@
+# How to Create a Skeleton Ambush Travel Event
+
+This guide shows you how to create a Simple Combat Travel Event that spawns 1-3 Skeleton Warriors.
+
+## Method 1: Using Unity's Create Menu (Recommended)
+
+### Step 1: Create the Event Asset
+1. In the **Project window**, navigate to `Assets/Resources/TravelEvents/`
+2. Right-click and select **Create → RPG → Travel Events → Combat Event**
+3. Name it `SkeletonAmbush`
+
+### Step 2: Configure the Event in Inspector
+Open the `SkeletonAmbush` asset and configure these settings:
+
+#### Basic Event Info
+- **Event Name**: `Skeleton Ambush`
+- **Event Description**: `Ancient skeletal warriors rise from the ground to attack your party!`
+- **Event Type**: `Combat`
+- **Rarity**: `Common`
+
+#### Terrain Preferences (where skeletons are more likely)
+- **Plains Chance**: `0.3` (30%)
+- **Forest Chance**: `0.8` (80% - very common in forests)
+- **Mountain Chance**: `0.6` (60%)
+- **Road Chance**: `0.2` (20% - safer on roads)
+- **River Chance**: `0.4` (40%)
+- **Lake Chance**: `0.3` (30%)
+- **Ocean Chance**: `0.1` (10%)
+
+#### Feature Preferences
+- **Town Chance**: `0.05` (5% - very rare in towns)
+- **Village Chance**: `0.15` (15%)
+- **Bridge Chance**: `0.4` (40%)
+- **Tunnel Chance**: `0.7` (70% - common in tunnels/caves)
+- **Ferry Chance**: `0.2` (20%)
+
+#### Timing
+- **Can Occur Multiple Times**: ✅ **Checked**
+- **Cooldown Days**: `0.5` (half a day before can happen again)
+
+#### Combat Event Settings
+- **Min Enemies**: `1`
+- **Max Enemies**: `3`
+- **Possible Enemy Types**: 
+  - Add `Skeleton Warrior`
+  - Add `Skeleton` (if you have both types)
+
+#### Combat Event Descriptions
+Add these dramatic descriptions (the system will pick one randomly):
+- `Bones clatter as skeletal warriors emerge from the earth!`
+- `Ancient skeletons wielding rusty weapons block your path!`
+- `The ground splits open as undead skeletons rise to attack!`
+- `Skeletal archers take aim from the shadows ahead!`
+
+#### Difficulty
+- **Difficulty**: `Easy` or `Normal` (depending on your game balance)
+
+### Step 3: Test the Event
+1. **Save** the asset
+2. In the **TravelEventSystem** component, add your new event to the **Available Events** list
+3. Use the **Debug** option `Trigger Event Check` to test it
+
+## Method 2: Using the Travel Event System (In-Game)
+
+### Auto-Loading from Resources
+If you put the event in `Assets/Resources/TravelEvents/`, the system will automatically load it when no events are assigned to the TravelEventSystem.
+
+### Manual Assignment
+1. Find the **TravelEventSystem** component in your scene
+2. In the **Available Events** list, click the **+** button
+3. Drag your `SkeletonAmbush` asset into the slot
+
+## Integration with Your Enemy System
+
+### Using Your Generated Enemy Names
+Since you have the enemy character creation system, use these enemy names in the **Possible Enemy Types**:
+- `Skeleton Warrior` (matches your SkeletonWarrior.asset)
+- `Skeleton` (if you create a basic skeleton variant)
+
+### Battle Integration
+When the event triggers, it will:
+1. **Stop Travel** (if configured to do so)
+2. **Create Battle Data** with the specified enemy count and type
+3. **Call HandleBattleEvent** in TravelEventSystem
+4. **Set up BattleSetupData** for your battle system
+
+### Example Battle Setup Code
+In `TravelEventSystem.cs`, the `HandleBattleEvent` method will populate your battle system:
+
+```csharp
+private void HandleBattleEvent(BattleEventData battleData, TravelEventContext context)
+{
+    if (battleData == null) return;
+
+    Debug.Log($"⚔️ Setting up battle: {battleData.enemyCount} {battleData.enemyType}(s)");
+
+    // This integrates with your battle system
+    BattleSetupData.enemySelections.Clear();
+    for (int i = 0; i < battleData.enemyCount; i++)
+    {
+        BattleSetupData.enemySelections.Add(new CharacterSelection
+        {
+            characterName = $"{battleData.enemyType}_{i+1}",
+            weaponType = "Bow" // Skeleton Warriors use bows
+        });
+    }
+    
+    // Start the battle scene
+    // SceneManager.LoadScene("BattleScene");
+}
+```
+
+## Testing Your Event
+
+### Debug Testing
+1. Enable **Show Debug Logs** in TravelEventSystem
+2. Set **Force Next Event** to true
+3. Click **Trigger Event Check** in the Inspector
+4. Check the Console for event messages
+
+### Travel Testing
+1. Start traveling on the map
+2. The event will trigger based on terrain probabilities
+3. Higher chance in forests (80%), lower on roads (20%)
+
+## Customization Tips
+
+### Adjust Spawning Numbers
+- **Easy encounters**: `minEnemies = 1, maxEnemies = 2`
+- **Normal encounters**: `minEnemies = 1, maxEnemies = 3` 
+- **Hard encounters**: `minEnemies = 2, maxEnemies = 4`
+
+### Terrain-Specific Variants
+Create different skeleton events for different terrains:
+- **Forest Skeleton Ambush**: High forest chance, includes Forest Skeleton types
+- **Mountain Skeleton Raiders**: High mountain chance, tougher skeleton variants
+- **Road Skeleton Bandits**: Moderate road chance, skeleton brigands
+
+### Loot and Rewards
+The system can also provide rewards after defeating skeletons:
+- **Gold Reward**: Based on the enemies defeated
+- **Experience**: From your enemy character data
+- **Items**: From the DropTable in your EnemyCharacterData
+
+Your Skeleton Ambush event is now ready to terrorize travelers! 💀⚔️

+ 247 - 0
TRAVEL_EVENT_SYSTEM_GUIDE.md

@@ -0,0 +1,247 @@
+# Travel Event System
+
+## Overview
+
+The Travel Event System adds random encounters and events during travel in your RPG. Events can be combat encounters (ambushes), trading opportunities (merchants), discoveries (treasure), and more. Events are terrain-aware, so bandits are more likely in forests and mountains, while merchants are more common on roads.
+
+## Quick Setup
+
+1. **Add the setup component to your travel system:**
+   - Find your GameObject with `TeamTravelSystem`
+   - Add the `TravelEventSystemSetup` component
+   - Click "Setup Event System" button in the inspector (or it will auto-setup on Start)
+
+2. **Create travel events:**
+   - Right-click in Project window
+   - Go to `Create > RPG > Travel Events`
+   - Choose the event type you want (Combat, Trading, Discovery, etc.)
+   - Configure the event settings
+
+3. **Assign events to the system:**
+   - Find the `TravelEventSystem` component
+   - Add your created events to the "Available Events" list
+
+## Event Types
+
+### Combat Events
+- **Forest Ambush**: Bandits attack from forest cover
+- **Mountain Ambush**: Dangerous encounters in rocky terrain
+- **Wild Animals**: Bears, wolves, or other creatures
+
+**Settings:**
+- More likely in wilderness (forests, mountains)
+- Less likely on roads and in towns
+- Can specify enemy count and types
+
+### Trading Events
+- **Traveling Merchant**: Traders offering goods
+- **Caravan**: Large trading groups
+- **Road Patrol**: Guards who may have supplies
+
+**Settings:**
+- More likely on roads and near settlements
+- Can have rare items and different price modifiers
+- Some merchants specialize in certain goods
+
+### Discovery Events
+- **Hidden Cache**: Abandoned treasure stashes
+- **Natural Resources**: Herbs, minerals, etc.
+- **Lost Items**: Equipment left by other travelers
+
+**Settings:**
+- More likely in remote areas off main roads
+- Can provide gold, items, or resources
+
+### Rest Events
+- **Safe Camping**: Peaceful spots for healing
+- **Natural Springs**: Healing waters
+- **Shelter**: Protection from weather
+
+**Settings:**
+- Common near water sources and in natural areas
+- Restores health and party morale
+
+### Hazard Events
+- **Rockslides**: Mountain dangers
+- **Difficult Terrain**: Swamps, thorns, etc.
+- **Weather**: Storms, extreme heat/cold
+
+**Settings:**
+- More likely in dangerous terrain
+- Can cause health loss or resource costs
+
+## Terrain Probability System
+
+Each event has probability modifiers for different terrain and feature types:
+
+### Terrain Types
+- **Plains**: 0.5 (baseline)
+- **Forest**: Higher for ambushes, lower for merchants
+- **Mountains**: Higher for ambushes and hazards
+- **Rivers/Lakes**: Higher for rest events
+- **Roads**: Higher for merchants, lower for ambushes
+
+### Feature Types
+- **Towns/Villages**: Safe, good for trading
+- **Bridges**: Common meeting points
+- **Tunnels**: Can be dangerous or shortcuts
+- **Ferries**: Trading opportunities
+
+## Configuration
+
+### Event System Settings
+```csharp
+public float baseEventChance = 0.15f;  // 15% base chance per check
+public int tilesPerEventCheck = 3;     // Check every 3 tiles
+```
+
+### Event Rarity
+- **Very Common**: 25% base chance
+- **Common**: 15% base chance  
+- **Uncommon**: 8% base chance
+- **Rare**: 4% base chance
+- **Very Rare**: 2% base chance
+- **Legendary**: 0.5% base chance
+
+## Creating Custom Events
+
+### 1. Create a ScriptableObject Event
+```csharp
+[CreateAssetMenu(fileName = "My Custom Event", menuName = "RPG/Travel Events/Custom Event")]
+public class MyCustomEvent : TravelEvent
+{
+    public override EventResult ExecuteEvent(TravelEventContext context)
+    {
+        // Your event logic here
+        return new EventResult("Something interesting happened!");
+    }
+}
+```
+
+### 2. Set Terrain Preferences
+```csharp
+void OnEnable()
+{
+    eventType = EventType.Discovery;
+    rarity = EventRarity.Uncommon;
+    
+    // More likely in forests
+    forestChance = 0.8f;
+    roadChance = 0.2f;
+    townChance = 0.1f;
+}
+```
+
+### 3. Handle Event Results
+```csharp
+public override EventResult ExecuteEvent(TravelEventContext context)
+{
+    return new EventResult("You found treasure!")
+    {
+        goldChange = 50,
+        healthChange = 10,
+        shouldStopTravel = false
+    };
+}
+```
+
+## Integration with Battle System
+
+Combat events can automatically trigger battles:
+
+```csharp
+return EventResult.SimpleBattle(
+    "Bandits attack your party!",
+    enemyCount: 3,
+    enemyType: "Forest Bandit"
+);
+```
+
+This will:
+1. Stop travel
+2. Show the event message
+3. Set up battle with specified enemies
+4. Transition to battle scene
+
+## Integration with Trading System
+
+Trading events can open shop interfaces:
+
+```csharp
+return EventResult.SimpleTrading(
+    "A merchant offers goods for sale.",
+    merchantType: "Traveling Merchant"
+);
+```
+
+This will:
+1. Stop travel
+2. Show the event message
+3. Open trading interface
+4. Apply any price modifiers
+
+## Event Context
+
+Events receive context information to make intelligent decisions:
+
+```csharp
+public class TravelEventContext
+{
+    public Vector2Int currentPosition;
+    public MapTile currentTile;
+    public TravelRoute currentRoute;
+    public List<TeamCharacter> teamMembers;
+    public int teamGold;
+    public TravelEventHistory eventHistory;
+}
+```
+
+## Testing and Debugging
+
+### Debug Features
+- Enable `showDebugLogs` for detailed event information
+- Use `TriggerEventCheck()` method to force event checks
+- Use `forceNextEvent` to guarantee next event occurs
+
+### Console Commands
+- Right-click TravelEventSystem → "Trigger Event Check"
+- Right-click TravelEventSystem → "Reset Event History"
+
+### Example Events
+Add `TravelEventExampleCreator` component to any GameObject and use "Create Example Events" to generate test events.
+
+## Best Practices
+
+1. **Balance**: Don't make events too frequent or rare
+2. **Variety**: Mix different event types for interesting travel
+3. **Terrain Logic**: Make events make sense for their location
+4. **Player Agency**: Some events should offer choices
+5. **Resource Management**: Events should interact with player resources meaningfully
+
+## Troubleshooting
+
+### Events Not Triggering
+- Check that `enableEvents` is true
+- Verify events are added to `availableEvents` list
+- Check terrain probability settings
+- Ensure travel system is active
+
+### Events Too Frequent/Rare
+- Adjust `baseEventChance` (0.15 = 15%)
+- Modify `tilesPerEventCheck` (higher = less frequent)
+- Adjust individual event rarity settings
+
+### UI Not Showing
+- Add `TravelEventUI` component to scene
+- Enable `useDebugUI` for simple debug display
+- Check console for event messages
+
+## Future Enhancements
+
+Possible extensions to the system:
+- Weather-based events
+- Seasonal event variations
+- Reputation-based event outcomes
+- Multi-part story events
+- Time-of-day event variations
+- Party composition effects on events

+ 175 - 0
TYPE_SAFE_TRAVEL_EVENTS_GUIDE.md

@@ -0,0 +1,175 @@
+# Type-Safe Enemy Travel Events Guide
+
+You're absolutely right! Using EnemyCharacterData references instead of strings is much safer and better design. Here's how the improved system works:
+
+## ✅ **Benefits of the New System**
+
+### **Before (String-Based - Risky)**
+```csharp
+possibleEnemyTypes = new string[] { "Skeleton Warrior", "Skelton", "Skelton Warior" };
+//                                    ✅ Correct      ❌ Typo   ❌ Typo
+```
+
+### **After (Type-Safe - Safe)**
+```csharp
+possibleEnemies = new EnemyCharacterData[] { skeletonWarriorAsset, goblinScoutAsset };
+//                                          ✅ Actual assets - no typos possible!
+```
+
+## 🎯 **How to Create Type-Safe Skeleton Ambush**
+
+### **Step 1: Create the Event**
+1. Right-click in Project → **Create → RPG → Travel Events → Specific → Skeleton Ambush**
+2. Name it `SkeletonAmbush`
+
+### **Step 2: Configure in Inspector**
+The new system has these fields:
+
+#### **Combat Event Settings**
+- **Min Enemies**: `1`
+- **Max Enemies**: `3`
+- **Possible Enemies**: ⭐ **NEW - Drag EnemyCharacterData assets here**
+  - Drag `SkeletonWarrior.asset`
+  - Drag `ForestTroll.asset` (if you want mixed encounters)
+  - Drag any other enemy assets you created
+
+#### **Backward Compatibility**
+- **Possible Enemy Types**: Leave empty (old string system)
+
+### **Step 3: Enhanced Battle Integration**
+When the event triggers, you get:
+
+```csharp
+// Enhanced debug info
+🎯 Using enemy data: Skeleton Warrior
+📊 Enemy stats: HP=10, AC=6, Threat=2
+
+// Enhanced battle setup with actual enemy data
+characterName = "Skeleton Warrior_1"
+weaponType = "Bow"           // From enemyData.preferredWeaponType
+health = 10                  // From enemyData.maxHealth  
+armorClass = 6              // From enemyData.armorClass
+threatLevel = 2             // From enemyData.threatLevel
+```
+
+## 🔧 **Technical Improvements**
+
+### **Enhanced BattleEventData**
+```csharp
+public class BattleEventData
+{
+    public int enemyCount = 1;
+    public string enemyType = "Bandit";              // Legacy fallback
+    public EnemyCharacterData enemyCharacterData;    // ⭐ NEW - Type-safe reference
+}
+```
+
+### **Smart Event Execution**
+```csharp
+// 1. Try to use EnemyCharacterData first (safe)
+if (possibleEnemies.Length > 0)
+{
+    selectedEnemy = possibleEnemies[Random.Range(0, possibleEnemies.Length)];
+    enemyType = selectedEnemy.enemyName;  // Get name from asset
+}
+// 2. Fall back to strings if needed (backward compatibility)
+else
+{
+    enemyType = possibleEnemyTypes[Random.Range(0, possibleEnemyTypes.Length)];
+}
+```
+
+### **Enhanced Battle Setup**
+```csharp
+private void HandleBattleEvent(BattleEventData battleData, TravelEventContext context)
+{
+    if (battleData.enemyCharacterData != null)
+    {
+        // ✅ Use actual enemy stats from the asset
+        var enemyData = battleData.enemyCharacterData;
+        
+        for (int i = 0; i < battleData.enemyCount; i++)
+        {
+            BattleSetupData.enemySelections.Add(new CharacterSelection
+            {
+                characterName = $"{enemyData.enemyName}_{i+1}",
+                weaponType = enemyData.preferredWeaponType.ToString(),
+                health = enemyData.maxHealth,
+                armorClass = enemyData.armorClass,
+                // Access ALL the enemy data you configured!
+            });
+        }
+    }
+}
+```
+
+## 🎮 **Practical Usage**
+
+### **Creating Mixed Encounters**
+You can now easily create varied encounters:
+
+**Forest Encounter:**
+- Drag `SkeletonWarrior.asset`
+- Drag `GoblinScout.asset`
+- **Result**: Random mix of skeletons and goblins!
+
+**Boss Encounter:**
+- Drag `ForestTroll.asset` only
+- Set `minEnemies = 1, maxEnemies = 1`
+- **Result**: Always spawns exactly 1 Forest Troll!
+
+### **Automatic Weapon Assignment**
+```csharp
+// Skeleton Warrior (preferredWeaponType = Bow)
+weaponType = "Bow"     // ✅ Automatic from asset
+
+// Goblin Scout (preferredWeaponType = Dagger)  
+weaponType = "Dagger"  // ✅ Automatic from asset
+
+// Forest Troll (preferredWeaponType = Mace)
+weaponType = "Mace"    // ✅ Automatic from asset
+```
+
+## 🛡️ **Safety Features**
+
+### **Null Protection**
+```csharp
+// Filters out null/missing references automatically
+var validEnemies = System.Array.FindAll(possibleEnemies, e => e != null);
+```
+
+### **Fallback System**
+```csharp
+// If no EnemyCharacterData, falls back to strings
+// If no strings either, uses "Unknown Enemy"
+// Never crashes due to missing enemies!
+```
+
+### **Inspector Validation**
+- **Visual feedback**: See enemy icons in Inspector
+- **Drag & drop**: Only EnemyCharacterData assets can be dragged
+- **Reference tracking**: Unity updates references if you rename assets
+
+## 📝 **Migration from String System**
+
+### **Old Events (Still Work)**
+```csharp
+possibleEnemyTypes = new string[] { "Skeleton Warrior" };
+// ✅ Still works for backward compatibility
+```
+
+### **New Events (Recommended)**
+```csharp
+possibleEnemies = new EnemyCharacterData[] { skeletonWarriorAsset };
+// ✅ Type-safe, no typos, full enemy data access
+```
+
+## 🚀 **Quick Setup Checklist**
+
+1. ✅ **Create enemy assets** using the Enemy Character Creator
+2. ✅ **Create travel event** using "Skeleton Ambush" template  
+3. ✅ **Drag enemy assets** into "Possible Enemies" field
+4. ✅ **Leave string arrays empty** (use new system)
+5. ✅ **Test** with "Trigger Event Check"
+
+The type-safe system is now ready! No more misspelled enemy names causing runtime errors. 🎉