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