Browse Source

Combat event workarounds and UI complete

Axel Nordh 10 tháng trước cách đây
mục cha
commit
fb5c1518cd
42 tập tin đã thay đổi với 7216 bổ sung3 xóa
  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. 🎉