Exemple #1
0
        // 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);
     }
 }
Exemple #4
0
 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();
                            }
                        });
                    }
                }
            }
        }