using System;
using System.Collections.Generic;
using UnityEngine;
namespace DoomBreakers
{
public class BattleColliderManager : MonoBehaviour
{
//
//The battle collider manager' purpose is too communicate collisions between enemy AI & player, vice versa.
//We will need to communicate some details about each object involved with the collision.
//
//
private Dictionary _battleEventDictionary;
private static BattleColliderManager _battleEventManager;
private static int _mostRecentCollidedPlayerId;
private static Dictionary _playerFaceDir;
private static Dictionary _playerState;
private static Dictionary _playerWeapon;
private static Dictionary _playerStats;
private static float _playerAttackButtonHeldTime;
private static int _mostRecentCollidedBasicEnemyId; //Needed for Enemy Hit By Power Attack behaviour state.
private static Dictionary _enemyFaceDir;
private static Dictionary _basicEnemyState;
private static Dictionary _basicBanditStats;
private static Dictionary _basicSkellyStats;
private static Dictionary _basicGoblinStats;
private static Dictionary _basicTrollStats;
public static BattleColliderManager _instance
{
get //When we access our instance from another place, we'll setup as appropriate if required.
{
if (!_battleEventManager)
{
//FindObjectOfType isn't a cheap call but we only do this once, if not at all.
_battleEventManager = FindObjectOfType(typeof(BattleColliderManager)) as BattleColliderManager;
if (!_battleEventManager)
print("\nBattleColliderManager= You need an active BattleColliderManager script attached to a GameObject within the scene!");
else
_battleEventManager.Setup();
}
return _battleEventManager;
}
}
private void Setup()
{
if (_battleEventDictionary == null) _battleEventDictionary = new Dictionary();
if (_playerFaceDir == null) _playerFaceDir = new Dictionary();
if (_playerState == null) _playerState = new Dictionary();
if (_playerWeapon == null) _playerWeapon = new Dictionary();
if (_playerStats == null) _playerStats = new Dictionary();
if (_enemyFaceDir == null) _enemyFaceDir = new Dictionary();
if (_basicEnemyState == null) _basicEnemyState = new Dictionary();
if (_basicBanditStats == null) _basicBanditStats = new Dictionary();
if (_basicSkellyStats == null) _basicSkellyStats = new Dictionary();
if (_basicGoblinStats == null) _basicGoblinStats = new Dictionary();
if (_basicTrollStats == null) _basicTrollStats = new Dictionary();
_mostRecentCollidedPlayerId = 0;
_playerAttackButtonHeldTime = 0f;
//_enemyType = EnemyAI.None;
}
private void OnDisable() => FreeMemory();
public void FreeMemory()
{
//Alerts GC to collect and free up memory.
_battleEventDictionary.Clear();
_playerFaceDir.Clear();
_playerState.Clear();
_playerWeapon.Clear();
_playerStats.Clear();
_enemyFaceDir.Clear();
_basicEnemyState.Clear();
_basicBanditStats.Clear();
_basicSkellyStats.Clear();
_basicGoblinStats.Clear();
_basicTrollStats.Clear();
_battleEventManager = null;
}
//
//Bundle all appropriate collision assignment calls into one method call.
//This is so far, AssignPlayerState(), AssignPlayerFaceDir() and TriggerEvent("ReportCollisionWithSomething").
//
//
public static void AssignCollisionDetails(string eventName, ref BaseState playerState, int forPlayerId, IPlayerSprite playerSprite,
ItemBase weapon, ref PlayerStats characterStat)
{
AssignPlayerFaceDir(forPlayerId, playerSprite);
AssignPlayerState(ref playerState, forPlayerId);
AssignPlayerWeapon(forPlayerId, weapon);
AssignPlayerStats(forPlayerId, ref characterStat);
BaseTriggerEvent(eventName);
}
//
//AssignPlayerState() is used to communicate player state during an attack.
//We will need this for enemy AI regarding the Bandit.cs->AttackedByPlayer() so
//we can determine the enemy' next state, as appropriate.
//
//
public static void AssignPlayerState(ref BaseState playerState, int playerId)
{
if (!_playerState.ContainsKey(playerId))
_playerState.Add(playerId, playerState);
else
{
if(playerState.GetType() != _playerState[playerId].GetType())
{
_playerState.Remove(playerId);
_playerState.Add(playerId, playerState);
}
}
}
public static BaseState GetAssignedPlayerState(int playerId) //=> _playerState[playerId];
{
if (!_playerState.ContainsKey(playerId)) return null;
return _playerState[playerId];
}
//
//AssignPlayerFaceDir() is used to communicate player face direction during an attack.
//We will need this for enemy AI regarding the HitByPowerAttack obj state.
//
//
public static void AssignPlayerFaceDir(int forPlayerId, IPlayerSprite playerSprite)
{
//PlayerCollision.cs->UpdateDetectEnemyTargets()
_mostRecentCollidedPlayerId = forPlayerId;
if (!_playerFaceDir.ContainsKey(forPlayerId))
_playerFaceDir.Add(forPlayerId, playerSprite.GetSpriteDirection());
else
{
if (_playerFaceDir[forPlayerId] != playerSprite.GetSpriteDirection())
{
_playerFaceDir.Remove(forPlayerId);
_playerFaceDir.Add(forPlayerId, playerSprite.GetSpriteDirection());//There we go dumbass.
}
}
}
public static int GetAssignedPlayerFaceDir(int forPlayerId)
{
if (_playerFaceDir.ContainsKey(forPlayerId))
return _playerFaceDir[forPlayerId];
else
return 1;
}
//
//AssignPlayerWeapon() is used to communicate player damage output during an attack.
//We will need this for enemy AI regarding the Bandit.cs->AttackedByPlayer() Method.
//But will use this Method at PlayerCollision.cs->UpdateDetectEnemyTargets()
//
public static void AssignPlayerWeapon(int forPlayerId, ItemBase weapon)
{
if (weapon == null) return;
if(!_playerWeapon.ContainsKey(forPlayerId))
_playerWeapon.Add(forPlayerId, weapon);
else
{
if (_playerWeapon[forPlayerId] != weapon)
{
_playerWeapon.Remove(forPlayerId);
_playerWeapon.Add(forPlayerId, weapon);
}
}
}
public static ItemBase GetAssignedPlayerWeapon(int forPlayerId)
{
if (_playerWeapon == null) return null;
if (_playerWeapon.ContainsKey(forPlayerId))
return _playerWeapon[forPlayerId];
else
return null;
}
public static void AssignPlayerStats(int forPlayerId, ref PlayerStats characterStat)
{
_mostRecentCollidedBasicEnemyId = forPlayerId;
if (!_playerStats.ContainsKey(forPlayerId))
_playerStats.Add(forPlayerId, characterStat);
else
{
if (_playerStats[forPlayerId] != characterStat)
{
_playerStats.Remove(forPlayerId);
_playerStats.Add(forPlayerId, characterStat);
}
}
}
public static int GetRecentCollidedPlayerId() => _mostRecentCollidedPlayerId;
public static PlayerStats GetAssignedPlayerStatus(int forPlayerId)// => _playerStats[forPlayerId];
{
if (!_playerStats.ContainsKey(forPlayerId)) return null;
return _playerStats[forPlayerId];
}
public static void SetPlayerHeldAttackButtonTime(float time) => _playerAttackButtonHeldTime = time;
public static float GetPlayerHeldAttackButtonTime() => _playerAttackButtonHeldTime;
//
//Bundle all appropriate collision assignment calls into one method call.
//This is so far, AssignBanditState(), AssignBanditFaceDir() and TriggerEvent("ReportCollisionWithSomething").
//We'll overload this from Player use for Bandit use.
//
public static void AssignCollisionDetails(string eventName, ref BasicEnemyBaseState banditState, int forBanditId, int faceDir, ref BanditStats characterStat)
{
AssignBasicEnemyFaceDir(forBanditId, faceDir);
AssignBasicEnemyState(ref banditState, forBanditId);
AssignBasicEnemyStats(forBanditId, ref characterStat);
BaseTriggerEvent(eventName);
}
public static void AssignCollisionDetails(string eventName, ref BasicEnemyBaseState skellyState, int forSkellyId, int faceDir, ref SkeletonStats characterStat)
{
AssignBasicEnemyFaceDir(forSkellyId, faceDir);
AssignBasicEnemyState(ref skellyState, forSkellyId);
AssignBasicEnemyStats(forSkellyId, ref characterStat);
BaseTriggerEvent(eventName);
}
public static void AssignCollisionDetails(string eventName, ref BasicEnemyBaseState goblinState, int forGoblinId, int faceDir, ref GoblinStats characterStat)
{
AssignBasicEnemyFaceDir(forGoblinId, faceDir);
AssignBasicEnemyState(ref goblinState, forGoblinId);
AssignBasicEnemyStats(forGoblinId, ref characterStat);
BaseTriggerEvent(eventName);
}
public static void AssignCollisionDetails(string eventName, ref BasicEnemyBaseState trollState, int forTrollId, int faceDir, ref TrollStats characterStat)
{
AssignBasicEnemyFaceDir(forTrollId, faceDir);
AssignBasicEnemyState(ref trollState, forTrollId);
AssignBasicEnemyStats(forTrollId, ref characterStat);
BaseTriggerEvent(eventName);
}
public static void AssignBasicEnemyState(ref BasicEnemyBaseState banditState, int enemyId)
{
if (!_basicEnemyState.ContainsKey(enemyId))
_basicEnemyState.Add(enemyId, banditState);
else
{
if (banditState.GetType() != _basicEnemyState[enemyId].GetType())
{
_basicEnemyState.Remove(enemyId);
_basicEnemyState.Add(enemyId, banditState);
}
}
}
public static BasicEnemyBaseState GetAssignedBasicEnemyState(int enemyId) //=> _basicEnemyState[enemyId];
{
if (!_basicEnemyState.ContainsKey(enemyId)) return null;
return _basicEnemyState[enemyId];
}
public static void AssignBasicEnemyFaceDir(int forEnemyId, int faceDir)
{
//BanditCollision.cs->UpdateDetectEnemyTargets()
_mostRecentCollidedBasicEnemyId = forEnemyId;
if (!_enemyFaceDir.ContainsKey(forEnemyId))
_enemyFaceDir.Add(forEnemyId, faceDir);
else
{
if (_enemyFaceDir[forEnemyId] != faceDir)
{
_enemyFaceDir.Remove(forEnemyId);
_enemyFaceDir.Add(forEnemyId, faceDir);
}
}
}
public static void AssignBasicEnemyStats(int forBanditId, ref BanditStats characterStat)
{
_mostRecentCollidedBasicEnemyId = forBanditId;
if (!_basicBanditStats.ContainsKey(forBanditId))
_basicBanditStats.Add(forBanditId, characterStat);
else
{
if (_basicBanditStats[forBanditId] != characterStat)
{
_basicBanditStats.Remove(forBanditId);
_basicBanditStats.Add(forBanditId, characterStat);
}
}
}
public static void AssignBasicEnemyStats(int forSkellyId, ref SkeletonStats characterStat)
{
_mostRecentCollidedBasicEnemyId = forSkellyId;
if (!_basicSkellyStats.ContainsKey(forSkellyId))
_basicSkellyStats.Add(forSkellyId, characterStat);
else
{
if (_basicSkellyStats[forSkellyId] != characterStat)
{
_basicSkellyStats.Remove(forSkellyId);
_basicSkellyStats.Add(forSkellyId, characterStat);
}
}
}
public static void AssignBasicEnemyStats(int forGoblinId, ref GoblinStats characterStat)
{
_mostRecentCollidedBasicEnemyId = forGoblinId;
if (!_basicGoblinStats.ContainsKey(forGoblinId))
_basicGoblinStats.Add(forGoblinId, characterStat);
else
{
if (_basicGoblinStats[forGoblinId] != characterStat)
{
_basicGoblinStats.Remove(forGoblinId);
_basicGoblinStats.Add(forGoblinId, characterStat);
}
}
}
public static void AssignBasicEnemyStats(int forTrollId, ref TrollStats characterStat)
{
_mostRecentCollidedBasicEnemyId = forTrollId;
if (!_basicTrollStats.ContainsKey(forTrollId))
_basicTrollStats.Add(forTrollId, characterStat);
else
{
if (_basicTrollStats[forTrollId] != characterStat)
{
_basicTrollStats.Remove(forTrollId);
_basicTrollStats.Add(forTrollId, characterStat);
}
}
}
public static int GetAssigneBasicEnemyFaceDir(int forEnemyId) => _enemyFaceDir[forEnemyId];
public static BanditStats GetAssignedBanditStatus(int forBanditId) //=> _basicBanditStats[forBanditId];
{
if (!_basicBanditStats.ContainsKey(forBanditId)) return null;
return _basicBanditStats[forBanditId];
}
public static int GetRecentCollidedBasicEnemyId() => _mostRecentCollidedBasicEnemyId;
public static SkeletonStats GetAssignedSkeletonStatus(int forSkellyId) //=> _basicBanditStats[forBanditId];
{
if (!_basicSkellyStats.ContainsKey(forSkellyId)) return null;
return _basicSkellyStats[forSkellyId];
}
public static GoblinStats GetAssignedGoblinStatus(int forGoblinId) //=> _basicBanditStats[forBanditId];
{
if (!_basicGoblinStats.ContainsKey(forGoblinId)) return null;
return _basicGoblinStats[forGoblinId];
}
public static TrollStats GetAssignedTrollStatus(int forTrollId) //=> _basicBanditStats[forBanditId];
{
if (!_basicTrollStats.ContainsKey(forTrollId)) return null;
return _basicTrollStats[forTrollId];
}
public static void Subscribe(string eventName, Action listener)
{
Action thisEvent;
//out: differs from the ref keyword in that it does not require parameter variables to be
//initialized before they are passed to a method. Must be explicitly declared in the method
//definition​ as well as in the calling method.
if (_instance._battleEventDictionary.TryGetValue(eventName, out thisEvent))
{
//Add another event to the existing ones.
thisEvent += listener;
//Update the dictionary.
_instance._battleEventDictionary[eventName] = thisEvent;
}
else
{
//Add the event to the dictionary for the first time.
thisEvent += listener;
_instance._battleEventDictionary.Add(eventName, thisEvent);
}
}
public static void Unsubscribe(string eventName, Action listener)
{
if (_battleEventManager == null) //Guard Clause.
return;
Action thisEvent;
if (_instance._battleEventDictionary.TryGetValue(eventName, out thisEvent))
{
//Remove the event from the existing ones.
thisEvent -= listener;
//Now update the dictionary.
_instance._battleEventDictionary[eventName] = thisEvent;
}
}
private static void BaseTriggerEvent(string eventName)
{
Action thisEvent = null;
if (_instance._battleEventDictionary.TryGetValue(eventName, out thisEvent))
{
_instance._battleEventDictionary[eventName]();
//thisEvent.Invoke();
}
}
public static void TriggerEvent(string eventName)
{
BaseTriggerEvent(eventName);
}
}
}