132 lines
5.6 KiB
C#
132 lines
5.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using CommonDomain;
|
|
using CommonDomain.BaseModel;
|
|
using CommonDomain.Enum;
|
|
using UserDomain.Entity;
|
|
|
|
namespace RedisService.Param
|
|
{
|
|
public static class RoomBotFactory
|
|
{
|
|
public static readonly int[] FixedBotSeats = Array.Empty<int>();
|
|
|
|
public static bool FixedBotSeatsEnabled => FixedBotSeats.Length > 0;
|
|
|
|
/// <summary>基础默认炮台(与 UserService.UnloadCannon 中一致)</summary>
|
|
public const string DefaultCannonNumber = "11001";
|
|
|
|
/// <summary>机器人初始等级范围</summary>
|
|
public const int MinBotLevel = 1;
|
|
public const int MaxBotLevel = 15;
|
|
|
|
/// <summary>机器人初始 VIP 等级范围</summary>
|
|
public const int MinBotVipLevel = 0;
|
|
public const int MaxBotVipLevel = 5;
|
|
|
|
public static RedisGamePlayer CreateBot(int position, RoomConfig roomConfig, GameConfig gameConfig, IReadOnlyList<BotProfileEntity> botProfiles)
|
|
{
|
|
if (roomConfig?.CannonMultipleList == null || roomConfig.CannonMultipleList.Count == 0
|
|
|| botProfiles == null || botProfiles.Count == 0)
|
|
return null;
|
|
|
|
var profile = botProfiles[System.Random.Shared.Next(botProfiles.Count)];
|
|
var maxMultiple = roomConfig.CannonMultipleList.Max();
|
|
var gold = maxMultiple * System.Random.Shared.Next(100, 501);
|
|
|
|
var botId = Guid.NewGuid().ToString("N");
|
|
var botNumber = Common.Utils.RandomHelper.RandomNumbers(8);
|
|
var bot = new RedisGamePlayer
|
|
{
|
|
UserId = botId,
|
|
UserNumber = botNumber,
|
|
UserName = profile.Name,
|
|
Avatar = profile.Avatar,
|
|
IsBot = true,
|
|
Gold = gold,
|
|
Diamond = System.Random.Shared.Next(100, 5001),
|
|
Position = position,
|
|
CannonMultiple = roomConfig.CannonMultipleList[System.Random.Shared.Next(roomConfig.CannonMultipleList.Count)],
|
|
BeginCoin = gold,
|
|
BeginTime = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds(),
|
|
CId = string.Empty,
|
|
State = 0,
|
|
PlayerFactor = new PlayerFactor()
|
|
};
|
|
|
|
ApplyBotBaseValues(bot, gameConfig);
|
|
return bot;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置机器人基础值:等级 1~15、VIP 0~5、经验与等级对应、炮台 30% 非默认 / 70% 默认、
|
|
/// 翅膀 15%、战神 5%。三处创建机器人的入口共用,避免取值不一致。
|
|
/// </summary>
|
|
public static void ApplyBotBaseValues(RedisGamePlayer bot, GameConfig gameConfig)
|
|
{
|
|
if (bot == null)
|
|
return;
|
|
|
|
var levelConfigs = gameConfig?.UserLevelConfigs ?? new List<UserLevelConfig>();
|
|
var inRangeLevels = levelConfigs
|
|
.Where(c => c != null && c.Level >= MinBotLevel && c.Level <= MaxBotLevel)
|
|
.ToList();
|
|
|
|
var levelCfg = inRangeLevels.Count > 0
|
|
? inRangeLevels[System.Random.Shared.Next(inRangeLevels.Count)]
|
|
: null;
|
|
bot.Level = levelCfg?.Level ?? MinBotLevel;
|
|
bot.MaxExp = levelCfg?.ExpMax ?? 0;
|
|
bot.Exp = levelCfg == null || levelCfg.ExpMax <= levelCfg.ExpMin
|
|
? (levelCfg?.ExpMin ?? 0)
|
|
: System.Random.Shared.NextInt64(levelCfg.ExpMin, levelCfg.ExpMax);
|
|
|
|
bot.VipLevel = System.Random.Shared.Next(MinBotVipLevel, MaxBotVipLevel + 1);
|
|
|
|
var props = gameConfig?.PropConfig ?? new List<PropInfConfig>();
|
|
var cannons = props.Where(p => p.Type == ProductTypeEnum.炮台 && p.IsEnable && !p.Number.StartsWith("401")).ToList();
|
|
var wings = props.Where(p => p.Type == ProductTypeEnum.翅膀 && p.IsEnable && p.IsSale).ToList();
|
|
var warGods = props.Where(p => p.Type == ProductTypeEnum.战神 && p.IsEnable && p.IsSale).ToList();
|
|
|
|
var nonDefaultCannons = cannons.Where(c => c.Number != DefaultCannonNumber).ToList();
|
|
bot.CannonId = System.Random.Shared.Next(100) < 30 && nonDefaultCannons.Count > 0
|
|
? nonDefaultCannons[System.Random.Shared.Next(nonDefaultCannons.Count)].Number
|
|
: DefaultCannonNumber;
|
|
|
|
bot.WingsId = wings.Count > 0 && System.Random.Shared.Next(100) < 15
|
|
? wings[System.Random.Shared.Next(wings.Count)].Number
|
|
: string.Empty;
|
|
|
|
bot.WarGodId = warGods.Count > 0 && System.Random.Shared.Next(100) < 5
|
|
? warGods[System.Random.Shared.Next(warGods.Count)].Number
|
|
: string.Empty;
|
|
}
|
|
|
|
public static List<RedisGamePlayer> CreateFixedSeatBots(RedisGameRoom room, RoomConfig roomConfig, GameConfig gameConfig, IReadOnlyList<BotProfileEntity> botProfiles, IReadOnlyList<int> fixedSeats = null)
|
|
{
|
|
var result = new List<RedisGamePlayer>();
|
|
if (room == null)
|
|
return result;
|
|
|
|
fixedSeats ??= FixedBotSeats;
|
|
if (fixedSeats.Count == 0)
|
|
return result;
|
|
|
|
room.Players ??= new List<RedisGamePlayer>();
|
|
foreach (var seat in fixedSeats.Distinct())
|
|
{
|
|
if (seat < 0 || seat >= room.MaxPlayerCount)
|
|
continue;
|
|
if (room.Players.Any(p => p.Position == seat))
|
|
continue;
|
|
|
|
var bot = CreateBot(seat, roomConfig, gameConfig, botProfiles);
|
|
if (bot != null)
|
|
result.Add(bot);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|