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.
 
 
 
 
 
 

292 lines
9.6 KiB

using System.Collections.Generic;
using System.Globalization;
using System;
[Serializable]
public class DispatchProperty
{
[Serializable]
public class AreaProperty
{
public WorldArea areaType;
public float[] rndMissionPosMoveTime = new float[] { 10, 20, 30, 40, 50, 60 };
public DispatchMissionProperty[] missionProperties;
public int MaxRndMissionPosCnt => rndMissionPosMoveTime.Length;
}
public uint maxLevel = 100;
public uint maxEmployeeCount = 3;
public float missionProgressTimeSec = 5;
public float missionRefreshTimeSec = 60;
public AreaProperty[] areas = new AreaProperty[]
{
new AreaProperty { areaType = WorldArea.East },
new AreaProperty { areaType = WorldArea.West },
new AreaProperty { areaType = WorldArea.South },
new AreaProperty { areaType = WorldArea.North },
};
}
[Serializable]
public class DispatchPlayerProperty
{
[Serializable]
public class AreaPlayerProperty
{
public WorldArea areaType;
public bool needRefreshMission;
public bool needClearEmployee;
public string refreshEndTime = DateTime.MaxValue.ToString(FormatString.DateTimeParse, CultureInfo.InvariantCulture);
public int missionPositionIndex;
public uint[] employeeIDs = new uint[0];
public DispatchMissionPlayerProperty mission;
}
public uint dispatchExp;
public AreaPlayerProperty[] areas = new AreaPlayerProperty[]
{
new AreaPlayerProperty { areaType = WorldArea.East },
new AreaPlayerProperty { areaType = WorldArea.West },
new AreaPlayerProperty { areaType = WorldArea.South },
new AreaPlayerProperty { areaType = WorldArea.North },
};
}
public partial class DispatchData
{
DispatchProperty property;
DispatchPlayerProperty playerProperty;
Area[] areas;
public uint MaxLevel => property.maxLevel;
public uint MaxEmployeeCount => property.maxEmployeeCount;
public float MissionRefreshTimeSec => property.missionRefreshTimeSec;
public uint DispatchLevel { get; private set; }
public uint DispatchExp => playerProperty.dispatchExp;
public IList<Area> Areas => areas;
public DispatchData(DispatchProperty property, DispatchPlayerProperty playerProperty)
{
this.property = property;
this.playerProperty = playerProperty;
areas = new Area[playerProperty.areas.Length];
for (int i = 0; i < areas.Length; ++i)
{
areas[i] = new Area(this, property.areas[i], playerProperty.areas[i]);
}
DispatchLevel = GetDispatchLevelByExp(playerProperty.dispatchExp);
}
public bool AddDispatchExp(uint exp)
{
playerProperty.dispatchExp += exp;
uint prevLevel = DispatchLevel;
DispatchLevel = GetDispatchLevelByExp(DispatchExp, DispatchLevel);
return prevLevel != DispatchLevel;
}
public uint GetDispatchLevelByExp(uint exp, uint offset = 2)
{
if (offset < 2)
offset = 2;
for (uint i = offset; i <= MaxLevel; i++)
{
if(exp < GetTotalExpToLevel(i))
return i - 1;
}
return MaxLevel;
}
public uint GetTotalExpToLevel(uint level)
{
//TODO : this is temp code
const uint baseExp = 100;
const uint expPerLevel = 10;
if(level < 2) return 0;
uint a = level - 1;
uint b = a - 1;
return baseExp * a + expPerLevel * Utility.PermutationAdd(b);
}
public bool TryGetArea(WorldArea areaType, out Area result)
{
result = null;
for (int i = 0; i < areas.Length; ++i)
{
if (areas[i].AreaType == areaType)
{
result = areas[i];
break;
}
}
return result != null;
}
}
public partial class DispatchData
{
[Serializable]
public class Area
{
DispatchProperty.AreaProperty property;
DispatchPlayerProperty.AreaPlayerProperty playerProperty;
public DispatchData DispatchData { get; private set; }
public DispatchMissionData Mission { get; private set; }
public WorldArea AreaType => playerProperty.areaType;
public DateTime RefreshEndTime => DateTime.ParseExact(playerProperty.refreshEndTime, FormatString.DateTimeParse, CultureInfo.InvariantCulture);
public int MissionPositionIndex => playerProperty.missionPositionIndex;
public IList<uint> EmployeeIDs => playerProperty.employeeIDs;
public float MissionMoveTime => property.rndMissionPosMoveTime[MissionPositionIndex];
public float MissionProgressTime => DispatchData.property.missionProgressTimeSec;
public bool NeedRefreshMission => playerProperty.needRefreshMission;
public bool NeedClearEmployee => playerProperty.needClearEmployee;
public string ImageAtlasPath => GameProperty.Instance.AreaImageAtlasName;
public string ImageNameInAtlas => AreaType.ToString();
public event Action OnRefreshMission;
public Area(DispatchData dispatchData, DispatchProperty.AreaProperty areaProperty, DispatchPlayerProperty.AreaPlayerProperty areaPlayerProperty)
{
property = areaProperty;
playerProperty = areaPlayerProperty;
DispatchData = dispatchData;
if (TryGetAreaMissionProperty(out var missionProp))
Mission = new DispatchMissionData(this, missionProp, playerProperty.mission);
else
RefreshMission(TimeUtils.Now());
}
private bool TryGetAreaMissionProperty(out DispatchMissionProperty result)
{
for (int j = 0; j < property.missionProperties.Length; ++j)
{
var missionProp = property.missionProperties[j];
if (missionProp.id == playerProperty.mission.id)
{
result = missionProp;
return true;
}
}
result = null;
return false;
}
public void SetEmployeeID(int slotIndex, uint id)
{
if (slotIndex >= playerProperty.employeeIDs.Length)
Array.Resize(ref playerProperty.employeeIDs, slotIndex + 1);
playerProperty.employeeIDs[slotIndex] = id;
}
public void ClearEmployeeID()
{
playerProperty.employeeIDs = new uint[DispatchData.MaxEmployeeCount];
}
public void StartRefreshTime(DateTime now)
{
playerProperty.needRefreshMission = true;
playerProperty.refreshEndTime = (now.AddSeconds(DispatchData.MissionRefreshTimeSec)).ToString(FormatString.DateTimeParse, CultureInfo.InvariantCulture);
}
public bool IsInRefreshTime(DateTime now) => now < RefreshEndTime;
public void StartMission(DateTime now)
{
playerProperty.needClearEmployee = true;
Mission.Start(now);
}
public void RefreshMission(DateTime now)
{
if (!property.missionProperties.TryGetRandomValue(out var missionProp))
{
Logger.LogError("Can't find mission property for area type: " + AreaType.ToString());
return;
}
playerProperty.needRefreshMission = false;
playerProperty.needClearEmployee = false;
playerProperty.refreshEndTime = now.ToString(FormatString.DateTimeParse, CultureInfo.InvariantCulture);
playerProperty.missionPositionIndex = UnityEngine.Random.Range(0, property.MaxRndMissionPosCnt);
ClearEmployeeID();
playerProperty.mission.id = missionProp.id;
playerProperty.mission.gotReward = true;
playerProperty.mission.needGetResult = false;
playerProperty.mission.hasResult = false;
playerProperty.mission.isSucceed = false;
playerProperty.mission.recommendNationalities = GetRecommendNationalities();
playerProperty.mission.bonusRewardTargets = GetRandomBonusRewards(missionProp);
playerProperty.mission.endTime = now.ToString(FormatString.DateTimeParse, CultureInfo.InvariantCulture);
Mission = new DispatchMissionData(this, missionProp, playerProperty.mission);
OnRefreshMission?.Invoke();
}
private uint[] GetRecommendNationalities()
{
//TODO : get max count by dispatch level
const int maxCount = 3;
var result = new uint[maxCount];
for (int i = 0; i < maxCount; ++i)
{
result[i] = (uint)UnityEngine.Random.Range(0, (int)Nationality.Kind.Count);
}
return result;
}
private uint[] GetRandomBonusRewards(DispatchMissionProperty missionProp)
{
//TODO : get random bonus rewards
const int maxCount = 3;
if(missionProp.rewardCandidates.Length < maxCount)
throw new Exception("Not enough reward candidates");
var result = new uint[maxCount];
var candidates = new HashSet<uint>();
for(uint i = 0; i < missionProp.rewardCandidates.Length; i++)
{
candidates.Add(i);
}
int curCount = 0;
while(curCount < maxCount)
{
uint rnd = (uint)UnityEngine.Random.Range(0, missionProp.rewardCandidates.Length);
if(candidates.Contains(rnd))
{
result[curCount++] = rnd;
candidates.Remove(rnd);
}
}
return result;
}
}
}