Advertisement
Guest User

Untitled

a guest
Jul 17th, 2017
541
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.25 KB | None | 0 0
  1. print("[[XenoBot]]\nHUD Made by: Martin\nScript made by: Martin\nEnjoy! " .. Self.Name())
  2. -- Name of Config File
  3. local configName = string.format("..\\Configs\\[%s] %s", Self.Name(), "Pain - General Lua")
  4. dofile(configName..".ini")
  5. -- Position
  6. local MainX = 290
  7. local MainY = 15
  8. -- Color
  9. local R = 255
  10. local G = 255
  11. local B = 255
  12.  
  13. -- Settings
  14. local index = 0
  15. local HoraInicio = os.time()
  16. local NivelesInicio = Self.Level()
  17. local ExperienciaInicio = Self.Experience()
  18. local NivelInicio = 0
  19. local LevelStep = 1
  20. local Stamina = 0
  21. local TimeStep = 1
  22. local ElapsedTime = 0
  23. local measurePerStamina = true
  24. local function FixTime(TotalSeconds)
  25. local seconds = math.floor(TotalSeconds % 60)
  26. local minutes = math.floor(TotalSeconds/60 % 60)
  27. local hours = math.floor(TotalSeconds/3600)
  28. return string.format("%02.f", hours)..":"..string.format("%02.f", minutes)..":"..string.format("%02.f", seconds)
  29. end
  30. -- Updates
  31. local function getTimeMeasure()
  32. if measurePerStamina then
  33. return " k/sh", math.max(Stamina, 1) *60
  34. else
  35. return " k/h", math.max(ElapsedTime, 1)
  36. end
  37. end
  38. local function UpdateExperienciaHora()
  39. local suffix, elapsed = getTimeMeasure()
  40. ExperienciaHora:SetText(math.floor((Self.Experience() - ExperienciaInicio)/elapsed * 36)/10 .. suffix)
  41. end
  42. local function UpdateExperiencia()
  43. Experiencia:SetText(Self.Experience() - ExperienciaInicio)
  44. end
  45. local function UpdateNiveles()
  46. NivelesGanados:SetText(Self.Level() - NivelesInicio)
  47. end
  48. local function UpdateNivel()
  49. Nivel:SetText(tostring(Self.Level()))
  50. end
  51. local function UpdateOnlineTime()
  52. local OldTime = ElapsedTime
  53. ElapsedTime = os.difftime(os.time(), HoraInicio)
  54. TimeStep = ElapsedTime - OldTime
  55. TiempoOnline:SetText(FixTime(ElapsedTime))
  56. end
  57. local function UpdatePing()
  58. PingHUD:SetText(Self.Ping() .. " ms")
  59. end
  60. local function UpdateBarHP()
  61. local currentHealth = math.floor(Self.Health()*100/Self.MaxHealth())
  62. local barStr = ''
  63. for i = 0, currentHealth, 2 do
  64. barStr = barStr .. 'l'
  65. end
  66. HpBar:SetText(barStr)
  67. if (currentHealth >= 80) then
  68. HpBar:SetTextColor(0, 250, 0)
  69. elseif (currentHealth >= 45) then
  70. HpBar:SetTextColor(255, 165, 0)
  71. else
  72. HpBar:SetTextColor(250, 0, 0)
  73. end
  74. end
  75. local function UpdateBarMP()
  76. local currentMana = math.floor(Self.Mana()*100/Self.MaxMana())
  77. local barStr = ''
  78. for i = 0, currentMana, 2 do
  79. barStr = barStr .. 'l'
  80. end
  81. ManaBar:SetText(barStr)
  82. if (currentMana >= 80) then
  83. ManaBar:SetTextColor(0, 183, 255)
  84. elseif (currentMana >= 45) then
  85. ManaBar:SetTextColor(255, 165, 0)
  86. else
  87. ManaBar:SetTextColor(250, 0, 0)
  88. end
  89. end
  90. local function UpdateStaminaBar()
  91. local curentStamina = math.floor(Self.Stamina()*100/(42*60))
  92. local barStr = ''
  93. for i = 0, curentStamina, 2 do
  94. barStr = barStr .. 'l'
  95. end
  96. StaminaBar:SetText(barStr)
  97. if (Self.Stamina() >= (40*60)) then
  98. StaminaBar:SetTextColor(0, 255, 0)
  99. elseif (Self.Stamina() >= (40*60)) then
  100. StaminaBar:SetTextColor(255, 139, 0)
  101. else
  102. StaminaBar:SetTextColor(255, 139, 0)
  103. end
  104. end
  105. local function UpdateHorasDeStamina()
  106. local OldStamina = Self.Stamina()
  107. local ElapsedStamina = 0
  108. local stamina = Self.Stamina()
  109. local diff = OldStamina - stamina
  110. OldStamina = stamina
  111. ElapsedStamina = ElapsedStamina + diff
  112. local staminaH = math.floor(stamina/60)
  113. local staminaM = stamina % 60
  114. HorasDeStamina:SetText(staminaH..":".. string.format("%02.f", staminaM) .. " ")
  115. end
  116. local function UpdateCapacity()
  117. Capacidad:SetText(string.format("%.0f", Self.Cap()) .. "")
  118. end
  119. local function UpdateHealth()
  120. PorcientoVida:SetText(Self.HPPC() .. "%")
  121. end
  122. local function UpdateMana()
  123. PorcientoMana:SetText(Self.MPPC() .. " %")
  124. end
  125. local function UpdateRound() --vocation
  126. Round:SetText(index)
  127. end
  128. local function UpdateHUD()
  129. UpdateNivel()
  130. UpdateNiveles()
  131. UpdateExperiencia()
  132. UpdateExperienciaHora()
  133. UpdateOnlineTime()
  134. UpdatePing()
  135. UpdateBarHP()
  136. UpdateBarMP()
  137. UpdateStaminaBar()
  138. UpdateCapacity()
  139. UpdateHorasDeStamina()
  140. UpdateHealth()
  141. UpdateMana()
  142. UpdateRound()
  143. end
  144. do
  145. -- Display
  146. function InitHUD()
  147. -- sombras
  148. HUD.New(MainX-250, MainY+41, "Keep Dreaming", 0, 0, 0)
  149. HUD.New(MainX-280, MainY+57, "Welcome: " .. Self.Name(), 0, 0, 0)
  150. HUD.New(MainX-280, MainY+72, "XenoBot " .. XenoBot.GetVersionInformation(), 0, 0, 0)
  151. Nivel = HUD.New(MainX-280, MainY+87, "Current Level: ", 0, 0, 0)
  152. HUD.New(MainX-280, MainY+102, "Levels Gained: ", 0, 0, 0)
  153. HUD.New(MainX-280, MainY+117, "Experience Gained: ", 0, 0, 0)
  154. HUD.New(MainX-280, MainY+132, "Current Experience: ", 0, 0, 0)
  155. HUD.New(MainX-250, MainY+147, "Modules Status", 0, 0, 0)
  156. HUD.New(MainX-280, MainY+162, "Use Console: ", 0, 0, 0)
  157. HUD.New(MainX-280, MainY+177, "Force Refill: ", 0, 0, 0)
  158. HUD.New(MainX-280, MainY+192, "Refill Soft Boots: ", 0, 0, 0)
  159. HUD.New(MainX-280, MainY+207, "Withdraw Ammo: ", 0, 0, 0)
  160. HUD.New(MainX-280, MainY+222, "Withdraw Rings: ", 0, 0, 0)
  161. HUD.New(MainX-250, MainY+237, "Bot Status", 0, 0, 0)
  162. HUD.New(MainX-280, MainY+252, "Targeting: ", 0, 0, 0)
  163. HUD.New(MainX-280, MainY+267, "Walker: ", 0, 0, 0)
  164. HUD.New(MainX-280, MainY+282, "Looter: ", 0, 0, 0)
  165. HUD.New(MainX-280, MainY+297, "Online For: ", 0, 0, 0)
  166. HUD.New(MainX-250, MainY+312, "Character Status", 0, 0, 0)
  167. HUD.New(MainX-280, MainY+327, "Ping: ", 0, 0, 0)
  168. HUD.New(MainX-280, MainY+342, "Health: ", 0, 0, 0)
  169. HUD.New(MainX-280, MainY+357, "Mana: ", 0, 0, 0)
  170. HUD.New(MainX-280, MainY+372, "Stamina: ", 0, 0, 0)
  171. HUD.New(MainX-280, MainY+387, "Capacity: ", 0, 0, 0)
  172. HUD.New(MainX-250, MainY+402, "Script Status", 0, 0, 0)
  173. HUD.New(MainX-280, MainY+417, "Currently Doing: ", 0, 0, 0)
  174. HUD.New(MainX-280, MainY+432, "Spawn Round: ", 0, 0, 0)
  175. HUD.New(MainX-250, MainY+447, "Profit Status", 0, 0, 0)
  176. HUD.New(MainX-279, MainY+462, "Profit:", 0, 0, 0)
  177. HUD.New(MainX-279, MainY+477, "Total Profit:", 0, 0, 0)
  178. HUD.New(MainX-250, MainY+492, "Supplies Status", 0, 0, 0)
  179. -- encabezados
  180. HUD.New(MainX-250, MainY+39, "Keep Dreaming", 255, 255, 255)
  181. HUD.New(MainX-250, MainY+145, "Modules Status", 255, 255, 255)
  182. HUD.New(MainX-250, MainY+235, "Bot Status", 255, 255, 255)
  183. HUD.New(MainX-250, MainY+310, "Character Status", 255, 255, 255)
  184. HUD.New(MainX-250, MainY+400, "Script Status", 255, 255, 255)
  185. HUD.New(MainX-250, MainY+445, "Profit Status", 255, 255, 255)
  186. HUD.New(MainX-250, MainY+490, "Supplies Status", 255, 255, 255)
  187. -- enunciados
  188. HUD.New(MainX-280, MainY+55, "Welcome: " .. Self.Name(), 255, 255, 255)
  189. HUD.New(MainX-280, MainY+70, "XenoBot " .. XenoBot.GetVersionInformation(), 255, 255, 255)
  190. HUD.New(MainX-280, MainY+85, "Current Level: ", 255, 255, 255)
  191. HUD.New(MainX-280, MainY+100, "Levels Gained: ", 255, 255, 255)
  192. HUD.New(MainX-280, MainY+115, "Experience Gained: ", 255, 255, 255)
  193. HUD.New(MainX-280, MainY+130, "Current Experience: ", 255, 255, 255)
  194. HUD.New(MainX-280, MainY+160, "Use Console: ", 255, 255, 255)
  195. HUD.New(MainX-280, MainY+175, "Force Refill: ", 255, 255, 255)
  196. HUD.New(MainX-280, MainY+190, "Refill Soft Boots: ", 255, 255, 255)
  197. HUD.New(MainX-280, MainY+205, "Withdraw Ammo: ", 255, 255, 255)
  198. HUD.New(MainX-280, MainY+220, "Withdraw Rings: ", 255, 255, 255)
  199. HUD.New(MainX-280, MainY+250, "Targeting: ", 255, 255, 255)
  200. HUD.New(MainX-280, MainY+265, "Walker: ", 255, 255, 255)
  201. HUD.New(MainX-280, MainY+280, "Looter: ", 255, 255, 255)
  202. HUD.New(MainX-280, MainY+295, "Online For: ", 255, 255, 255)
  203. HUD.New(MainX-280, MainY+325, "Ping: ", 255, 255, 255)
  204. HUD.New(MainX-280, MainY+340, "Health: ", 255, 255, 255)
  205. HUD.New(MainX-280, MainY+355, "Mana: ", 255, 255, 255)
  206. HUD.New(MainX-280, MainY+370, "Stamina: ", 255, 255, 255)
  207. HUD.New(MainX-280, MainY+385, "Capacity: ", 255, 255, 255)
  208. HUD.New(MainX-280, MainY+415, "Currently Doing: ", 255, 255, 255)
  209. HUD.New(MainX-280, MainY+430, "Spawn Round: ", 255, 255, 255)
  210. -- bot update calls
  211. Nivel = HUD.New(MainX-70, MainY+85, "999", 255, 255, 255)
  212. NivelesGanados = HUD.New(MainX-70, MainY+100, " ", 255, 255, 255)
  213. Experiencia = HUD.New(MainX-70, MainY+115, " ", 255, 255, 255)
  214. ExperienciaHora = HUD.New(MainX-70, MainY+130, " ", 255, 255, 255)
  215. UsarConsola = HUD.New(MainX-70, MainY+160, uConsole, 255, 255, 255)
  216. ForzarRefill = HUD.New(MainX-70, MainY+175, ForceRefill, 255, 255, 255)
  217. RefillearSofts = HUD.New(MainX-70, MainY+190, RefillSoft, 255, 255, 255)
  218. WithdrawAmmo = HUD.New(MainX-70, MainY+205, WithdrawAmmo, 255, 255, 255)
  219. WithdrawRings = HUD.New(MainX-70, MainY+220, WithdrawRings, 255, 255, 255)
  220. Targeting = HUD.New(MainX-70, MainY+250, "", 255, 255, 255)
  221. Walker = HUD.New(MainX-70, MainY+265, "", 255, 255, 255)
  222. Looter = HUD.New(MainX-70, MainY+280, "", 255, 255, 255)
  223. TiempoOnline = HUD.New(MainX-70, MainY+295, "", 255, 255, 255)
  224. PingHUD = HUD.New(MainX-70, MainY+325, "", 255, 255, 255)
  225. HUD.New(MainX-205, MainY+340, "lllllllllllllllllllllllllllllllllllllllllllllllllll" , 166, 166, 166)
  226. HUD.New(MainX-205, MainY+355, "lllllllllllllllllllllllllllllllllllllllllllllllllll" , 166, 166, 166)
  227. HUD.New(MainX-205, MainY+370, "lllllllllllllllllllllllllllllllllllllllllllllllllll" , 166, 166, 166)
  228. HpBar = HUD.New(MainX-205, MainY+340, "", 255, 255, 255)
  229. ManaBar = HUD.New(MainX-205, MainY+355, "", 255, 255, 255)
  230. StaminaBar = HUD.New(MainX-205, MainY+370, "Stamina: ", 255, 255, 255)
  231. HorasDeStamina = HUD.New(MainX-225, MainY+370, "", 255, 255, 255)
  232. Capacidad = HUD.New(MainX-70, MainY+385, "", 255, 255, 255)
  233. PorcientoVida = HUD.New(MainX-235, MainY+340, "", 255, 255, 255)
  234. HUD.New(MainX-50, MainY+340, "Max.", 255, 255, 255)
  235. HUD.New(MainX-50, MainY+355, "Max.", 255, 255, 255)
  236. HUD.New(MainX-50, MainY+370, "42:00", 255, 255, 255)
  237. PorcientoMana = HUD.New(MainX-235, MainY+355, "", 255, 255, 255)
  238. Currently = HUD.New(MainX-170, MainY+415, "Start Walker", 255, 255, 255)
  239. Round = HUD.New(MainX-70, MainY+430, "Spawn Round: ", 255, 255, 255)
  240. end
  241. InitHUD()
  242. Module("HUD", function(update)
  243. UpdateHUD()
  244. update:Delay(500)
  245. end)
  246. end
  247. Targeting_Check = Module.New('Targeting_Check', function (mod)
  248. Targeting:SetText("Enabled")
  249. if Targeting.IsEnabled() then
  250. Targeting:SetTextColor(0, 250, 0)
  251. else
  252. Targeting:SetText("Disabled")
  253. Targeting:SetTextColor(255, 0, 0)
  254. end
  255. end)
  256. Walker_Check = Module.New('Walker_Check', function(mod)
  257. Walker:SetText("Enabled")
  258. if Walker.IsEnabled() then
  259. Walker:SetTextColor(0, 250, 0)
  260. else
  261. Walker:SetText("Disabled")
  262. Walker:SetTextColor(255, 0, 0)
  263. end
  264. end)
  265. Looter_Check = Module.New('Looter_Check', function(mod)
  266. Looter:SetText("Enabled")
  267. if Looter.IsEnabled() then
  268. Looter:SetTextColor(0, 250, 0)
  269. else
  270. Looter:SetText("Disabled")
  271. Looter:SetTextColor(255, 0, 0)
  272. end
  273. end)
  274.  
  275. function Targeting.IsEnabled()
  276. return (getXenoBotStatus()["targeting"] == 1)
  277. end
  278. function Walker.IsEnabled()
  279. return (getXenoBotStatus()["walker"] == 1)
  280. end
  281. function Looter.IsEnabled()
  282. return (getXenoBotStatus()["looter"] == 1)
  283. end
  284. function Self.HPPC()
  285. return math.ceil((Self.Health() * 100 / Self.MaxHealth()))
  286. end
  287. function Self.MPPC()
  288. return math.ceil((Self.Mana() * 100 / Self.MaxMana()))
  289. end
  290. registerEventListener(WALKER_SELECTLABEL, 'onWalkerSelectLabel')
  291. function onWalkerSelectLabel(labelName)
  292. if (labelName == "Continue") then
  293. index = index + 1
  294. Currently:SetText("At spawn hunting")
  295. wait(500,900)
  296. elseif (labelName == "Backpacks") then
  297. Currently:SetText("Opening backpacks")
  298. elseif (labelName == "Potions_NPC") then
  299. Currently:SetText("Buying supplies")
  300. elseif (labelName == "Go_Hunt") then
  301. Currently:SetText("Going to spawn")
  302. elseif (labelName == "dBackpacks") then
  303. Currently:SetText("Depositing loot")
  304. elseif (labelName == "Bank_NPC") then
  305. Currently:SetText("Withdrawing money")
  306. elseif (labelName == "Leave") then
  307. Currently:SetText("Leaving spawn")
  308. end
  309. end
  310.  
  311. local supplies =
  312. {
  313. sName,
  314. ssName,
  315. tsName,
  316. }
  317. local location =
  318. {
  319. x = 0,
  320. y = 525
  321. }
  322. local colors =
  323. {
  324. label = {255, 255, 255},
  325. count = {255, 255, 255},
  326. title = {255, 255, 255}
  327. }
  328. local HUDITEMSDATA = {}
  329. for index, supply in ipairs(supplies) do
  330. local data = {}
  331. data.itemhuditemid = Item.GetItemIDFromDualInput(supply)
  332. data.itemhuditemlabel = HUD.CreateTextDisplay(
  333. location.x + 40,
  334. location.y + ((index - 1) * 20),
  335. supply,
  336. unpack(colors.label)
  337. )
  338. data.countitemhud = HUD.CreateTextDisplay(
  339. location.x + 215,
  340. location.y + ((index - 1) * 20) + 0,
  341. "",
  342. unpack(colors.count)
  343. )
  344. data.itemhudicon = HUD.CreateItemDisplay(
  345. location.x+10,
  346. location.y-10 + ((index - 1) * 20),
  347. data.itemhuditemid,
  348. 25,
  349. 100
  350. )
  351. HUDITEMSDATA[index] = data
  352. end
  353. Module.New("UpdateHuD", function(module)
  354. for index, data in ipairs(HUDITEMSDATA) do
  355. data.countitemhud:SetText(Self.ItemCount(data.itemhuditemid).." Left")
  356. end
  357. module:Delay(990)
  358. end)
  359. -- Parameters to the HUD that should not be visible to the regular user,
  360. -- but that the developer might want to change in the future
  361. HiddenConfig =
  362. {
  363. panelWidth = 200,
  364. timeTick = 1,
  365. yInset = 30,
  366. xDescWidth = 145,
  367. xTitleInset = 60,
  368. xHeaderInset = 80,
  369. xImageOffset = -25,
  370. yImageOffset = -5,
  371. yStandardHeight = 15,
  372. imageSize = 10,
  373. headerColor = {r=255, g=255, b=255},
  374. keyColor = {r=255, g=255, b=255},
  375. valColor = {r=255, g=255, b=255},
  376. goldChangeLimit = 300,
  377. stackableChangeLimit = 10,
  378. nonStackableChangeLimit = 3,
  379. WasteMod = 10000,
  380. }
  381.  
  382. Config = (function()
  383. local CustomPrices = {}
  384.  
  385. local function getMarketPrice(item)
  386. local id = Item.GetItemIDFromDualInput(item)
  387. return CustomPrices[id]
  388. end
  389.  
  390.  
  391. local function fileExists(name)
  392. local f = io.open(name)
  393. if not f then
  394. return false
  395. end
  396. f:close()
  397. return true
  398. end
  399.  
  400.  
  401. local configText = [[
  402. -- If you want to change item price do it here.
  403. CustomPrices = {
  404. ["Cluster of Solace"] = 50000,
  405. }]]
  406. local configName = "../Configs/MartinHUD.ini"
  407.  
  408. local function loadConfig()
  409. -- If the config file does not exist, create it
  410. if not fileExists(configName) then
  411. local f = io.open(configName, "w+")
  412. if f then
  413. f:write(configText)
  414. f:close()
  415. end
  416. end
  417.  
  418. dofile(configName)
  419.  
  420. for name, price in pairs(CustomPrices) do
  421. CustomPrices[Item.GetID(name)] = price
  422. end
  423. end
  424.  
  425. return
  426. {
  427. getMarketPrice = getMarketPrice,
  428. loadConfig = loadConfig,
  429. }
  430. end)()
  431.  
  432. Data = (function()
  433. local wornSoftID = 6530
  434. local activeSoftID = 3549
  435. local passiveSoftID = 6529
  436.  
  437. local durations =
  438. {
  439. [Item.GetID("Sword Ring")] = 30 * 60,
  440. [Item.GetID("Club Ring")] = 30 * 60,
  441. [Item.GetID("Axe Ring")] = 30 * 60,
  442. [Item.GetID("Energy Ring")] = 10 * 60,
  443. [Item.GetID("Stealth Ring")] = 10 * 60,
  444. [Item.GetID("Life Ring")] = 20 * 60,
  445. [Item.GetID("Ring of Healing")] = 7.5 * 60,
  446. [Item.GetID("Prismatic Ring")] = 60 * 60,
  447. [Item.GetID("Time Ring")] = 10 * 60,
  448. }
  449.  
  450. -- Translation map for getting the passive id from an active id
  451. local passiveIDs = {[activeSoftID] = passiveSoftID, [wornSoftID] = passiveSoftID}
  452. for passive, _ in pairs(durations) do
  453. passiveIDs[Item.GetRingActiveID(passive)] = passive
  454. end
  455.  
  456. -- Add the soft boots duration after doing the ring translations
  457. durations[passiveSoftID] = 4 * 60 * 60
  458.  
  459.  
  460. -- If we loot one of these items something fishy is going on, so invalidate the whole count.
  461. local invalidationIDs =
  462. {
  463. Item.GetID("shovel"),
  464. Item.GetID("light shovel"),
  465. Item.GetID("rope"),
  466. Item.GetID("elvenhair rope"),
  467. Item.GetID("fishing rod"),
  468. SoftID,
  469. WornSoftID,
  470. PassiveSoftID
  471. }
  472.  
  473. -- These are items whose count may decrease, and should then be counted as waste
  474. local supplies =
  475. {
  476. -- Arrows
  477. [Item.GetID("arrow")] = true,
  478. [Item.GetID("burst arrow")] = true,
  479. [Item.GetID("crystalline arrow")] = true,
  480. [Item.GetID("earth arrow")] = true,
  481. [Item.GetID("envenomed arrow")] = true,
  482. [Item.GetID("flaming arrow")] = true,
  483. [Item.GetID("flash arrow")] = true,
  484. [Item.GetID("onyx arrow")] = true,
  485. [Item.GetID("poison arrow")] = true,
  486. [Item.GetID("shiver arrow")] = true,
  487. [Item.GetID("simple arrow")] = true,
  488. [Item.GetID("sniper arrow")] = true,
  489. [Item.GetID("tarsal arrow")] = true,
  490.  
  491. -- Bolts
  492. [Item.GetID("bolt")] = true,
  493. [Item.GetID("drill bolt")] = true,
  494. [Item.GetID("infernal bolt")] = true,
  495. [Item.GetID("piercing bolt")] = true,
  496. [Item.GetID("power bolt")] = true,
  497. [Item.GetID("prismatic bolt")] = true,
  498. [Item.GetID("vortex bolt")] = true,
  499.  
  500. -- Throwing weapons
  501. [Item.GetID("enchanted spear")] = true,
  502. [Item.GetID("glooth spear")] = true,
  503. [Item.GetID("hunting spear")] = true,
  504. [Item.GetID("mean paladin spear")] = true,
  505. [Item.GetID("royal spear")] = true,
  506. [Item.GetID("spear")] = true,
  507. [Item.GetID("assassin star")] = true,
  508. [Item.GetID("snowball")] = true,
  509. [Item.GetID("small stone")] = true,
  510. [Item.GetID("throwing knife")] = true,
  511. [Item.GetID("throwing star")] = true,
  512. [Item.GetID("viper star")] = true,
  513.  
  514. -- Amulets
  515. [Item.GetID("gill necklace")] = true,
  516. [Item.GetID("prismatic necklace")] = true,
  517. [Item.GetID("protection amulet")] = true,
  518.  
  519. -- Misc
  520. [Item.GetID("scarab coin")] = true,
  521. }
  522.  
  523. local supplyPatterns =
  524. {
  525. "rune",
  526. "mana",
  527. "health",
  528. "spirit potion",
  529. }
  530.  
  531. local function isSupply(item)
  532. local name = Item.GetName(item):lower()
  533. local matchesSupplyPattern = false
  534. for _, pattern in ipairs(supplyPatterns) do
  535. matchesSupplyPattern = matchesSupplyPattern or name:match(pattern)
  536. end
  537.  
  538. local id = Item.GetItemIDFromDualInput(item)
  539. return matchesSupplyPattern or supplies[id]
  540. end
  541.  
  542.  
  543. function getCost(id)
  544. local shopCost = Item.GetCost(id)
  545. return id == passiveSoftID and 10000 or (shopCost == 0 and Config.getMarketPrice(id) or shopCost)
  546. end
  547.  
  548. function getValue(id)
  549. return Config.getMarketPrice(id) or (isSupply(id) and getCost(id)) or Item.GetValue(id)
  550. end
  551.  
  552.  
  553. return
  554. {
  555. wornSoftID = wornSoftID,
  556. activeSoftID = activeSoftID,
  557. passiveSoftID = passiveSoftID,
  558.  
  559. durations = durations,
  560. passiveIDs = passiveIDs,
  561. invalidationIDs = invalidationIDs,
  562.  
  563. isSupply = isSupply,
  564. getCost = getCost,
  565. getValue = getValue,
  566. }
  567. end)()
  568.  
  569. HUDData = (function()
  570. -- Initial data
  571. local startTime = os.time()
  572. local startExp = Self.Experience()
  573. local startStamina = Self.Stamina()
  574.  
  575. -- The data that will be visible to the rest of the HUD
  576. local data = { countsAreValid = true, general = { lastTick = os.time() } }
  577. -- The functions that update the data, in the order they will be called.
  578. local updateFunctions = {}
  579.  
  580. -- Helper functions and their accumulative data
  581. data.general.balance = 0
  582. NpcMessageProxy.OnReceive("Gets Bank Balance", function(proxy, npcName, message)
  583. local balance = string.match(message, "Your account balance is (.+) gold.")
  584. if balance and tonumber(balance) then
  585. data.general.balance = tonumber(balance)
  586. end
  587. end)
  588.  
  589. local function isEmptyFlask(id)
  590. return table.find({283, 284, 285}, id)
  591. end
  592.  
  593. local function ignoreItem(id)
  594. return id == 0 or isEmptyFlask(id) or Item.isContainer(id)
  595. end
  596.  
  597. local corpseNames = {"the", "demonic", "dead", "slain", "dissolved", "remains", "elemental", "split"}
  598. local function isCorpse(cont)
  599. if Item.isCorpse(cont:ID()) then return true end
  600. local name = cont:Name():lower()
  601. for _, CPartName in ipairs(corpseNames) do
  602. if name:find(CPartName) then
  603. return true
  604. end
  605. end
  606. return false
  607. end
  608.  
  609. local function countItems()
  610. newCounts = {}
  611.  
  612. veryUnsafeFunctionEnterCriticalMode()
  613.  
  614. -- Count equipped
  615. local slots = {Self.Head, Self.Armor, Self.Legs, Self.Amulet, Self.Feet, Self.Ring, Self.Weapon, Self.Shield, Self.Ammo}
  616. for i = 1, #slots do
  617. local slot = slots[i]()
  618.  
  619. if not ignoreItem(slot.id) then
  620. newCounts[slot.id] = (newCounts[slot.id] or 0) + math.max(slot.count, 1)
  621. end
  622. end
  623.  
  624. -- Count in backpacks
  625. for i = 0, 16 do
  626. local cont = Container(i)
  627. if cont:isOpen() and not isCorpse(cont) and cont:Name() ~= "Browse Field" then
  628. for spot = 0, cont:ItemCount() - 1 do
  629. local item = cont:GetItemData(spot)
  630. if not ignoreItem(item.id) then
  631. newCounts[item.id] = (newCounts[item.id] or 0) + item.count
  632. end
  633. end
  634. end
  635. end
  636.  
  637. veryUnsafeFunctionExitCriticalMode()
  638.  
  639. -- Handle changing ring and feet ids
  640. for activeID, passiveID in pairs(Data.passiveIDs) do
  641. newCounts[passiveID] = (newCounts[passiveID] or 0) + (newCounts[activeID] or 0)
  642. newCounts[activeID] = nil
  643. end
  644.  
  645. -- Handle worn soft boots
  646. newCounts[Data.passiveSoftID] = (newCounts[Data.passiveSoftID] or 0) + (newCounts[Data.wornSoftID] or 0)
  647.  
  648. return newCounts
  649. end
  650.  
  651. local function changeIsWithinLimits(id, change)
  652. if id == Item.GetID("gold coin") then
  653. return change < HiddenConfig.goldChangeLimit
  654. elseif Item.isStackable(id) then
  655. return change < HiddenConfig.stackableChangeLimit
  656. else
  657. return change < HiddenConfig.nonStackableChangeLimit
  658. end
  659. end
  660.  
  661. -- We only want to update the diff if it contains reasonable values
  662. local totalNewItemLimit = (Self.Level() < 100 and 5 or (Self.Level() < 200 and 7 or 9))
  663. local lastBpCount = 0
  664. local function validateDiff(diff, new)
  665. local totalNewCount = 0
  666. -- If we discovered too many of any one item we invalidate the diff
  667. for id, count in pairs(diff) do
  668. if (count > 0 and not changeIsWithinLimits(id, count)) or
  669. (count < 0 and Data.isSupply(id) and not changeIsWithinLimits(id, -1*count)) or
  670. (count < 0 and not Data.isSupply(id) and new[id] and not changeIsWithinLimits(id, new[id])) then
  671. return false
  672. end
  673. if count > 0 then
  674. totalNewCount = totalNewCount + (Item.isStackable(id) and 1 or count)
  675. elseif count < 0 and not Data.isSupply(id) then
  676. totalNewCount = totalNewCount + (Item.isStackable(id) and 1 or new[id] or 0)
  677. end
  678. end
  679. -- If we discovered too many new items in total we invalidate the diff
  680. if totalNewCount > totalNewItemLimit then
  681. return false
  682. end
  683. -- If we discovered a new tool we invalidate the diff
  684. for _, id in ipairs(Data.invalidationIDs) do
  685. local change = diff[id]
  686. if change and change ~= 0 then
  687. return false
  688. end
  689. end
  690.  
  691. local goldID = Item.GetID("gold coin")
  692. local platID = Item.GetID("platinum coin")
  693. -- If we're on an OT and lost gold or plats we invalidate the diff, because of gold changing
  694. if not XenoBot.IsInRealTibia() and
  695. ((diff[goldID] and diff[goldID] < 0) or
  696. (diff[platID] and diff[platID] < 0)) then
  697. return false
  698. end
  699.  
  700. -- If the number of open backpacks have changed we invalidate
  701. local bpCount = 0
  702. for i = 0, 16 do
  703. local cont = Container(i)
  704. if cont:isOpen() and not isCorpse(cont) and cont:Name() ~= "Browse Field" then
  705. bpCount = bpCount + 1
  706. end
  707. end
  708. if bpCount ~= lastBpCount then
  709. lastBpCount = bpCount
  710. return false
  711. end
  712.  
  713. -- Otherwise we're valid
  714. return true
  715. end
  716.  
  717. local function idOnScreen(ids)
  718. local myPos = Self.Position()
  719. for dx = -7, 7 do
  720. for dy = -5, 5 do
  721. local pos = {x = myPos.x + dx, y = myPos.y + dy, z = myPos.z}
  722. if table.find(ids, Map.GetTopUseItem(pos.x, pos.y, pos.z).id) then
  723. return true
  724. end
  725. end
  726. end
  727. return false
  728. end
  729.  
  730. local function trainerOnScreen()
  731. return idOnScreen({16201, 16198, 16202, 16199, 16200})
  732. end
  733.  
  734. local function depotOnScreen()
  735. return idOnScreen({3497, 3498, 3499, 3500})
  736. end
  737.  
  738. local function hasCloseNPC()
  739. for _, c in Creature.iNpcs() do
  740. if c:isOnScreen() then
  741. return true
  742. end
  743. end
  744. return false
  745. end
  746.  
  747. local lastTalkedToNPC = 0
  748. NpcMessageProxy:OnReceive("Spoke With NPC Detector", function(_)
  749. lastTalkedToNPC = os.time()
  750. end)
  751.  
  752. -- We don't want to update the diff while doing certain things
  753. -- that are normally done when refilling
  754. local function isRefilling()
  755. return (XenoBot.IsInRealTibia() and hasCloseNPC()) or
  756. os.difftime(os.time(), lastTalkedToNPC) < 10 or
  757. depotOnScreen() or
  758. trainerOnScreen()
  759. end
  760.  
  761. data.itemCounts = countItems()
  762. local function updateDiffs()
  763. local newCounts = countItems()
  764.  
  765. -- Calculate the diff
  766. local diff = {}
  767. for id, count in pairs(newCounts) do
  768. diff[id] = count
  769. end
  770.  
  771. for id, count in pairs(data.itemCounts) do
  772. diff[id] = (diff[id] or 0) - count
  773. end
  774.  
  775. for id, count in pairs(diff) do
  776. if diff[id] == 0 then
  777. diff[id] = nil
  778. end
  779. end
  780.  
  781. -- Store the new counts
  782. data.itemCounts = newCounts
  783.  
  784. -- Validate the diff
  785. data.countsAreValid = validateDiff(diff, data.itemCounts) and (not isRefilling())
  786.  
  787. -- Filter the diff into loot and waste
  788. local newLoot = {}
  789. local newWaste = {}
  790. for id, count in pairs(diff) do
  791. if count > 0 then
  792. newLoot[id] = count
  793. -- Do not accept count based waste of active items
  794. elseif Data.isSupply(id) then
  795. newWaste[id] = 0-count
  796. end
  797. end
  798.  
  799. -- Check for active items
  800. local slots = {Self.Head, Self.Armor, Self.Legs, Self.Feet, Self.Amulet, Self.Weapon, Self.Ring, Self.Shield, Self.Ammo}
  801. for i = 1, #slots do
  802. local slot = slots[i]()
  803. local passiveID = Data.passiveIDs[slot.id]
  804. if (passiveID and Data.durations[passiveID]) then
  805. -- The count for an active item is the time it was active for
  806. newWaste[passiveID] = os.time() - data.general.lastTick
  807. end
  808. end
  809. data.general.lastTick = os.time()
  810.  
  811. -- Store the filtered diffs
  812. data.newLoot = newLoot
  813. data.newWaste = newWaste
  814. end
  815. table.insert(updateFunctions, updateDiffs)
  816.  
  817. data.general.totalLoot = 0
  818. data.general.totalWaste = 0
  819. data.general.totalProfit = 0
  820. local function updateProfits()
  821. if data.countsAreValid then
  822. for id, num in pairs(data.newLoot) do
  823. data.general.totalLoot = data.general.totalLoot + Data.getValue(id) * num
  824. end
  825. for id, num in pairs(data.newWaste) do
  826. if Data.durations[id] then
  827. data.general.totalWaste = data.general.totalWaste + Data.getCost(id) * num / Data.durations[id]
  828. else
  829. data.general.totalWaste = data.general.totalWaste + Data.getCost(id) * num
  830. end
  831. end
  832. data.general.totalProfit = data.general.totalLoot - data.general.totalWaste
  833. end
  834. end
  835. table.insert(updateFunctions, updateProfits)
  836.  
  837. local function updateLevel()
  838. data.general.level = Self.Level()
  839. end
  840. table.insert(updateFunctions, updateLevel)
  841.  
  842. local function updateExp()
  843. data.general.gainedExp = Self.Experience() - startExp
  844. end
  845. table.insert(updateFunctions, updateExp)
  846.  
  847. local previously = os.time()
  848. data.general.usedSeconds = 1
  849. data.general.usedHours = 0
  850. local function updateTime()
  851. local now = os.time()
  852. local diff = now - previously
  853. -- If the time since the last tick was too long we've very likely been offline
  854. if diff < 30 then
  855. data.general.usedSeconds = data.general.usedSeconds + diff
  856. data.general.usedHours = data.general.usedSeconds / 3600
  857. end
  858. previously = now
  859. end
  860. table.insert(updateFunctions, updateTime)
  861.  
  862. local previousStamina = Self.Stamina()
  863. data.general.usedStaminaMinutes = 0
  864. data.general.usedStaminaHours = 0
  865. local function updateStamina()
  866. local current = Self.Stamina()
  867. data.general.stamina = current
  868. local diff = current - previousStamina
  869. -- Stamina cannot increase while we are online, and
  870. -- we dont want being offlane to corrupt the stats
  871. if diff >= 0 then
  872. data.general.usedStaminaMinutes = data.general.usedStaminaMinutes + diff
  873. data.general.usedStaminaHours = data.general.usedStaminaMinutes / 60
  874. end
  875. previousStamina = current
  876. end
  877. table.insert(updateFunctions, updateStamina)
  878.  
  879. local function updateRates()
  880. data.general.expS = data.general.gainedExp / data.general.usedSeconds
  881. data.general.expH = data.general.gainedExp / data.general.usedHours
  882. data.general.expSH = data.general.usedStaminaHours < 0.017 and data.general.expH or data.general.gainedExp / data.general.usedStaminaHours
  883.  
  884. data.general.profitsH = data.general.totalProfit / data.general.usedHours
  885. data.general.profitsSH = data.general.usedStaminaHours < 0.017 and data.general.profitsH or data.general.totalProfit / data.general.usedStaminaHours
  886. end
  887. table.insert(updateFunctions, updateRates)
  888.  
  889. local function expForLevel(x)
  890. return 50/3*(x*x*x - 6*x*x + 17*x - 12)
  891. end
  892.  
  893. local function updateTimeToLevel()
  894. local nextLevelExp = expForLevel(Self.Level() + 1)
  895. local missingExp = nextLevelExp - Self.Experience()
  896. data.general.timeToLevel = data.general.expS == 0 and -1 or math.floor(missingExp / data.general.expS)
  897. end
  898. table.insert(updateFunctions, updateTimeToLevel)
  899.  
  900. data.general.ping = 0
  901. local function updatePing()
  902. data.general.ping = Self.Ping()
  903. end
  904. table.insert(updateFunctions, updatePing)
  905.  
  906. local function getStats()
  907. for _, f in ipairs(updateFunctions) do
  908. f()
  909. end
  910. return data
  911. end
  912.  
  913. return
  914. {
  915. getStats = getStats,
  916. }
  917. end)()
  918.  
  919. Events = (function()
  920.  
  921. local topics = {}
  922.  
  923. local function subscribe(topic, callback)
  924. local subs = topics[topic] or {}
  925. table.insert(subs, callback)
  926. topics[topic] = subs
  927. end
  928.  
  929. local function publish(topic, data)
  930. local subs = topics[topic] or {}
  931. for _, callback in ipairs(subs) do
  932. callback(data)
  933. end
  934. end
  935.  
  936. local function keyset(tab)
  937. local set = {}
  938. for key, _ in pairs(tab) do
  939. table.insert(set, key)
  940. end
  941. return set
  942. end
  943.  
  944. Module("Update HUD", function(module)
  945. local stats = HUDData.getStats()
  946.  
  947. -- Notify general subscribers
  948. publish("general", stats.general)
  949.  
  950. -- Only notify count based subscribers when the counts are valid
  951. if stats.countsAreValid then
  952. -- Notify about new possible new ids
  953. local newLootIDs = keyset(stats.newLoot)
  954. publish("newLootIDs", newLootIDs)
  955. local newWasteIDs = keyset(stats.newWaste)
  956. publish("newWasteIDs", newWasteIDs)
  957.  
  958. -- Notify about new counts
  959. for id, count in pairs(stats.newLoot) do
  960. publish(id, count)
  961. end
  962.  
  963. for id, count in pairs(stats.newWaste) do
  964. publish(id + HiddenConfig.WasteMod, count)
  965. end
  966. end
  967.  
  968. module:Delay(1000)
  969. end)
  970.  
  971. -- Let main scripts stop the HUD when they logout.
  972. Signal.OnReceive("Stop HUD", function(_, Msg)
  973. if Msg == "Stop" then
  974. Module.Stop("Update HUD")
  975. end
  976. end)
  977.  
  978. return
  979. {
  980. publish = publish,
  981. subscribe = subscribe,
  982. }
  983. end)()
  984.  
  985.  
  986. -- HUDContainer is an abstract super class
  987. HUDContainer = {}
  988. HUDContainer_mt = {__index = HUDContainer}
  989.  
  990. function HUDContainer:move(newx, newy)
  991. self.y = newy
  992. self.x = newx
  993. for inset, hud in pairs(self.huds) do
  994. hud:SetPosition(self.x + inset, self.y)
  995. end
  996. end
  997.  
  998. function HUDContainer:moveRelative(diffx, diffy)
  999. self:move(self.x + diffx, self.y + diffy)
  1000. end
  1001.  
  1002. HeaderHUDContainer = {}
  1003. HeaderHUDContainer_mt = {__index = HeaderHUDContainer}
  1004.  
  1005. function HeaderHUDContainer.new(title, parent, inset)
  1006. local c = {}
  1007. setmetatable(c, HeaderHUDContainer_mt)
  1008.  
  1009. c.x = 0
  1010. c.y = 0
  1011. c.height = HiddenConfig.yStandardHeight
  1012.  
  1013. c.huds = {}
  1014.  
  1015. local inset = inset or HiddenConfig.xHeaderInset
  1016.  
  1017. c.headerHUD = HUD.New(c.x + inset, c.y, title, HiddenConfig.headerColor.r, HiddenConfig.headerColor.g, HiddenConfig.headerColor.b)
  1018. c.huds[inset] = c.headerHUD
  1019.  
  1020. parent:addChild(c)
  1021.  
  1022. return c
  1023. end
  1024.  
  1025. setmetatable(HeaderHUDContainer, { __index = HUDContainer, __call = function(_, ...) return HeaderHUDContainer.new(...) end })
  1026.  
  1027. EmptyHUDContainer = {}
  1028. EmptyHUDContainer_mt = {__index = EmptyHUDContainer}
  1029.  
  1030. function EmptyHUDContainer.new(parent, height)
  1031. local c = {}
  1032. setmetatable(c, EmptyHUDContainer_mt)
  1033.  
  1034. c.x = 0
  1035. c.y = 0
  1036. c.height = height or HiddenConfig.yStandardHeight
  1037.  
  1038. c.huds = {}
  1039.  
  1040. parent:addChild(c)
  1041.  
  1042. return c
  1043. end
  1044.  
  1045. setmetatable(EmptyHUDContainer, { __index = HUDContainer, __call = function(_, ...) return EmptyHUDContainer.new(...) end })
  1046.  
  1047. KeyValHUDContainer = {}
  1048. KeyValHUDContainer_mt = {__index = KeyValHUDContainer}
  1049.  
  1050. function KeyValHUDContainer.new(desc, parent)
  1051. local c = {}
  1052. setmetatable(c, KeyValHUDContainer_mt)
  1053.  
  1054. c.x = 0
  1055. c.y = 0
  1056. c.height = HiddenConfig.yStandardHeight
  1057. c.accum = 0
  1058.  
  1059. c.huds = {}
  1060.  
  1061. c.keyHUD = HUD.New(c.x , c.y, desc, HiddenConfig.keyColor.r, HiddenConfig.keyColor.g, HiddenConfig.keyColor.b)
  1062. c.huds[0] = c.keyHUD
  1063. c.valHUD = HUD.New(c.x + HiddenConfig.xDescWidth, c.y, "", HiddenConfig.valColor.r, HiddenConfig.valColor.g, HiddenConfig.valColor.b)
  1064. c.huds[HiddenConfig.xDescWidth] = c.valHUD
  1065.  
  1066. parent:addChild(c)
  1067.  
  1068. return c
  1069. end
  1070.  
  1071. setmetatable(KeyValHUDContainer, {__index = HUDContainer, __call = function(_, ...) return KeyValHUDContainer.new(...) end})
  1072.  
  1073. function KeyValHUDContainer:setValText(newText)
  1074. self.valHUD:SetText(newText)
  1075. end
  1076.  
  1077. function KeyValHUDContainer:incAccum(val)
  1078. self.accum = self.accum + val
  1079. end
  1080.  
  1081. function KeyValHUDContainer:getAccum(newText)
  1082. return self.accum
  1083. end
  1084.  
  1085. ContainerContainer = {}
  1086. ContainerContainer_mt = {__index = ContainerContainer}
  1087.  
  1088. function ContainerContainer.new(x, y, parent)
  1089. local c = {}
  1090. setmetatable(c, ContainerContainer_mt)
  1091.  
  1092. c.id = -1 -- To be set by the parent
  1093. c.x = x
  1094. c.y = y
  1095. c.height = 0
  1096. c.parent = parent
  1097. -- Only used by those containers that contain item huds
  1098. c.containedItemIDs = {}
  1099.  
  1100. c.children = {}
  1101. c.nextChildID = 1
  1102.  
  1103. if parent then
  1104. parent:addChild(c)
  1105. end
  1106.  
  1107. return c
  1108. end
  1109. setmetatable(ContainerContainer, {__call = function(_, ...) return ContainerContainer.new(...) end})
  1110.  
  1111. function ContainerContainer:addChild(child)
  1112. child.id = self.nextChildID
  1113. self.nextChildID = self.nextChildID + 1
  1114. table.insert(self.children, child)
  1115. child:move(self.x, self.y + self.height)
  1116. self:grow(child.height)
  1117. end
  1118.  
  1119. function ContainerContainer:grow(diffy)
  1120. self.height = self.height + diffy
  1121. if self.parent then
  1122. for id = self.id + 1, self.parent.nextChildID - 1 do
  1123. self.parent.children[id]:moveRelative(0, diffy)
  1124. end
  1125. self.parent:grow(diffy)
  1126. end
  1127. end
  1128.  
  1129. function ContainerContainer:moveRelative(x, y)
  1130. for _, child in ipairs(self.children) do
  1131. child:moveRelative(x, y)
  1132. end
  1133. self.x = self.x + x
  1134. self.y = self.y + y
  1135. end
  1136.  
  1137. function ContainerContainer:move(x, y)
  1138. local diffx = x - self.x
  1139. local diffy = y - self.y
  1140. self:moveRelative(diffx, diffy)
  1141. end
  1142.  
  1143. ItemHUDContainer = {}
  1144. ItemHUDContainer_mt = {__index = ItemHUDContainer}
  1145.  
  1146. function ItemHUDContainer.new(id, parent, formatFunc)
  1147. local c = {}
  1148. setmetatable(c, ItemHUDContainer_mt)
  1149.  
  1150. c.formatFunc = formatFunc
  1151. c.x = 0
  1152. c.y = 0
  1153. c.itemID = id
  1154. c.height = HiddenConfig.yStandardHeight
  1155. c.accum = 0
  1156.  
  1157. c.imageHUD = HUD.New(c.x - HiddenConfig.xImageOffset, c.y + HiddenConfig.yImageOffset, id, 0, 0, 0)
  1158. c.imageHUD:SetItemSize(HiddenConfig.imageSize)
  1159. c.keyHUD = HUD.New(c.x , c.y, Item.GetName(id), HiddenConfig.keyColor.r, HiddenConfig.keyColor.g, HiddenConfig.keyColor.b)
  1160. c.valHUD = HUD.New(c.x + HiddenConfig.xDescWidth, c.y, "", HiddenConfig.valColor.r, HiddenConfig.valColor.g, HiddenConfig.valColor.b)
  1161. c:addCount(0)
  1162. parent:addChild(c)
  1163.  
  1164. return c
  1165. end
  1166.  
  1167. setmetatable(ItemHUDContainer, {__index = HUDContainer, __call = function(_, ...) return ItemHUDContainer.new(...) end})
  1168.  
  1169. function ItemHUDContainer:addCount(num)
  1170. self.accum = self.accum + num
  1171. self.valHUD:SetText(self.formatFunc(self.itemID, self.accum))
  1172. end
  1173.  
  1174. function ItemHUDContainer:move(newx, newy)
  1175. self.y = newy
  1176. self.x = newx
  1177. self.imageHUD:SetPosition(self.x + HiddenConfig.xImageOffset, self.y + HiddenConfig.yImageOffset)
  1178. self.keyHUD:SetPosition(self.x, self.y)
  1179. self.valHUD:SetPosition(self.x + HiddenConfig.xDescWidth, self.y)
  1180. end
  1181.  
  1182. function ItemHUDContainer:moveRelative(diffx, diffy)
  1183. self:move(self.x + diffx, self.y + diffy)
  1184. end
  1185.  
  1186. local function lootFormatFunc(id, count)
  1187. return string.format("%d", count, count * Data.getValue(id))
  1188. end
  1189.  
  1190. local function wasteFormatFunc(id, count)
  1191. return string.format("%d", count, count * Data.getCost(id))
  1192. end
  1193.  
  1194. local function activeWasteFormatFunc(id, count)
  1195. local hour = math.floor(count / 3600)
  1196. local min = math.floor((count / 60) % 60)
  1197. local sec = math.floor(count % 60)
  1198. return string.format("%02.f:%02.f:%02.f", hour, min, sec, count * Data.getCost(id) / Data.durations[id])
  1199. end
  1200.  
  1201. function LootItemHUDContainer(id, parent)
  1202. local c = ItemHUDContainer(id, parent, lootFormatFunc)
  1203. Events.subscribe(id, function(diff)
  1204. c:addCount(diff)
  1205. end)
  1206. return c
  1207. end
  1208.  
  1209. function WasteItemHUDContainer(id, parent)
  1210. local c = ItemHUDContainer(id, parent, wasteFormatFunc)
  1211. Events.subscribe(id + HiddenConfig.WasteMod, function(diff)
  1212. c:addCount(diff)
  1213. end)
  1214. return c
  1215. end
  1216.  
  1217. function ActiveWasteItemHUDContainer(id, parent)
  1218. local c = ItemHUDContainer(id, parent, activeWasteFormatFunc)
  1219. Events.subscribe(id + HiddenConfig.WasteMod, function(diff)
  1220. c:addCount(diff)
  1221. end)
  1222. return c
  1223. end
  1224.  
  1225. Config.loadConfig()
  1226.  
  1227. local function formatGain(total)
  1228. if total > 1e+6 then
  1229. return string.format("%.01fkk", total/1e+6)
  1230. elseif total > 1e+3 then
  1231. return string.format("%.01fk", total/1e+3)
  1232. else
  1233. return tostring(math.floor(total))
  1234. end
  1235. end
  1236.  
  1237. local screen = HUD.GetMainWindowDimensions()
  1238. local leftx = 0
  1239. local rightx = 0
  1240.  
  1241. -- Create the left column of the HUD
  1242. local leftColumn = ContainerContainer(leftx-30, HiddenConfig.yInset+445)
  1243. local leftColumn2 = ContainerContainer(leftx+10, HiddenConfig.yInset+445)
  1244. local leftColumn3 = ContainerContainer(leftx+10, HiddenConfig.yInset+460)
  1245. local leftColumn4 = ContainerContainer(leftx+70, HiddenConfig.yInset+460)
  1246. local leftColumn5 = ContainerContainer(leftx+70, HiddenConfig.yInset+445)
  1247.  
  1248.  
  1249. -- Profit gain
  1250. EmptyHUDContainer(leftColumn)
  1251. local profitsPerH = KeyValHUDContainer("Profit:", leftColumn2)
  1252. local profitsPerSH = KeyValHUDContainer("", leftColumn5)
  1253. Events.subscribe("general", function(general)
  1254. local profitsSHK = general.profitsSH / 1000
  1255. profitsPerSH:setValText(string.format("%.01f k/h", profitsSHK))
  1256. end)
  1257.  
  1258. -- Totals
  1259. EmptyHUDContainer(leftColumn)
  1260. local expTotal = KeyValHUDContainer("Total Profit:", leftColumn3)
  1261. local profitsTotal = KeyValHUDContainer("", leftColumn4)
  1262. Events.subscribe("general", function(general)
  1263. profitsTotal:setValText(string.format("%s gp", formatGain(general.totalProfit)))
  1264. end)
  1265.  
  1266. -- Right Column
  1267. local rightColumn = ContainerContainer(rightx, HiddenConfig.yInset)
  1268. local rightColumn2 = ContainerContainer(rightx+1500, HiddenConfig.yInset)
  1269. local rightColumn3 = ContainerContainer(rightx+1420, HiddenConfig.yInset-20)
  1270. local loot = ContainerContainer(0, 0, rightColumn2)
  1271. local loot2 = ContainerContainer(0, 0, rightColumn3)
  1272. local waste = ContainerContainer(0, 0, rightColumn2)
  1273.  
  1274. -- Waste
  1275. EmptyHUDContainer(waste)
  1276. local wasteHeader = HeaderHUDContainer("Supplies Used", waste)
  1277. EmptyHUDContainer(waste, 10)
  1278.  
  1279. local wasteParts = ContainerContainer(0, 0, waste)
  1280. Events.subscribe("newWasteIDs", function(newids)
  1281. for _, id in ipairs(newids) do
  1282. if not wasteParts.containedItemIDs[id] then
  1283. if Data.durations[id] then
  1284. ActiveWasteItemHUDContainer(id, wasteParts)
  1285. else
  1286. WasteItemHUDContainer(id, wasteParts)
  1287. end
  1288. wasteParts.containedItemIDs[id] = true
  1289. end
  1290. end
  1291. end)
  1292.  
  1293. local wasteSum = ContainerContainer(0, 0, waste)
  1294. EmptyHUDContainer(wasteSum)
  1295. local totalWaste = KeyValHUDContainer("Total Wasted:", wasteSum)
  1296. Events.subscribe("general", function(general)
  1297. totalWaste:setValText(string.format("%d gp", general.totalWaste))
  1298. end)
  1299.  
  1300. -- Loot
  1301. local lootHeader = HeaderHUDContainer("Looted Items - Amount", loot2)
  1302. EmptyHUDContainer(waste, 10)
  1303.  
  1304. local lootParts = ContainerContainer(0, 0, loot)
  1305. Events.subscribe("newLootIDs", function(newids)
  1306. for _, id in ipairs(newids) do
  1307. if not lootParts.containedItemIDs[id] then
  1308. LootItemHUDContainer(id, lootParts)
  1309. lootParts.containedItemIDs[id] = true
  1310. end
  1311. end
  1312. end)
  1313.  
  1314. local lootSum = ContainerContainer(0, 0, loot)
  1315. EmptyHUDContainer(lootSum)
  1316. local totalLoot = KeyValHUDContainer("Total Looted:", lootSum)
  1317. Events.subscribe("general", function(general)
  1318. totalLoot:setValText(string.format("%d gp", general.totalLoot))
  1319. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement