WXMC/.svn/pristine/13/13ac73c5910ae434de7e2beeb14c7fb325bbedd9.svn-base
2024-12-04 16:18:46 +08:00

655 lines
17 KiB
Plaintext

using Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public delegate void OnAfterPHomeUnitHitHandler(PHomeUnit attacker, PHomeUnit victim);
public enum NodeType
{
Strong,
Health,
Pet,
Lottery,
Dialogue,
}
public class PHomeGameMode : MonoBehaviour
{
public static PHomeGameMode main;
public PHomeGameConfig GameConfig;
public float MysticalScentTime;
public Transform m_mysticalScentPos;
[SerializeField]
private SceneTransition m_transition;
[SerializeField]
public PHomePlayer PlayerUnit;
[SerializeField]
private PHomeWorldBall m_worldBallMainWorld;
[SerializeField]
private Transform m_playerStart;
[SerializeField]
private GameObject m_playerPrefab;
[SerializeField]
private GameObject m_portalPrefab;
[SerializeField]
private bool m_transiting;
[SerializeField]
private bool m_mysticalScentDes;
[SerializeField]
private PHomeSpawner m_spawner;
[SerializeField]
private PHomePush m_push;
[SerializeField]
private GameObject m_dropGemPrefab;
public PHomePush Push
{
get
{
return m_push;
}
}
[SerializeField]
private List<WeaponUpdate> m_weaponUpdateConfig;
[SerializeField]
private AnimationCurve m_levelDifficultyCurve;
[SerializeField]
public VirtualJoystick m_joystick;
[SerializeField]
public List<PHomeEventCard> m_eventCards;
private PHomePortal m_portal;
public void DoUnitAttack(PHomeUnit source, PHomeUnit target, PHomeProjectile projectile = null)
{
float curHealth = target.Health;
float attack = PHomeGameMode.CalcTotalDamage(source, target, 0);
if (source is PHomeMonster)
{
attack *= GetMultiWithType(EventTargetUnitType.Enemy, EventCardEffectType.Damage);
}
else if (source is PHomePet)
{
attack *= GetMultiWithType(EventTargetUnitType.Pet, EventCardEffectType.Damage);
}
source.OnAfterHit(source, target);
target.OnAfterHitted(source, target);
DealDamage(source, target, projectile, attack);
source.EnterCooldown();
}
public void DoProjectileAttack(PHomeUnit source, PHomeUnit target, PHomeProjectile projectile, float attack)
{
attack = PHomeGameMode.CalcTotalDamage(source, target, attack);
if (source is PHomeMonster)
{
attack *= GetMultiWithType(EventTargetUnitType.Enemy, EventCardEffectType.Damage);
}
else if (source is PHomePet)
{
attack *= GetMultiWithType(EventTargetUnitType.Pet, EventCardEffectType.Damage);
}
source.OnAfterHit(source, target);
target.OnAfterHitted(source, target);
DealDamage(source, target, projectile, attack);
}
public void DealDamage(PHomeUnit source, PHomeUnit target, PHomeProjectile projectile, float attack)
{
float curHealth = target.Health;
curHealth -= attack;
bool dead = false;
if (curHealth <= 0)
{
curHealth = 0;
dead = true;
}
target.Health = curHealth;
target.Attacked();
if (dead)
{
target.IsDead = true;
if (target is PHomeMonster monster)
{
m_spawner.OnMonsterKilled(monster);
DropGem(monster.transform.position, monster.GemDropMin, monster.GemDropMax);
Destroy(target.gameObject);
}
else if (target is PHomePlayer)
{
RestartPlayer();
}
}
}
public static float CalcTotalDamage(PHomeUnit attacker, PHomeUnit victim, float additionalDmg = 0)
{
float result = additionalDmg;
result += attacker.Attack;
PHomePet pet = attacker as PHomePet;
if (pet != null)
{
result += pet.Player.Attack;
}
return result;
}
public PHomeProjectile SpawnProjectile(PHomeUnit instigator, ShootData data, GameObject projectilePrefab)
{
GameObject projectile = Instantiate(projectilePrefab, Vector3.zero, Quaternion.identity);
PHomeProjectile result = projectile.GetComponent<PHomeProjectile>();
result.Instigator = instigator;
result.Init(data);
return projectile.GetComponent<PHomeProjectile>();
}
public PHomeUnit SpawnUnit(Vector3 at, GameObject unitPrefab)
{
GameObject monster = Instantiate(unitPrefab, at, Quaternion.identity);
PHomeUnit result = monster.GetComponent<PHomeUnit>();
result.Health = result.MaxHealth;
foreach (var item in result.StartBuffs)
{
AddBuff(result, item);
}
return result;
}
public PHomeMonster SpawnMonster(Vector3 at, GameObject monsterPrefab)
{
PHomeMonster result = SpawnUnit(at, monsterPrefab) as PHomeMonster;
return result;
}
public PHomePlayer SpawnPlayer(Vector3 at, GameObject playerPrefab)
{
PHomePlayer player = SpawnUnit(at, playerPrefab) as PHomePlayer;
foreach (var item in player.StartPets)
{
AddPet(player, item);
}
return player;
}
public PHomeWeapon SpawnWeapon(Vector3 at, GameObject weaponPrefab, Transform parent = null)
{
GameObject weaponGo = Instantiate(weaponPrefab, at, Quaternion.identity, parent);
PHomeWeapon result = weaponGo.GetComponent<PHomeWeapon>();
return result;
}
public PHomePet SpawnPet(Vector3 at, GameObject petPrefab)
{
GameObject petGo = Instantiate(petPrefab, at, Quaternion.identity);
PHomePet result = petGo.GetComponent<PHomePet>();
return result;
}
public void DropGem(Vector3 position, int min, int max)
{
float randRadius = 0.6f;
int randCount = UnityEngine.Random.Range(min, max);
for (int i = 0; i < randCount; i++)
{
Vector3 randOffset = Vector3.right * UnityEngine.Random.Range(-randRadius, randRadius) + Vector3.up * UnityEngine.Random.Range(-randRadius, randRadius);
GameObject go = Instantiate(m_dropGemPrefab, position + randOffset, Quaternion.identity);
PGem gem = go.GetComponent<PGem>();
Destroy(go, gem.GemSpawnLifeTime);
}
}
public PHomeWorldBall SpawnWorldBall(GameObject worldBallPrefab, PHomeInventory toInventory)
{
GameObject worldBallGo = Instantiate(worldBallPrefab, Vector3.zero, Quaternion.identity);
PHomeWorldBall result = worldBallGo.GetComponent<PHomeWorldBall>();
result.transform.parent = toInventory.transform;
result.Inventory = toInventory;
toInventory.Items.Add(result);
return result;
}
public PHomePortal SpawnPortal(PHomeWorldBall worldBall, Vector3 portalPos, bool spawnInPlayerProtal = false, Action beforeEnterAction = null)
{
if (m_portal == null)
{
GameObject worldBallGo = Instantiate(m_portalPrefab, portalPos, Quaternion.identity);
m_portal = worldBallGo.GetComponent<PHomePortal>();
}
m_portal.transform.position = spawnInPlayerProtal ? PlayerUnit.m_portalPos.position : portalPos;
if (worldBall == null)
{
m_portal.Init(m_worldBallMainWorld, beforeEnterAction);
}
else
{
m_portal.Init(worldBall, beforeEnterAction);
}
return m_portal;
}
public void AddGem(PHomePlayer player, int gemCount)
{
player.GemCount += gemCount;
}
public void AddWeapon(PHomeUnit unit, PHomeWeapon weapon)
{
PHomeWeapon weaponScript = SpawnWeapon(Vector3.zero, weapon.gameObject, unit.transform);
unit.AddWeapon(weaponScript);
weaponScript.Init(unit);
for (int j = 0; j < m_weaponUpdateConfig.Count; j++)
{
List<string> matchNames = m_weaponUpdateConfig[j].MatchNames;
bool isContain = false;
for (int k = 0; k < matchNames.Count; k++)
{
if (matchNames[k] == weapon.WeaponName)
{
isContain = true;
}
}
if (isContain)
{
bool canUpdate = true;
for (int k = 0; k < matchNames.Count; k++)
{
if (!unit.HaveWeapon(matchNames[k]))
{
canUpdate = false;
break;
}
}
if (canUpdate)
{
for (int k = 0; k < matchNames.Count; k++)
{
RemoveWeapon(unit, matchNames[k]);
}
AddWeapon(unit, m_weaponUpdateConfig[j].SpawnWeaponPrefabs);
}
}
}
}
public void RemoveWeapon(PHomeUnit unit, string weaponName)
{
if (unit.HaveWeapon(weaponName))
{
unit.RemoveWeapon(weaponName);
}
}
public void StartMyticalScent(float time)
{
m_mysticalScentDes = false;
MysticalScentTime = time;
}
public void RestartPlayer()
{
PlayerUnit.Health = PlayerUnit.MaxHealth;
PlayerUnit.transform.position = m_playerStart.position;
PlayerUnit.IsDead = false;
}
public void StartPlayer()
{
PlayerUnit = SpawnPlayer(m_playerStart.position, m_playerPrefab);
m_joystick.SetPlayer(PlayerUnit);
}
public void FinishGame()
{
PHomeInventory.instance.GemCount += PlayerUnit.GemCount;
}
#region Utils
public IEnumerable<PHomeUnit> FindMonsters(Vector3 at, float range, PHomeUnit refUnit = null)
{
Vector2 point = new Vector2()
{
x = at.x,
y = at.y,
};
Collider2D[] colliders = Physics2D.OverlapCircleAll(point, range);
if (colliders.Length == 0)
{
yield break;
}
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].attachedRigidbody == null)
{
continue;
}
PHomeUnit script = colliders[i].attachedRigidbody.GetComponent<PHomeUnit>();
if (refUnit != null)
{
if (!IsEnemy(refUnit, script))
{
continue;
}
}
yield return script;
}
}
public PHomeMonster FindClosestMonster(Vector3 at, float range, PHomeUnit refUnit = null)
{
Vector2 point = new Vector2()
{
x = at.x,
y = at.y,
};
Collider2D[] colliders = Physics2D.OverlapCircleAll(point, range);
if (colliders.Length == 0)
{
return null;
}
Collider2D result = null;
float length = float.MaxValue;
for (int i = 0; i < colliders.Length; i++)
{
if (colliders[i].attachedRigidbody == null)
{
continue;
}
if (refUnit != null)
{
if (!IsEnemy(refUnit, colliders[i].attachedRigidbody.GetComponent<PHomeUnit>()))
{
continue;
}
}
float len = Vector3.Distance(at, colliders[i].transform.position);
if (len < length)
{
length = len;
result = colliders[i];
}
}
if (result == null)
{
return null;
}
return result.attachedRigidbody.GetComponent<PHomeMonster>();
}
public static bool IsEnemy(PHomeUnit unit, PHomeUnit other)
{
if (unit == other)
{
return false;
}
if (unit == null || other == null)
{
return false;
}
return (unit is PHomePet && other is PHomeMonster) || (unit is PHomeMonster && other is PHomePet);
}
#endregion
#region Pet
[Button]
public void AddPet(PHomePlayer player, PHomePet pet)
{
PHomePet samePet = player.GetHavePet(pet);
if (samePet != null)
{
samePet.LevelUp();
}
else
{
samePet = SpawnPet(Vector3.zero, pet.gameObject);
samePet.FromPet = pet;
player.AddPet(samePet);
}
float getCountAdd = GetMultiWithType(EventTargetUnitType.Pet, EventCardEffectType.Number) - 1;
for (int i = 0; i < getCountAdd; i++)
{
samePet.LevelUp();
}
samePet.MaxHealth *= GetMultiWithType(EventTargetUnitType.Pet, EventCardEffectType.Hp);
samePet.Health = samePet.MaxHealth;
}
public void PetLevelUp()
{
PlayerUnit.RandomPetLevelUp();
}
[Button]
public void ClearPets()
{
PlayerUnit.ClearPets();
}
#endregion
#region Buff
public PHomeBuff AddBuff(PHomeUnit unit, PHomeBuff buffPrefab)
{
return unit.AddBuff(buffPrefab);
}
#endregion
public void KillAllMonster()
{
m_spawner.KillAllMonster();
}
List<PHomeEventCard> selectEventCard;
public List<PHomeEventCard> SelectEventCard()
{
if (selectEventCard == null) selectEventCard = new List<PHomeEventCard>();
List<PHomeEventCard> currCards = new List<PHomeEventCard>();
currCards.AddRange(m_eventCards);
for (int i = 0; i < 2; i++)
{
int currIndex = UnityEngine.Random.Range(0, currCards.Count);
selectEventCard.Add(currCards[currIndex]);
currCards.RemoveAt(currIndex);
}
if (GetMultiWithType(EventTargetUnitType.Pet, EventCardEffectType.Hp) != 1)
{
PlayerUnit.ResetPet();
}
for (int i = 0; i < selectEventCard.Count; i++)
{
if (selectEventCard[i].EventCardType == EventCardType.CoinMonster)
{
// TODO iii
//m_spawner.TrySpawnCoinMonster(selectEventCard[i]);
}
}
return selectEventCard;
}
public float GetMultiWithType(EventTargetUnitType unitType, EventCardEffectType effectType)
{
float multiCount = 1;
if (selectEventCard == null)
{
return multiCount;
}
for (int i = 0; i < selectEventCard.Count; i++)
{
List<EventEffectData> effctData = selectEventCard[i].EventEffectDatas;
for (int j = 0; j < effctData.Count; j++)
{
if (effctData[j].EventTargetUnitType == unitType && effctData[j].EventCardEffectType == effectType)
{
multiCount *= effctData[j].EventCardEffectNumber;
}
}
}
return multiCount;
}
void UpdateMysticalScent()
{
if (MysticalScentTime > 0)
{
MysticalScentTime -= Time.deltaTime;
}
else if (!m_mysticalScentDes)
{
KillAllMonster();
m_mysticalScentDes = true;
}
}
int m_currLevel = -1;
int m_finalLevel;
void UpdateLevelDifficulty()
{
m_finalLevel = m_push.FinishNodeCount;
if (m_finalLevel != m_currLevel)
{
m_currLevel = m_finalLevel;
m_spawner.MonsterHpBoost = m_levelDifficultyCurve.Evaluate(m_push.FinishNodeCount);
}
}
#region Cart Pushing
private bool m_isInPreStage;
public PuzzleGameMode.VoidDelegate OnAfterIsInPreStageChanged;
public bool IsInPreStage
{
get
{
return m_isInPreStage;
}
set
{
if (m_isInPreStage != value)
{
m_isInPreStage = value;
OnAfterIsInPreStageChanged?.Invoke();
}
}
}
private float m_preStageStartTime;
public float PreStageStartTime
{
get
{
return m_preStageStartTime;
}
}
[SerializeField]
private float m_preStageDuration;
public float PreStageDuration
{
get
{
return m_preStageDuration;
}
}
public void StartPreStage(PHomeWorldBall wordBall)
{
if (IsInPreStage)
{
Debug.LogWarning($"Already in prestage");
return;
}
IsInPreStage = true;
m_preStageStartTime = Time.time;
Push.SelectWorldBall(wordBall);
}
private void Update_PreStage()
{
if (!IsInPreStage)
{
return;
}
float timePassed = Time.time - m_preStageStartTime;
if (timePassed > m_preStageDuration)
{
IsInPreStage = false;
Push.StartPush();
}
}
#endregion
private void Awake()
{
main = this;
StartPlayer();
}
// Update is called once per frame
void Update()
{
UpdateMysticalScent();
UpdateLevelDifficulty();
Update_PreStage();
}
}
[System.Serializable]
public class WeaponUpdate
{
public List<string> MatchNames;
public PHomeWeapon SpawnWeaponPrefabs;
}