|
| 1 | +-------------------------------------------------------- |
| 2 | +-- This file is part of the JX3 Mingyi Plugin. |
| 3 | +-- @link : https://jx3.derzh.com/ |
| 4 | +-- @desc : 自动按上次配方合石头 |
| 5 | +-- @author : 茗伊 @双梦镇 @追风蹑影 |
| 6 | +-- @modifier : Emil Zhai ([email protected]) |
| 7 | +-- @copyright: Copyright (c) 2013 EMZ Kingsoft Co., Ltd. |
| 8 | +-------------------------------------------------------- |
| 9 | +------------------------------------------------------------------------------------------------------- |
| 10 | +-- these global functions are accessed all the time by the event handler |
| 11 | +-- so caching them is worth the effort |
| 12 | +------------------------------------------------------------------------------------------------------- |
| 13 | +local ipairs, pairs, next, pcall, select = ipairs, pairs, next, pcall, select |
| 14 | +local string, math, table = string, math, table |
| 15 | +-- lib apis caching |
| 16 | +local X = MY |
| 17 | +local UI, GLOBAL, CONSTANT, wstring, lodash = X.UI, X.GLOBAL, X.CONSTANT, X.wstring, X.lodash |
| 18 | +------------------------------------------------------------------------------------------------------- |
| 19 | +local PLUGIN_NAME = 'MY_Toolbox' |
| 20 | +local PLUGIN_ROOT = X.PACKET_INFO.ROOT .. PLUGIN_NAME |
| 21 | +local MODULE_NAME = 'MY_Toolbox' |
| 22 | +local _L = X.LoadLangPack(PLUGIN_ROOT .. '/lang/') |
| 23 | +-------------------------------------------------------------------------- |
| 24 | +if not X.AssertVersion(MODULE_NAME, _L[MODULE_NAME], '^9.0.0') then |
| 25 | + return |
| 26 | +end |
| 27 | +X.RegisterRestriction('MY_AutoDiamond', { ['*'] = true }) |
| 28 | +-------------------------------------------------------------------------- |
| 29 | + |
| 30 | +--------------------------------------------------------------------- |
| 31 | +-- 本地函数和变量 |
| 32 | +--------------------------------------------------------------------- |
| 33 | +local O = X.CreateUserSettingsModule('MY_AutoDiamond', _L['General'], { |
| 34 | + bEnable = { -- 五行石精炼完成后自动再摆上次材料 |
| 35 | + ePathType = X.PATH_TYPE.ROLE, |
| 36 | + szLabel = _L['MY_Toolbox'], |
| 37 | + xSchema = X.Schema.Boolean, |
| 38 | + xDefaultValue = false, |
| 39 | + }, |
| 40 | +}) |
| 41 | +local D = {} |
| 42 | + |
| 43 | +-- 获取五行石数据 |
| 44 | +function D.GetDiamondData(dwBox, dwX) |
| 45 | + if not dwX then |
| 46 | + dwBox, dwX = select(2, dwBox:GetObjectData()) |
| 47 | + end |
| 48 | + local d, item = {}, GetClientPlayer().GetItem(dwBox, dwX) |
| 49 | + d.dwBox, d.dwX = dwBox, dwX |
| 50 | + if item then |
| 51 | + d.level = string.match(item.szName, _L['DIAMOND_REGEX']) |
| 52 | + d.id, d.bind, d.num, d.detail = item.nUiId, item.bBind, item.nStackNum, item.nDetail |
| 53 | + d.dwTabType, d.dwIndex = item.dwTabType, item.dwIndex |
| 54 | + end |
| 55 | + return d |
| 56 | +end |
| 57 | + |
| 58 | +-- get refine |
| 59 | +function D.GetRefineHandle() |
| 60 | + local handle = Station.Lookup('Normal/CastingPanel/PageSet_All/Page_Refine', '') |
| 61 | + return assert(handle, 'Can not find handle') |
| 62 | +end |
| 63 | + |
| 64 | +-- 保存五行石精炼方案 |
| 65 | +function D.SaveDiamondFormula() |
| 66 | + local t = {} |
| 67 | + local handle = D.GetRefineHandle() |
| 68 | + local box, hL = handle:Lookup('Handle_BoxItem/Box_Refine'), handle:Lookup('Handle_RefineExpend') |
| 69 | + table.insert(t, D.GetDiamondData(box)) |
| 70 | + for i = 1, 16 do |
| 71 | + local box = hL:Lookup('Box_RefineExpend_' .. i) |
| 72 | + if box:IsObjectEnable() and box:GetObjectData() ~= -1 then |
| 73 | + table.insert(t, D.GetDiamondData(box)) |
| 74 | + end |
| 75 | + end |
| 76 | + D.dFormula = t |
| 77 | +end |
| 78 | + |
| 79 | +-- 扫描背包石头及空位信息(存在 buggy cache) |
| 80 | +function D.LoadBagDiamond() |
| 81 | + local me, t = GetClientPlayer(), {} |
| 82 | + for dwBox = 1, X.GetBagPackageCount() do |
| 83 | + for dwX = 0, me.GetBoxSize(dwBox) - 1 do |
| 84 | + local d = D.GetDiamondData(dwBox, dwX) |
| 85 | + if not d.id or d.level then |
| 86 | + for _, v in ipairs(D.dFormula) do |
| 87 | + if v.dwBox == dwBox and v.dwX == dwX then |
| 88 | + d = nil |
| 89 | + end |
| 90 | + end |
| 91 | + if d then |
| 92 | + table.insert(t, d) |
| 93 | + end |
| 94 | + end |
| 95 | + end |
| 96 | + end |
| 97 | + D.tBagCache = t |
| 98 | +end |
| 99 | + |
| 100 | +-- 还原背包格子里的石头,失败返回 false,成功返回 true |
| 101 | +function D.RestoreBagDiamond(d) |
| 102 | + local me = GetClientPlayer() |
| 103 | + local tBag = D.tBagCache |
| 104 | + -- move box item |
| 105 | + local item = me.GetItem(d.dwBox, d.dwX) |
| 106 | + -- to stack |
| 107 | + if item then |
| 108 | + for k, v in ipairs(tBag) do |
| 109 | + if v.id == item.nUiId and v.bind == item.bBind and (v.num + item.nStackNum) <= item.nMaxStackNum then |
| 110 | + v.num = v.num + item.nStackNum |
| 111 | + me.ExchangeItem(d.dwBox, d.dwX, v.dwBox, v.dwX) |
| 112 | + item = nil |
| 113 | + break |
| 114 | + end |
| 115 | + end |
| 116 | + end |
| 117 | + -- to empty |
| 118 | + if item then |
| 119 | + for k, v in ipairs(tBag) do |
| 120 | + if not v.id then |
| 121 | + local v2 = D.GetDiamondData(d.dwBox, d.dwX) |
| 122 | + v2.dwBox, v2.dwX = v.dwBox, v.dwX |
| 123 | + tBag[k] = v2 |
| 124 | + me.ExchangeItem(d.dwBox, d.dwX, v.dwBox, v.dwX) |
| 125 | + item = nil |
| 126 | + break |
| 127 | + end |
| 128 | + end |
| 129 | + end |
| 130 | + -- no freebox |
| 131 | + if item then |
| 132 | + return false |
| 133 | + end |
| 134 | + -- group bag by type/bind: same type, same bind, ... others |
| 135 | + local tBag2, nLeft = {}, d.num |
| 136 | + for _, v in ipairs(tBag) do |
| 137 | + if v.level == d.level and (v.bind == d.bind or v.bind == false) then |
| 138 | + local vt = nil |
| 139 | + for _, vv in ipairs(tBag2) do |
| 140 | + if vv.bind == v.bind then |
| 141 | + vt = vv |
| 142 | + break |
| 143 | + end |
| 144 | + end |
| 145 | + if not vt then |
| 146 | + vt = { num = 0, bind = v.bind } |
| 147 | + local vk = #tBag2 + 1 |
| 148 | + if vk > 1 then |
| 149 | + if v.bind ~= d.bind then |
| 150 | + vk = 2 |
| 151 | + else |
| 152 | + vk = 1 |
| 153 | + end |
| 154 | + end |
| 155 | + table.insert(tBag2, vk, vt) |
| 156 | + end |
| 157 | + vt.num = vt.num + v.num |
| 158 | + table.insert(vt, v) |
| 159 | + end |
| 160 | + end |
| 161 | + -- select diamond1 (same type) |
| 162 | + for _, v in ipairs(tBag2) do |
| 163 | + if v.num >= nLeft then |
| 164 | + for _, vv in ipairs(v) do |
| 165 | + if vv.num >= nLeft then |
| 166 | + me.ExchangeItem(vv.dwBox, vv.dwX, d.dwBox, d.dwX, nLeft) |
| 167 | + vv.num = vv.num - nLeft |
| 168 | + break |
| 169 | + elseif vv.num > 0 then |
| 170 | + me.ExchangeItem(vv.dwBox, vv.dwX, d.dwBox, d.dwX, vv.num) |
| 171 | + nLeft = nLeft - vv.num |
| 172 | + vv.num = 0 |
| 173 | + end |
| 174 | + end |
| 175 | + return true |
| 176 | + end |
| 177 | + end |
| 178 | + return false |
| 179 | +end |
| 180 | + |
| 181 | +function D.GetCastingAction() |
| 182 | + if D.bReady and O.bEnable then |
| 183 | + local frame = Station.Lookup('Topmost/MB_CastingPanelConfirm') |
| 184 | + if frame then |
| 185 | + D.ProduceDiamond = frame:Lookup('Wnd_All/Btn_Option1').fnAction |
| 186 | + D.SaveDiamondFormula() |
| 187 | + end |
| 188 | + end |
| 189 | +end |
| 190 | + |
| 191 | +-- 自动摆五行石材料 |
| 192 | +function D.OnDiamondUpdate() |
| 193 | + if not D.bReady or not O.bEnable or not D.dFormula or arg0 ~= 1 then |
| 194 | + return |
| 195 | + end |
| 196 | + local box = D.GetRefineHandle():Lookup('Handle_BoxItem/Box_Refine') |
| 197 | + if not box then |
| 198 | + D.dFormula = nil |
| 199 | + return |
| 200 | + end |
| 201 | + -- 移除加锁(延迟一帧) |
| 202 | + X.DelayCall(50, function() |
| 203 | + local dwBox, dwX = select(2, box:GetObjectData()) |
| 204 | + RemoveUILockItem('CastingPanel:' .. dwBox .. ',' .. dwX) |
| 205 | + box:SetObject(UI_OBJECT_NOT_NEED_KNOWN, 0) |
| 206 | + box:SetObjectIcon(3388 - GetClientPlayer().nGender) |
| 207 | + end) |
| 208 | + -- 重新放入配方(延迟8帧执行,确保 unlock) |
| 209 | + X.DelayCall(200, function() |
| 210 | + if not D.bReady or not O.bEnable then |
| 211 | + return |
| 212 | + end |
| 213 | + D.LoadBagDiamond() |
| 214 | + for _, v in ipairs(D.dFormula) do |
| 215 | + if not D.RestoreBagDiamond(v) then |
| 216 | + box:ClearObject() |
| 217 | + D.dFormula = nil |
| 218 | + D.tBagCache = nil |
| 219 | + return |
| 220 | + end |
| 221 | + end |
| 222 | + D.ProduceDiamond() |
| 223 | + D.RegisterNextRefineDuang() |
| 224 | + end) |
| 225 | +end |
| 226 | + |
| 227 | +-- 注册下次精炼结果显示 |
| 228 | +function D.PlayCommonRefineDuang(bSuccess) |
| 229 | + local frame = Station.Lookup('Normal/CastingPanel') |
| 230 | + if not frame then |
| 231 | + return |
| 232 | + end |
| 233 | + local sfxSuccess = frame:Lookup('PageSet_All/Page_Refine', 'SFX_CommonRefineSuccess') |
| 234 | + local sfxFailure = frame:Lookup('PageSet_All/Page_Refine', 'SFX_CommonRefineFailure') |
| 235 | + sfxSuccess:Hide() |
| 236 | + sfxFailure:Hide() |
| 237 | + |
| 238 | + local sfx |
| 239 | + if bSuccess then |
| 240 | + sfx = sfxSuccess |
| 241 | + PlaySound(SOUND.UI_SOUND, g_sound.ElementalStoneSuccess) |
| 242 | + else |
| 243 | + sfx = sfxFailure |
| 244 | + PlaySound(SOUND.UI_SOUND, g_sound.ElementalStoneFailed) |
| 245 | + end |
| 246 | + sfx:Show() |
| 247 | + sfx:Play() |
| 248 | +end |
| 249 | + |
| 250 | +-- 注册下次精炼结果显示 |
| 251 | +function D.RegisterNextRefineDuang() |
| 252 | + -- 播放结果动画 |
| 253 | + X.RegisterEvent('DIAMON_UPDATE', 'MY_AutoDiamond__Duang', function() |
| 254 | + local nResult = arg0 |
| 255 | + if nResult == DIAMOND_RESULT_CODE.SUCCESS then |
| 256 | + local d = D.dFormula and D.dFormula[1] |
| 257 | + if d and d.detail and d.detail > 0 then |
| 258 | + local KItem = GetPlayerItem(GetClientPlayer(), d.dwBox, d.dwX) |
| 259 | + if KItem then |
| 260 | + if KItem.nDetail > d.detail then |
| 261 | + D.PlayCommonRefineDuang(true) |
| 262 | + OutputMessage('MSG_ANNOUNCE_YELLOW', g_tStrings.tFEProduce.SUCCEED) |
| 263 | + else |
| 264 | + D.PlayCommonRefineDuang(false) |
| 265 | + OutputMessage('MSG_ANNOUNCE_RED', g_tStrings.tFEProduce.FAILED) |
| 266 | + end |
| 267 | + end |
| 268 | + end |
| 269 | + end |
| 270 | + X.RegisterEvent('DIAMON_UPDATE', 'MY_AutoDiamond__Duang', false) |
| 271 | + end) |
| 272 | +end |
| 273 | + |
| 274 | +------------------------------------- |
| 275 | +-- 设置界面 |
| 276 | +------------------------------------- |
| 277 | +function D.CheckInjection(bRemove) |
| 278 | + local frame = Station.SearchFrame('CastingPanel') |
| 279 | + local page = frame and frame:Lookup('PageSet_All/Page_Refine') |
| 280 | + if not page then |
| 281 | + return |
| 282 | + end |
| 283 | + if not bRemove and not X.IsRestricted('MY_AutoDiamond') then |
| 284 | + UI(page):Append('WndCheckBox', { |
| 285 | + name = 'WndCheckBox_MYDiamond', |
| 286 | + text = _L['Produce diamond as last formula'], |
| 287 | + x = 100, y = 390, w = 'auto', |
| 288 | + checked = O.bEnable, font = 57, |
| 289 | + oncheck = function(bChecked) |
| 290 | + O.bEnable = bChecked |
| 291 | + D.dFormula = nil |
| 292 | + end, |
| 293 | + }) |
| 294 | + else |
| 295 | + UI(page):Fetch('WndCheckBox_MYDiamond'):Remove() |
| 296 | + end |
| 297 | +end |
| 298 | +X.RegisterFrameCreate('CastingPanel', 'MY_AutoDiamond', function() D.CheckInjection() end) |
| 299 | +X.RegisterEvent('MY_RESTRICTION', 'MY_AutoDiamond', function() |
| 300 | + if arg0 and arg0 ~= 'MY_AutoDiamond' then |
| 301 | + return |
| 302 | + end |
| 303 | + D.CheckInjection() |
| 304 | +end) |
| 305 | +X.RegisterInit('MY_AutoDiamond', function() D.CheckInjection() end) |
| 306 | +X.RegisterReload('MY_AutoDiamond', function() D.CheckInjection(true) end) |
| 307 | + |
| 308 | +X.RegisterUserSettingsUpdate('@@INIT@@', 'MY_AutoDiamond', function() |
| 309 | + D.bReady = true |
| 310 | +end) |
| 311 | + |
| 312 | +X.RegisterUserSettingsUpdate('@@UNINIT@@', 'MY_AutoDiamond', function() |
| 313 | + D.bReady = false |
| 314 | +end) |
| 315 | + |
| 316 | +X.RegisterEvent('DIAMON_UPDATE', 'MY_AutoDiamond', D.OnDiamondUpdate) |
| 317 | +X.RegisterEvent('ON_MESSAGE_BOX_OPEN', 'MY_AutoDiamond', D.GetCastingAction) |
0 commit comments