You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
6.7 KiB
219 lines
6.7 KiB
using BigFloatNumerics;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
using static BattleMgr;
|
|
|
|
public class ProtectTheMerchantDg : GameMod
|
|
{
|
|
[SerializeField] Transform merchantSpawnPos;
|
|
[SerializeField] Transform merchantDestinationPos;
|
|
|
|
[SerializeField] Transform playerSpawnPos;
|
|
|
|
[SerializeField] ProtectTheMerchantDgView view;
|
|
|
|
BattleMgr battleMgr => BattleMgr.Instance;
|
|
float modElapsedTime;
|
|
|
|
IVCharacter player;
|
|
|
|
Character merchant;
|
|
Dictionary<uint, IMonoObjectPool<Character>> normalEnemyPoolMap;
|
|
|
|
int currentWave;
|
|
float prevWaveTime;
|
|
float elapsedTimeSincePrevWave => Time.time - prevWaveTime;
|
|
|
|
public ProtectTheMerchantDgData Data { get; private set; }
|
|
public float ModRemainingTime => Mathf.Max(Data.LimitTime - modElapsedTime, 0f);
|
|
public float MerchantProgress => modElapsedTime > 0 ? modElapsedTime / Data.LimitTime : 0f;
|
|
|
|
protected override void OnInitialize()
|
|
{
|
|
if (GameModDataGroup.Instance.TryGetModData(ModID, out ProtectTheMerchantDgData modData))
|
|
{
|
|
Data = modData;
|
|
}
|
|
|
|
Debug.Assert(Data != null, Logger.LogMessage(LogType.Assert, nameof(ProtectTheMerchantDgData), "Data is null"));
|
|
|
|
normalEnemyPoolMap = new Dictionary<uint, IMonoObjectPool<Character>>();
|
|
}
|
|
|
|
protected override void OnStartMod()
|
|
{
|
|
//Set enemy pool
|
|
foreach (var creator in Data.NormalEnemyCreators)
|
|
{
|
|
var pool = new DynamicMonoObjectPool<Character>();
|
|
pool.Initialize(() => InstantiateEnemy(pool, creator.property, () => creator.GetHp(Data.Level), creator.GetAtk), DestroyCharacter, (int)creator.countPerWave);
|
|
normalEnemyPoolMap.Add(creator.property.id, pool);
|
|
}
|
|
|
|
//Summon player
|
|
player = battleMgr.GetPlayer();
|
|
|
|
var buffMgr = BuffMgr.Instance;
|
|
player.ResetDebuff();
|
|
player.SetStatus(
|
|
buffMgr.GetCharAtk(),
|
|
buffMgr.GetCharHp(),
|
|
buffMgr.GetCharCrtDam(),
|
|
buffMgr.GetCharCrtRate(),
|
|
buffMgr.GetCharMov(),
|
|
buffMgr.GetCharSpd(),
|
|
GameProperty.Instance.PlayerCharacterAttackRange);
|
|
player.transform.position = playerSpawnPos.position;
|
|
|
|
player.Summon();
|
|
battleMgr.SetPetsSummonState(true);
|
|
battleMgr.SetGudiansSummonState(true);
|
|
|
|
//Summon merchant
|
|
var merchantData = new CharacterData(Data.MerchantCreator.property);
|
|
if(merchantData.TryGetStat(StatID.Hp, out var hpStat))
|
|
hpStat.DefaultValue = Data.MerchantCreator.GetHp();
|
|
|
|
merchant = Instantiate(merchantData.Prefab);
|
|
merchant.SetData(merchantData);
|
|
merchant.AddTags(EntityTag.PlayerBaseCamp);
|
|
merchant.OnDisposed += DestroyCharacter;
|
|
merchant.Spawn(merchantSpawnPos.transform.position);
|
|
merchant.ChangeLookDirection(Vector2.right);
|
|
battleMgr.RegistBattleEntities(merchant);
|
|
|
|
if (merchant.StateHandler.TryGetState<MerchantMove>(out var moveState))
|
|
{
|
|
moveState.Setup(merchantSpawnPos, merchantDestinationPos, Data.LimitTime, () => modElapsedTime);
|
|
}
|
|
|
|
battleMgr.ShowTalkBox(TalkType.Summon);
|
|
|
|
currentWave = 0;
|
|
prevWaveTime = Time.time - Data.WaveIntervalTime;
|
|
modElapsedTime = 0f;
|
|
|
|
//Set UI
|
|
GameUIMgr.OnOffStageInfo(false);
|
|
|
|
view?.SetDungeon(this);
|
|
view?.Show();
|
|
|
|
IVCameraController.SMoveCamera(player.transform.position);
|
|
}
|
|
|
|
private Character InstantiateEnemy(DynamicMonoObjectPool<Character> targetPool, CharacterProperty prop, Func<BigFloat> getHpFunc, Func<BigFloat> getAtkFunc)
|
|
{
|
|
var enemyData = new CharacterData(prop);
|
|
|
|
if (enemyData.TryGetStat(StatID.Hp, out var hpStat))
|
|
hpStat.DefaultValue = getHpFunc();
|
|
if (enemyData.TryGetStat(StatID.Attack, out var atkStat))
|
|
atkStat.DefaultValue = getAtkFunc();
|
|
|
|
var enemy = Instantiate(enemyData.Prefab);
|
|
|
|
enemy.SetData(enemyData);
|
|
enemy.AddTags(EntityTag.Enemy);
|
|
enemy.SetTargetTags(LayerMask.GetMask(GameProperty.Instance.CharacterLayerName), EntityTag.PlayerBaseCamp);
|
|
|
|
enemy.OnDisposed += (obj) =>
|
|
{
|
|
BattleMgr.Instance.UnregistBattleEntities(obj);
|
|
targetPool.Return(obj);
|
|
};
|
|
|
|
return enemy;
|
|
}
|
|
|
|
private void DestroyCharacter(Character target)
|
|
{
|
|
BattleMgr.Instance.UnregistBattleEntities(target);
|
|
CoroutineHandler.Instance.DelayCall(1f, () => Destroy(target.gameObject));
|
|
}
|
|
|
|
protected override void OnUpdate()
|
|
{
|
|
if(BattleMgr.Instance.BattlePause) return;
|
|
|
|
modElapsedTime += Time.deltaTime;
|
|
|
|
if (modElapsedTime >= Data.LimitTime)
|
|
{
|
|
battleMgr.ShowTalkBox(TalkType.Attack);
|
|
|
|
Data.SetLevel(Data.Level + 1);
|
|
Data.TryGetReward((totalReward, result) =>
|
|
{
|
|
if (!result) return;
|
|
|
|
GameUIMgr.SOpenPopupGoods(totalReward);
|
|
|
|
Data.EnterTicketCount--;
|
|
GameUIMgr.RefreshProtectTheMerchantDgTicket();
|
|
});
|
|
|
|
FireOnDone(Result.Success);
|
|
}
|
|
else
|
|
{
|
|
if(merchant.IsDead)
|
|
{
|
|
battleMgr.ShowTalkBox(TalkType.Die);
|
|
FireOnDone(Result.MissionFail);
|
|
}
|
|
else if (player.IsDead)
|
|
{
|
|
battleMgr.ShowTalkBox(TalkType.Die);
|
|
FireOnDone(Result.Dead);
|
|
}
|
|
else if (currentWave < Data.WaveCount && elapsedTimeSincePrevWave >= Data.WaveIntervalTime)
|
|
{
|
|
prevWaveTime = Time.time;
|
|
currentWave++;
|
|
SpawnWave();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SpawnWave()
|
|
{
|
|
var areaSize = BattleMgr.Instance.GetBgSize();
|
|
|
|
foreach (var creator in Data.NormalEnemyCreators)
|
|
{
|
|
var rndPositions = TargetFinder.GetRandom(areaSize.bounds, (int)creator.countPerWave);
|
|
var pool = normalEnemyPoolMap[creator.property.id];
|
|
|
|
for (int i = 0; i < creator.countPerWave; i++)
|
|
{
|
|
var enemy = pool.Get();
|
|
|
|
enemy.Spawn(rndPositions[i]);
|
|
enemy.ChangeLookDirection(player.transform);
|
|
BattleMgr.Instance.RegistBattleEntities(enemy);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnEndMod()
|
|
{
|
|
view?.Hide();
|
|
|
|
GameUIMgr.OnOffStageInfo(true);
|
|
|
|
if (!merchant.IsDead)
|
|
{
|
|
DestroyCharacter(merchant);
|
|
}
|
|
|
|
foreach (var pool in normalEnemyPoolMap.Values)
|
|
{
|
|
pool.Dispose();
|
|
}
|
|
|
|
normalEnemyPoolMap.Clear();
|
|
}
|
|
}
|