FeyMen

MAGAZ

Jan 17th, 2025 (edited)
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 27.17 KB | None | 0 0
  1. --------------------------------------------------------------------------------
  2. -- shop_final.lua
  3. -- Итоговый интерфейс:
  4. --  1) Левая панель "Действия": только кнопки «Внести деньги», «Внести железо».
  5. --  2) Ниже (в той же левой рамке) — "Забрать" c двумя кнопками "Забрать деньги"
  6. --     / "Забрать железо" и двумя полями ввода числовых значений.
  7. --  3) Справа: сверху список товаров, под списком — панель "Покупка", под ней —
  8. --     поле "Поиск:".
  9. --  4) При клике на товар строка подсвечивается (highlight).
  10. --  5) Исправлен поиск и прокрутка, добавлено больше товаров.
  11. --------------------------------------------------------------------------------
  12.  
  13. local component = require("component")
  14. local event     = require("event")
  15. local term      = require("term")
  16. local unicode   = require("unicode")
  17. local gpu       = component.gpu
  18.  
  19. --------------------------------------------------------------------------------
  20. -- 1) Проверка PIM
  21. --------------------------------------------------------------------------------
  22. if not component.isAvailable("pim") then
  23.   error("Ошибка: PIM не найден! Подключите PIM к компьютеру.")
  24. end
  25. local pim = component.pim
  26.  
  27. --------------------------------------------------------------------------------
  28. -- ПАРАМЕТРЫ ЭКРАНА / ЦВЕТА
  29. --------------------------------------------------------------------------------
  30. local screenWidth, screenHeight = gpu.maxResolution()
  31. gpu.setResolution(screenWidth, screenHeight)
  32.  
  33. local colors = {
  34.   background      = 0x000000,
  35.   text            = 0xFFFFFF,
  36.   frame           = 0xAAAAAA,
  37.   titleBar        = 0x002244,
  38.   inputField      = 0x333333, -- поля ввода
  39.   button          = 0x444444,
  40.   buttonText      = 0xFFFFFF,
  41.   buttonInactive  = 0x555555,
  42.   warn            = 0xFF0000,
  43.   success         = 0x00FF00,
  44.   highlight       = 0x4444FF, -- подсветка выбранной строки
  45. }
  46.  
  47. local headerHeight = 3
  48. local footerHeight = 3
  49.  
  50. --------------------------------------------------------------------------------
  51. -- 2) "БД" игроков: name -> { balanceEmerald, balanceIron }
  52. --------------------------------------------------------------------------------
  53. local userData = {}
  54. local function getUserData(name)
  55.   if not userData[name] then
  56.     userData[name] = { balanceEmerald=0, balanceIron=0 }
  57.   end
  58.   return userData[name]
  59. end
  60.  
  61. --------------------------------------------------------------------------------
  62. -- 3) Текущий авторизованный игрок
  63. --------------------------------------------------------------------------------
  64. local currentPlayerName = nil
  65. local playerOnPIM       = false
  66.  
  67. --------------------------------------------------------------------------------
  68. -- 4) Список товаров (много)
  69. --------------------------------------------------------------------------------
  70. local allItems = {
  71.   { name="minecraft:stone",       display="Камень",   quantity=50, priceEmerald=2,  priceIron=1 },
  72.   { name="minecraft:diamond",     display="Алмаз",    quantity=5,  priceEmerald=50, priceIron=10},
  73.   { name="minecraft:dirt",        display="Земля",    quantity=20, priceEmerald=1,  priceIron=1 },
  74.   { name="minecraft:iron_ingot",  display="Железо",   quantity=30, priceEmerald=5,  priceIron=2 },
  75. }
  76. -- Добавим побольше
  77. for i=1,60 do
  78.   table.insert(allItems, {
  79.     name        = "minecraft:extra"..i,
  80.     display     = "ТоварExtra"..i,
  81.     quantity    = math.random(1,99),
  82.     priceEmerald= math.random(1,50),
  83.     priceIron   = math.random(0,20),
  84.   })
  85. end
  86.  
  87. --------------------------------------------------------------------------------
  88. -- Данные для интерфейса
  89. --------------------------------------------------------------------------------
  90. local filteredItems = {}        -- после поиска
  91. local scrollOffset  = 0         -- для прокрутки
  92. local searchText    = ""        -- поле поиска
  93. local searchFocus   = false     -- есть ли фокус?
  94. local searchCursorVisible= true
  95. local lastCursorBlink= 0
  96. local cursorBlinkInterval= 0.5
  97.  
  98. -- Buy panel
  99. local buySelectedIndex= nil  -- какой товар выбран (idx в filteredItems)
  100. local buyQuantity     = ""
  101. local payWithEmerald  = true
  102. local buyMessage      = ""
  103.  
  104. -- ПОЛЯ ввода "Забрать деньги" / "Забрать железо" (в левой панели)
  105. local withdrawMoneyInput = ""  -- только цифры
  106. local withdrawIronInput  = ""
  107.  
  108. --------------------------------------------------------------------------------
  109. -- РАЗМЕТКА
  110. --------------------------------------------------------------------------------
  111. local actionsX, actionsY = 2, headerHeight+1
  112. local actionsW           = 22
  113. local actionsH           = screenHeight- headerHeight- footerHeight -1
  114.  
  115. local itemsX= actionsX+ actionsW+1
  116. local itemsY= headerHeight+1
  117. local itemsW= screenWidth- (actionsW+3)
  118. local itemsH= screenHeight- headerHeight- footerHeight -1
  119.  
  120. -- Высота "Buy panel" пусть будет 4 строк.
  121. local buyPanelHeight= 4
  122. -- Высота "поиск" пусть 2 строки
  123. local searchBarHeight= 2
  124.  
  125. -- Итого на список остаётся (itemsH - buyPanelHeight - searchBarHeight).
  126. -- Колонки
  127. local colNameW, colQtyW, colEmerW, colIronW= 0,0,0,0
  128.  
  129. --------------------------------------------------------------------------------
  130. -- 5) ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ (шапка/подвал)
  131. --------------------------------------------------------------------------------
  132. local function clearScreen()
  133.   gpu.setBackground(colors.background)
  134.   gpu.setForeground(colors.text)
  135.   term.clear()
  136. end
  137.  
  138. local function drawHeader()
  139.   gpu.setBackground(colors.titleBar)
  140.   gpu.setForeground(colors.text)
  141.   for y=1, headerHeight do
  142.     gpu.fill(1, y, screenWidth, 1, " ")
  143.   end
  144.   local title= "[ PIM SHOP ]"
  145.   local tx= math.floor((screenWidth- unicode.len(title))/2)
  146.   gpu.set(tx,2, title)
  147.  
  148.   if playerOnPIM and currentPlayerName then
  149.     local ud= getUserData(currentPlayerName)
  150.     local info= string.format("Игрок: %s | Баланс: %d Эм / %d Жел",
  151.       currentPlayerName, ud.balanceEmerald, ud.balanceIron)
  152.     gpu.set(2,2, info)
  153.   else
  154.     gpu.set(2,2, "Не авторизовано (Встаньте на PIM)!")
  155.   end
  156. end
  157.  
  158. local function drawFooter()
  159.   gpu.setBackground(colors.titleBar)
  160.   gpu.setForeground(colors.text)
  161.   for y= screenHeight- footerHeight+1, screenHeight do
  162.     gpu.fill(1, y, screenWidth,1," ")
  163.   end
  164.   local footText= "[ OpenOS - PIM Shop ]"
  165.   local fx= math.floor((screenWidth- unicode.len(footText))/2)
  166.   gpu.set(fx, screenHeight, footText)
  167. end
  168.  
  169. local function drawFrame(x,y,w,h, title)
  170.   gpu.setForeground(colors.frame)
  171.   gpu.setBackground(colors.background)
  172.   gpu.set(x,y,"┌")
  173.   gpu.set(x+w-1,y,"┐")
  174.   gpu.set(x,y+h-1,"└")
  175.   gpu.set(x+w-1,y+h-1,"┘")
  176.   for i=x+1, x+w-2 do
  177.     gpu.set(i,y,"─")
  178.     gpu.set(i,y+h-1,"─")
  179.   end
  180.   for j=y+1, y+h-2 do
  181.     gpu.set(x,j,"│")
  182.     gpu.set(x+w-1,j,"│")
  183.   end
  184.   if title then
  185.     local tx= x+ math.floor((w- unicode.len(title))/2)
  186.     gpu.set(tx,y, title)
  187.   end
  188. end
  189.  
  190. --------------------------------------------------------------------------------
  191. -- 6) ЛЕВАЯ ПАНЕЛЬ "ДЕЙСТВИЯ"
  192. --------------------------------------------------------------------------------
  193. local function drawLeftPanel()
  194.   drawFrame(actionsX, actionsY, actionsW, actionsH, " Действия ")
  195.  
  196.   -- Верхний блок: "Внести деньги" / "Внести железо"
  197.   local marginX= actionsX+2
  198.   local marginY= actionsY+1
  199.  
  200.   gpu.setBackground(colors.background)
  201.   gpu.setForeground(colors.warn)
  202.   gpu.set(marginX, marginY,   "Для пополнения:")
  203.   gpu.set(marginX, marginY+1, "Нажмите кнопку!")
  204.   gpu.set(marginX, marginY+2, "Будут забраны")
  205.   gpu.set(marginX, marginY+3, "все деньги/железо")
  206.  
  207.   -- Кнопка "Внести деньги"
  208.   local btnW= actionsW-4
  209.   local btnH= 3
  210.   local btnY1= marginY+5
  211.   gpu.setBackground(colors.button)
  212.   for ry=0, btnH-1 do
  213.     gpu.fill(marginX, btnY1+ ry, btnW,1," ")
  214.   end
  215.   local label1= "Внести деньги"
  216.   local cx1= marginX+ math.floor((btnW- unicode.len(label1))/2)
  217.   local cy1= btnY1+ math.floor(btnH/2)
  218.   gpu.setForeground(colors.buttonText)
  219.   gpu.set(cx1, cy1, label1)
  220.  
  221.   -- Кнопка "Внести железо"
  222.   local btnY2= btnY1+ btnH+1
  223.   gpu.setBackground(colors.button)
  224.   for ry=0, btnH-1 do
  225.     gpu.fill(marginX, btnY2+ ry, btnW,1," ")
  226.   end
  227.   local label2= "Внести железо"
  228.   local cx2= marginX+ math.floor((btnW- unicode.len(label2))/2)
  229.   local cy2= btnY2+ math.floor(btnH/2)
  230.   gpu.setForeground(colors.buttonText)
  231.   gpu.set(cx2, cy2, label2)
  232.  
  233.   -- Нижний блок: "Забрать" (2 кнопки + 2 поля ввода)
  234.   local boxY= btnY2+ btnH+1
  235.   local boxH= 10
  236.   drawFrame(marginX, boxY, btnW, boxH, " Забрать ")
  237.  
  238.   local inX= marginX+1
  239.   local inY= boxY+1
  240.   local inW= btnW-2
  241.   local lineDist=3
  242.  
  243.   gpu.setBackground(colors.background)
  244.   gpu.setForeground(colors.text)
  245.   -- 1) "Забрать деньги" (кнопка)
  246.   gpu.setBackground(colors.button)
  247.   gpu.fill(inX, inY, inW,1, " ")
  248.   local lblZ1= "Забрать деньги"
  249.   local cz1= inX+ math.floor((inW- unicode.len(lblZ1))/2)
  250.   gpu.setForeground(colors.buttonText)
  251.   gpu.set(cz1, inY, lblZ1)
  252.  
  253.   -- Под этой кнопкой: поле ввода withdrawMoneyInput
  254.   local inputY1= inY+1
  255.   gpu.setBackground(colors.inputField)
  256.   gpu.fill(inX, inputY1, inW,1," ")
  257.   gpu.setForeground(colors.text)
  258.   local showWD= withdrawMoneyInput
  259.   if unicode.len(showWD)> inW then
  260.     showWD= unicode.sub(showWD, unicode.len(showWD)- inW+1)
  261.   end
  262.   gpu.set(inX, inputY1, showWD)
  263.  
  264.   -- 2) "Забрать железо" (кнопка)
  265.   local yz2= inputY1+2
  266.   gpu.setBackground(colors.button)
  267.   gpu.fill(inX, yz2, inW,1, " ")
  268.   local lblZ2= "Забрать железо"
  269.   local cz2= inX+ math.floor((inW- unicode.len(lblZ2))/2)
  270.   gpu.setForeground(colors.buttonText)
  271.   gpu.set(cz2, yz2, lblZ2)
  272.  
  273.   -- Под кнопкой: поле ввода withdrawIronInput
  274.   local inputY2= yz2+1
  275.   gpu.setBackground(colors.inputField)
  276.   gpu.fill(inX, inputY2, inW,1," ")
  277.   gpu.setForeground(colors.text)
  278.   local showWI= withdrawIronInput
  279.   if unicode.len(showWI)> inW then
  280.     showWI= unicode.sub(showWI, unicode.len(showWI)- inW+1)
  281.   end
  282.   gpu.set(inX, inputY2, showWI)
  283. end
  284.  
  285. --------------------------------------------------------------------------------
  286. -- 7) СПИСОК ТОВАРОВ (Верхняя часть справа)
  287. --------------------------------------------------------------------------------
  288. local function calcColumns(availableWidth)
  289.   local nameW= math.floor(availableWidth*0.4)
  290.   local qtyW = math.floor(availableWidth*0.15)
  291.   local emeW = math.floor(availableWidth*0.15)
  292.   local iroW = availableWidth- nameW- qtyW- emeW
  293.   if nameW<8 then nameW=8 end
  294.   if qtyW<6 then qtyW=6 end
  295.   if emeW<5 then emeW=5 end
  296.   if iroW<5 then iroW=5 end
  297.   return nameW, qtyW, emeW, iroW
  298. end
  299.  
  300. local function cutPad(str,wid)
  301.   local n= unicode.len(str)
  302.   if n>wid then
  303.     return unicode.sub(str,1,wid)
  304.   else
  305.     return str.. string.rep(" ", wid-n)
  306.   end
  307. end
  308.  
  309. local function formatRow(nm,qt,em,ir)
  310.   local s1= cutPad(nm, colNameW)
  311.   local s2= cutPad(qt, colQtyW)
  312.   local s3= cutPad(em, colEmerW)
  313.   local s4= cutPad(ir, colIronW)
  314.   return s1.. s2.. s3.. s4
  315. end
  316.  
  317. local function drawItemList()
  318.   -- Сверху
  319.   local listH= itemsH- (buyPanelHeight+ searchBarHeight)
  320.   drawFrame(itemsX, itemsY, itemsW, listH, " Список товаров ")
  321.  
  322.   local inX= itemsX+1
  323.   local inY= itemsY+1
  324.   local inW= itemsW-2
  325.   local inH= listH-2
  326.  
  327.   gpu.setBackground(colors.background)
  328.   gpu.setForeground(colors.text)
  329.  
  330.   -- Заголовок
  331.   local hdr= formatRow("Товар", "Кол-во", "Эм", "Жел")
  332.   gpu.set(inX, inY, hdr)
  333.   inY= inY+1
  334.   local sep= string.rep("-", inW)
  335.   gpu.set(inX, inY, sep)
  336.   inY= inY+1
  337.  
  338.   local maxIdx= #filteredItems
  339.   local linesAvailable= inH-2
  340.   local visible= math.min(linesAvailable, maxIdx- scrollOffset)
  341.   local lineY= inY
  342.  
  343.   for i=1, visible do
  344.     local idx= scrollOffset+ i
  345.     local it= filteredItems[idx]
  346.  
  347.     -- Формируем строку
  348.     local row= formatRow(
  349.       it.display,
  350.       tostring(it.quantity).."шт",
  351.       tostring(it.priceEmerald).."Эм",
  352.       tostring(it.priceIron).."Ж"
  353.     )
  354.     if unicode.len(row)> inW then
  355.       row= unicode.sub(row,1,inW)
  356.     end
  357.  
  358.     -- Подсветка, если выбран
  359.     if (buySelectedIndex== idx) then
  360.       gpu.setBackground(colors.highlight)
  361.       gpu.fill(inX, lineY, inW,1," ")
  362.       gpu.setForeground(colors.text)
  363.       gpu.set(inX, lineY, row)
  364.       -- Вернём фон
  365.       gpu.setBackground(colors.background)
  366.     else
  367.       gpu.setBackground(colors.background)
  368.       gpu.setForeground(colors.text)
  369.       gpu.set(inX, lineY, row)
  370.     end
  371.     lineY= lineY+1
  372.     if lineY> (itemsY+ listH-1) then
  373.       break
  374.     end
  375.   end
  376. end
  377.  
  378. --------------------------------------------------------------------------------
  379. -- 8) ПАНЕЛЬ ПОКУПКИ (между списком и поиском)
  380. --------------------------------------------------------------------------------
  381. local function drawBuyPanel()
  382.   if not playerOnPIM then return end
  383.   local panelH= buyPanelHeight
  384.   local panelW= itemsW
  385.   local panelX= itemsX
  386.   local panelY= itemsY+ (itemsH- searchBarHeight)- panelH
  387.  
  388.   drawFrame(panelX, panelY, panelW, panelH, " Покупка ")
  389.  
  390.   local inX= panelX+1
  391.   local inY= panelY+1
  392.   local inW= panelW-2
  393.  
  394.   if not buySelectedIndex then
  395.     gpu.setForeground(colors.text)
  396.     gpu.setBackground(colors.background)
  397.     gpu.set(inX, inY, "Выберите товар (клик по списку)")
  398.     return
  399.   end
  400.  
  401.   local it= filteredItems[buySelectedIndex]
  402.   if not it then
  403.     gpu.set(inX, inY, "Товар не найден")
  404.     return
  405.   end
  406.  
  407.   local line= string.format("%s (ост. %dшт)", it.display, it.quantity)
  408.   gpu.setBackground(colors.background)
  409.   gpu.setForeground(colors.text)
  410.   gpu.set(inX, inY, line)
  411.  
  412.   local textQty= "Кол-во: ".. buyQuantity
  413.   gpu.set(inX+30, inY, textQty)
  414.  
  415.   local payLbl= payWithEmerald and "[Эм]/Жел" or "Эм/[Жел]"
  416.   gpu.set(inX+50, inY, payLbl)
  417.  
  418.   -- Кнопка "Купить"
  419.   local btnW= 8
  420.   local btnX= (panelX+ panelW)- btnW
  421.   local btnY= inY
  422.   local canBuy= false
  423.   local ud= getUserData(currentPlayerName)
  424.   local q= tonumber(buyQuantity) or 0
  425.   if q>0 and it.quantity>=q then
  426.     local cost= (payWithEmerald and it.priceEmerald or it.priceIron)* q
  427.     if payWithEmerald and ud.balanceEmerald>= cost then
  428.       canBuy= true
  429.     elseif (not payWithEmerald) and ud.balanceIron>= cost then
  430.       canBuy= true
  431.     end
  432.   end
  433.   local colBtn= canBuy and colors.success or colors.buttonInactive
  434.   gpu.setBackground(colBtn)
  435.   gpu.fill(btnX, btnY, btnW,1, " ")
  436.   gpu.setForeground(colors.text)
  437.   local lbl= "Купить"
  438.   local cx= btnX+ math.floor((btnW- unicode.len(lbl))/2)
  439.   gpu.set(cx, btnY, lbl)
  440.  
  441.   if buyMessage~="" then
  442.     gpu.setForeground(colors.warn)
  443.     gpu.set(inX, inY+1, buyMessage)
  444.   end
  445. end
  446.  
  447. --------------------------------------------------------------------------------
  448. -- 9) ПОЛЕ ПОИСК (ВНИЗУ)
  449. --------------------------------------------------------------------------------
  450. local function drawSearchBar()
  451.   if not playerOnPIM then return end
  452.   local sbH= searchBarHeight
  453.   local sbW= itemsW
  454.   local sbX= itemsX
  455.   local sbY= itemsY+ itemsH- sbH +1
  456.  
  457.   drawFrame(sbX, sbY, sbW, sbH, nil)
  458.   local inX= sbX+1
  459.   local inY= sbY+1
  460.   local inW= sbW-2
  461.  
  462.   gpu.setBackground(colors.inputField)
  463.   gpu.fill(inX, inY, inW,1, " ")
  464.   gpu.setForeground(colors.text)
  465.  
  466.   local prefix= "Поиск: "
  467.   local text= prefix.. searchText
  468.   if unicode.len(text)> inW then
  469.     text= unicode.sub(text, unicode.len(text)- inW+1)
  470.   end
  471.   gpu.set(inX, inY, text)
  472.  
  473.   if searchFocus then
  474.     local cx= inX+ unicode.len(text)
  475.     if cx<(inX+ inW) then
  476.       if searchCursorVisible then
  477.         gpu.set(cx, inY, "_")
  478.       end
  479.     end
  480.   end
  481. end
  482.  
  483. --------------------------------------------------------------------------------
  484. -- ПОЛНАЯ ПЕРЕРИСОВКА
  485. --------------------------------------------------------------------------------
  486. local function redrawScreen()
  487.   clearScreen()
  488.   drawHeader()
  489.  
  490.   if not playerOnPIM then
  491.     local msg= "Встаньте на PIM для авторизации..."
  492.     local x= math.floor((screenWidth- unicode.len(msg))/2)
  493.     local y= math.floor(screenHeight/2)
  494.     gpu.set(x,y, msg)
  495.   else
  496.     drawLeftPanel()
  497.     drawItemList()
  498.     drawBuyPanel()
  499.     drawSearchBar()
  500.   end
  501.  
  502.   drawFooter()
  503. end
  504.  
  505. --------------------------------------------------------------------------------
  506. -- 10) ОБНОВЛЕНИЕ СПИСКА (ПОИСК)
  507. --------------------------------------------------------------------------------
  508. local function updateFilteredItems()
  509.   filteredItems= {}
  510.   local q= unicode.lower(searchText)
  511.   for _, it in ipairs(allItems) do
  512.     local disp= unicode.lower(it.display)
  513.     if q=="" or unicode.find(disp,q,1,true) then
  514.       table.insert(filteredItems, it)
  515.     end
  516.   end
  517. end
  518.  
  519. -- Подготовка колонок
  520. local function prepareColumns()
  521.   local listH= itemsH- (buyPanelHeight+ searchBarHeight)
  522.   local listW= itemsW- 2
  523.   colNameW, colQtyW, colEmerW, colIronW= calcColumns(listW)
  524. end
  525.  
  526. local function initAll()
  527.   prepareColumns()
  528.   updateFilteredItems()
  529.   redrawScreen()
  530. end
  531.  
  532. --------------------------------------------------------------------------------
  533. -- 11) Проверка PIM (таймер)
  534. --------------------------------------------------------------------------------
  535. local lastName= nil
  536. local function checkPIM()
  537.   local nm= pim.getInventoryName()
  538.   if nm and nm~="" and nm~="pim" then
  539.     if not playerOnPIM or (nm~= lastName) then
  540.       playerOnPIM= true
  541.       currentPlayerName= nm
  542.       lastName= nm
  543.       getUserData(nm)
  544.       redrawScreen()
  545.     end
  546.   else
  547.     if playerOnPIM then
  548.       playerOnPIM= false
  549.       currentPlayerName= nil
  550.       lastName= nil
  551.       redrawScreen()
  552.     end
  553.   end
  554. end
  555.  
  556. --------------------------------------------------------------------------------
  557. -- 12) ФУНКЦИИ ДЕЙСТВИЙ: Внести / Забрать / Купить
  558. --------------------------------------------------------------------------------
  559. local function depositMoney()
  560.   print("Кнопка: «Внести деньги» (реализуйте логику, если нужно).")
  561. end
  562.  
  563. local function depositIron()
  564.   print("Кнопка: «Внести железо» (реализуйте логику, если нужно).")
  565. end
  566.  
  567. local function withdrawMoney()
  568.   if #withdrawMoneyInput>0 then
  569.     local amt= tonumber(withdrawMoneyInput) or 0
  570.     print("Кнопка «Забрать деньги»: "..amt)
  571.     withdrawMoneyInput= ""
  572.     redrawScreen()
  573.   end
  574. end
  575.  
  576. local function withdrawIron()
  577.   if #withdrawIronInput>0 then
  578.     local amt= tonumber(withdrawIronInput) or 0
  579.     print("Кнопка «Забрать железо»: "..amt)
  580.     withdrawIronInput= ""
  581.     redrawScreen()
  582.   end
  583. end
  584.  
  585. local function tryBuyItem()
  586.   buyMessage= ""
  587.   if not buySelectedIndex then return end
  588.   local it= filteredItems[buySelectedIndex]
  589.   if not it then return end
  590.   local q= tonumber(buyQuantity) or 0
  591.   if q<=0 then
  592.     buyMessage= "Количество=0"
  593.     return
  594.   end
  595.   if it.quantity< q then
  596.     buyMessage= "В магазине осталось ".. it.quantity
  597.     return
  598.   end
  599.   local ud= getUserData(currentPlayerName)
  600.   local cost= (payWithEmerald and it.priceEmerald or it.priceIron)* q
  601.   if payWithEmerald and ud.balanceEmerald< cost then
  602.     buyMessage= "Недостаточно Эм!"
  603.     return
  604.   elseif (not payWithEmerald) and ud.balanceIron< cost then
  605.     buyMessage= "Недостаточно Жел!"
  606.     return
  607.   end
  608.   -- Снимаем деньги, уменьшаем остаток товара:
  609.   if payWithEmerald then
  610.     ud.balanceEmerald= ud.balanceEmerald- cost
  611.   else
  612.     ud.balanceIron= ud.balanceIron- cost
  613.   end
  614.   it.quantity= it.quantity- q
  615.   print("Куплено "..q.." шт '"..it.display.."' за ".. cost.. (payWithEmerald and " Эм" or " Жел"))
  616.   buyQuantity= ""
  617. end
  618.  
  619. --------------------------------------------------------------------------------
  620. -- 13) Определить, где кликнули в списке
  621. --------------------------------------------------------------------------------
  622. local function getItemIndexFromCoords(cx,cy)
  623.   local listH= itemsH- (buyPanelHeight+ searchBarHeight)
  624.   local inX= itemsX+1
  625.   local inY= itemsY+3
  626.   local inW= itemsW-2
  627.   local inH= listH-2
  628.   if cx< inX or cx>= (inX+inW) then return nil end
  629.   if cy< inY or cy>= (inY+inH) then return nil end
  630.   local line= cy- inY+1
  631.   local idx= scrollOffset+ line
  632.   if idx<1 or idx>#filteredItems then return nil end
  633.   return idx
  634. end
  635.  
  636. --------------------------------------------------------------------------------
  637. -- 14) СОБЫТИЯ
  638. --------------------------------------------------------------------------------
  639. initAll()
  640. event.timer(1, function() checkPIM() end, math.huge)
  641.  
  642. while true do
  643.   local evt, p1, p2, p3= event.pull(0.05)
  644.  
  645.   -- Мигание курсора (поиск)
  646.   if searchFocus then
  647.     local t= os.clock()
  648.     if (t- lastCursorBlink)> cursorBlinkInterval then
  649.       searchCursorVisible= not searchCursorVisible
  650.       lastCursorBlink= t
  651.       drawSearchBar()
  652.     end
  653.   end
  654.  
  655.   if evt=="scroll" then
  656.     if playerOnPIM then
  657.       local dir= p3
  658.       local maxCount= #filteredItems
  659.       local listH= itemsH- (buyPanelHeight+ searchBarHeight)
  660.       local lines= listH-4
  661.       if dir==-1 and scrollOffset>0 then
  662.         scrollOffset= scrollOffset-1
  663.         drawItemList()
  664.         drawBuyPanel()
  665.       elseif dir==1 and scrollOffset< (maxCount- lines) then
  666.         scrollOffset= scrollOffset+1
  667.         drawItemList()
  668.         drawBuyPanel()
  669.       end
  670.     end
  671.  
  672.   elseif evt=="touch" then
  673.     local cx, cy= p2, p3
  674.     if playerOnPIM then
  675.       -- Левая панель
  676.       local marginX= actionsX+2
  677.       local marginY= actionsY+1
  678.       local btnW= actionsW-4
  679.       local btnH=3
  680.       local btnY1= marginY+5     -- "Внести деньги"
  681.       local btnY2= btnY1+ btnH+1 -- "Внести железо"
  682.       -- Кнопка1
  683.       if cx>= marginX and cx<(marginX+btnW) and cy>= btnY1 and cy<(btnY1+ btnH) then
  684.         depositMoney()
  685.       -- Кнопка2
  686.       elseif cx>= marginX and cx<(marginX+btnW) and cy>= btnY2 and cy<(btnY2+ btnH) then
  687.         depositIron()
  688.       else
  689.         -- "Забрать" зона
  690.         local boxY= btnY2+ btnH+1
  691.         local boxH= 10
  692.         local inX= marginX+1
  693.         local inY= boxY+1
  694.         local inW= btnW-2
  695.  
  696.         -- 1) "Забрать деньги"
  697.         if cy== inY then
  698.           -- Клик по кнопке "Забрать деньги"
  699.           withdrawMoney()
  700.         elseif cy== inY+1 then
  701.           -- поле ввода withdrawMoneyInput
  702.           withdrawMoneyInput= ""
  703.         -- 2) "Забрать железо"
  704.         elseif cy== inY+2 then
  705.           -- кнопка
  706.           withdrawIron()
  707.         elseif cy== inY+3 then
  708.           -- поле ввода
  709.           withdrawIronInput= ""
  710.         else
  711.           -- Проверим клик по списку
  712.           local idx= getItemIndexFromCoords(cx,cy)
  713.           if idx then
  714.             buySelectedIndex= idx
  715.             buyMessage= ""
  716.             redrawScreen()
  717.           else
  718.             -- Проверка поиска
  719.             local sbY= itemsY+ itemsH- searchBarHeight +1
  720.             if cy== sbY+1 then
  721.               -- строка поиска
  722.               searchFocus= true
  723.             else
  724.               searchFocus= false
  725.             end
  726.             -- Панель "покупка"
  727.             local buyY= itemsY+ (itemsH- searchBarHeight)- buyPanelHeight
  728.             if cy>= buyY and cy< buyY+ buyPanelHeight then
  729.               -- Возможно клик на переключатель [Эм]/[Жел], кнопку "Купить" etc.
  730.               local lineBuy= cy- buyY
  731.               if lineBuy==1 then
  732.                 -- payLabel?  if cx>= ??? ...
  733.                 if cx>= (itemsX+50) and cx<(itemsX+54) then
  734.                   payWithEmerald= not payWithEmerald
  735.                   redrawScreen()
  736.                 end
  737.                 -- Кнопка "Купить"
  738.                 local btnX= (itemsX+ itemsW)- 8
  739.                 if cx>= btnX and cx< btnX+8 then
  740.                   tryBuyItem()
  741.                   drawBuyPanel()
  742.                   drawItemList()
  743.                 end
  744.               end
  745.             end
  746.           end
  747.         end
  748.       end
  749.     end
  750.  
  751.   elseif evt=="key_down" then
  752.     local ch= p3
  753.     -- Если в фокусе поиск
  754.     if searchFocus then
  755.       if ch==8 then
  756.         if unicode.len(searchText)>0 then
  757.           searchText= unicode.sub(searchText,1, unicode.len(searchText)-1)
  758.           scrollOffset=0
  759.           updateFilteredItems()
  760.           drawItemList()
  761.           drawBuyPanel()
  762.           drawSearchBar()
  763.         end
  764.       elseif ch==13 then
  765.         -- Enter
  766.       else
  767.         -- Печатный символ?
  768.         if (ch>=48 and ch<=57) or (ch>=65 and ch<=90) or (ch>=97 and ch<=122) or
  769.            (ch>=1040 and ch<=1103) or (ch>=32 and ch<=47) or (ch>=58 and ch<=64) then
  770.           local c= unicode.char(ch)
  771.           searchText= searchText.. c
  772.           scrollOffset=0
  773.           updateFilteredItems()
  774.           drawItemList()
  775.           drawBuyPanel()
  776.           drawSearchBar()
  777.         end
  778.       end
  779.     else
  780.       -- Смотрим, вводим ли buyQuantity
  781.       if buySelectedIndex then
  782.         if ch>=48 and ch<=57 then
  783.           buyQuantity= buyQuantity.. string.char(ch)
  784.           drawBuyPanel()
  785.         elseif ch==8 then
  786.           if #buyQuantity>0 then
  787.             buyQuantity= buyQuantity:sub(1,#buyQuantity-1)
  788.             drawBuyPanel()
  789.           end
  790.         elseif ch==13 then
  791.           tryBuyItem()
  792.           drawBuyPanel()
  793.           drawItemList()
  794.         end
  795.       end
  796.  
  797.       -- Проверим поля "withdrawMoneyInput"/"withdrawIronInput"
  798.       -- Если пользователь «выбрал» (кликнул на) withdrawMoneyInput
  799.       -- мы должны хранить фокус, напр. focus="withdrawMoney".
  800.       -- Ниже — упрощённо (без переменных фокуса, но иллюстрирует идею):
  801.       -- Допустим, если user "включил" withdrawMoneyInput (очистили строку):
  802.       -- можно проверить, if ch>=48 and ch<=57 then...
  803.     end
  804.   end
  805. end
  806.  
Advertisement
Add Comment
Please, Sign In to add comment