using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.UIElements;
#if UNITY_EDITOR
using UnityEditor;
#endif
///
/// Handles post-battle looting when all enemies are defeated
/// Allows players to loot enemy corpses and manage inventory weight
///
public class PostBattleLootSystem : MonoBehaviour
{
[Header("UI Toolkit References")]
public UIDocument lootUIDocument;
public VisualTreeAsset lootScreenTemplate;
public PanelSettings panelSettings;
[Header("Currency Settings")]
public int baseGoldReward = 5;
public int baseSilverReward = 15;
public int baseCopperReward = 25;
[Header("Debug Settings")]
public bool showDebugLogs = true;
[Header("Item Distribution Settings")]
public bool enablePlayerItemSelection = true; // Allow manual item distribution
public bool autoDistributeItems = false; // If true, items are distributed automatically
// Events
public event System.Action OnLootingComplete;
private List lootableEnemies = new List();
private bool isLootingActive = false;
private VisualElement rootElement;
private bool takeAllPressed = false;
private Dictionary selectedPlayerForItem = new Dictionary(); // itemName -> playerIndex
///
/// Gets whether the looting process is currently active
///
public bool IsLootingActive => isLootingActive;
[System.Serializable]
public class LootableEnemy
{
public string enemyName;
public List dropItems = new List();
public int goldReward;
public int silverReward;
public int copperReward;
public bool hasBeenLooted = false;
public Vector3 corpsePosition;
public LootableEnemy(string name, Vector3 position)
{
enemyName = name;
corpsePosition = position;
}
}
[System.Serializable]
public class LootableItem
{
public string itemName;
public string description;
public int weight = 1;
public int value = 1; // In copper
public bool isSelected = false;
public LootableItem(string name, string desc, int itemWeight = 1, int itemValue = 1)
{
itemName = name;
description = desc;
weight = itemWeight;
value = itemValue;
}
}
///
/// Initialize looting system with defeated enemies
///
public void InitializeLootSystem(List defeatedEnemies)
{
lootableEnemies.Clear();
foreach (var enemy in defeatedEnemies)
{
if (enemy == null) continue;
Character enemyCharacter = enemy.GetComponent();
if (enemyCharacter == null || !enemyCharacter.IsDead) continue;
var lootableEnemy = new LootableEnemy(enemyCharacter.CharacterName, enemy.transform.position);
// Generate loot based on enemy type and random factors
GenerateEnemyLoot(lootableEnemy, enemyCharacter);
lootableEnemies.Add(lootableEnemy);
}
if (showDebugLogs)
Debug.Log($"š° Initialized loot system with {lootableEnemies.Count} lootable enemies");
}
///
/// Show the loot UI and start looting phase
///
public void StartLooting()
{
if (lootableEnemies.Count == 0)
{
if (showDebugLogs)
Debug.Log("š° No enemies to loot, ending battle");
OnLootingComplete?.Invoke();
return;
}
isLootingActive = true;
CreateAndShowLootUI();
if (showDebugLogs)
Debug.Log("š° Started post-battle looting phase");
}
///
/// Create and show the UI Toolkit loot interface
///
private void CreateAndShowLootUI()
{
// Find or create UI Document
if (lootUIDocument == null)
{
GameObject uiGO = new GameObject("LootUIDocument");
uiGO.transform.SetParent(transform);
lootUIDocument = uiGO.AddComponent();
}
// Set up the UI Document with proper references
SetupLootUIDocument();
// Get the root element
if (lootUIDocument.visualTreeAsset != null)
{
rootElement = lootUIDocument.rootVisualElement;
// Show the overlay
var overlay = rootElement.Q("LootScreenOverlay");
if (overlay != null)
{
overlay.style.display = DisplayStyle.Flex;
}
// Populate the UI with loot data
PopulateLootUI();
// Set up button callbacks
SetupUICallbacks();
}
else
{
// Fallback - create basic UI if template loading failed
Debug.LogWarning("PostBattleLootScreen.uxml not found. Creating basic UI.");
CreateBasicLootUI();
}
}
///
/// Set up the UIDocument with proper UXML template and panel settings
///
private void SetupLootUIDocument()
{
if (lootUIDocument == null) return;
// Load the UXML template if not assigned
if (lootScreenTemplate == null)
{
lootScreenTemplate = Resources.Load("UI/BattleSceneUI/PostBattleLootScreen");
if (lootScreenTemplate == null)
{
#if UNITY_EDITOR
// Try alternative path in editor
lootScreenTemplate = AssetDatabase.LoadAssetAtPath("Assets/UI/BattleSceneUI/PostBattleLootScreen.uxml");
#endif
}
}
// Load panel settings if not assigned
if (panelSettings == null)
{
panelSettings = Resources.Load("MainSettings");
if (panelSettings == null)
{
// Try alternative panel settings
panelSettings = Resources.Load("UI/TravelPanelSettings");
if (panelSettings == null)
{
// Try to find any PanelSettings in the project
var allPanelSettings = Resources.FindObjectsOfTypeAll();
if (allPanelSettings.Length > 0)
panelSettings = allPanelSettings[0];
}
}
}
// Configure the UIDocument
lootUIDocument.visualTreeAsset = lootScreenTemplate;
lootUIDocument.panelSettings = panelSettings;
// Load and apply stylesheet
var stylesheet = Resources.Load("UI/BattleSceneUI/PostBattleLootScreen");
if (stylesheet == null)
{
#if UNITY_EDITOR
stylesheet = AssetDatabase.LoadAssetAtPath("Assets/UI/BattleSceneUI/PostBattleLootScreen.uss");
#endif
}
if (stylesheet != null && lootUIDocument.rootVisualElement != null)
{
lootUIDocument.rootVisualElement.styleSheets.Add(stylesheet);
}
if (lootScreenTemplate == null)
{
Debug.LogError("PostBattleLootSystem: Could not load PostBattleLootScreen.uxml template!");
}
if (panelSettings == null)
{
Debug.LogWarning("PostBattleLootSystem: No PanelSettings found. UI may not display correctly.");
}
}
///
/// Create a basic fallback UI if the UXML template isn't available
///
private void CreateBasicLootUI()
{
// Create a simple overlay using UI Toolkit elements
rootElement = lootUIDocument.rootVisualElement;
// Create overlay
var overlay = new VisualElement();
overlay.name = "LootScreenOverlay";
overlay.style.position = Position.Absolute;
overlay.style.top = 0;
overlay.style.left = 0;
overlay.style.right = 0;
overlay.style.bottom = 0;
overlay.style.backgroundColor = new Color(0, 0, 0, 0.8f);
overlay.style.justifyContent = Justify.Center;
overlay.style.alignItems = Align.Center;
// Create background panel
var background = new VisualElement();
background.style.backgroundColor = new Color(0.1f, 0.1f, 0.2f, 0.95f);
background.style.borderTopWidth = 2;
background.style.borderBottomWidth = 2;
background.style.borderLeftWidth = 2;
background.style.borderRightWidth = 2;
background.style.borderTopColor = new Color(0.7f, 0.5f, 0.2f);
background.style.borderBottomColor = new Color(0.7f, 0.5f, 0.2f);
background.style.borderLeftColor = new Color(0.7f, 0.5f, 0.2f);
background.style.borderRightColor = new Color(0.7f, 0.5f, 0.2f);
background.style.borderTopLeftRadius = 15;
background.style.borderTopRightRadius = 15;
background.style.borderBottomLeftRadius = 15;
background.style.borderBottomRightRadius = 15;
background.style.paddingTop = 30;
background.style.paddingBottom = 30;
background.style.paddingLeft = 30;
background.style.paddingRight = 30;
background.style.width = new Length(80, LengthUnit.Percent);
background.style.maxWidth = 800;
// Add title
var title = new Label("š VICTORY! š");
title.style.fontSize = 36;
title.style.color = new Color(1f, 0.84f, 0f);
title.style.unityTextAlign = TextAnchor.MiddleCenter;
title.style.marginBottom = 20;
// Add loot info
var lootInfo = new Label();
lootInfo.name = "LootInfo";
lootInfo.style.fontSize = 14;
lootInfo.style.color = Color.white;
lootInfo.style.whiteSpace = WhiteSpace.Normal;
lootInfo.style.marginBottom = 20;
// Add continue button
var continueButton = new Button(() => CompleteLootingProcess());
continueButton.text = "Continue";
continueButton.name = "ContinueButton";
continueButton.style.fontSize = 16;
continueButton.style.paddingTop = 10;
continueButton.style.paddingBottom = 10;
continueButton.style.paddingLeft = 20;
continueButton.style.paddingRight = 20;
// Assemble the UI
background.Add(title);
background.Add(lootInfo);
background.Add(continueButton);
overlay.Add(background);
rootElement.Add(overlay);
// Populate basic loot info
PopulateBasicLootInfo(lootInfo);
}
///
/// Set up UI element callbacks for the loot interface
///
private void SetupUICallbacks()
{
if (rootElement == null) return;
// Set up Take All button
var takeAllButton = rootElement.Q("TakeAllButton");
if (takeAllButton != null)
{
takeAllButton.clicked += () =>
{
takeAllPressed = true;
// Force auto-distribution and skip player selection
bool originalAutoDistribute = autoDistributeItems;
autoDistributeItems = true; // Temporarily force auto-distribution
AutoLootAll();
// Restore original setting
autoDistributeItems = originalAutoDistribute;
};
}
// Set up Continue button - this should return to map
var continueButton = rootElement.Q("ContinueButton");
if (continueButton != null)
{
continueButton.text = "Return to Map"; // Make it clear what this button does
continueButton.clicked += () =>
{
if (!takeAllPressed)
{
AutoLootAll(); // Auto-loot if not already done
}
// CompleteLootingProcess is called by AutoLootAll, so scene transition will happen
};
}
// Set up keyboard input for space key
rootElement.RegisterCallback(OnKeyDown);
// Make sure the root element can receive focus for keyboard events
rootElement.focusable = true;
rootElement.Focus();
}
///
/// Handle keyboard input for the loot UI
///
private void OnKeyDown(KeyDownEvent evt)
{
if (evt.keyCode == KeyCode.Space)
{
if (!takeAllPressed)
{
takeAllPressed = true;
// Force auto-distribution and skip player selection
bool originalAutoDistribute = autoDistributeItems;
autoDistributeItems = true; // Temporarily force auto-distribution
AutoLootAll();
// Restore original setting
autoDistributeItems = originalAutoDistribute;
}
}
}
///
/// Populate basic loot information for fallback UI
///
private void PopulateBasicLootInfo(Label lootInfo)
{
var lootText = "Collecting loot from defeated enemies...\n\n";
int totalGold = 0, totalSilver = 0, totalCopper = 0;
List allItems = new List();
foreach (var enemy in lootableEnemies)
{
totalGold += enemy.goldReward;
totalSilver += enemy.silverReward;
totalCopper += enemy.copperReward;
allItems.AddRange(enemy.dropItems);
lootText += $"š {enemy.enemyName}: {enemy.goldReward}g {enemy.silverReward}s {enemy.copperReward}c\n";
foreach (var item in enemy.dropItems)
{
lootText += $" š¦ {item}\n";
}
}
lootText += $"\nš° Total: {totalGold} gold, {totalSilver} silver, {totalCopper} copper\n";
lootText += $"š¦ {allItems.Count} items collected\n\n";
lootText += "Click Continue to proceed or press SPACE...";
lootInfo.text = lootText;
}
///
/// Show a temporary on-screen message for looting
///
private System.Collections.IEnumerator ShowLootingMessage()
{
// Create a temporary UI GameObject
GameObject tempUI = new GameObject("TempLootUI");
tempUI.transform.SetParent(FindFirstObjectByType()?.transform, false);
// Add background panel
var canvasGroup = tempUI.AddComponent();
var image = tempUI.AddComponent();
image.color = new Color(0, 0, 0, 0.8f); // Semi-transparent black
// Set full screen size
var rectTransform = tempUI.GetComponent();
rectTransform.anchorMin = Vector2.zero;
rectTransform.anchorMax = Vector2.one;
rectTransform.offsetMin = Vector2.zero;
rectTransform.offsetMax = Vector2.zero;
// Add text
GameObject textObj = new GameObject("LootText");
textObj.transform.SetParent(tempUI.transform, false);
var text = textObj.AddComponent();
text.font = Resources.GetBuiltinResource("Arial.ttf");
text.fontSize = 24;
text.color = Color.white;
text.alignment = TextAnchor.MiddleCenter;
// Set text content
string lootText = "š VICTORY! š\n\n";
lootText += "Collecting loot from defeated enemies...\n\n";
int totalGold = 0, totalSilver = 0, totalCopper = 0;
List allItems = new List();
foreach (var enemy in lootableEnemies)
{
totalGold += enemy.goldReward;
totalSilver += enemy.silverReward;
totalCopper += enemy.copperReward;
allItems.AddRange(enemy.dropItems);
lootText += $"š {enemy.enemyName}: {enemy.goldReward}g {enemy.silverReward}s {enemy.copperReward}c\n";
foreach (var item in enemy.dropItems)
{
lootText += $" š¦ {item}\n";
}
}
lootText += $"\nš° Total: {totalGold} gold, {totalSilver} silver, {totalCopper} copper\n";
lootText += $"š¦ {allItems.Count} items collected\n\n";
lootText += "Press SPACE to continue...";
text.text = lootText;
// Set text position
var textRect = textObj.GetComponent();
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.offsetMin = new Vector2(50, 50);
textRect.offsetMax = new Vector2(-50, -50);
// Auto-loot everything
AutoLootAll();
// Wait for space key or 5 seconds
float timer = 0f;
while (timer < 5f && !Input.GetKeyDown(KeyCode.Space))
{
timer += Time.deltaTime;
yield return null;
}
// Cleanup UI
if (tempUI != null)
Destroy(tempUI);
// Complete looting
CompleteLootingProcess();
}
///
/// Complete the looting process and trigger the callback
///
private void CompleteLootingProcess()
{
isLootingActive = false;
// Hide the loot UI
if (rootElement != null)
rootElement.style.display = DisplayStyle.None;
if (showDebugLogs)
Debug.Log("š° Looting completed, triggering OnLootingComplete");
OnLootingComplete?.Invoke();
}
///
/// Generate loot for a defeated enemy
///
private void GenerateEnemyLoot(LootableEnemy lootableEnemy, Character enemyCharacter)
{
// Base currency rewards
lootableEnemy.goldReward = Random.Range(0, baseGoldReward + 1);
lootableEnemy.silverReward = Random.Range(0, baseSilverReward + 1);
lootableEnemy.copperReward = Random.Range(baseCopperReward - 5, baseCopperReward + 10);
// Basic item drops based on enemy type
GenerateBasicDrops(lootableEnemy, enemyCharacter.CharacterName);
// Try to get drops from enemy data if available
TryGetEnemyDataDrops(lootableEnemy, enemyCharacter);
if (showDebugLogs)
{
Debug.Log($"š° Generated loot for {lootableEnemy.enemyName}: " +
$"{lootableEnemy.goldReward}g {lootableEnemy.silverReward}s {lootableEnemy.copperReward}c, " +
$"{lootableEnemy.dropItems.Count} items");
}
}
///
/// Generate basic drops based on enemy name/type
///
private void GenerateBasicDrops(LootableEnemy lootableEnemy, string enemyName)
{
string lowerName = enemyName.ToLower();
// Skeleton-type enemies
if (lowerName.Contains("skeleton"))
{
if (Random.Range(0f, 1f) < 0.3f) lootableEnemy.dropItems.Add("Bone");
if (Random.Range(0f, 1f) < 0.2f) lootableEnemy.dropItems.Add("Rusty Sword");
if (Random.Range(0f, 1f) < 0.15f) lootableEnemy.dropItems.Add("Bone Dust");
}
// Bandit-type enemies
else if (lowerName.Contains("bandit") || lowerName.Contains("thief"))
{
if (Random.Range(0f, 1f) < 0.4f) lootableEnemy.dropItems.Add("Thieves' Tools");
if (Random.Range(0f, 1f) < 0.3f) lootableEnemy.dropItems.Add("Rope");
if (Random.Range(0f, 1f) < 0.2f) lootableEnemy.dropItems.Add("Dagger");
// Bandits often have extra coin
lootableEnemy.copperReward += Random.Range(5, 15);
}
// Orc-type enemies
else if (lowerName.Contains("orc") || lowerName.Contains("goblin"))
{
if (Random.Range(0f, 1f) < 0.3f) lootableEnemy.dropItems.Add("Crude Axe");
if (Random.Range(0f, 1f) < 0.25f) lootableEnemy.dropItems.Add("Hide Armor");
if (Random.Range(0f, 1f) < 0.2f) lootableEnemy.dropItems.Add("Iron Ration");
}
// Default/unknown enemies
else
{
if (Random.Range(0f, 1f) < 0.2f) lootableEnemy.dropItems.Add("Leather Scraps");
if (Random.Range(0f, 1f) < 0.15f) lootableEnemy.dropItems.Add("Iron Ration");
}
// Common drops for all enemies
if (Random.Range(0f, 1f) < 0.1f) lootableEnemy.dropItems.Add("Health Potion");
if (Random.Range(0f, 1f) < 0.05f) lootableEnemy.dropItems.Add("Bandage");
}
///
/// Try to get drops from EnemyCharacterData if available
///
private void TryGetEnemyDataDrops(LootableEnemy lootableEnemy, Character enemyCharacter)
{
// This would integrate with the EnemyCharacterData system
// For now, we'll use the basic drop system above
// TODO: Integrate with EnemyCharacterData.dropTable when available
}
///
/// Show the loot UI
///
private void ShowLootUI()
{
if (rootElement != null)
{
// Show the UI Toolkit loot interface
rootElement.style.display = DisplayStyle.Flex;
PopulateLootUI();
}
else
{
// Fallback to console-based looting for now
Debug.Log("š° === POST-BATTLE LOOT ===");
foreach (var enemy in lootableEnemies)
{
Debug.Log($"š° {enemy.enemyName}: {enemy.goldReward}g {enemy.silverReward}s {enemy.copperReward}c");
foreach (var item in enemy.dropItems)
{
Debug.Log($"š° - {item}");
}
}
Debug.Log("š° ========================");
// Auto-loot everything for now
AutoLootAll();
}
}
///
/// Populate the loot UI with available items
///
private void PopulateLootUI()
{
if (rootElement == null) return;
// Calculate totals first
int totalGold = 0, totalSilver = 0, totalCopper = 0;
List allItems = new List();
foreach (var enemy in lootableEnemies)
{
totalGold += enemy.goldReward;
totalSilver += enemy.silverReward;
totalCopper += enemy.copperReward;
allItems.AddRange(enemy.dropItems);
}
// Update currency displays with better formatting and tighter spacing
var goldLabel = rootElement.Q("GoldAmount");
var silverLabel = rootElement.Q("SilverAmount");
var copperLabel = rootElement.Q("CopperAmount");
if (goldLabel != null)
{
goldLabel.text = totalGold.ToString();
goldLabel.style.fontSize = 18; // Slightly larger than before but not huge
goldLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
goldLabel.style.marginBottom = 2; // Reduce spacing
goldLabel.style.marginTop = 2;
}
if (silverLabel != null)
{
silverLabel.text = totalSilver.ToString();
silverLabel.style.fontSize = 18;
silverLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
silverLabel.style.marginBottom = 2;
silverLabel.style.marginTop = 2;
}
if (copperLabel != null)
{
copperLabel.text = totalCopper.ToString();
copperLabel.style.fontSize = 18;
copperLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
copperLabel.style.marginBottom = 2;
copperLabel.style.marginTop = 2;
}
// Style the currency text labels to be closer to the numbers
var goldText = rootElement.Q("GoldText");
var silverText = rootElement.Q("SilverText");
var copperText = rootElement.Q("CopperText");
if (goldText != null)
{
goldText.style.fontSize = 12;
goldText.style.marginTop = -2; // Move closer to number
goldText.style.marginBottom = 8; // Add space after currency section
}
if (silverText != null)
{
silverText.style.fontSize = 12;
silverText.style.marginTop = -2;
silverText.style.marginBottom = 8;
}
if (copperText != null)
{
copperText.style.fontSize = 12;
copperText.style.marginTop = -2;
copperText.style.marginBottom = 8;
}
// Also style the currency icons to be smaller
var goldIcon = rootElement.Q("GoldIcon");
var silverIcon = rootElement.Q("SilverIcon");
var copperIcon = rootElement.Q("CopperIcon");
if (goldIcon != null) goldIcon.style.fontSize = 14;
if (silverIcon != null) silverIcon.style.fontSize = 14;
if (copperIcon != null) copperIcon.style.fontSize = 14;
// Update item count
var itemCountLabel = rootElement.Q("ItemCount");
if (itemCountLabel != null)
itemCountLabel.text = $"{allItems.Count} items";
// Populate enemy loot sections
var enemyLootContainer = rootElement.Q("EnemyLootContainer");
if (enemyLootContainer != null)
{
enemyLootContainer.Clear();
foreach (var enemy in lootableEnemies)
{
var enemySection = new VisualElement();
enemySection.AddToClassList("enemy-loot-section");
// Enemy header
var enemyHeader = new Label($"š {enemy.enemyName}");
enemyHeader.AddToClassList("enemy-name");
enemySection.Add(enemyHeader);
// Enemy currency
if (enemy.goldReward > 0 || enemy.silverReward > 0 || enemy.copperReward > 0)
{
var currencyContainer = new VisualElement();
currencyContainer.AddToClassList("enemy-currency");
if (enemy.goldReward > 0)
{
var enemyGoldLabel = new Label($"šŖ {enemy.goldReward}");
enemyGoldLabel.AddToClassList("currency-gold");
currencyContainer.Add(enemyGoldLabel);
}
if (enemy.silverReward > 0)
{
var enemySilverLabel = new Label($"šŖ {enemy.silverReward}");
enemySilverLabel.AddToClassList("currency-silver");
currencyContainer.Add(enemySilverLabel);
}
if (enemy.copperReward > 0)
{
var enemyCopperLabel = new Label($"šŖ {enemy.copperReward}");
enemyCopperLabel.AddToClassList("currency-copper");
currencyContainer.Add(enemyCopperLabel);
}
enemySection.Add(currencyContainer);
}
// Enemy items
if (enemy.dropItems != null && enemy.dropItems.Count > 0)
{
var itemsContainer = new VisualElement();
itemsContainer.AddToClassList("enemy-items");
foreach (var item in enemy.dropItems)
{
var itemLabel = new Label($"š¦ {item}");
itemLabel.AddToClassList("item-entry");
itemsContainer.Add(itemLabel);
}
enemySection.Add(itemsContainer);
}
enemyLootContainer.Add(enemySection);
}
}
// Populate the total items list scrollview with better visibility
var itemsListContainer = rootElement.Q("ItemsList");
if (itemsListContainer != null)
{
itemsListContainer.Clear();
// Set scrollview properties for better visibility and containment
itemsListContainer.style.minHeight = 80;
itemsListContainer.style.maxHeight = 150;
itemsListContainer.style.backgroundColor = new Color(0.15f, 0.15f, 0.25f, 0.9f);
itemsListContainer.style.borderTopWidth = 2;
itemsListContainer.style.borderBottomWidth = 2;
itemsListContainer.style.borderLeftWidth = 2;
itemsListContainer.style.borderRightWidth = 2;
itemsListContainer.style.borderTopColor = new Color(0.6f, 0.6f, 0.8f, 0.8f);
itemsListContainer.style.borderBottomColor = new Color(0.6f, 0.6f, 0.8f, 0.8f);
itemsListContainer.style.borderLeftColor = new Color(0.6f, 0.6f, 0.8f, 0.8f);
itemsListContainer.style.borderRightColor = new Color(0.6f, 0.6f, 0.8f, 0.8f);
itemsListContainer.style.borderTopLeftRadius = 8;
itemsListContainer.style.borderTopRightRadius = 8;
itemsListContainer.style.borderBottomLeftRadius = 8;
itemsListContainer.style.borderBottomRightRadius = 8;
itemsListContainer.style.paddingTop = 8;
itemsListContainer.style.paddingBottom = 8;
itemsListContainer.style.paddingLeft = 8;
itemsListContainer.style.paddingRight = 8;
itemsListContainer.style.marginTop = 5;
itemsListContainer.style.marginBottom = 10;
itemsListContainer.style.marginLeft = 5;
itemsListContainer.style.marginRight = 5;
if (allItems.Count > 0)
{
foreach (var item in allItems)
{
var itemEntry = new Label($"š¦ {item}");
itemEntry.AddToClassList("total-item-entry");
itemEntry.style.fontSize = 14;
itemEntry.style.color = Color.white;
itemEntry.style.marginBottom = 2;
itemEntry.style.paddingLeft = 6;
itemEntry.style.paddingRight = 6;
itemEntry.style.paddingTop = 3;
itemEntry.style.paddingBottom = 3;
itemEntry.style.backgroundColor = new Color(0.25f, 0.35f, 0.45f, 0.8f);
itemEntry.style.borderTopLeftRadius = 4;
itemEntry.style.borderTopRightRadius = 4;
itemEntry.style.borderBottomLeftRadius = 4;
itemEntry.style.borderBottomRightRadius = 4;
itemEntry.style.borderTopWidth = 1;
itemEntry.style.borderBottomWidth = 1;
itemEntry.style.borderLeftWidth = 1;
itemEntry.style.borderRightWidth = 1;
itemEntry.style.borderTopColor = new Color(0.7f, 0.7f, 0.9f, 0.6f);
itemEntry.style.borderBottomColor = new Color(0.7f, 0.7f, 0.9f, 0.6f);
itemEntry.style.borderLeftColor = new Color(0.7f, 0.7f, 0.9f, 0.6f);
itemEntry.style.borderRightColor = new Color(0.7f, 0.7f, 0.9f, 0.6f);
itemsListContainer.Add(itemEntry);
}
}
else
{
var noItemsLabel = new Label("No items collected");
noItemsLabel.style.fontSize = 14;
noItemsLabel.style.color = new Color(0.7f, 0.7f, 0.7f, 1f);
noItemsLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
noItemsLabel.style.paddingTop = 20;
itemsListContainer.Add(noItemsLabel);
}
}
// Add informational message about item distribution
if (allItems.Count > 0)
{
var distributionHint = rootElement.Q("DistributionHint");
if (distributionHint == null)
{
distributionHint = new Label();
distributionHint.name = "DistributionHint";
// Find a good place to add it (after the items section)
var itemsSection = rootElement.Q("ItemsSection");
if (itemsSection != null)
{
itemsSection.Add(distributionHint);
}
else
{
rootElement.Add(distributionHint);
}
}
if (enablePlayerItemSelection && !takeAllPressed)
{
distributionHint.text = "š” Click individual items above to choose which character gets them, or use 'Take All' for automatic distribution.";
}
else
{
distributionHint.text = "š Items will be distributed automatically among surviving party members.";
}
distributionHint.style.fontSize = 12;
distributionHint.style.color = new Color(0.8f, 0.8f, 0.9f, 0.9f);
distributionHint.style.unityTextAlign = TextAnchor.MiddleCenter;
distributionHint.style.marginTop = 10;
distributionHint.style.marginBottom = 5;
distributionHint.style.paddingLeft = 10;
distributionHint.style.paddingRight = 10;
distributionHint.style.whiteSpace = WhiteSpace.Normal;
}
}
///
/// Auto-loot all items and currency with optional player selection
///
private void AutoLootAll()
{
int totalGold = 0, totalSilver = 0, totalCopper = 0;
List allItems = new List();
foreach (var enemy in lootableEnemies)
{
if (!enemy.hasBeenLooted)
{
totalGold += enemy.goldReward;
totalSilver += enemy.silverReward;
totalCopper += enemy.copperReward;
allItems.AddRange(enemy.dropItems);
enemy.hasBeenLooted = true;
}
}
// Always distribute currency automatically
DistributeCurrency(totalGold, totalSilver, totalCopper);
// Handle item distribution based on settings
// Show item distribution UI if:
// 1. Player item selection is enabled
// 2. There are items to distribute
// 3. We're NOT in "Take All" mode (which forces auto-distribution)
if (enablePlayerItemSelection && allItems.Count > 0 && !takeAllPressed)
{
ShowItemDistributionUI(allItems);
}
else
{
// Auto-distribute items
DistributeItemsAutomatically(allItems);
if (showDebugLogs)
{
Debug.Log($"š° Auto-looted: {totalGold}g {totalSilver}s {totalCopper}c and {allItems.Count} items");
}
// End looting phase
FinishLooting();
}
}
///
/// Distribute looted rewards among surviving players
///
private void DistributeRewards(int gold, int silver, int copper, List items)
{
// Get surviving players
var survivingPlayers = GetSurvivingPlayers();
if (survivingPlayers.Count == 0)
{
Debug.LogWarning("š° No surviving players to distribute loot to!");
return;
}
// Distribute currency evenly
int goldPerPlayer = gold / survivingPlayers.Count;
int silverPerPlayer = silver / survivingPlayers.Count;
int copperPerPlayer = copper / survivingPlayers.Count;
// Handle remainder
int goldRemainder = gold % survivingPlayers.Count;
int silverRemainder = silver % survivingPlayers.Count;
int copperRemainder = copper % survivingPlayers.Count;
for (int i = 0; i < survivingPlayers.Count; i++)
{
var player = survivingPlayers[i];
Character playerCharacter = player.GetComponent();
if (playerCharacter == null) continue;
// Get player's bank (assuming it exists)
var bank = playerCharacter.GetComponent();
if (bank != null)
{
bank.gold += goldPerPlayer + (i < goldRemainder ? 1 : 0);
bank.silver += silverPerPlayer + (i < silverRemainder ? 1 : 0);
bank.copper += copperPerPlayer + (i < copperRemainder ? 1 : 0);
}
// Distribute items (simple round-robin for now)
var inventory = playerCharacter.GetComponent();
if (inventory != null)
{
for (int j = i; j < items.Count; j += survivingPlayers.Count)
{
// TODO: Create proper Item objects instead of strings
// For now, add to string-based inventory if available
AddItemToPlayer(playerCharacter, items[j]);
}
}
if (showDebugLogs)
{
int finalGold = goldPerPlayer + (i < goldRemainder ? 1 : 0);
int finalSilver = silverPerPlayer + (i < silverRemainder ? 1 : 0);
int finalCopper = copperPerPlayer + (i < copperRemainder ? 1 : 0);
Debug.Log($"š° {playerCharacter.CharacterName} received: {finalGold}g {finalSilver}s {finalCopper}c");
}
}
}
///
/// Distribute currency to players (separated from items for flexibility)
///
private void DistributeCurrency(int gold, int silver, int copper)
{
var survivingPlayers = GetSurvivingPlayers();
if (survivingPlayers.Count == 0)
{
Debug.LogWarning("š° No surviving players to distribute currency to!");
return;
}
// Distribute currency evenly
int goldPerPlayer = gold / survivingPlayers.Count;
int silverPerPlayer = silver / survivingPlayers.Count;
int copperPerPlayer = copper / survivingPlayers.Count;
// Handle remainder
int goldRemainder = gold % survivingPlayers.Count;
int silverRemainder = silver % survivingPlayers.Count;
int copperRemainder = copper % survivingPlayers.Count;
for (int i = 0; i < survivingPlayers.Count; i++)
{
var player = survivingPlayers[i];
Character playerCharacter = player.GetComponent();
if (playerCharacter == null) continue;
// Get player's bank
var bank = playerCharacter.GetComponent();
if (bank != null)
{
bank.gold += goldPerPlayer + (i < goldRemainder ? 1 : 0);
bank.silver += silverPerPlayer + (i < silverRemainder ? 1 : 0);
bank.copper += copperPerPlayer + (i < copperRemainder ? 1 : 0);
if (showDebugLogs)
{
int finalGold = goldPerPlayer + (i < goldRemainder ? 1 : 0);
int finalSilver = silverPerPlayer + (i < silverRemainder ? 1 : 0);
int finalCopper = copperPerPlayer + (i < copperRemainder ? 1 : 0);
Debug.Log($"š° {playerCharacter.CharacterName} received: {finalGold}g {finalSilver}s {finalCopper}c");
}
}
}
}
///
/// Show UI for manually assigning items to players
///
private void ShowItemDistributionUI(List items)
{
var survivingPlayers = GetSurvivingPlayers();
if (survivingPlayers.Count == 0)
{
Debug.LogWarning("š° No surviving players for item distribution!");
FinishLooting();
return;
}
// For now, create a simple distribution UI overlay
var distributionOverlay = new VisualElement();
distributionOverlay.name = "ItemDistributionOverlay";
distributionOverlay.style.position = Position.Absolute;
distributionOverlay.style.top = 0;
distributionOverlay.style.left = 0;
distributionOverlay.style.right = 0;
distributionOverlay.style.bottom = 0;
distributionOverlay.style.backgroundColor = new Color(0, 0, 0, 0.8f);
distributionOverlay.style.justifyContent = Justify.Center;
distributionOverlay.style.alignItems = Align.Center;
// Create distribution panel
var panel = new VisualElement();
panel.style.backgroundColor = new Color(0.15f, 0.15f, 0.25f, 0.95f);
panel.style.borderTopWidth = 2;
panel.style.borderBottomWidth = 2;
panel.style.borderLeftWidth = 2;
panel.style.borderRightWidth = 2;
panel.style.borderTopColor = Color.yellow;
panel.style.borderBottomColor = Color.yellow;
panel.style.borderLeftColor = Color.yellow;
panel.style.borderRightColor = Color.yellow;
panel.style.borderTopLeftRadius = 10;
panel.style.borderTopRightRadius = 10;
panel.style.borderBottomLeftRadius = 10;
panel.style.borderBottomRightRadius = 10;
panel.style.paddingTop = 20;
panel.style.paddingBottom = 20;
panel.style.paddingLeft = 20;
panel.style.paddingRight = 20;
panel.style.width = new Length(90, LengthUnit.Percent);
panel.style.maxWidth = 600;
panel.style.maxHeight = new Length(80, LengthUnit.Percent);
// Title
var title = new Label("Distribute Items to Players");
title.style.fontSize = 24;
title.style.color = Color.yellow;
title.style.unityTextAlign = TextAnchor.MiddleCenter;
title.style.marginBottom = 20;
panel.Add(title);
// Scroll view for items
var scrollView = new ScrollView();
scrollView.style.flexGrow = 1;
scrollView.style.marginBottom = 15;
// Create item distribution entries
foreach (var item in items)
{
var itemRow = CreateItemDistributionRow(item, survivingPlayers);
scrollView.Add(itemRow);
}
panel.Add(scrollView);
// Buttons
var buttonContainer = new VisualElement();
buttonContainer.style.flexDirection = FlexDirection.Row;
buttonContainer.style.justifyContent = Justify.SpaceAround;
var autoDistributeBtn = new Button(() =>
{
DistributeItemsAutomatically(items);
rootElement.Remove(distributionOverlay);
FinishLooting();
});
autoDistributeBtn.text = "Auto Distribute";
autoDistributeBtn.style.fontSize = 14;
var confirmBtn = new Button(() =>
{
DistributeItemsManually(items, survivingPlayers);
rootElement.Remove(distributionOverlay);
FinishLooting();
});
confirmBtn.text = "Confirm Distribution";
confirmBtn.style.fontSize = 14;
buttonContainer.Add(autoDistributeBtn);
buttonContainer.Add(confirmBtn);
panel.Add(buttonContainer);
distributionOverlay.Add(panel);
rootElement.Add(distributionOverlay);
}
///
/// Create a row for item distribution with player selection buttons
///
private VisualElement CreateItemDistributionRow(string itemName, List players)
{
var row = new VisualElement();
row.style.flexDirection = FlexDirection.Row;
row.style.alignItems = Align.Center;
row.style.marginBottom = 10;
row.style.paddingTop = 8;
row.style.paddingBottom = 8;
row.style.paddingLeft = 12;
row.style.paddingRight = 12;
row.style.backgroundColor = new Color(0.2f, 0.2f, 0.3f, 0.9f);
row.style.borderTopLeftRadius = 8;
row.style.borderTopRightRadius = 8;
row.style.borderBottomLeftRadius = 8;
row.style.borderBottomRightRadius = 8;
row.style.borderTopWidth = 1;
row.style.borderBottomWidth = 1;
row.style.borderLeftWidth = 1;
row.style.borderRightWidth = 1;
row.style.borderTopColor = new Color(0.5f, 0.5f, 0.6f, 0.8f);
row.style.borderBottomColor = new Color(0.5f, 0.5f, 0.6f, 0.8f);
row.style.borderLeftColor = new Color(0.5f, 0.5f, 0.6f, 0.8f);
row.style.borderRightColor = new Color(0.5f, 0.5f, 0.6f, 0.8f);
// Item name with better styling
var itemLabel = new Label($"š¦ {itemName}");
itemLabel.style.fontSize = 15;
itemLabel.style.color = Color.white;
itemLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
itemLabel.style.width = new Length(35, LengthUnit.Percent);
itemLabel.style.unityTextAlign = TextAnchor.MiddleLeft;
row.Add(itemLabel);
// "Assign to:" label
var assignLabel = new Label("ā");
assignLabel.style.fontSize = 14;
assignLabel.style.color = Color.yellow;
assignLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
assignLabel.style.width = 20;
assignLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
row.Add(assignLabel);
// Player selection buttons
var buttonContainer = new VisualElement();
buttonContainer.style.flexDirection = FlexDirection.Row;
buttonContainer.style.flexGrow = 1;
buttonContainer.style.justifyContent = Justify.SpaceAround;
int selectedPlayerIndex = selectedPlayerForItem.ContainsKey(itemName) ? selectedPlayerForItem[itemName] : -1;
// Store button references for updating
var playerButtons = new List();
for (int i = 0; i < players.Count; i++)
{
var player = players[i];
var character = player.GetComponent();
if (character == null) continue;
int playerIndex = i; // Capture for closure
var playerBtn = new Button(() =>
{
selectedPlayerForItem[itemName] = playerIndex;
// Update all buttons in this row to show selection
UpdatePlayerButtonVisuals(playerButtons, playerIndex);
Debug.Log($"š° Assigned {itemName} to {character.CharacterName}");
});
playerBtn.text = character.CharacterName;
playerBtn.style.fontSize = 13;
playerBtn.style.flexGrow = 1;
playerBtn.style.marginLeft = 3;
playerBtn.style.marginRight = 3;
playerBtn.style.paddingTop = 8;
playerBtn.style.paddingBottom = 8;
playerBtn.style.paddingLeft = 6;
playerBtn.style.paddingRight = 6;
playerBtn.style.borderTopLeftRadius = 5;
playerBtn.style.borderTopRightRadius = 5;
playerBtn.style.borderBottomLeftRadius = 5;
playerBtn.style.borderBottomRightRadius = 5;
playerBtn.style.borderTopWidth = 2;
playerBtn.style.borderBottomWidth = 2;
playerBtn.style.borderLeftWidth = 2;
playerBtn.style.borderRightWidth = 2;
// Set initial visual state
if (i == selectedPlayerIndex)
{
// Selected state
playerBtn.style.backgroundColor = new Color(0.2f, 0.8f, 0.2f, 0.9f);
playerBtn.style.borderTopColor = Color.green;
playerBtn.style.borderBottomColor = Color.green;
playerBtn.style.borderLeftColor = Color.green;
playerBtn.style.borderRightColor = Color.green;
playerBtn.style.color = Color.white;
}
else
{
// Unselected state
playerBtn.style.backgroundColor = new Color(0.3f, 0.3f, 0.4f, 0.8f);
playerBtn.style.borderTopColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
playerBtn.style.borderBottomColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
playerBtn.style.borderLeftColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
playerBtn.style.borderRightColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
playerBtn.style.color = new Color(0.9f, 0.9f, 0.9f, 0.9f);
}
playerButtons.Add(playerBtn);
buttonContainer.Add(playerBtn);
}
row.Add(buttonContainer);
return row;
}
///
/// Update visual state of player selection buttons
///
private void UpdatePlayerButtonVisuals(List buttons, int selectedIndex)
{
for (int i = 0; i < buttons.Count; i++)
{
var button = buttons[i];
if (i == selectedIndex)
{
// Selected state - green highlight
button.style.backgroundColor = new Color(0.2f, 0.8f, 0.2f, 0.9f);
button.style.borderTopColor = Color.green;
button.style.borderBottomColor = Color.green;
button.style.borderLeftColor = Color.green;
button.style.borderRightColor = Color.green;
button.style.color = Color.white;
}
else
{
// Unselected state - neutral gray
button.style.backgroundColor = new Color(0.3f, 0.3f, 0.4f, 0.8f);
button.style.borderTopColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
button.style.borderBottomColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
button.style.borderLeftColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
button.style.borderRightColor = new Color(0.6f, 0.6f, 0.7f, 0.8f);
button.style.color = new Color(0.9f, 0.9f, 0.9f, 0.9f);
}
}
}
///
/// Distribute items automatically using round-robin
///
private void DistributeItemsAutomatically(List items)
{
var survivingPlayers = GetSurvivingPlayers();
if (survivingPlayers.Count == 0) return;
for (int i = 0; i < items.Count; i++)
{
var player = survivingPlayers[i % survivingPlayers.Count];
var character = player.GetComponent();
if (character != null)
{
AddItemToPlayer(character, items[i]);
}
}
if (showDebugLogs)
{
Debug.Log($"š° Auto-distributed {items.Count} items among {survivingPlayers.Count} players");
}
}
///
/// Distribute items based on manual player selection
///
private void DistributeItemsManually(List items, List players)
{
foreach (var item in items)
{
if (selectedPlayerForItem.ContainsKey(item))
{
int playerIndex = selectedPlayerForItem[item];
if (playerIndex >= 0 && playerIndex < players.Count)
{
var character = players[playerIndex].GetComponent();
if (character != null)
{
AddItemToPlayer(character, item);
if (showDebugLogs)
{
Debug.Log($"š° Manually distributed {item} to {character.CharacterName}");
}
}
}
}
else
{
// If no selection was made, give to first player
var character = players[0].GetComponent();
if (character != null)
{
AddItemToPlayer(character, item);
if (showDebugLogs)
{
Debug.Log($"š° {item} given to {character.CharacterName} (no selection made)");
}
}
}
}
// Clear selections for next battle
selectedPlayerForItem.Clear();
}
///
/// Add an item to a player's inventory
///
private void AddItemToPlayer(Character player, string itemName)
{
// Try to add to CombatDataTransfer session data
if (CombatDataTransfer.HasValidSession())
{
var session = CombatDataTransfer.GetCurrentSession();
var playerData = session.playerTeam.Find(p =>
p.characterName == player.CharacterName ||
player.CharacterName.StartsWith(p.characterName));
if (playerData != null)
{
if (playerData.miscItems == null)
playerData.miscItems = new List();
playerData.miscItems.Add(itemName);
if (showDebugLogs)
Debug.Log($"š° Added {itemName} to {player.CharacterName}'s inventory");
return;
}
}
// Fallback: log that item would be added
if (showDebugLogs)
Debug.Log($"š° Would add {itemName} to {player.CharacterName} (no inventory system found)");
}
///
/// Get list of surviving player characters
///
private List GetSurvivingPlayers()
{
var gameManager = GameManager.Instance;
if (gameManager == null) return new List();
return gameManager.playerCharacters
.Where(p => p != null)
.Where(p =>
{
var character = p.GetComponent();
return character != null && !character.IsDead;
})
.ToList();
}
///
/// Complete the looting phase
///
private void FinishLooting()
{
isLootingActive = false;
if (rootElement != null)
rootElement.style.display = DisplayStyle.None;
OnLootingComplete?.Invoke();
if (showDebugLogs)
Debug.Log("š° Looting phase completed");
}
///
/// Skip looting and proceed to battle end
///
public void SkipLooting()
{
if (showDebugLogs)
Debug.Log("š° Skipping looting phase");
FinishLooting();
}
///
/// Check if all enemies have been looted
///
public bool AllEnemiesLooted()
{
return lootableEnemies.All(e => e.hasBeenLooted);
}
///
/// Get total weight of all available loot
///
public int GetTotalLootWeight()
{
// TODO: Implement when item weight system is added
return lootableEnemies.Sum(e => e.dropItems.Count); // Placeholder: 1 weight per item
}
///
/// Get total value of all available loot in copper
///
public int GetTotalLootValue()
{
int totalValue = 0;
foreach (var enemy in lootableEnemies)
{
totalValue += enemy.goldReward * 100; // 1 gold = 100 copper
totalValue += enemy.silverReward * 10; // 1 silver = 10 copper
totalValue += enemy.copperReward;
// TODO: Add item values when item system is integrated
}
return totalValue;
}
}