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.
278 lines
9.8 KiB
278 lines
9.8 KiB
using System.Globalization;
|
|
using System.Numerics;
|
|
using System;
|
|
using IVDataFormat;
|
|
using IVServerFormat;
|
|
using System.Collections.Generic;
|
|
|
|
[Serializable]
|
|
public class DispatchMissionProperty
|
|
{
|
|
public enum MissionType
|
|
{
|
|
Normal,
|
|
Battle,
|
|
}
|
|
|
|
public uint id;
|
|
public MissionType type;
|
|
public GoodsProperty[] rewardCandidates;
|
|
}
|
|
|
|
[Serializable]
|
|
public class DispatchMissionPlayerProperty
|
|
{
|
|
public uint id = 0;
|
|
public bool gotReward = true;
|
|
public bool needGetResult = false;
|
|
public bool hasResult = false;
|
|
public bool isSucceed = false;
|
|
public string recommendBattlePower = "0";
|
|
public uint[] recommendNationalities = new uint[0];
|
|
public uint[] bonusRewardTargets = new uint[0];
|
|
public string endTime = DateTime.MaxValue.ToString(FormatString.DateTimeParse, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public class DispatchMissionData
|
|
{
|
|
DispatchData.Area area;
|
|
DispatchMissionProperty property;
|
|
DispatchMissionPlayerProperty playerProperty;
|
|
|
|
int requestCount = 0;
|
|
Action<IList<nGoods>, bool> onDoneGetResult;
|
|
|
|
public DispatchMissionProperty.MissionType Type => property.type;
|
|
public uint ID => property.id;
|
|
public bool GotReward => playerProperty.gotReward;
|
|
public bool HasResult => playerProperty.hasResult;
|
|
public bool IsSucceed => playerProperty.isSucceed;
|
|
public bool NeedGetResult => playerProperty.needGetResult;
|
|
public float TotalProgressTime => area.MissionProgressTime + (area.MissionMoveTime * 2);
|
|
public DateTime EndTime => DateTime.ParseExact(playerProperty.endTime, FormatString.DateTimeParse, CultureInfo.InvariantCulture);
|
|
public BigInteger RecommendBattlePower => BigInteger.Parse(playerProperty.recommendBattlePower);
|
|
public string ContentStringKey => FormatString.StringFormat("dispatch_content_{0}_{1}", area.AreaType, ID);
|
|
public string ContentIconAtlasPath => GameProperty.Instance.MissionContentIconAtlasName;
|
|
public string ContentIconNameInAtlas => ContentStringKey;
|
|
public Nationality[] RecommendNationalities { get; set; }
|
|
public nGoods[] DefaultRewards { get; private set; }
|
|
public nGoods[] TotalRewards
|
|
{
|
|
get
|
|
{
|
|
var employees = new SlotGroup<MateData>(area.EmployeeIDs.Count);
|
|
for (int i = 0; i < area.EmployeeIDs.Count; i++)
|
|
{
|
|
if (MateDataGroup.Instance.TryGetMateData(area.EmployeeIDs[i], out var mate))
|
|
employees[i] = mate;
|
|
}
|
|
|
|
var totalRewards = new Dictionary<GoodsProperty, BigInteger>(new GoodsPropertyComparer());
|
|
for (int i = 0; i < DefaultRewards.Length; i++)
|
|
totalRewards.SafeInsert(DefaultRewards[i].GetProperty(), DefaultRewards[i].propertyCount);
|
|
|
|
var dispatchLvBonus = bonusRewardByDispatchLv;
|
|
var dispatchLvBonusProperty = dispatchLvBonus.GetProperty();
|
|
if (totalRewards.TryGetValue(dispatchLvBonusProperty, out var count))
|
|
totalRewards[dispatchLvBonusProperty] = count + dispatchLvBonus.propertyCount;
|
|
|
|
var nationalityBonus = GetBonusRewardByNationality(employees);
|
|
var nationalityBonusProperty = nationalityBonus.GetProperty();
|
|
if (totalRewards.TryGetValue(nationalityBonusProperty, out count))
|
|
totalRewards[nationalityBonusProperty] = count + nationalityBonus.propertyCount;
|
|
|
|
var employeeCountBonus = GetBonusRewardByEmployeeCount(employees);
|
|
var employeeCountBonusProperty = employeeCountBonus.GetProperty();
|
|
if (totalRewards.TryGetValue(employeeCountBonusProperty, out count))
|
|
totalRewards[employeeCountBonusProperty] = count + employeeCountBonus.propertyCount;
|
|
|
|
var result = new nGoods[totalRewards.Count];
|
|
int idx = 0;
|
|
foreach (var reward in totalRewards)
|
|
{
|
|
result[idx++] = new nGoods(reward.Key, reward.Value);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public nGoods bonusRewardByDispatchLv => new nGoods(property.rewardCandidates[playerProperty.bonusRewardTargets[0]], area.DispatchData.DispatchLevel * 10);
|
|
|
|
public DispatchMissionData(DispatchData.Area area, DispatchMissionProperty property, DispatchMissionPlayerProperty playerProperty)
|
|
{
|
|
this.area = area;
|
|
this.property = property;
|
|
this.playerProperty = playerProperty;
|
|
|
|
RecommendNationalities = new Nationality[playerProperty.recommendNationalities.Length];
|
|
for (int i = 0; i < playerProperty.recommendNationalities.Length; i++)
|
|
{
|
|
RecommendNationalities[i] = new Nationality { kind = (Nationality.Kind)playerProperty.recommendNationalities[i] };
|
|
}
|
|
|
|
DefaultRewards = new nGoods[property.rewardCandidates.Length];
|
|
for (int i = 0; i < property.rewardCandidates.Length; i++)
|
|
{
|
|
//TODO : temp reward amount
|
|
DefaultRewards[i] = new nGoods(property.rewardCandidates[i], area.DispatchData.DispatchLevel * 10);
|
|
}
|
|
}
|
|
|
|
public void Start(DateTime now)
|
|
{
|
|
playerProperty.needGetResult = true;
|
|
playerProperty.hasResult = false;
|
|
playerProperty.gotReward = false;
|
|
|
|
//미션 소요 시간 : 수행 시간 + 지역 왕복 시간
|
|
float totalProgressTime = area.MissionProgressTime + (area.MissionMoveTime * 2);
|
|
playerProperty.endTime = now.AddSeconds(totalProgressTime).ToString(FormatString.DateTimeParse, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public nGoods GetBonusRewardByNationality(SlotGroup<MateData> mates)
|
|
{
|
|
int[] remainCounts = new int[(int)Nationality.Kind.Count];
|
|
for (int i = 0; i < RecommendNationalities.Length; i++)
|
|
{
|
|
remainCounts[(int)RecommendNationalities[i].kind]++;
|
|
}
|
|
|
|
int matchCount = 0;
|
|
mates.LoopValidSlot((mate) =>
|
|
{
|
|
int idx = (int)mate.nationality.kind;
|
|
if (remainCounts[idx] > 0)
|
|
{
|
|
remainCounts[idx]--;
|
|
matchCount++;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
return new nGoods(property.rewardCandidates[playerProperty.bonusRewardTargets[1]], matchCount * 10);
|
|
}
|
|
|
|
public nGoods GetBonusRewardByEmployeeCount(SlotGroup<MateData> mates)
|
|
{
|
|
int count = 0;
|
|
mates.LoopValidSlot((mate) =>
|
|
{
|
|
count++;
|
|
return true;
|
|
});
|
|
|
|
return new nGoods(property.rewardCandidates[playerProperty.bonusRewardTargets[2]], count * 10);
|
|
}
|
|
|
|
public bool InProgress(DateTime now) => now < EndTime;
|
|
|
|
public bool IsAvailableGetResult(DateTime now)
|
|
{
|
|
//미션 지역 도착 + 수행 시간 이후 결과 확인 가능.
|
|
return EndTime.AddSeconds(-area.MissionMoveTime) <= now;
|
|
}
|
|
|
|
public void SetResult(BigInteger battlePower)
|
|
{
|
|
if (!playerProperty.needGetResult) return;
|
|
|
|
var scRate = GetSuccessRate(battlePower);
|
|
var rand = UnityEngine.Random.Range(0.0f, 1.0f);
|
|
playerProperty.isSucceed = rand <= scRate;
|
|
|
|
playerProperty.needGetResult = false;
|
|
playerProperty.hasResult = true;
|
|
}
|
|
|
|
public void RemoveResult()
|
|
{
|
|
playerProperty.hasResult = false;
|
|
playerProperty.isSucceed = false;
|
|
}
|
|
|
|
public void TryGetReward(Action<IList<nGoods>, bool> onRequestDone)
|
|
{
|
|
if(requestCount > 0) return;
|
|
|
|
requestCount = DefaultRewards.Length;
|
|
onDoneGetResult = onRequestDone;
|
|
|
|
foreach (var reward in TotalRewards)
|
|
{
|
|
SvConnectManager.Instance.RequestSvPost(true, 0, UrlApi.GetUrl(UrlApi.Property), typeof(nGoodsGet), OnGetRewardSuccess, OnGetRewardFail, reward, true);
|
|
}
|
|
}
|
|
|
|
private void OnGetRewardSuccess(object result, object request)
|
|
{
|
|
if(--requestCount <= 0)
|
|
{
|
|
playerProperty.gotReward = true;
|
|
|
|
nGoodsGet data = result as nGoodsGet;
|
|
var totalReward = TotalRewards;
|
|
|
|
DataHandler.AddGoods(totalReward, data.playCurrency, true);
|
|
onDoneGetResult?.Invoke(totalReward, true);
|
|
}
|
|
}
|
|
|
|
private void OnGetRewardFail(SvError error, object request) => onDoneGetResult?.Invoke(new nGoods[0], false);
|
|
|
|
public int GetSuccessRateLevel(BigInteger battlePower)
|
|
{
|
|
if (Type == DispatchMissionProperty.MissionType.Normal) return 5;
|
|
|
|
//-50미만 : 매우낮음
|
|
//-50이상 ~ -10미만 : 낮음
|
|
//-10이상 ~ 10미만 : 보통
|
|
//10이상 ~ 50미만 : 높음
|
|
//50이상 : 매우높음
|
|
|
|
var bpBoundaries = new BigInteger[]
|
|
{
|
|
RecommendBattlePower - (RecommendBattlePower / 100) * 50,
|
|
RecommendBattlePower - (RecommendBattlePower / 100) * 10,
|
|
RecommendBattlePower + (RecommendBattlePower / 100) * 10,
|
|
RecommendBattlePower + (RecommendBattlePower / 100) * 50,
|
|
};
|
|
|
|
for (int i = 0; i < bpBoundaries.Length; i++)
|
|
{
|
|
if (battlePower < bpBoundaries[i])
|
|
return i + 1;
|
|
}
|
|
|
|
return 5;
|
|
}
|
|
|
|
public float GetSuccessRate(BigInteger battlePower)
|
|
{
|
|
int scLevel = GetSuccessRateLevel(battlePower);
|
|
|
|
if (scLevel <= 1) return 0.05f;
|
|
else if (scLevel == 2) return 0.3f;
|
|
else if (scLevel == 3) return 0.7f;
|
|
else if (scLevel == 4) return 0.9f;
|
|
else return 1.0f;
|
|
}
|
|
|
|
public uint CalculateExp()
|
|
{
|
|
//TODO : this is temp code
|
|
const uint normalBaseExp = 5;
|
|
const uint normalExpPerLevel = 1;
|
|
|
|
const uint battleBaseExp = 10;
|
|
const uint battleExpPerLevel = 1;
|
|
|
|
switch (Type)
|
|
{
|
|
case DispatchMissionProperty.MissionType.Normal: return normalBaseExp + (area.DispatchData.DispatchLevel - 1) * normalExpPerLevel;
|
|
case DispatchMissionProperty.MissionType.Battle: return battleBaseExp + (area.DispatchData.DispatchLevel - 1) * battleExpPerLevel;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|