punish v6.8.18.0
This commit is contained in:
commit
cfb4dea47e
316 changed files with 554088 additions and 0 deletions
217
Questionable/Questionable.Controller/ContextMenuController.cs
Normal file
217
Questionable/Questionable.Controller/ContextMenuController.cs
Normal file
|
@ -0,0 +1,217 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Game.Gui.ContextMenu;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||
using LLib.GameData;
|
||||
using LLib.GameUI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Data;
|
||||
using Questionable.Functions;
|
||||
using Questionable.GameStructs;
|
||||
using Questionable.Model;
|
||||
using Questionable.Model.Gathering;
|
||||
using Questionable.Model.Questing;
|
||||
|
||||
namespace Questionable.Controller;
|
||||
|
||||
internal sealed class ContextMenuController : IDisposable
|
||||
{
|
||||
private readonly IContextMenu _contextMenu;
|
||||
|
||||
private readonly QuestController _questController;
|
||||
|
||||
private readonly GatheringPointRegistry _gatheringPointRegistry;
|
||||
|
||||
private readonly GatheringData _gatheringData;
|
||||
|
||||
private readonly QuestRegistry _questRegistry;
|
||||
|
||||
private readonly QuestData _questData;
|
||||
|
||||
private readonly GameFunctions _gameFunctions;
|
||||
|
||||
private readonly QuestFunctions _questFunctions;
|
||||
|
||||
private readonly IGameGui _gameGui;
|
||||
|
||||
private readonly IChatGui _chatGui;
|
||||
|
||||
private readonly IClientState _clientState;
|
||||
|
||||
private readonly ILogger<ContextMenuController> _logger;
|
||||
|
||||
public ContextMenuController(IContextMenu contextMenu, QuestController questController, GatheringPointRegistry gatheringPointRegistry, GatheringData gatheringData, QuestRegistry questRegistry, QuestData questData, GameFunctions gameFunctions, QuestFunctions questFunctions, IGameGui gameGui, IChatGui chatGui, IClientState clientState, ILogger<ContextMenuController> logger)
|
||||
{
|
||||
_contextMenu = contextMenu;
|
||||
_questController = questController;
|
||||
_gatheringPointRegistry = gatheringPointRegistry;
|
||||
_gatheringData = gatheringData;
|
||||
_questRegistry = questRegistry;
|
||||
_questData = questData;
|
||||
_gameFunctions = gameFunctions;
|
||||
_questFunctions = questFunctions;
|
||||
_gameGui = gameGui;
|
||||
_chatGui = chatGui;
|
||||
_clientState = clientState;
|
||||
_logger = logger;
|
||||
_contextMenu.OnMenuOpened += MenuOpened;
|
||||
}
|
||||
|
||||
private void MenuOpened(IMenuOpenedArgs args)
|
||||
{
|
||||
if (args.AddonName != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint num = GetHoveredSatisfactionSupplyItemId();
|
||||
if (num == 0)
|
||||
{
|
||||
_logger.LogTrace("Ignoring context menu, no item hovered");
|
||||
return;
|
||||
}
|
||||
if (num > 1000000)
|
||||
{
|
||||
num -= 1000000;
|
||||
}
|
||||
if (num >= 500000)
|
||||
{
|
||||
num -= 500000;
|
||||
}
|
||||
if (_gatheringData.TryGetCustomDeliveryNpc(num, out var npcId))
|
||||
{
|
||||
AddContextMenuEntry(args, num, npcId, EClassJob.Miner, "Mine");
|
||||
AddContextMenuEntry(args, num, npcId, EClassJob.Botanist, "Harvest");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("No custom delivery NPC found for item {ItemId}.", num);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe uint GetHoveredSatisfactionSupplyItemId()
|
||||
{
|
||||
AgentSatisfactionSupply* ptr = AgentSatisfactionSupply.Instance();
|
||||
if (ptr == null || !ptr->IsAgentActive())
|
||||
{
|
||||
return 0u;
|
||||
}
|
||||
if (_gameGui.TryGetAddonByName<AddonSatisfactionSupply>("SatisfactionSupply", out var addonPtr) && LAddon.IsAddonReady(&addonPtr->AtkUnitBase))
|
||||
{
|
||||
int hoveredElementIndex = addonPtr->HoveredElementIndex;
|
||||
if (hoveredElementIndex >= 0 && hoveredElementIndex <= 2)
|
||||
{
|
||||
return ptr->Items[addonPtr->HoveredElementIndex].Id;
|
||||
}
|
||||
}
|
||||
return 0u;
|
||||
}
|
||||
|
||||
private unsafe void AddContextMenuEntry(IMenuOpenedArgs args, uint itemId, uint npcId, EClassJob classJob, string verb)
|
||||
{
|
||||
EClassJob rowId = (EClassJob)_clientState.LocalPlayer.ClassJob.RowId;
|
||||
bool flag = classJob != rowId;
|
||||
if (flag)
|
||||
{
|
||||
bool flag2 = rowId - 16 <= EClassJob.Gladiator;
|
||||
flag = flag2;
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!_gatheringPointRegistry.TryGetGatheringPointId(itemId, classJob, out GatheringPointId _))
|
||||
{
|
||||
_logger.LogInformation("No gathering point found for {ClassJob}.", classJob);
|
||||
return;
|
||||
}
|
||||
ushort collectability = _gatheringData.GetRecommendedCollectability(itemId);
|
||||
int quantityToGather = ((collectability > 0) ? 6 : int.MaxValue);
|
||||
if (collectability != 0)
|
||||
{
|
||||
AgentSatisfactionSupply* ptr = AgentSatisfactionSupply.Instance();
|
||||
if (ptr->IsAgentActive())
|
||||
{
|
||||
int maxTurnIns = ((ptr->NpcInfo.SatisfactionRank == 1) ? 3 : 6);
|
||||
quantityToGather = Math.Min(ptr->NpcData.RemainingAllowances, ((AgentSatisfactionSupply2*)ptr)->CalculateTurnInsToNextRank(maxTurnIns));
|
||||
}
|
||||
string text = string.Empty;
|
||||
if (!_questFunctions.IsClassJobUnlocked(classJob))
|
||||
{
|
||||
text = $"{classJob} not unlocked";
|
||||
}
|
||||
else if (quantityToGather == 0)
|
||||
{
|
||||
text = "No allowances";
|
||||
}
|
||||
else if (quantityToGather > _gameFunctions.GetFreeInventorySlots())
|
||||
{
|
||||
text = "Inventory full";
|
||||
}
|
||||
else if (_gameFunctions.IsOccupied())
|
||||
{
|
||||
text = "Can't be used while interacting";
|
||||
}
|
||||
string text2 = verb + " with Questionable";
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
text2 = text2 + " (" + text + ")";
|
||||
}
|
||||
args.AddMenuItem(new MenuItem
|
||||
{
|
||||
Prefix = SeIconChar.Hyadelyn,
|
||||
PrefixColor = 52,
|
||||
Name = text2,
|
||||
OnClicked = delegate
|
||||
{
|
||||
StartGathering(npcId, itemId, quantityToGather, collectability, classJob);
|
||||
},
|
||||
IsEnabled = string.IsNullOrEmpty(text)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void StartGathering(uint npcId, uint itemId, int quantity, ushort collectability, EClassJob classJob)
|
||||
{
|
||||
SatisfactionSupplyInfo satisfactionSupplyInfo = (SatisfactionSupplyInfo)_questData.GetAllByIssuerDataId(npcId).Single((IQuestInfo x) => x is SatisfactionSupplyInfo);
|
||||
if (_questRegistry.TryGetQuest(satisfactionSupplyInfo.QuestId, out Quest quest))
|
||||
{
|
||||
QuestSequence questSequence = quest.FindSequence(0);
|
||||
QuestStep questStep = questSequence.Steps.Single((QuestStep x) => x.InteractionType == EInteractionType.SwitchClass);
|
||||
questStep.TargetClass = classJob switch
|
||||
{
|
||||
EClassJob.Miner => EExtendedClassJob.Miner,
|
||||
EClassJob.Botanist => EExtendedClassJob.Botanist,
|
||||
_ => throw new ArgumentOutOfRangeException("classJob", classJob, null),
|
||||
};
|
||||
QuestStep questStep2 = questSequence.Steps.Single((QuestStep x) => x.InteractionType == EInteractionType.Gather);
|
||||
int num = 1;
|
||||
List<GatheredItem> list = new List<GatheredItem>(num);
|
||||
CollectionsMarshal.SetCount(list, num);
|
||||
Span<GatheredItem> span = CollectionsMarshal.AsSpan(list);
|
||||
int index = 0;
|
||||
span[index] = new GatheredItem
|
||||
{
|
||||
ItemId = itemId,
|
||||
ItemCount = quantity,
|
||||
Collectability = collectability
|
||||
};
|
||||
questStep2.ItemsToGather = list;
|
||||
_questController.SetGatheringQuest(quest);
|
||||
_questController.StartGatheringQuest("SatisfactionSupply prepare gathering");
|
||||
}
|
||||
else
|
||||
{
|
||||
_chatGui.PrintError($"No associated quest ({satisfactionSupplyInfo.QuestId}).", "Questionable");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_contextMenu.OnMenuOpened -= MenuOpened;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue