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

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;
}
}