CTT/Server/Hotfix/Game/Helper/CharacterHelper.cs

621 lines
24 KiB
C#
Raw Normal View History

2021-04-08 20:09:59 +08:00
using System;
using System.Collections.Generic;
using Cal;
using Cal.DataTable;
using System.Linq;
namespace ET
{
public class CharacterHelper
{
public enum MoneyType
{
UnKnown = 0,
YuanBao = 1,
Voucher = 2,
Coin = 3,
Gem = 4,
}
private readonly static float[] CharacterPointScaleArr = { 0.1f, 0.42f, 1.07f, 1.89f };
internal static void ResetAddNumeric(Unit unit, NumericComponent num)
{
num ??= unit.GetComponent<NumericComponent>();
if (num == null)
{
Log.Error($"num == null where id = {unit?.Id}");
return;
}
num.ReSetAddNum();
}
public static void InitData(NumericComponent num)
{
Character character = num.Parent.GetComponent<Character>();
num.Set(NumericType.Level, 1);
num.Set(NumericType.Exp, 0);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
}
public static void RecoverUnit(Unit unit)
{
var num = unit.GetComponent<NumericComponent>();
num.Set(NumericType.Hp, num.Get(NumericType.MaxHp));
num.Set(NumericType.Mp, num.Get(NumericType.MaxMp));
}
private static NumericType[] numTypeArr;
public static M2C_SyncUnitAttributeList GetSyncUnitAttributeList(Unit unit)
{
var num = unit.GetComponent<NumericComponent>();
if (numTypeArr == null)
{
var arr = Enum.GetValues(typeof(NumericType));
numTypeArr = (NumericType[])arr;
}
M2C_SyncUnitAttributeList list = new M2C_SyncUnitAttributeList();
foreach (NumericType type in numTypeArr)
{
if (type < NumericType.Max)
{
float value = num.Get(type);
if (value != 0)
list.NumericMap.Add(new AttributeMap
{
Key = (int)type,
Value = value,
});
}
}
return list;
}
public static void SyncAttribute(Unit unit)
{
if (!unit) return;
var num = unit.GetComponent<NumericComponent>();
var component = DelaySendSyncAttributeComponent.instance;
if (numTypeArr == null)
{
var arr = Enum.GetValues(typeof(NumericType));
numTypeArr = (NumericType[])arr;
}
foreach (NumericType type in numTypeArr)
{
if (type < NumericType.Max)
{
float value = num.Get(type);
if (value != 0)
component.Add(unit, type, value);
}
}
}
public static void SyncNumeric(Unit unit)
{
var num = unit.GetComponent<NumericComponent>();
var combat = unit.GetComponent<Combat>();
if (combat)
SyncNumeric(num, combat);
}
public static void SyncNumeric(NumericComponent num, Combat combat)
{
foreach (AttributeType type in Enum.GetValues(typeof(AttributeType)))
{
SetNumValue(num, combat, type);
}
}
private static void SetNumValue(NumericComponent num, Combat combat, AttributeType type)
{
switch (type)
{
case AttributeType.:
num.Set(NumericType.MaxHpBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.MaxMpBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.StrBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.QukBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.SpiBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.WimBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.PhyAtkBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.SpiAtkBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.PhyDefBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.SpiDefBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.PcrirBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.McrirBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.PcriBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.McriBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.RpcrirBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.RmcrirBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.RpcriBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.RmcriBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.DvoBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.PhyBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.StaBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.NphyiBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.NmeniBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.SpdBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.HitBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.ResBase, combat.GetAtribute(type));
break;
case AttributeType.:
break;
case AttributeType.:
num.Set(NumericType.SuckRBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.SuckVBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.HpRecoverBase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.PhyDABase, combat.GetAtribute(type));
break;
case AttributeType.:
num.Set(NumericType.MicDABase, combat.GetAtribute(type));
break;
default:
break;
}
}
public static int GetCharacterPoint(int oldLevel, int level, int perLevel)
{
if (perLevel == 0)
{
Log.Error($"perLevel == 0");
return 0;
}
// 9->10 10->11 11->30 30->40
// 0,1 1,1 1,3 3->4
int oldTimes = oldLevel / perLevel;
int newTimes = level / perLevel;
return newTimes - oldTimes;
}
public static float GetCharacterPoint(float oldLevel, float level, float perLevel)
{
if (perLevel == 0)
{
Log.Error($"perLevel == 0");
return 0;
}
int oldTimes = (int)(oldLevel / perLevel);
int newTimes = (int)(level / perLevel);
return newTimes-oldTimes;
}
public static float GetAttributeByPoint(Combat combat, AttributeType attributeType, float str, float wim, float quk, float spi, float phy, float sta)
{
User user = UserComponent.Instance.Get(combat.Id);
if (user == null) return 0;
int job = (user.JobId + 1) / 2;
CharacterGrowth growth = DataTableHelper.Get<CharacterGrowth>((int)attributeType * 10 + job);
if (growth == null)
{
Log.Error($"growth = null where id = {(int)attributeType * 10 + job}");
}
return growth.Str * str + growth.Wim * wim + growth.Quk * quk + growth.Spi * spi + growth.Phy * phy + growth.Sta * sta;
}
public static void AddPoint(Character num, AttributeType type, int value)
{
num.AddPoint(type, value);
}
public static void ResetPoint(Unit unit)
{
Character character = unit.GetComponent<Character>();
int point = character.RemovePoint();
var data = unit.GetComponent<PlayerData>();
data.CharacterPointKV.Deconstruct(out int canUse, out int total);
canUse += point;
data.CharacterPointKV = KeyValuePair.Create(canUse, total);
}
public static void AddExp(Unit unit, long exp)
{
var num = unit.GetComponent<NumericComponent>();
num.AddSet(NumericType.Exp, exp);
}
public static void AddLevel(Unit unit, int _level)
{
var num = unit.GetComponent<NumericComponent>();
int level = num.GetAsInt(NumericType.Level);
int trans = num.GetAsInt(NumericType.Transmigration);
long needExp = 0;
int currLevel = level;
for (int i = level; i < level + _level; i++)
{
long need = GetUpgradeLevelExp(trans, currLevel++);
if (need == -1) continue;
needExp += need;
}
AddExp(unit, needExp);
}
public static int GetLargerAtk(NumericComponent num)
{
int phyAtk = num.GetAsInt(NumericType.PhyAtk);
int spiAtk = num.GetAsInt(NumericType.SpiAtk);
return phyAtk > spiAtk ? phyAtk : spiAtk;
}
public static AttributeType GetAtkType(int jobId)
{
if (jobId <= 4)
return AttributeType.;
else
return AttributeType.;
}
private const int MaxSpeed = 7000;
public static float GetSpeed(int value)
{
return (float)(MaxSpeed * Math.Atan(value / 10000f) * 2 / MathF.PI);
}
/// <summary>
/// 1-(x/7000)^2 1 -> 0
/// 6000 -> 4000
/// 4000 + 2000*(1-(x/7000)^2)
/// </summary>
/// <param name="spd"></param>
/// <returns></returns>
public static float GetSkillCD(float spd)
{
float cd = 4000 + 2000 * (1 - MathF.Pow(spd / MaxSpeed, 2));
if (cd < 4000)
cd = 4000;
return cd;
}
public static bool CheckCanTransmigrate(NumericComponent num, int level)
{
var trans = GetTransmigrationByLevel(level);
var transNum = num.GetAsInt(NumericType.Transmigration);
if (transNum >= trans)
return true;
return false;
}
private readonly static int[] levelArr = { 0, 6000, 13000, 21500, 31500 };
public static int GetTransmigrationLevel(int level)
{
for (int i = 0; i < levelArr.Length - 1; i++)
{
if (level < levelArr[i])
{
return levelArr[i];
}
}
return levelArr[0];
}
public static int GetTransmigrationLevelByTrans(int trans)
{
return levelArr[trans + 1];
}
public static int GetCurrBaseLevel(int level)
{
for (int i = 0; i < levelArr.Length - 1; i++)
{
if (level <= levelArr[i])
{
if (i == 0) return levelArr[0];
return levelArr[i - 1];
}
}
return levelArr[0];
}
public static int GetTransmigrationByLevel(int level)
{
for (int i = 0; i < levelArr.Length - 1; i++)
{
if (level < levelArr[i])
{
if (i == 0) return 0;
return i - 1;
}
}
return 0;
}
public static async ETTask<UnitCharacter> GetUnitCharacter(Unit unit, User user = null, NumericComponent num = null)
{
user ??= await UserComponent.Instance.Query(unit.Id);
if (user == null)
{
Log.Error($"user == null where id= {unit?.Id}");
return new UnitCharacter();
}
var data = unit.GetComponent<PlayerData>();
num ??= unit.GetComponent<NumericComponent>();
UnitCharacter unitCharacter = new UnitCharacter
{
Id = unit.Id,
NickName = user.NickName,
JobId = user.JobId,
Title = num.GetAsInt( NumericType.Title),
CampType = user.CampType,
Family = user.Family,
SkinId = user.SkinId,
Level = user.Level,
LeaderId=unit.TeamLeaderId,
Trans = num.GetAsInt( NumericType.Transmigration),
Hp = num.GetAsInt( NumericType.Hp),
MaxHp = num.GetAsInt( NumericType.MaxHp),
Mp = num.GetAsInt( NumericType.Mp),
MaxMp = num.GetAsInt( NumericType.MaxMp),
};
unitCharacter.CharacterPoint = data.CharacterPointKV.Key;
unitCharacter.SkillPoint = data.SkillPointKV.Key;
return unitCharacter;
}
/// <summary>
/// 支付
/// </summary>
/// <param name="unit"></param>
/// <param name="moneyType"></param>
/// <param name="price"></param>
/// <returns>null is correct</returns>
public static string ReduceMoney(Unit unit, MoneyType moneyType, long price)
{
var num = unit.GetComponent<NumericComponent>();
switch (moneyType)
{
case MoneyType.Coin:
{
if (num.GetAsLong(NumericType.Coin) < price)
return "您的金币不足,无法购买!";
num.ReduceSet(NumericType.Coin, price);
}
break;
case MoneyType.YuanBao:
{
if (num.GetAsInt(NumericType.YuanBao) < price)
return "您的元宝不足,无法购买!";
num.ReduceSet(NumericType.YuanBao, (int)price);
}
break;
case MoneyType.Voucher:
{
if (num.GetAsInt(NumericType.Voucher) < price)
return "您的代金券不足,无法购买!";
num.ReduceSet(NumericType.Voucher, (int)price);
}
break;
case MoneyType.Gem:
{
if (num.GetAsLong(NumericType.Gem) < price)
return "您的星币不足,无法购买!";
num.ReduceSet(NumericType.Gem, price);
}
break;
}
return null;
}
public static void AddMoney(Unit unit, MoneyType moneyType, long price)
{
var num = unit.GetComponent<NumericComponent>();
switch (moneyType)
{
case MoneyType.Coin:
num.AddSet(NumericType.Coin, price);
break;
case MoneyType.YuanBao:
num.AddSet(NumericType.YuanBao, (int)price);
break;
case MoneyType.Voucher:
num.AddSet(NumericType.Voucher, (int)price);
break;
case MoneyType.Gem:
num.AddSet(NumericType.Gem, price);
break;
}
}
public static void AddAutoCharacterPoint(NumericComponent num, PlayerData data, int oldLevel, int level)
{
//!10级一个自动属性
int dLevel = GetRelationLevel(level);
int point = CharacterHelper.GetCharacterPoint(oldLevel, level, ConstDefine.AutoAddCharacterPointPerLevel);
if (point > 0)
{
var unit = num.GetParent<Unit>();
var character = unit.GetComponent<Character>();
character.AddAllPoint(point);
CharacterHelper.SyncNumeric(unit);
}
var kp = data.CharacterPointKV;
int totalPoint = dLevel / ConstDefine.AddCharacterPointPerLevel;
kp.Deconstruct(out var key, out var value);
int dPoint = totalPoint - value;
value = totalPoint;
key += dPoint;
data.CharacterPointKV = KeyValuePair.Create(key, value);
Log.Info($"当前属性点数{key} 总属性点数{value}");
}
public static void AddSkillPoint(PlayerData data, int level)
{
int trans = data.Parent.GetComponent<NumericComponent>().GetAsInt(NumericType.Transmigration);
int totalPoint = 0;
for (int i = 0; i < trans; i++)
{
totalPoint += GetRelationLevel(levelArr[i + 1]) / ConstDefine.AddSkillPointPerLevelArr[i];
}
totalPoint += GetRelationLevel(level) / ConstDefine.AddSkillPointPerLevelArr[trans];
data.SkillPointKV.Deconstruct(out var key, out var value);
int dPoint = totalPoint - value;
value = totalPoint;
key += dPoint;
data.SkillPointKV = KeyValuePair.Create(key, value);
Log.Info($"当前技能点数{key} 总技能点数{value}");
}
public static async ETTask ReSetCharacter(Unit unit)
{
if (unit == null)
{
return;
}
var character = unit.GetComponent<Character>();
character.ReSet();
var num = unit.GetComponent<NumericComponent>();
CharacterHelper.InitData(num);
num.Set(NumericType.Transmigration, 0);
PlayerData data = unit.GetComponent<PlayerData>();
data.CharacterPointKV = KeyValuePair.Create(0, 0);
data.SkillPointKV = KeyValuePair.Create(0, 0);
UnitSkillComponent unitSkillComponent = unit.GetComponent<UnitSkillComponent>();
await unitSkillComponent.ResetSkill();
CharacterHelper.SyncNumeric(unit);
UnitHelper.SaveComponenet(character).Coroutine();
UnitHelper.SaveComponenet(data).Coroutine();
UnitHelper.SaveComponenet(num).Coroutine();
CharacterHelper.SyncAttribute(unit);
}
public static long GetUpgradeLevelExp(Unit unit)
{
NumericComponent num = unit.GetComponent<NumericComponent>();
int trans = num.GetAsInt(NumericType.Transmigration);
int level = num.GetAsInt(NumericType.Level);
long needExp = GetUpgradeLevelExp(trans, level);
return needExp;
}
public static long GetUpgradeLevelExp(int trans, int level)
{
int trans_ = GetTransmigrationByLevel(level);
if (trans_ != trans) return -1;
level = GetRelationLevel(level);
long needExp = (long)(ConstDefine.ExpBaseArr[trans] * MathF.Pow(level, ConstDefine.ExpPowerArr[trans]));
return needExp;
}
/// <summary>
/// 获取相对于转生等级的等级差,0-5999->0
/// </summary>
/// <param name="level"></param>
/// <returns></returns>
public static int GetRelationLevel(int level)
{
int transLevel = GetCurrBaseLevel(level);
return level - transLevel;
}
public static async ETTask<string> Transmigration(Unit unit)
{
var num = unit.GetComponent<NumericComponent>();
int trans = num.GetAsInt(NumericType.Transmigration);
int level = num.GetAsInt(NumericType.Level);
int transLevel = GetTransmigrationLevelByTrans(trans);
if (level != transLevel)
{
Log.Info($"【{UserComponent.Instance.Get(unit.Id)?.NickName}({unit.Id})】level = {level} not equals transLevel = {transLevel}");
return "等级不符合";
}
if (++trans >= levelArr.Length) return "达到上限";
User user = await UserComponent.Instance.Query(unit.Id);
if (user == null) return "玩家不存在";
int id = (user.JobId + 1) / 2 * 10 + trans;
TransmigrationAddConfig addConfig = TransmigrationAddConfigCategory.Instance.Get(id);
if (addConfig == null) return $"配置不存在 {id}";
//重置等级,属性点
Character character = unit.GetComponent<Character>();
num.Set(NumericType.Exp, 0, false);
num.AddSet(NumericType.Level, 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.Set(AttributeType., 1);
character.ReSet();
PlayerData data = unit.GetComponent<PlayerData>();
data.CharacterPointKV = KeyValuePair.Create(0, 0);
//增加永久属性
foreach (var addAttribute in addConfig.AddAttributeArr)
{
character.SetAdd((AttributeType)addAttribute.Key, addAttribute.Value);
}
num.Set(NumericType.Transmigration, trans);
//计算结果,同步
CharacterHelper.SyncNumeric(unit);
UnitHelper.SaveComponenet(character).Coroutine();
UnitHelper.SaveComponenet(data).Coroutine();
UnitHelper.SaveComponenet(num).Coroutine();
CharacterHelper.SyncAttribute(unit);
return null;
}
/// <summary>
/// 转职
/// </summary>
/// <param name="unit"></param>
/// <param name="jobType">1,2,3,4</param>
public static async ETTask TransferJob(Unit unit,int jobType,bool isFree)
{
User user = await UserComponent.Instance.Query(unit.Id);
int jobId = user.JobId;
SexType sexType = JobHelper.GetSexType(jobId);
user.JobId = (int)(sexType + jobType*2-1);
UnitSkillComponent unitSkillComponent = unit.GetComponent<UnitSkillComponent>();
unitSkillComponent.TransferJob(jobType);
await UserComponent.Instance.Save(user);
}
}
}