282 lines
8.4 KiB
Plaintext
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();
|
|
}
|
|
}
|
|
}
|