2023-10-01 20:50:21 +00:00
using System ;
using System.Linq ;
2023-10-19 18:46:01 +00:00
using Dalamud.Game.Addon.Lifecycle ;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes ;
2023-10-30 00:44:42 +00:00
using FFXIVClientStructs.FFXIV.Client.Game ;
2023-10-19 18:46:01 +00:00
using FFXIVClientStructs.FFXIV.Client.UI ;
2023-10-01 20:50:21 +00:00
using FFXIVClientStructs.FFXIV.Component.GUI ;
using Workshoppa.GameData ;
using ValueType = FFXIVClientStructs . FFXIV . Component . GUI . ValueType ;
namespace Workshoppa ;
partial class WorkshopPlugin
{
private uint? _contributingItemId ;
2023-10-04 22:57:44 +00:00
/// <summary>
/// Check if delivery window is open when we clicked resume.
/// </summary>
private unsafe bool CheckContinueWithDelivery ( )
{
if ( _configuration . CurrentlyCraftedItem ! = null )
{
AtkUnitBase * addonMaterialDelivery = GetMaterialDeliveryAddon ( ) ;
if ( addonMaterialDelivery = = null )
return false ;
_pluginLog . Warning ( "Material delivery window is open, although unexpected... checking current craft" ) ;
CraftState ? craftState = ReadCraftState ( addonMaterialDelivery ) ;
if ( craftState = = null | | craftState . ResultItem = = 0 )
{
_pluginLog . Error ( "Unable to read craft state" ) ;
_continueAt = DateTime . Now . AddSeconds ( 1 ) ;
return false ;
}
var craft = _workshopCache . Crafts . SingleOrDefault ( x = > x . ResultItem = = craftState . ResultItem ) ;
if ( craft = = null | | craft . WorkshopItemId ! = _configuration . CurrentlyCraftedItem . WorkshopItemId )
{
_pluginLog . Error ( "Unable to match currently crafted item with game state" ) ;
_continueAt = DateTime . Now . AddSeconds ( 1 ) ;
return false ;
}
_pluginLog . Information ( "Delivering materials for current active craft, switching to delivery" ) ;
return true ;
}
return false ;
}
2023-10-01 20:50:21 +00:00
private void SelectCraftBranch ( )
{
2024-03-20 18:52:54 +00:00
if ( SelectSelectString ( "contrib" , 0 , s = > s . StartsWith ( "Contribute materials." , StringComparison . Ordinal ) ) )
2023-10-01 21:33:21 +00:00
{
2023-10-01 20:50:21 +00:00
CurrentStage = Stage . ContributeMaterials ;
2023-10-01 21:33:21 +00:00
_continueAt = DateTime . Now . AddSeconds ( 1 ) ;
}
2024-03-20 18:52:54 +00:00
else if ( SelectSelectString ( "advance" , 0 , s = > s . StartsWith ( "Advance to the next phase of production." , StringComparison . Ordinal ) ) )
2023-10-01 20:50:21 +00:00
{
2023-10-04 22:07:36 +00:00
_pluginLog . Information ( "Phase is complete" ) ;
2023-10-04 22:57:44 +00:00
_configuration . CurrentlyCraftedItem ! . PhasesComplete + + ;
_configuration . CurrentlyCraftedItem ! . ContributedItemsInCurrentPhase = new ( ) ;
_pluginInterface . SavePluginConfig ( _configuration ) ;
2023-10-01 20:50:21 +00:00
CurrentStage = Stage . TargetFabricationStation ;
_continueAt = DateTime . Now . AddSeconds ( 3 ) ;
}
2024-03-20 18:52:54 +00:00
else if ( SelectSelectString ( "complete" , 0 , s = > s . StartsWith ( "Complete the construction of" , StringComparison . Ordinal ) ) )
2023-10-01 20:50:21 +00:00
{
2023-10-04 22:07:36 +00:00
_pluginLog . Information ( "Item is almost complete, confirming last cutscene" ) ;
2023-10-01 20:50:21 +00:00
CurrentStage = Stage . TargetFabricationStation ;
_continueAt = DateTime . Now . AddSeconds ( 3 ) ;
}
else if ( SelectSelectString ( "collect" , 0 , s = > s = = "Collect finished product." ) )
{
2023-10-04 22:07:36 +00:00
_pluginLog . Information ( "Item is complete" ) ;
2023-10-01 20:50:21 +00:00
CurrentStage = Stage . ConfirmCollectProduct ;
_continueAt = DateTime . Now . AddSeconds ( 0.25 ) ;
}
}
private unsafe void ContributeMaterials ( )
{
AtkUnitBase * addonMaterialDelivery = GetMaterialDeliveryAddon ( ) ;
if ( addonMaterialDelivery = = null )
return ;
CraftState ? craftState = ReadCraftState ( addonMaterialDelivery ) ;
if ( craftState = = null | | craftState . ResultItem = = 0 )
{
2023-10-04 22:07:36 +00:00
_pluginLog . Warning ( "Could not parse craft state" ) ;
2023-10-01 20:50:21 +00:00
_continueAt = DateTime . Now . AddSeconds ( 1 ) ;
return ;
}
2023-10-04 22:57:44 +00:00
if ( _configuration . CurrentlyCraftedItem ! . UpdateFromCraftState ( craftState ) )
{
_pluginLog . Information ( "Saving updated current craft information" ) ;
_pluginInterface . SavePluginConfig ( _configuration ) ;
}
2023-10-01 20:50:21 +00:00
for ( int i = 0 ; i < craftState . Items . Count ; + + i )
{
var item = craftState . Items [ i ] ;
if ( item . Finished )
continue ;
if ( ! HasItemInSingleSlot ( item . ItemId , item . ItemCountPerStep ) )
{
2023-10-04 22:57:44 +00:00
_pluginLog . Error (
$"Can't contribute item {item.ItemId} to craft, couldn't find {item.ItemCountPerStep}x in a single inventory slot" ) ;
2023-10-30 00:44:42 +00:00
InventoryManager * inventoryManager = InventoryManager . Instance ( ) ;
int itemCount = 0 ;
if ( inventoryManager ! = null )
{
itemCount = inventoryManager - > GetInventoryItemCount ( item . ItemId , true , false , false ) +
inventoryManager - > GetInventoryItemCount ( item . ItemId , false , false , false ) ;
}
if ( itemCount < item . ItemCountPerStep )
_chatGui . PrintError (
$"[Workshoppa] You don't have the needed {item.ItemCountPerStep}x {item.ItemName} to continue." ) ;
else
_chatGui . PrintError (
$"[Workshoppa] You don't have {item.ItemCountPerStep}x {item.ItemName} in a single stack, you need to merge the items in your inventory manually to continue." ) ;
2023-10-01 20:50:21 +00:00
CurrentStage = Stage . RequestStop ;
break ;
}
2023-10-19 18:46:01 +00:00
_externalPluginHandler . SaveTextAdvance ( ) ;
2023-10-04 22:07:36 +00:00
_pluginLog . Information ( $"Contributing {item.ItemCountPerStep}x {item.ItemName}" ) ;
2023-10-01 20:50:21 +00:00
_contributingItemId = item . ItemId ;
var contributeMaterial = stackalloc AtkValue [ ]
{
new ( ) { Type = ValueType . Int , Int = 0 } ,
new ( ) { Type = ValueType . UInt , Int = i } ,
new ( ) { Type = ValueType . UInt , UInt = item . ItemCountPerStep } ,
new ( ) { Type = 0 , Int = 0 }
} ;
addonMaterialDelivery - > FireCallback ( 4 , contributeMaterial ) ;
2023-10-19 18:46:01 +00:00
_fallbackAt = DateTime . Now . AddSeconds ( 0.2 ) ;
CurrentStage = Stage . OpenRequestItemWindow ;
2023-10-01 20:50:21 +00:00
break ;
}
}
2023-10-19 18:46:01 +00:00
private unsafe void RequestPostSetup ( AddonEvent type , AddonArgs addon )
{
var addonRequest = ( AddonRequest * ) addon . Addon ;
_pluginLog . Verbose ( $"{nameof(RequestPostSetup)}: {CurrentStage}, {addonRequest->EntryCount}" ) ;
if ( CurrentStage ! = Stage . OpenRequestItemWindow )
return ;
if ( addonRequest - > EntryCount ! = 1 )
return ;
_fallbackAt = DateTime . MaxValue ;
CurrentStage = Stage . OpenRequestItemSelect ;
var contributeMaterial = stackalloc AtkValue [ ]
{
new ( ) { Type = ValueType . Int , Int = 2 } ,
new ( ) { Type = ValueType . UInt , Int = 0 } ,
new ( ) { Type = ValueType . UInt , UInt = 44 } ,
new ( ) { Type = ValueType . UInt , UInt = 0 }
} ;
addonRequest - > AtkUnitBase . FireCallback ( 4 , contributeMaterial ) ;
}
private unsafe void ContextIconMenuPostReceiveEvent ( AddonEvent type , AddonArgs addon )
{
if ( CurrentStage ! = Stage . OpenRequestItemSelect )
return ;
CurrentStage = Stage . ConfirmRequestItemWindow ;
var selectSlot = stackalloc AtkValue [ ]
{
new ( ) { Type = ValueType . Int , Int = 0 } ,
new ( ) { Type = ValueType . Int , Int = 0 /* slot */ } ,
new ( ) { Type = ValueType . UInt , UInt = 20802 /* probably the item's icon */ } ,
new ( ) { Type = ValueType . UInt , UInt = 0 } ,
new ( ) { Type = 0 , Int = 0 } ,
} ;
( ( AddonContextIconMenu * ) addon . Addon ) - > AtkUnitBase . FireCallback ( 5 , selectSlot ) ;
}
private unsafe void RequestPostRefresh ( AddonEvent type , AddonArgs addon )
{
_pluginLog . Verbose ( $"{nameof(RequestPostRefresh)}: {CurrentStage}" ) ;
if ( CurrentStage ! = Stage . ConfirmRequestItemWindow )
return ;
var addonRequest = ( AddonRequest * ) addon . Addon ;
if ( addonRequest - > EntryCount ! = 1 )
return ;
CurrentStage = Stage . ConfirmMaterialDelivery ;
var closeWindow = stackalloc AtkValue [ ]
{
new ( ) { Type = ValueType . Int , Int = 0 } ,
new ( ) { Type = ValueType . UInt , UInt = 0 } ,
new ( ) { Type = ValueType . UInt , UInt = 0 } ,
new ( ) { Type = ValueType . UInt , UInt = 0 }
} ;
addonRequest - > AtkUnitBase . FireCallback ( 4 , closeWindow ) ;
addonRequest - > AtkUnitBase . Close ( false ) ;
_externalPluginHandler . RestoreTextAdvance ( ) ;
}
private unsafe void ConfirmMaterialDeliveryFollowUp ( )
2023-10-01 20:50:21 +00:00
{
AtkUnitBase * addonMaterialDelivery = GetMaterialDeliveryAddon ( ) ;
if ( addonMaterialDelivery = = null )
return ;
CraftState ? craftState = ReadCraftState ( addonMaterialDelivery ) ;
if ( craftState = = null | | craftState . ResultItem = = 0 )
{
2023-10-04 22:07:36 +00:00
_pluginLog . Warning ( "Could not parse craft state" ) ;
2023-10-01 20:50:21 +00:00
_continueAt = DateTime . Now . AddSeconds ( 1 ) ;
return ;
}
2023-10-19 18:46:01 +00:00
var item = craftState . Items . Single ( x = > x . ItemId = = _contributingItemId ) ;
item . StepsComplete + + ;
if ( craftState . IsPhaseComplete ( ) )
2023-10-01 21:33:21 +00:00
{
2023-10-19 18:46:01 +00:00
CurrentStage = Stage . TargetFabricationStation ;
_continueAt = DateTime . Now . AddSeconds ( 0.5 ) ;
2023-10-01 21:33:21 +00:00
}
2023-10-19 18:46:01 +00:00
else
2023-10-01 20:50:21 +00:00
{
2023-10-19 18:46:01 +00:00
_configuration . CurrentlyCraftedItem ! . ContributedItemsInCurrentPhase
. Single ( x = > x . ItemId = = item . ItemId )
. QuantityComplete = item . QuantityComplete ;
2023-10-01 20:50:21 +00:00
_pluginInterface . SavePluginConfig ( _configuration ) ;
2023-10-19 18:46:01 +00:00
CurrentStage = Stage . ContributeMaterials ;
_continueAt = DateTime . Now . AddSeconds ( 1 ) ;
2023-10-01 20:50:21 +00:00
}
}
}