Advertisement
Guest User

Enchanting.cs

a guest
Sep 21st, 2015
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.99 KB | None | 0 0
  1. //Arcanum Enchanting v1.1.0 Korean localization for Korean client 한국어 로컬라이제이션
  2. //by [갓베]로무현 2015-09-21
  3. //사용법: plugins\zArcanum\Enchanting.cs 파일을 이 파일로 교체
  4.  
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.RegularExpressions;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Windows.Input;
  13. using System.Windows.Navigation;
  14. using JetBrains.Annotations;
  15. using QuestTools;
  16. using QuestTools.Helpers;
  17. using Zeta.Game;
  18. using Zeta.Game.Internals;
  19.  
  20. namespace Arcanum
  21. {
  22. public class Enchanting
  23. {
  24. static Enchanting()
  25. {
  26. OnStateChanged += (previous, current) =>
  27. {
  28. Logger.Log("State Changed from {0} to {1}", previous, current);
  29. };
  30. }
  31.  
  32. public static UIElement EnchantButton { get { return UIElement.FromHash(0xBA58F7018A622DB3); } }
  33. public static UIElement EnchantStackPanel { get { return UIElement.FromHash(11989936962002177713); } }
  34. public static UIElement ConfirmEnchantDialog { get { return UIElement.FromHash(0x891D21408238D18E); } }
  35. public static UIElement ChoosePropertyText { get { return UIElement.FromHash(9844980432208557595); } }
  36. public static UIElement AlreadyEnchantedText { get { return UIElement.FromHash(8315348018061129442); } }
  37. public static UIElement RequiredMaterialsPanel { get { return UIElement.FromHash(10214243498069811485); } }
  38. public static UIElement AffixesDialog { get { return UIElement.FromHash(0x6C9DC02BBB83980F); } }
  39. public static UIElement CloseValidAffixesDialogButton { get { return UIElement.FromHash(0x78F39C99FC122C5C); } }
  40. public static UIElement OpenAffixesDialogButton { get { return UIElement.FromHash(0xAAEABCC414252CF6); } }
  41. public static UIElement ValidAffixesStackPanel { get { return UIElement.FromHash(2200502231488149432); } }
  42.  
  43. public static Worker Worker = new Worker();
  44.  
  45. public enum EnchantingState
  46. {
  47. /// <summary>
  48. /// Enchanting panel is not open
  49. /// </summary>
  50. NotEnchanting = 0,
  51.  
  52. /// <summary>
  53. /// Box on enchanter panel doesnt have an item in it
  54. /// </summary>
  55. NoItemSelected,
  56.  
  57. /// <summary>
  58. /// Item hasn't been enchanted before, select which property to replace
  59. /// </summary>
  60. SelectPropertyToEnchant,
  61.  
  62. /// <summary>
  63. /// Ready to re-enchant a previously enchanted property
  64. /// </summary>
  65. EnchantProperty,
  66.  
  67. /// <summary>
  68. /// Cant afford to click enchant button
  69. /// </summary>
  70. CantAffordToEnchant,
  71.  
  72. /// <summary>
  73. /// New enchantment options are presented
  74. /// </summary>
  75. SelectNewEnchant,
  76.  
  77. /// <summary>
  78. /// A New enchantment option is selected
  79. /// </summary>
  80. AcceptSelectedEnchant,
  81. }
  82.  
  83. private static List<Enchantment> _validAffixes;
  84. public static List<Enchantment> ValidAffixes
  85. {
  86. get
  87. {
  88. UpdateValidAffixes();
  89. return _validAffixes;
  90. }
  91. private set { _validAffixes = value; }
  92. }
  93.  
  94. private static int _previousItemsHash;
  95. private static void UpdateValidAffixes()
  96. {
  97. using (new MemoryHelper())
  98. {
  99. var result = new List<Enchantment>();
  100.  
  101. if (!EnchantButton.IsValid || !EnchantButton.IsVisible || !EnchantStackPanel.IsValid || !EnchantStackPanel.IsVisible)
  102. return;
  103.  
  104. if (EnchantButton.Text.ToLowerInvariant().Contains("place an item"))
  105. return;
  106.  
  107. if (!AffixesDialog.IsVisible && !OpenAffixesDialogButton.IsVisible)
  108. return;
  109.  
  110. if (!AffixesDialog.IsVisible)
  111. {
  112. OpenAffixesDialogButton.Click();
  113. Thread.Sleep(200);
  114. }
  115.  
  116. if (!AffixesDialog.IsVisible)
  117. return;
  118.  
  119. var items = ValidAffixesStackPanel.GetStackPanelItems();
  120. var itemsHash = StackPanelReader.GetStackPanelHashCode(items);
  121.  
  122. if (itemsHash == _previousItemsHash)
  123. {
  124. Logger.Verbose("Skipping Affixes update due to same hash");
  125. return;
  126. }
  127.  
  128.  
  129. Logger.Verbose("Updating Valid Affixes");
  130.  
  131. _previousItemsHash = itemsHash;
  132.  
  133. items.ForEach(item =>
  134. {
  135. var text = CleanString(item.TextElement.Text);
  136. var enchant = ParseEnchantment(text);
  137.  
  138. if (enchant.ItemProperty == ItemProperty.Unknown)
  139. {
  140. Logger.Log("Unknown ValidElement: {0}", text);
  141. return;
  142. }
  143.  
  144. result.Add(enchant);
  145. });
  146.  
  147. ValidAffixes = result;
  148. }
  149. }
  150.  
  151. internal static void Enchant(List<Enchantment> desiredEnchants)
  152. {
  153. if (Worker.IsRunning || !desiredEnchants.Any())
  154. return;
  155.  
  156. var startTime = DateTime.UtcNow;
  157.  
  158. //Logger.Debug("Searching for: {0} >= {1}", desiredEnchant.Name, desiredEnchant.Value);
  159.  
  160. UpdateValidAffixes();
  161.  
  162. Worker.Start(() =>
  163. {
  164. using (new MemoryHelper())
  165. {
  166. Logger.Debug("State = {0}", State);
  167.  
  168. if (UI.TimeoutEnabled && DateTime.UtcNow.Subtract(startTime).TotalSeconds > 600)
  169. {
  170. Logger.Log("Timeout Reached ({0}s)", 600);
  171. return true;
  172. }
  173.  
  174. if (State != EnchantingState.EnchantProperty && State != EnchantingState.SelectNewEnchant)
  175. {
  176. switch (State)
  177. {
  178. case EnchantingState.NotEnchanting:
  179. Logger.Log("Enchanting Panel is not Visible");
  180. break;
  181. case EnchantingState.NoItemSelected:
  182. Logger.Log("You must put an item in the enchanting panel first");
  183. break;
  184. case EnchantingState.SelectPropertyToEnchant:
  185. Logger.Warn("First enchant is currently disabled for your safety");
  186. break;
  187. case EnchantingState.CantAffordToEnchant:
  188. Logger.Warn("You cannot afford to enchant any more");
  189. break;
  190. }
  191. return true;
  192. }
  193.  
  194. if (State == EnchantingState.EnchantProperty)
  195. {
  196. var invalidEnchants = desiredEnchants.Where(e => !ValidAffixes.Contains(e)).ToList();
  197. if (invalidEnchants.Any())
  198. {
  199. invalidEnchants.ForEach(e => Logger.Log("The selected affix {0} is not valid for this item type", e.Name));
  200. return true;
  201. }
  202.  
  203. //if (!ValidAffixes.Any(a => a.ItemProperty == desiredEnchant.ItemProperty && a.Variant == desiredEnchant.Variant ))
  204. //{
  205. // Logger.Log("The selected affix {0} is not valid for this item type", desiredEnchant);
  206. // return true;
  207. //}
  208.  
  209. EnchantButton.Click();
  210. Thread.Sleep(500);
  211. return false;
  212. }
  213.  
  214. return SelectNewProperty(desiredEnchants);
  215. }
  216. });
  217.  
  218. }
  219.  
  220. private static bool SelectNewProperty(List<Enchantment> desiredEnchants)
  221. {
  222. var panelChildren = UIElement.GetChildren(EnchantStackPanel).ToList();
  223. var matchFound = false;
  224. var upgradeFound = false;
  225. var currentEnchant = new Enchantment();
  226.  
  227. Thread.Sleep(1500);
  228.  
  229. Func<Enchantment, bool> isMatch = newEnchant =>
  230. {
  231. Logger.Verbose("Checking for Match {0} {1} against {2} desired enchants",
  232. newEnchant.Name,
  233. newEnchant.Value,
  234. desiredEnchants.Count);
  235.  
  236. foreach (var desiredEnchant in desiredEnchants)
  237. {
  238. if (desiredEnchant.Equals(newEnchant))
  239. {
  240. Logger.Verbose(">> {0} {1} >= {2} {3}",
  241. newEnchant.Name,
  242. newEnchant.Value,
  243. desiredEnchant.Name,
  244. desiredEnchant.Value);
  245.  
  246. return newEnchant.Value >= desiredEnchant.Value;
  247. }
  248. }
  249. Logger.Verbose(">> {0} {1} not a match", newEnchant.Name, newEnchant.Value);
  250. return false;
  251. };
  252.  
  253. Func<Enchantment, bool> isUpgrade = newEnchant =>
  254. {
  255. Logger.Verbose("Checking for Upgrade on existing enchant: {0} {1}",
  256. currentEnchant.Name,
  257. currentEnchant.Value);
  258.  
  259. var isNewEnchantDesired = desiredEnchants.Contains(newEnchant);
  260. var isCurrentEnchantDesired = desiredEnchants.Contains(currentEnchant);
  261.  
  262. // Allow upgrade if current enchant is not what we're looking for and new enchant is
  263. if (!isCurrentEnchantDesired && isNewEnchantDesired)
  264. {
  265. Logger.Verbose(">> {0} {1} is an upgrade because current enchant ({2}) is not what we're looking for",
  266. newEnchant.Name,
  267. newEnchant.Value,
  268. currentEnchant.Name);
  269.  
  270. return true;
  271. }
  272.  
  273. // Allow upgrade if current enchant is the same (ItemProperty and Variant) as new enchant and new enchant is better.
  274. if (isNewEnchantDesired && newEnchant.Equals(currentEnchant))
  275. {
  276. Logger.Verbose(">> {0} {1} >= {2} {3}",
  277. newEnchant.Name,
  278. newEnchant.Value,
  279. currentEnchant.Name,
  280. currentEnchant.Value);
  281.  
  282. return newEnchant.Value > currentEnchant.Value;
  283. }
  284.  
  285. // Allow cross-type upgrades for variants of the same ItemPropery E.g. Fire Damage 12% > Poison Damage 10%
  286. if (newEnchant.ItemProperty == currentEnchant.ItemProperty && currentEnchant.ItemProperty == ItemProperty.BaseDamage)
  287. {
  288. Logger.Verbose(">> {0} {1} >= {2} {3}",
  289. newEnchant.Name,
  290. newEnchant.Value,
  291. currentEnchant.Name,
  292. currentEnchant.Value);
  293.  
  294. return newEnchant.Value > currentEnchant.Value;
  295. }
  296.  
  297. Logger.Verbose(">> {0} {1} not an upgrade", newEnchant.Name, newEnchant.Value);
  298. return false;
  299.  
  300. };
  301.  
  302. var items = EnchantStackPanel.GetStackPanelItems();
  303.  
  304. if (!items.Any())
  305. {
  306. Logger.Debug("No Enchant UIElements were found");
  307. return false;
  308. }
  309.  
  310. var upgradeElement = panelChildren[0];
  311. var matchElement = panelChildren[0];
  312.  
  313. foreach (var item in items)
  314. {
  315. var text = CleanString(item.TextElement.Text);
  316. var enchant = ParseEnchantment(text);
  317.  
  318. if (items.ElementAt(0) == item)
  319. {
  320. currentEnchant = enchant;
  321. Logger.Debug("Existing Enchant: {0} ({1}) {2}", enchant.ItemProperty, enchant.Value, enchant.Variant);
  322. }
  323. else if (isMatch(enchant))
  324. {
  325. Logger.Warn("Found Match!: {0} ({1}) {2}", enchant.ItemProperty, enchant.Value, enchant.Variant);
  326. matchElement = item.ItemElement; ;
  327. matchFound = true;
  328. }
  329. else if (isUpgrade(enchant))
  330. {
  331. Logger.Warn("Found Upgrade!: {0} ({1}) {2}, still searching though...", enchant.ItemProperty, enchant.Value, enchant.Variant);
  332. upgradeElement = item.ItemElement;
  333. upgradeFound = true;
  334. }
  335. else
  336. {
  337. Logger.Log("Found: {0} ({1}) {2}", enchant.ItemProperty, enchant.Value, enchant.Variant);
  338. }
  339.  
  340. if (enchant.ItemProperty == ItemProperty.Unknown)
  341. Logger.Log("Failed to understand string: {0}", text);
  342.  
  343. Thread.Sleep(50);
  344. }
  345.  
  346. if (matchFound)
  347. {
  348. matchElement.Click();
  349. }
  350. else if (upgradeFound)
  351. {
  352. upgradeElement.Click();
  353. }
  354. else
  355. {
  356. panelChildren[0].Click();
  357. }
  358. Thread.Sleep(50);
  359.  
  360. if (EnchantButton.IsEnabled)
  361. {
  362. EnchantButton.Click();
  363. Thread.Sleep(50);
  364. }
  365.  
  366. if (ConfirmEnchantDialog != null && ConfirmEnchantDialog.IsValid && ConfirmEnchantDialog.IsVisible)
  367. ConfirmEnchantDialog.Click();
  368.  
  369. Thread.Sleep(500);
  370.  
  371. return matchFound;
  372. }
  373.  
  374.  
  375.  
  376. internal static Enchantment ParseEnchantment(string input)
  377. {
  378. var e = new Enchantment();
  379.  
  380. if (string.IsNullOrEmpty(input))
  381. return e;
  382.  
  383. // http://regexhero.net/tester/
  384.  
  385. var regex = new Regex(@"(?<value>[\d\.,]+)(?<=[^\.])|(?<1>생명력)|(?<2>방어도)|(?<3>극대화 확률)|(?<4>극대화 피해)|(?<5>.*)로 주는 피해|(?<6>소모한 공력 1당 생명력)|(?<7>민첩)|(?<8>힘)|(?<9>지능)|(?<10>활력)|(?<11>광역 피해)|(?<12>재사용 대기시간)|(?<13>자원 소모량)|(?<14>Durability)|(?<15>물리 저항)|(?<16>냉기 저항)|(?<17>화염 저항)|(?<18>번개 저항)|(?<19>비전 저항)|(?<20>독 저항)|(?<21>적에게서 얻는 금화)|(?<22>공격자에게 적중 시)|(?<23>획득 반경)|(?<24>적중 시 오한)|(?<25>내구도 감소 무시)|(?<26>생명의 구슬과 물약으로)|(?<27>요구 레벨)|(?<28>이동 속도)|(?<29>모든 원소)|(?<30>적을 처치하고 얻는)|(?<31>적중 시 이동 불가)|(?<32>적중 시 실명)|(?<33>제어 방해 효과의 지속시간)|(?<34>냉기 기술로)|(?<35>화염 기술로)|(?<36>신성 기술로)|(?<37>번개 기술로)|(?<38>독 기술로)|(?<39>물리 기술로)|(?<40>진노 생성량)|(?<41>공격 속도)|(?<42>적중 시 생명력)|(?<43>정예에게 받는 피해)|(?<44>확률로 출혈)|(?<45>증오 회복량)|(?<46>홈)|(?<47>화염 무기 공격력|비전 무기 공격력|독 무기 공격력|번개 무기 공격력|냉기 무기 공격력|신성 무기 공격력|무기 공격력)(?<!\]%|%)(?!\sper|\.)|(?<48>소모한 진노 1당 생명력)|(?<49>최대 진노)|(?<50>소모한 분노 1당 생명력)|(?<51>공력 회복량)|(?<52>정예에게 주는 피해)|(?<53>처치 시 생명력)|(?<54>최대 마나)|(?<55>최대 비전력)|(?<56>근접 공격으로 받는)|(?<57>원거리 공격으로 받는)|(?<58>최대 공력)|(?<59>최대 분노)|(?<60>방패막기 확률)|(?<61>적중 시 공포)|(?<62>적중 시 기절)|(?<63>적중 시 빙결)|(?<64>적중 시 감속)|(?<65>적중 시 밀치기)|(?<66>초당 생명력)|(?<67>최대 절제)|(?<68>극대화 적중 시 비전력)|(?<69>비전 기술로)|(?<70>마나 회복량)|(?<71>(?!\sper|\.)피해)");
  386.  
  387. var groupMatches = regex.GroupMatches(input);
  388.  
  389. if (!groupMatches.Strings.Any())
  390. return e;
  391.  
  392. e.ItemProperty = (ItemProperty)groupMatches.Strings.First().GroupIndex;
  393.  
  394. if (groupMatches.Numbers.Any())
  395. {
  396. e.Maximum = groupMatches.Numbers.Max(i => i.NumberValue);
  397. e.Minimum = groupMatches.Numbers.Min(i => i.NumberValue);
  398. }
  399.  
  400. if (e.ItemProperty == ItemProperty.SkillDamage || e.ItemProperty == ItemProperty.BaseDamage)
  401. {
  402. e.Variant = CleanString(groupMatches.Strings.First().StringValue);
  403. }
  404.  
  405. e.Value = e.Maximum;
  406. e.Original = input;
  407.  
  408. return e;
  409. }
  410.  
  411. private static EnchantingState _lastState = EnchantingState.NotEnchanting;
  412. public static EnchantingState State
  413. {
  414. get
  415. {
  416. var state = EnchantingState.NotEnchanting;
  417.  
  418. using(new MemoryHelper())
  419. {
  420. if (!ZetaDia.IsInGame || ZetaDia.Me == null || !ZetaDia.Me.IsValid || !ZetaDia.IsInTown)
  421. state = EnchantingState.NotEnchanting;
  422.  
  423. else if (!EnchantButton.IsValid || !EnchantButton.IsVisible || !EnchantStackPanel.IsValid || !EnchantStackPanel.IsVisible)
  424. state = EnchantingState.NotEnchanting;
  425.  
  426. else if (EnchantButton.Text.ToLowerInvariant().Contains("아이템을 올려놓으십시오"))
  427. state = EnchantingState.NoItemSelected;
  428.  
  429. else if (EnchantButton.Text.ToLowerInvariant().Contains("교체할 속성을 선택하십시오"))
  430. state = EnchantingState.SelectPropertyToEnchant;
  431.  
  432. else if (EnchantButton.Text.ToLowerInvariant().Contains("속성 선택"))
  433. state = EnchantingState.SelectNewEnchant;
  434.  
  435. else if (EnchantButton.Text.ToLowerInvariant().Contains("속성 교체"))
  436. {
  437. if (RequiredMaterialsPanel.IsValid && RequiredMaterialsPanel.IsVisible && EnchantButton.IsValid && !EnchantButton.IsEnabled)
  438. state = EnchantingState.CantAffordToEnchant;
  439. else
  440. state = EnchantingState.EnchantProperty;
  441. }
  442. }
  443.  
  444. if (_lastState != state)
  445. {
  446. OnStateChanged(_lastState, state);
  447. }
  448.  
  449. _lastState = state;
  450. return state;
  451. }
  452. }
  453.  
  454. public delegate void LoaderEvent(EnchantingState previous, EnchantingState current);
  455. public static event LoaderEvent OnStateChanged = (p,v) => { };
  456.  
  457. /// <summary>
  458. /// Strips out a name from color encoded UI string e.g.
  459. /// {c:ff6969ff}Corrupted Angel{/c}
  460. /// </summary>
  461. public static string CleanString(string s)
  462. {
  463. try
  464. {
  465. return Regex.Replace(s, "{([^}]*)}", "").Trim();
  466. }
  467. catch (Exception ex)
  468. {
  469. Logger.Debug("Exception in CleanString {0}", ex);
  470. }
  471. return s.Trim();
  472. }
  473.  
  474. }
  475.  
  476.  
  477.  
  478.  
  479.  
  480. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement