// TODO: QuestPreparation.Quest(bool repeat) 와 로직이 흡사하기 때문에 정리할 여지가 있습니다. private void HackAndSlash(int stageId) { var sheets = Game.Game.instance.TableSheets; var stageRow = sheets.StageSheet.OrderedList.FirstOrDefault(row => row.Id == stageId); if (stageRow is null) { return; } var requiredCost = stageRow.CostAP; if (States.Instance.CurrentAvatarState.actionPoint < requiredCost) { // NOTE: AP가 부족합니다. return; } if (!sheets.WorldSheet.TryGetByStageId(stageId, out var worldRow)) { return; } var worldId = worldRow.Id; Find <BottomMenu>().Close(true); Find <LoadingScreen>().Show(); var stage = Game.Game.instance.Stage; stage.isExitReserved = false; stage.repeatStage = false; var player = stage.GetPlayer(); player.StartRun(); ActionCamera.instance.ChaseX(player.transform); ActionRenderHandler.Instance.Pending = true; Game.Game.instance.ActionManager .HackAndSlash(player, worldId, stageId) .Subscribe(_ => { LocalLayerModifier.ModifyAvatarActionPoint( States.Instance.CurrentAvatarState.address, requiredCost); }, e => ActionRenderHandler.BackToMain(false, e)) .AddTo(this); LocalLayerModifier.ModifyAvatarActionPoint(States.Instance.CurrentAvatarState.address, -requiredCost); var props = new Value { ["StageID"] = stageId, }; Mixpanel.Track("Unity/Click Guided Quest Enter Dungeon", props); }
private void ResponseCombinationConsumable(ActionBase.ActionEvaluation <CombinationConsumable> eval) { if (eval.Exception is null) { var agentAddress = eval.Signer; var avatarAddress = eval.Action.AvatarAddress; var slot = eval.OutputStates.GetCombinationSlotState(avatarAddress, eval.Action.slotIndex); var result = (CombinationConsumable.ResultModel)slot.Result; var itemUsable = result.itemUsable; var avatarState = eval.OutputStates.GetAvatarState(avatarAddress); LocalLayerModifier.ModifyAgentGold(agentAddress, result.gold); LocalLayerModifier.ModifyAvatarActionPoint(avatarAddress, result.actionPoint); foreach (var pair in result.materials) { // NOTE: 최종적으로 UpdateCurrentAvatarState()를 호출한다면, 그곳에서 상태를 새로 설정할 것이다. LocalLayerModifier.AddItem(avatarAddress, pair.Key.ItemId, pair.Value, false); } LocalLayerModifier.RemoveItem(avatarAddress, itemUsable.ItemId); LocalLayerModifier.AddNewAttachmentMail(avatarAddress, result.id); LocalLayerModifier.ResetCombinationSlot(slot); var format = L10nManager.Localize("NOTIFICATION_COMBINATION_COMPLETE"); UI.Notification.Reserve( MailType.Workshop, string.Format(format, result.itemUsable.GetLocalizedName()), slot.UnlockBlockIndex, result.itemUsable.ItemId ); AnalyticsManager.Instance.OnEvent(AnalyticsManager.EventName.ActionCombinationSuccess); //[TentuPlay] Consumable 합성에 사용한 골드 기록 //Local에서 변경하는 States.Instance 보다는 블락에서 꺼내온 eval.OutputStates를 사용 if (eval.OutputStates.TryGetGoldBalance(agentAddress, GoldCurrency, out var balance)) { var total = balance - new FungibleAssetValue(balance.Currency, result.gold, 0); new TPStashEvent().CharacterCurrencyUse( player_uuid: agentAddress.ToHex(), character_uuid: States.Instance.CurrentAvatarState.address.ToHex().Substring(0, 4), currency_slug: "gold", currency_quantity: (float)result.gold, currency_total_quantity: float.Parse(total.GetQuantityString()), reference_entity: entity.Items, reference_category_slug: "consumables_combination", reference_slug: result.itemUsable.Id.ToString()); } UpdateAgentState(eval); UpdateCurrentAvatarState(eval); UpdateCombinationSlotState(slot); RenderQuest(avatarAddress, avatarState.questList.completedQuestIds); } }
private void ResponseChargeActionPoint(ActionBase.ActionEvaluation <ChargeActionPoint> eval) { if (eval.Exception is null) { var avatarAddress = eval.Action.avatarAddress; LocalLayerModifier.ModifyAvatarActionPoint(avatarAddress, -States.Instance.GameConfigState.ActionPointMax); var row = Game.Game.instance.TableSheets.MaterialItemSheet.Values.First(r => r.ItemSubType == ItemSubType.ApStone); LocalLayerModifier.AddItem(avatarAddress, row.ItemId, 1); UpdateCurrentAvatarState(eval); } }
private static void ChargeActionPoint(CountableItem item) { if (item.ItemBase.Value is Nekoyume.Model.Item.Material material) { Notification.Push(Nekoyume.Model.Mail.MailType.System, L10nManager.Localize("UI_CHARGE_AP")); Game.Game.instance.ActionManager.ChargeActionPoint(); LocalLayerModifier.RemoveItem(States.Instance.CurrentAvatarState.address, material.ItemId, 1); LocalLayerModifier.ModifyAvatarActionPoint( States.Instance.CurrentAvatarState.address, States.Instance.GameConfigState.ActionPointMax); } }
private void ResponseCombinationEquipment(ActionBase.ActionEvaluation <CombinationEquipment> eval) { if (eval.Exception is null) { var agentAddress = eval.Signer; var avatarAddress = eval.Action.AvatarAddress; var slot = eval.OutputStates.GetCombinationSlotState(avatarAddress, eval.Action.SlotIndex); var result = (CombinationConsumable.ResultModel)slot.Result; var avatarState = eval.OutputStates.GetAvatarState(avatarAddress); // NOTE: 사용한 자원에 대한 레이어 벗기기. LocalLayerModifier.ModifyAgentGold(agentAddress, result.gold); LocalLayerModifier.ModifyAvatarActionPoint(avatarAddress, result.actionPoint); foreach (var pair in result.materials) { // NOTE: 최종적으로 UpdateCurrentAvatarState()를 호출한다면, 그곳에서 상태를 새로 설정할 것이다. LocalLayerModifier.AddItem(avatarAddress, pair.Key.ItemId, pair.Value, false); } // NOTE: 메일 레이어 씌우기. LocalLayerModifier.RemoveItem(avatarAddress, result.itemUsable.ItemId); LocalLayerModifier.AddNewAttachmentMail(avatarAddress, result.id); LocalLayerModifier.ResetCombinationSlot(slot); // NOTE: 노티 예약 걸기. var format = L10nManager.Localize("NOTIFICATION_COMBINATION_COMPLETE"); UI.Notification.Reserve( MailType.Workshop, string.Format(format, result.itemUsable.GetLocalizedName()), slot.UnlockBlockIndex, result.itemUsable.ItemId); AnalyticsManager.Instance.OnEvent(AnalyticsManager.EventName.ActionCombinationSuccess); //[TentuPlay] Equipment 합성에 사용한 골드 기록 //Local에서 변경하는 States.Instance 보다는 블락에서 꺼내온 eval.OutputStates를 사용 if (eval.OutputStates.TryGetGoldBalance(agentAddress, GoldCurrency, out var balance)) { var total = balance - new FungibleAssetValue(balance.Currency, result.gold, 0); new TPStashEvent().CharacterCurrencyUse( player_uuid: agentAddress.ToHex(), character_uuid: States.Instance.CurrentAvatarState.address.ToHex().Substring(0, 4), currency_slug: "gold", currency_quantity: (float)result.gold, currency_total_quantity: float.Parse(total.GetQuantityString()), reference_entity: entity.Items, reference_category_slug: "equipments_combination", reference_slug: result.itemUsable.Id.ToString()); } var gameInstance = Game.Game.instance; var nextQuest = gameInstance.States.CurrentAvatarState.questList? .OfType <CombinationEquipmentQuest>() .Where(x => !x.Complete) .OrderBy(x => x.StageId) .FirstOrDefault(x => gameInstance.TableSheets.EquipmentItemRecipeSheet.TryGetValue(x.RecipeId, out _)); UpdateAgentState(eval); UpdateCurrentAvatarState(eval); RenderQuest(avatarAddress, avatarState.questList.completedQuestIds); UpdateCombinationSlotState(slot); if (!(nextQuest is null)) { var isRecipeMatch = nextQuest.RecipeId == eval.Action.RecipeId; if (isRecipeMatch) { var celebratesPopup = Widget.Find <CelebratesPopup>(); celebratesPopup.Show(nextQuest); celebratesPopup.OnDisableObservable .First() .Subscribe(_ => { var menu = Widget.Find <Menu>(); if (menu.isActiveAndEnabled) { menu.UpdateGuideQuest(avatarState); } var combination = Widget.Find <Combination>(); if (combination.isActiveAndEnabled) { combination.UpdateRecipe(); } }); } } } }