PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/CorsixTH/Lua/dialogs/furnish_corridor.lua

http://corsix-th.googlecode.com/
Lua | 230 lines | 186 code | 23 blank | 21 comment | 28 complexity | d6672529ee284f7286d689312773f408 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. --[[ Copyright (c) 2009 Peter "Corsix" Cawley
  2. Permission is hereby granted, free of charge, to any person obtaining a copy of
  3. this software and associated documentation files (the "Software"), to deal in
  4. the Software without restriction, including without limitation the rights to
  5. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  6. of the Software, and to permit persons to whom the Software is furnished to do
  7. so, subject to the following conditions:
  8. The above copyright notice and this permission notice shall be included in all
  9. copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  14. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  16. SOFTWARE. --]]
  17. local TH = require "TH"
  18. local math_floor
  19. = math.floor
  20. --! Dialog for purchasing `Object`s (for the corridor or for rooms).
  21. class "UIFurnishCorridor" (Window)
  22. function UIFurnishCorridor:UIFurnishCorridor(ui, objects, edit_dialog)
  23. self:Window()
  24. local app = ui.app
  25. if edit_dialog then
  26. self.modal_class = "furnish"
  27. self.edit_dialog = edit_dialog
  28. else
  29. self.modal_class = "main"
  30. end
  31. self.esc_closes = true
  32. self.ui = ui
  33. self.anims = app.anims
  34. self.width = 360
  35. self.height = 274
  36. self:setDefaultPosition(0.5, 0.4)
  37. self.panel_sprites = app.gfx:loadSpriteTable("QData", "Req10V", true)
  38. self.white_font = app.gfx:loadFont("QData", "Font01V")
  39. self.blue_font = app.gfx:loadFont("QData", "Font02V")
  40. self.title_text = _S.buy_objects_window.choose_items
  41. self.price_text = (_S.buy_objects_window.price .. " "):gsub(" $", " ")
  42. self.total_text = (_S.buy_objects_window.total .. " "):gsub(" $", " ")
  43. self.item_price = 0
  44. self.total_price = 0
  45. self.list_hover_index = 0
  46. self.preview_anim = TH.animation()
  47. self.objects = {
  48. }
  49. if objects then
  50. for _, object in pairs(objects) do
  51. self.objects[#self.objects + 1] = {object = object.object, start_qty = object.qty, qty = object.qty, min_qty = object.min_qty} -- Had to make a copy of objects list. Otherwise, we will modify the original variable (Opening dialog twice keeps memory of previously choosen quantities)
  52. end
  53. else
  54. for _, object in ipairs(app.objects) do
  55. if object.corridor_object then
  56. self.objects[#self.objects + 1] = {object = object, start_qty = 0, qty = 0, min_qty = 0}
  57. end
  58. end
  59. table.sort(self.objects, function(o1, o2)
  60. return o1.object.corridor_object < o2.object.corridor_object
  61. end)
  62. end
  63. self:addPanel(228, 0, 0) -- Grid top
  64. for y = 33, 103, 10 do
  65. self:addPanel(229, 0, y) -- Grid body
  66. end
  67. self:addPanel(230, 0, 113) -- Grid bottom
  68. self:addPanel(231, 0, 148) -- Cost / total top
  69. self:addPanel(232, 0, 173) -- Cost / total body
  70. self:addPanel(233, 0, 215) -- Cost / total bottom
  71. self:addPanel(234, 0, 248) -- Close button background
  72. self:addPanel(234, 0, 252) -- Close button background extension
  73. self:addPanel(242, 9, 237):makeButton(0, 0, 129, 28, 243, self.close):setTooltip(_S.tooltip.buy_objects_window.cancel)
  74. self:addPanel(235, 146, 0) -- List top
  75. self:addPanel(236, 146, 223) -- List bottom
  76. self:addPanel(237, 154, 238):makeButton(0, 0, 197, 28, 238, self.confirm):setTooltip(_S.tooltip.buy_objects_window.confirm)
  77. local i = 1
  78. local function item_callback(index, qty)
  79. local is_negative_quantity = qty < 0
  80. return --[[persistable:furnish_corridor_item_callback]] function(self)
  81. if self:purchaseItem(index, qty) == 0 and not is_negative_quantity then
  82. -- give visual warning that player doesn't have enough $ to buy
  83. self.ui.adviser:say(_A.warnings.cannot_afford_2, false, true)
  84. self.ui:playSound "wrong2.wav"
  85. elseif qty > 0 then
  86. self.ui:playSound "AddItemJ.wav"
  87. else
  88. self.ui:playSound "DelItemJ.wav"
  89. end
  90. end
  91. end
  92. for y = 34, 205, 19 do
  93. local x = 146
  94. self:addPanel(239, x, y) -- List body
  95. if i <= #self.objects then
  96. self:addPanel(240, x + 12, y):makeButton(0, 0, 125, 19, 241, item_callback(i, 1), nil, item_callback(i, -1)):setTooltip(self.objects[i].object.tooltip)
  97. self:addPanel(244, x + 139, y + 1):makeButton(0, 0, 17, 17, 245, item_callback(i, -1)):setTooltip(_S.tooltip.buy_objects_window.decrease)
  98. self:addPanel(246, x + 183, y + 1):makeButton(0, 0, 17, 17, 247, item_callback(i, 1)):setTooltip(_S.tooltip.buy_objects_window.increase)
  99. end
  100. i = i + 1
  101. end
  102. self:makeTooltip(_S.tooltip.buy_objects_window.price, 20, 168, 127, 187)
  103. self:makeTooltip(_S.tooltip.buy_objects_window.total_value, 20, 196, 127, 215)
  104. self:addKeyHandler("Enter", self.confirm)
  105. end
  106. function UIFurnishCorridor:purchaseItem(index, quantity)
  107. local o = self.objects[index]
  108. local is_negative_quantity = quantity < 0
  109. if self.buttons_down.ctrl then
  110. quantity = quantity * 10
  111. elseif self.buttons_down.shift then
  112. quantity = quantity * 5
  113. end
  114. quantity = quantity + o.qty
  115. if quantity < o.min_qty then
  116. quantity = o.min_qty
  117. elseif quantity > 99 then
  118. quantity = 99
  119. end
  120. quantity = quantity - o.qty
  121. local hospital = self.ui.hospital
  122. if hospital.balance >= self.total_price + quantity * hospital:getObjectBuildCost(o.object.id) or is_negative_quantity then
  123. o.qty = o.qty + quantity
  124. self.total_price = self.total_price + quantity * hospital:getObjectBuildCost(o.object.id)
  125. if o.object.id == "reception_desk" then
  126. if o.qty > 0 then
  127. self.ui:tutorialStep(1, 2, 3)
  128. else
  129. self.ui:tutorialStep(1, 3, 2)
  130. end
  131. end
  132. else
  133. quantity = 0
  134. end
  135. return quantity
  136. end
  137. function UIFurnishCorridor:confirm()
  138. self.ui:tutorialStep(1, 3, 4)
  139. local to_purchase = {}
  140. local to_sell = {}
  141. for i, o in ipairs(self.objects) do
  142. local build_cost = self.ui.hospital:getObjectBuildCost(o.object.id)
  143. if o.qty - o.start_qty > 0 then
  144. local diff_qty = o.qty - o.start_qty
  145. to_purchase[#to_purchase + 1] = { object = o.object, qty = diff_qty }
  146. self.ui.hospital:spendMoney(build_cost * diff_qty, _S.transactions.buy_object .. ": " .. o.object.name, build_cost * diff_qty)
  147. elseif o.qty - o.start_qty < 0 then
  148. local diff_qty = o.start_qty - o.qty
  149. to_sell[#to_sell + 1] = { object = o.object, qty = diff_qty }
  150. self.ui.hospital:receiveMoney(build_cost * diff_qty, _S.transactions.sell_object .. ": " .. o.object.name, build_cost * diff_qty)
  151. end
  152. end
  153. if self.edit_dialog then
  154. self.edit_dialog:addObjects(to_purchase, false) -- payment already handled here
  155. self.edit_dialog:removeObjects(to_sell, false) -- payment already handled here
  156. self:close()
  157. else
  158. if #to_purchase == 0 then
  159. self:close()
  160. else
  161. self.ui:addWindow(UIPlaceObjects(self.ui, to_purchase))
  162. end
  163. end
  164. end
  165. function UIFurnishCorridor:close()
  166. self.ui:tutorialStep(1, {2, 3}, 1)
  167. if self.edit_dialog then
  168. self.edit_dialog:addObjects() -- No objects added. Call the function anyway to handle visibility etc.
  169. end
  170. Window.close(self)
  171. end
  172. function UIFurnishCorridor:draw(canvas, x, y)
  173. Window.draw(self, canvas, x, y)
  174. x, y = x + self.x, y + self.y
  175. self.white_font:draw(canvas, self.title_text, x + 163, y + 18)
  176. self.white_font:draw(canvas, self.price_text .. self.item_price, x + 24, y + 173)
  177. self.white_font:draw(canvas, self.total_text .. self.total_price, x + 24, y + 202)
  178. for i, o in ipairs(self.objects) do
  179. local font = self.white_font
  180. if i == self.list_hover_index then
  181. font = self.blue_font
  182. end
  183. font:draw(canvas, o.object.name, x + 163, y + 20 + i * 19)
  184. font:draw(canvas, o.qty, x + 306, y + 20 + i * 19, 19, 0)
  185. end
  186. self.preview_anim:draw(canvas, x + 72, y + 57)
  187. end
  188. function UIFurnishCorridor:onMouseMove(x, y, dx, dy)
  189. local repaint = Window.onMouseMove(self, x, y, dx, dy)
  190. local hover_idx = 0
  191. if 158 <= x and x < 346 and 34 <= y and y < 224 then
  192. hover_idx = math_floor((y - 15) / 19)
  193. end
  194. if hover_idx ~= self.list_hover_index then
  195. if 1 <= hover_idx and hover_idx <= #self.objects then
  196. local obj = self.objects[hover_idx].object
  197. self.item_price = self.ui.hospital:getObjectBuildCost(obj.id)
  198. self.preview_anim:setAnimation(self.anims, obj.build_preview_animation)
  199. end
  200. self.list_hover_index = hover_idx
  201. repaint = true
  202. end
  203. return repaint
  204. end