WXMC/.svn/pristine/5d/5d37b1d3202117e900b8a9626d1211818fec1c0f.svn-base
2024-12-04 16:18:46 +08:00

282 lines
8.4 KiB
Plaintext

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public struct WeightedObject<TObj>
{
public float Weight;
public TObj Obj;
public WeightedObject(float weight, TObj obj)
{
Weight = weight;
Obj = obj;
}
public static TObj GetRandomWeightedObject(IEnumerable<WeightedObject<TObj>> weightedObjects)
{
float totalWeightSum = 0;
// Calculate the total sum of weights
foreach (var weightedObj in weightedObjects)
{
totalWeightSum += weightedObj.Weight;
}
// Generate a random number between 0 and the total weight sum
float randomNumber = UnityEngine.Random.Range(0, totalWeightSum);
// Find the corresponding object based on the random number
float currentWeightSum = 0;
foreach (var weightedObj in weightedObjects)
{
currentWeightSum += weightedObj.Weight;
if (randomNumber < currentWeightSum)
{
return weightedObj.Obj;
}
}
// If no object is found (should not reach this point in normal circumstances)
throw new Exception("Failed to retrieve a random weighted object.");
}
}
public class PHomeSpawner : MonoBehaviour
{
[SerializeField]
private WeightedObject<GameObject>[] m_spawnPrefabs;
[SerializeField]
private float m_spawnInterval;
public float SpawnInterval
{
get
{
return m_spawnInterval;
}
set
{
if (m_spawnInterval != value)
{
m_spawnInterval = value;
}
}
}
[SerializeField]
private float m_monsterHpBoost;
public float MonsterHpBoost
{
get
{
return m_monsterHpBoost;
}
set
{
if (m_monsterHpBoost != value)
{
m_monsterHpBoost = value;
}
}
}
[SerializeField]
private float m_spawnRadius;
public float SpawnRadius
{
get
{
return m_spawnRadius;
}
set
{
if (m_spawnRadius != value)
{
m_spawnRadius = value;
}
}
}
[SerializeField]
private float m_spawnTimer;
[SerializeField]
private int m_spawnMaxCount;
[Header("MysticalScentConfig")]
[SerializeField]
private WeightedObject<GameObject>[] m_spawnPrefabsMC;
[SerializeField]
private GameObject m_coinPrefabsMC;
[SerializeField]
private float m_spawnIntervalMC;
[SerializeField]
private float m_spawnMaxCountMC;
[SerializeField]
private Transform m_topRightPos;
private HashSet<PHomeMonster> m_monsters = new HashSet<PHomeMonster>();
public void OnMonsterKilled(PHomeMonster monster)
{
m_monsters.Remove(monster);
PHomeGameMode.main.PlayerUnit.KillMonsterCount++;
}
public void KillAllMonster()
{
foreach (var item in m_monsters)
{
PHomeGameMode.main.DropGem(item.transform.position, item.GemDropMin, item.GemDropMax);
Destroy(item.gameObject);
PHomeGameMode.main.PlayerUnit.KillMonsterCount++;
}
m_monsters.Clear();
}
private void TrySpawnOneMonster()
{
if (m_spawnTimer >= 0)
{
return;
}
if (m_monsters.Count >= m_spawnMaxCount)
{
return;
}
m_spawnTimer = m_spawnInterval;
int spawnCount = Mathf.FloorToInt(PHomeGameMode.main.GetMultiWithType(EventTargetUnitType.Enemy, EventCardEffectType.Number));
float monsterHpMulti = PHomeGameMode.main.GetMultiWithType(EventTargetUnitType.Enemy, EventCardEffectType.Hp);
for (int j = 0; j < spawnCount; j++)
{
GameObject randMonster = WeightedObject<GameObject>.GetRandomWeightedObject(m_spawnPrefabsMC);
Vector2 randomPointInUnitCircle = UnityEngine.Random.insideUnitCircle * SpawnRadius;
Vector3 randomPos = GetRandomPoint();
PHomeMonster currMonster = PHomeGameMode.main.SpawnMonster(randomPos, randMonster);
currMonster.MaxHealth *= (1f + m_monsterHpBoost) * monsterHpMulti;
currMonster.Health = currMonster.MaxHealth;
m_monsters.Add(currMonster);
}
}
public void TrySpawnCoinMonster(PHomeEventCard eventCard)
{
EventEffectData effectData = eventCard.EventEffectDatas[0];
int spawnCount = UnityEngine.Random.Range(Mathf.FloorToInt(effectData.EventCardEffectNumberMin),
Mathf.FloorToInt(effectData.EventCardEffectNumberMax));
float multiNumber = PHomeGameMode.main.GetMultiWithType(EventTargetUnitType.Enemy, EventCardEffectType.Number);
spawnCount = Mathf.FloorToInt(spawnCount * multiNumber);
float monsterHpMulti = PHomeGameMode.main.GetMultiWithType(EventTargetUnitType.Enemy, EventCardEffectType.Hp);
for (int j = 0; j < 1; j++)
{
GameObject randMonster = m_coinPrefabsMC;
Vector2 randomPointInUnitCircle = UnityEngine.Random.insideUnitCircle * SpawnRadius;
Vector3 randomPos = GetRandomPoint();
PHomeMonster currMonster = PHomeGameMode.main.SpawnMonster(randomPos, randMonster);
currMonster.MaxHealth *= (1f + m_monsterHpBoost) * monsterHpMulti;
currMonster.Health = currMonster.MaxHealth;
m_monsters.Add(currMonster);
}
}
private void TrySpawnOneMonsterMysticalScent()
{
if (m_spawnTimer > m_spawnIntervalMC) m_spawnTimer = m_spawnIntervalMC;
if (m_spawnTimer >= 0)
{
return;
}
if (m_monsters.Count >= m_spawnMaxCountMC)
{
return;
}
m_spawnTimer = m_spawnIntervalMC;
GameObject randMonster = WeightedObject<GameObject>.GetRandomWeightedObject(m_spawnPrefabs);
Vector2 randomPointInUnitCircle = UnityEngine.Random.insideUnitCircle * SpawnRadius;
Vector3 randomPos = GetRandomPoint();
PHomeMonster currMonster = PHomeGameMode.main.SpawnMonster(randomPos, randMonster);
currMonster.MaxHealth *= 1f + m_monsterHpBoost;
currMonster.Health = currMonster.MaxHealth;
m_monsters.Add(currMonster);
}
Vector3 GetRandomPoint()
{
Vector3 randomPoint = Vector3.zero;
bool foundPoint = false;
Vector2 screenSize = PHomeGameMode.main.PlayerUnit.PlayerScreen.Size;
Vector3 finalPos = PHomeGameMode.main.PlayerUnit.transform.position + randomPoint;
while (!foundPoint)
{
// 随机生成一个点
Vector2 randomPoint2D = UnityEngine.Random.insideUnitCircle.normalized * SpawnRadius;
randomPoint.x = randomPoint2D.x;
randomPoint.y = randomPoint2D.y;
finalPos = PHomeGameMode.main.PlayerUnit.transform.position + randomPoint;
// 检查该点是否在矩形范围外
if (!IsPointInsideRectangle(randomPoint, screenSize.x, screenSize.y) && (Mathf.Abs(finalPos.x) < m_topRightPos.position.x && Mathf.Abs(finalPos.y) < m_topRightPos.position.y))
{
foundPoint = true;
Debug.Log("Random point in circle and outside rectangle: " + randomPoint);
}
}
return finalPos;
}
// 检查点是否在矩形范围内
bool IsPointInsideRectangle(Vector3 point, float width, float height)
{
return Mathf.Abs(point.x) <= width / 2f && Mathf.Abs(point.z) <= height / 2f;
}
private void Start()
{
MessageDispatcher.Instance.RegisterMessageHandler((uint)MsgType.GameWin, GameWin);
gameWin = false;
}
void OnDestroy()
{
MessageDispatcher.Instance.UnRegisterMessageHandler((uint)MsgType.GameWin, GameWin);
}
bool gameWin = false;
void GameWin(uint iMessageType, object arg)
{
gameWin = true;
}
// Update is called once per frame
void Update()
{
if (gameWin) return;
if (m_spawnTimer >= 0)
{
m_spawnTimer -= Time.deltaTime;
}
else if (PHomeGameMode.main.MysticalScentTime > 0)
{
TrySpawnOneMonsterMysticalScent();
}
else
{
TrySpawnOneMonster();
}
if (Input.GetKeyDown(KeyCode.N))
{
KillAllMonster();
}
}
}