public override async Task InputAsync(MainRepository repo, uint characterId, IEnumerable <GameDateTime> gameDates, params CharacterCommandParameter[] options) { var itemType = (CharacterItemType)options.FirstOrDefault(p => p.Type == 1).Or(ErrorCode.LackOfCommandParameter).NumberValue; var resourceSize = options.FirstOrDefault(p => p.Type == 3)?.NumberValue; var chara = await repo.Character.GetByIdAsync(characterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var items = await repo.Character.GetItemsAsync(chara.Id); if (!items.Any(i => i.Type == itemType && (i.Status == CharacterItemStatus.CharacterHold || i.Status == CharacterItemStatus.CharacterPending))) { ErrorCode.InvalidCommandParameter.Throw(); } var info = CharacterItemInfoes.Get(itemType).GetOrError(ErrorCode.InvalidCommandParameter); if (!info.CanSell) { ErrorCode.InvalidCommandParameter.Throw(); } if (info.IsResource) { if (resourceSize == null) { ErrorCode.LackOfCommandParameter.Throw(); } if (resourceSize > info.DefaultResource) { ErrorCode.InvalidCommandParameter.Throw(); } } await repo.CharacterCommand.SetAsync(characterId, this.Type, gameDates, options); }
public static async Task <bool> ResultAsync(MainRepository repo, SystemData system, DelayEffect delay, Func <uint, string, Task> logAsync) { var chara = await repo.Character.GetByIdAsync(delay.CharacterId); var type = (CharacterItemType)delay.TypeData; if (!chara.HasData) { return(false); } if (chara.Data.HasRemoved) { return(true); } var generateInfo = GenerateItemInfo.GetInfo(chara.Data, type); if (generateInfo == null) { return(false); } if (delay.IntAppearGameDateTime + generateInfo.Length <= system.IntGameDateTime) { var info = CharacterItemInfoes.Get(type); if (info.HasData) { var item = new CharacterItem { Type = type, Status = CharacterItemStatus.CharacterPending, CharacterId = chara.Data.Id, IntLastStatusChangedGameDate = system.IntGameDateTime, }; if (info.Data.IsResource) { item.Resource = (ushort)(info.Data.DefaultResource + RandomService.Next((int)(generateInfo.ResourceAttribute(chara.Data) * 1.4f))); } await ItemService.GenerateItemAndSaveAsync(repo, item); await ItemService.SetCharacterPendingAsync(repo, item, chara.Data); if (info.Data.IsResource) { await logAsync(chara.Data.Id, $"アイテム {info.Data.Name} を生産しました。資源量: <num>{item.Resource}</num>"); } else { await logAsync(chara.Data.Id, $"アイテム {info.Data.Name} を生産しました"); } return(true); } } return(false); }
public override async Task InputAsync(MainRepository repo, uint characterId, IEnumerable <GameDateTime> gameDates, params CharacterCommandParameter[] options) { var itemType = (CharacterItemType)options.FirstOrDefault(p => p.Type == 1).Or(ErrorCode.LackOfCommandParameter).NumberValue; var resourceSize = options.FirstOrDefault(p => p.Type == 4)?.NumberValue; var chara = await repo.Character.GetByIdAsync(characterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var town = await repo.Town.GetByIdAsync(chara.TownId).GetOrErrorAsync(ErrorCode.InternalDataNotFoundError, new { command = "item", townId = chara.TownId, }); var items = await repo.Town.GetItemsAsync(town.Id); if (!items.Any(i => i.Status == CharacterItemStatus.TownOnSale && i.Type == itemType)) { ErrorCode.InvalidCommandParameter.Throw(); } var info = CharacterItemInfoes.Get(itemType); if (!info.HasData) { ErrorCode.InvalidCommandParameter.Throw(); } if (info.Data.IsResource) { if (resourceSize == null) { ErrorCode.LackOfCommandParameter.Throw(); } if (resourceSize > info.Data.DefaultResource) { ErrorCode.InvalidCommandParameter.Throw(); } } var optionsWithoutResult = options.Where(o => o.Type == 1 || o.Type == 4); options = optionsWithoutResult.Append(new CharacterCommandParameter { Type = 2, NumberValue = (int)chara.TownId, }).ToArray(); await repo.CharacterCommand.SetAsync(characterId, this.Type, gameDates, options); }
public override async Task InputAsync(MainRepository repo, uint characterId, IEnumerable <GameDateTime> gameDates, params CharacterCommandParameter[] options) { var itemType = (CharacterItemType)options.FirstOrDefault(p => p.Type == 1).Or(ErrorCode.LackOfCommandParameter).NumberValue; var targetId = (uint)options.FirstOrDefault(p => p.Type == 2).Or(ErrorCode.LackOfCommandParameter).NumberValue; var resourceSize = options.FirstOrDefault(p => p.Type == 4)?.NumberValue ?? 0; var chara = await repo.Character.GetByIdAsync(characterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); var target = await repo.Character.GetByIdAsync(targetId).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); if (target.HasRemoved) { ErrorCode.CharacterNotFoundError.Throw(); } if (target.Id == chara.Id) { ErrorCode.InvalidCommandParameter.Throw(); } var items = await repo.Character.GetItemsAsync(chara.Id); if (!items.Any(i => i.Type == itemType && (i.Status == CharacterItemStatus.CharacterHold || i.Status == CharacterItemStatus.CharacterPending))) { ErrorCode.InvalidCommandParameter.Throw(); } var info = CharacterItemInfoes.Get(itemType).GetOrError(ErrorCode.InvalidCommandParameter); if (!info.CanHandOver) { ErrorCode.InvalidCommandParameter.Throw(); } if (info.IsResource && (info.DefaultResource < resourceSize || resourceSize == 0)) { ErrorCode.NumberRangeError.Throw(new ErrorCode.RangeErrorParameter("resourceSize", resourceSize, 1, info.DefaultResource)); } await repo.CharacterCommand.SetAsync(characterId, this.Type, gameDates, options); }
public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var isRegularly = options.Any(p => p.Type == CharacterCommandParameterTypes.Regularly); var itemTypeOptional = options.FirstOrDefault(p => p.Type == 1); if (itemTypeOptional == null || itemTypeOptional.NumberValue == null) { await game.CharacterLogAsync("アイテム生産のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } var itemType = (CharacterItemType)itemTypeOptional.NumberValue; var delays = await repo.DelayEffect.GetAllAsync(); if (delays.Any(d => d.CharacterId == character.Id && d.Type == DelayEffectType.GenerateItem)) { if (!isRegularly) { await game.CharacterLogAsync($"アイテム生産しようとしましたが、複数のアイテムを同時に生産することはできません"); } return; } var infoOptional = CharacterItemInfoes.Get(itemType); if (!infoOptional.HasData) { await game.CharacterLogAsync($"ID: {(short)itemType} のアイテムは存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var info = infoOptional.Data; var generateInfo = GenerateItemInfo.GetInfo(character, itemType); if (generateInfo == null) { await game.CharacterLogAsync("アイテム生産の情報が不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } var money = info.IsResource ? info.MoneyPerResource * info.DefaultResource / 16 : info.Money / 16; if (character.Money < money) { await game.CharacterLogAsync("アイテム生産しようとしましたが、金が足りません。<num>" + money + "</num> 必要です"); return; } var townOptional = await repo.Town.GetByIdAsync(character.TownId); if (townOptional.HasData) { var country = await repo.Country.GetByIdAsync(character.CountryId); var town = townOptional.Data; if (town.CountryId != character.CountryId && country.HasData && !country.Data.HasOverthrown) { await game.CharacterLogAsync($"<town>{town.Name}</town> でアイテム生産しようとしましたが、自国の都市ではありません"); return; } character.Money -= money; var delay = new DelayEffect { CharacterId = character.Id, CountryId = character.CountryId, AppearGameDateTime = game.GameDateTime, Type = DelayEffectType.GenerateItem, TypeData = (int)itemType, }; await repo.DelayEffect.AddAsync(delay); await repo.SaveChangesAsync(); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(delay), character.Id); var finish = GameDateTime.FromInt(game.GameDateTime.ToInt() + generateInfo.Length); generateInfo.AddExAttribute(character); if (!isRegularly) { character.Contribution += generateInfo.Contribution; character.SkillPoint++; } await game.CharacterLogAsync($"<town>{town.Name}</town> で <num>{money}</num> を投し、{info.Name} の生産を開始しました。結果は <num>{finish.Year}</num> 年 <num>{finish.Month}</num> 月に来ます"); } else { await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>"); } }
public static async Task SetCharacterAsync(MainRepository repo, CharacterItem item, Character chara) { if (item.Status == CharacterItemStatus.CharacterHold) { if (item.CharacterId == chara.Id) { return; } var oldChara = await repo.Character.GetByIdAsync(item.CharacterId); if (oldChara.HasData) { await ReleaseCharacterAsync(repo, item, oldChara.Data); } } var strong = (short)item.GetSumOfValues(CharacterItemEffectType.Strong); var intellect = (short)item.GetSumOfValues(CharacterItemEffectType.Intellect); var leadership = (short)item.GetSumOfValues(CharacterItemEffectType.Leadership); var popularity = (short)item.GetSumOfValues(CharacterItemEffectType.Popularity); chara.Strong += strong; chara.Intellect += intellect; chara.Leadership += leadership; chara.Popularity += popularity; item.Status = CharacterItemStatus.CharacterHold; item.CharacterId = chara.Id; item.TownId = 0; var infoOptional = CharacterItemInfoes.Get(item.Type); if (infoOptional.HasData) { var info = infoOptional.Data; if (info.IsResource) { var characterItems = await repo.Character.GetItemsAsync(chara.Id); var resource = characterItems.FirstOrDefault(i => i.Id != item.Id && i.Status == CharacterItemStatus.CharacterHold && i.Type == item.Type); if (resource != null) { // 2つの資源アイテムを統合 resource.Resource += item.Resource; item.Status = CharacterItemStatus.CharacterSpent; item.CharacterId = 0; item.Resource = 0; await StatusStreaming.Default.SendAllAsync(ApiData.From(resource)); } else { // 今の資源アイテムがそのまま所持物となる item.IsAvailable = true; } } } await CharacterService.StreamCharacterAsync(repo, chara); await StatusStreaming.Default.SendAllAsync(ApiData.From(item)); }
public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var itemTypeOptional = options.FirstOrDefault(p => p.Type == 1).ToOptional(); if (!itemTypeOptional.HasData) { await game.CharacterLogAsync("アイテム使用のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } var itemType = (CharacterItemType)itemTypeOptional.Data.NumberValue; var infoOptional = CharacterItemInfoes.Get(itemType); if (!infoOptional.HasData) { await game.CharacterLogAsync($"ID: {(short)itemType} のアイテムは存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var info = infoOptional.Data; var charaItems = await repo.Character.GetItemsAsync(character.Id); var target = charaItems.FirstOrDefault(i => i.Type == itemType && i.Status == CharacterItemStatus.CharacterHold); if (target == null) { target = charaItems.FirstOrDefault(i => i.Type == itemType && i.Status == CharacterItemStatus.CharacterPending); var skills = await repo.Character.GetSkillsAsync(character.Id); if (target == null) { await game.CharacterLogAsync($"アイテム {info.Name} を使用しようとしましたが、それは現在所持していません"); return; } } if (info.UsingEffects != null && info.UsingEffects.Any(ue => ue.Type == CharacterItemEffectType.AddSubBuildingExtraSize)) { var townOptional = await repo.Town.GetByIdAsync(character.TownId); if (townOptional.HasData) { var town = townOptional.Data; if (town.CountryId != character.CountryId) { await game.CharacterLogAsync($"アイテム {info.Name} は、自国の都市でしか使用できません"); return; } if (town.TownSubBuildingExtraSpace + info.UsingEffects.Where(ue => ue.Type == CharacterItemEffectType.AddSubBuildingExtraSize).Sum(ue => ue.Value) > 4) { await game.CharacterLogAsync($"アイテム {info.Name} を使おうとしましたが、<town>{town.Name}</town> の追加の敷地を <num>4</num> より多くすることはできません"); return; } } } var log = await ItemService.SpendCharacterAsync(repo, target, character); await game.CharacterLogAsync($"アイテム {info.Name} を使用しました。効果: {log}"); }
public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var townOptional = await repo.Town.GetByIdAsync(character.TownId); var itemTypeOptional = options.FirstOrDefault(p => p.Type == 1).ToOptional(); var resourceSizeOptional = options.FirstOrDefault(p => p.Type == 3).ToOptional(); if (!townOptional.HasData) { await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var town = townOptional.Data; if (!itemTypeOptional.HasData) { await game.CharacterLogAsync("アイテム売却のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } var itemType = (CharacterItemType)itemTypeOptional.Data.NumberValue; var infoOptional = CharacterItemInfoes.Get(itemType); if (!infoOptional.HasData) { await game.CharacterLogAsync($"ID: {(short)itemType} のアイテムは存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var info = infoOptional.Data; if (info.IsResource) { if (resourceSizeOptional.Data?.NumberValue == null) { await game.CharacterLogAsync("アイテム(資源)売却のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } } CharacterItem target; var resourceSize = resourceSizeOptional.Data?.NumberValue ?? 0; if (!info.IsResource) { var charaItems = await repo.Character.GetItemsAsync(character.Id); target = charaItems.FirstOrDefault(i => i.Type == itemType && (i.Status == CharacterItemStatus.CharacterHold || i.Status == CharacterItemStatus.CharacterPending)); } else { var charaItems = await repo.Character.GetItemsAsync(character.Id); var targets = charaItems.Where(i => i.Type == itemType && (i.Status == CharacterItemStatus.CharacterHold || i.Status == CharacterItemStatus.CharacterPending)); if (!targets.Any()) { target = null; } else { var allSize = targets.Sum(i => i.Resource); if (allSize < resourceSize) { resourceSize = allSize; } if (targets.First().Resource > resourceSize) { target = await ItemService.DivideResourceAndSaveAsync(repo, targets.First(), resourceSize); } else if (targets.First().Resource == resourceSize) { target = targets.First(); } else if (targets.Count() >= 2) { target = targets.First(); var currentSize = target.Resource; foreach (var t in targets.Skip(1)) { currentSize += t.Resource; var size = currentSize <= resourceSize ? 0 : currentSize - resourceSize; target.Resource += t.Resource - size; t.Resource = size; if (t.Resource == 0) { t.Status = CharacterItemStatus.CharacterSpent; t.CharacterId = 0; } await StatusStreaming.Default.SendAllAsync(ApiData.From(t)); if (currentSize >= resourceSize) { break; } } await StatusStreaming.Default.SendAllAsync(ApiData.From(target)); } else { target = targets.First(); resourceSize = target.Resource; } } } if (target == null) { await game.CharacterLogAsync($"アイテム {info.Name} を売却しようとしましたが、それは現在所持していません"); return; } var itemMoney = info.GetMoney(target); character.Money += itemMoney / 2; await ItemService.ReleaseCharacterAsync(repo, target, character); await game.CharacterLogAsync($"<town>{town.Name}</town> にアイテム {info.Name} を売却しました。金 <num>+{itemMoney / 2}</num>"); }
public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var itemTypeOptional = options.FirstOrDefault(p => p.Type == 1).ToOptional(); var townIdOptional = options.FirstOrDefault(p => p.Type == 2).ToOptional(); var resourceSizeOptional = options.FirstOrDefault(p => p.Type == 4).ToOptional(); if (!itemTypeOptional.HasData || !townIdOptional.HasData) { await game.CharacterLogAsync("アイテム購入のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } var itemType = (CharacterItemType)itemTypeOptional.Data.NumberValue; var townOptional = await repo.Town.GetByIdAsync((uint)townIdOptional.Data.NumberValue); if (!townOptional.HasData) { await game.CharacterLogAsync("ID:" + character.TownId + " の都市は存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var town = townOptional.Data; var infoOptional = CharacterItemInfoes.Get(itemType); if (!infoOptional.HasData) { await game.CharacterLogAsync($"ID: {(short)itemType} のアイテムは存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var info = infoOptional.Data; if (info.IsResource) { if (resourceSizeOptional.Data?.NumberValue == null) { await game.CharacterLogAsync("アイテム(資源)購入のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } } var items = await repo.Character.GetItemsAsync(character.Id); var itemsMax = CharacterService.GetItemMax(await repo.Character.GetSkillsAsync(character.Id)); if ((!info.IsResource || info.IsResourceItem) && CharacterService.CountLimitedItems(items) >= itemsMax) { await game.CharacterLogAsync($"アイテム購入しようとしましたが、アイテム所持数が上限 <num>{itemsMax}</num> に達しています"); return; } List <Func <Task> > onSucceeds = new List <Func <Task> >(); CharacterItem target; var resourceSize = resourceSizeOptional.Data?.NumberValue ?? 0; if (!info.IsResource) { var allItems = await repo.CharacterItem.GetAllAsync(); target = allItems.FirstOrDefault(i => i.Status == CharacterItemStatus.TownOnSale && i.TownId == townIdOptional.Data.NumberValue && i.Type == itemType); } else { var allItems = await repo.CharacterItem.GetAllAsync(); var targets = allItems.Where(i => i.Status == CharacterItemStatus.TownOnSale && i.TownId == townIdOptional.Data.NumberValue && i.Type == itemType); if (!targets.Any()) { target = null; } else { var allSize = targets.Sum(i => i.Resource); if (allSize < resourceSize) { resourceSize = allSize; } if (targets.First().Resource > resourceSize) { target = await ItemService.DivideResourceAndSaveAsync(repo, targets.First(), resourceSize); } else if (targets.First().Resource == resourceSize) { target = targets.First(); } else if (targets.Count() >= 2) { target = targets.First(); onSucceeds.Add(async() => { var currentSize = target.Resource; foreach (var t in targets.Skip(1)) { currentSize += t.Resource; var size = currentSize <= resourceSize ? 0 : currentSize - resourceSize; target.Resource += t.Resource - size; t.Resource = size; if (t.Resource == 0) { t.Status = CharacterItemStatus.CharacterSpent; t.TownId = 0; } await StatusStreaming.Default.SendAllAsync(ApiData.From(t)); if (currentSize >= resourceSize) { break; } } await StatusStreaming.Default.SendAllAsync(ApiData.From(target)); }); } else { target = targets.First(); resourceSize = target.Resource; } } } if (target == null) { await game.CharacterLogAsync($"アイテムを購入しようとしましたが、<town>{town.Name}</town> の {info.Name} はすでに売り切れています"); return; } var skills = await repo.Character.GetSkillsAsync(character.Id); var discountRate = (1 - skills.GetSumOfValues(CharacterSkillEffectType.ItemDiscountPercentage) / 100.0f); var needMoney = !info.IsResource ? (int)(info.Money * discountRate) : (int)(info.MoneyPerResource * discountRate * resourceSize); if (needMoney > character.Money) { await game.CharacterLogAsync("アイテム購入の金が足りません"); return; } foreach (var run in onSucceeds) { await run(); } character.Money -= needMoney; await ItemService.SetCharacterAsync(repo, target, character); await game.CharacterLogAsync($"<num>{needMoney}</num> を投じて、<town>{town.Name}</town> のアイテム {info.Name} を購入しました"); }
public static async Task <bool> ResultAsync(MainRepository repo, SystemData system, DelayEffect delay, Func <uint, string, Task> logAsync) { if (delay.IntAppearGameDateTime + 36 <= system.IntGameDateTime) { var chara = await repo.Character.GetByIdAsync(delay.CharacterId); var town = await repo.Town.GetByIdAsync(delay.TownId); if (chara.HasData && town.HasData) { var results = new List <string>(); var skills = await repo.Character.GetSkillsAsync(chara.Data.Id); var currentItems = await repo.Character.GetItemsAsync(chara.Data.Id); var items = (await repo.Town.GetItemsAsync(chara.Data.TownId)).Where(i => i.Status == CharacterItemStatus.TownHidden); if (RandomService.Next(0, 10) < items.Count()) { var item = RandomService.Next(items); var info = CharacterItemInfoes.Get(item.Type); if (info.HasData && (info.Data.DiscoverFroms == null || info.Data.DiscoverFroms.Contains(chara.Data.From))) { await ItemService.SetCharacterPendingAsync(repo, item, chara.Data); results.Add($"アイテム {info.Data.Name}"); } } var money = RandomService.Next(chara.Data.Intellect * 32, Math.Max(chara.Data.Intellect * 48, system.GameDateTime.Year * 650 + 10000)); chara.Data.Money += money; results.Add($"金 <num>{money}</num>"); var country = await repo.Country.GetByIdAsync(chara.Data.CountryId); if (country.HasData) { var name = string.Empty; var add = RandomService.Next(20, 60); var target = RandomService.Next(0, 5); if (target == 0) { name = "農業"; town.Data.Agriculture = Math.Min(town.Data.AgricultureMax, town.Data.Agriculture + add); } else if (target == 1) { name = "商業"; town.Data.Commercial = Math.Min(town.Data.CommercialMax, town.Data.Commercial + add); } else if (target == 2) { name = "技術"; town.Data.Technology = Math.Min(town.Data.TechnologyMax, town.Data.Technology + add); } else if (target == 3) { name = "城壁"; town.Data.Wall = Math.Min(town.Data.WallMax, town.Data.Wall + add); } else if (target == 4) { name = "都市施設"; town.Data.TownBuildingValue = Math.Min(Config.TownBuildingMax, town.Data.TownBuildingValue + add); } await logAsync(chara.Data.Id, $"<town>{town.Data.Name}</town> に投資し、{name} の開発に <num>+{add}</num> 貢献し、{string.Join("と", results)}を得ました"); } else { await logAsync(chara.Data.Id, $"<town>{town.Data.Name}</town> に投資し、{string.Join("と", results)}を得ました"); } return(true); } } return(false); }
public override async Task ExecuteAsync(MainRepository repo, Character character, IEnumerable <CharacterCommandParameter> options, CommandSystemData game) { var itemTypeOptional = options.FirstOrDefault(p => p.Type == 1).ToOptional(); var targetIdOptional = options.FirstOrDefault(p => p.Type == 2).ToOptional(); var resourceSizeOptional = options.FirstOrDefault(p => p.Type == 4).ToOptional(); if (!itemTypeOptional.HasData || !targetIdOptional.HasData) { await game.CharacterLogAsync("アイテム売却のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } var itemType = (CharacterItemType)itemTypeOptional.Data.NumberValue; var targetOptional = await repo.Character.GetByIdAsync((uint)targetIdOptional.Data.NumberValue); if (!targetOptional.HasData) { await game.CharacterLogAsync("ID:" + character.TownId + " の武将は存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } if (targetOptional.Data.HasRemoved) { await game.CharacterLogAsync($"<character>{targetOptional.Data.Name}</character> にアイテムを譲渡しようとしましたが、その武将はすでに削除されています"); return; } if (character.AiType == CharacterAiType.Human && targetOptional.Data.AiType != CharacterAiType.Human && targetOptional.Data.AiType != CharacterAiType.Administrator) { await game.CharacterLogAsync($"<character>{targetOptional.Data.Name}</character> にアイテムを譲渡しようとしましたが、その武将は人間ではありません"); return; } var target = targetOptional.Data; var infoOptional = CharacterItemInfoes.Get(itemType); if (!infoOptional.HasData) { await game.CharacterLogAsync($"ID: {(short)itemType} のアイテムは存在しません。<emerge>管理者にお問い合わせください</emerge>"); return; } var info = infoOptional.Data; if (info.IsResource) { if (resourceSizeOptional.Data?.NumberValue == null) { await game.CharacterLogAsync("アイテム(資源)譲渡のパラメータが不正です。<emerge>管理者にお問い合わせください</emerge>"); return; } } var charaItems = await repo.Character.GetItemsAsync(character.Id); var item = charaItems.FirstOrDefault(i => i.Type == itemType && (i.Status == CharacterItemStatus.CharacterHold)); if (item == null) { item = charaItems.FirstOrDefault(i => i.Type == itemType && (i.Status == CharacterItemStatus.CharacterPending)); } if (item == null) { await game.CharacterLogAsync($"アイテム {info.Name} を譲渡しようとしましたが、それは現在所持していません"); return; } var resourceSize = resourceSizeOptional.Data?.NumberValue ?? 0; if (info.IsResource) { // 譲渡や購入などで、資源がすべて1つのアイテムデータとしてまとめられているのが前提 // 同じ資源アイテムを2つ以上持ってた場合は想定しない if (item.Resource < resourceSize) { resourceSize = item.Resource; } } character.Contribution += 15; character.SkillPoint++; if (!info.IsResource) { await ItemService.ReleaseCharacterAsync(repo, item, character); await ItemService.SetCharacterPendingAsync(repo, item, target); await game.CharacterLogAsync($"<character>{target.Name}</character> にアイテム {info.Name} を譲渡しました"); await game.CharacterLogByIdAsync(target.Id, $"<character>{character.Name}</character> からアイテム {info.Name} を受け取りました"); } else { if (item.Resource > resourceSize) { // 資源の分解 var newItem = await ItemService.DivideResourceAndSaveAsync(repo, item, resourceSize); await ItemService.ReleaseCharacterAsync(repo, newItem, character); await ItemService.SetCharacterPendingAsync(repo, newItem, target); } else { await ItemService.ReleaseCharacterAsync(repo, item, character); await ItemService.SetCharacterPendingAsync(repo, item, target); } await game.CharacterLogAsync($"<character>{target.Name}</character> に資源 {info.Name} を <num>{resourceSize}</num> 譲渡しました"); await game.CharacterLogByIdAsync(target.Id, $"<character>{character.Name}</character> から資源 {info.Name} を <num>{resourceSize}</num> 受け取りました"); } }