trader.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. --This code comes almost exclusively from the trader and inventory of mobf, by Sapier.
  2. --The copyright notice bellow is from mobf:
  3. -------------------------------------------------------------------------------
  4. -- Mob Framework Mod by Sapier
  5. --
  6. -- You may copy, use, modify or do nearly anything except removing this
  7. -- copyright notice.
  8. -- And of course you are NOT allow to pretend you have written it.
  9. --
  10. --! @file inventory.lua
  11. --! @brief component containing mob inventory related functions
  12. --! @copyright Sapier
  13. --! @author Sapier
  14. --! @date 2013-01-02
  15. --
  16. --! @defgroup Inventory Inventory subcomponent
  17. --! @brief Component handling mob inventory
  18. --! @ingroup framework_int
  19. --! @{
  20. --
  21. -- Contact sapier a t gmx net
  22. -------------------------------------------------------------------------------
  23. function lottmobs.allow_move(inv, from_list, from_index, to_list, to_index, count, player)
  24. if to_list ~= "selection" or
  25. from_list == "price" or
  26. from_list == "payment" or
  27. from_list == "takeaway" or
  28. from_list == "identifier" then
  29. return 0
  30. end
  31. -- forbid moving of parts of stacks
  32. local old_stack = inv.get_stack(inv, from_list, from_index)
  33. if count ~= old_stack.get_count(old_stack) then
  34. return 0;
  35. end
  36. return count
  37. end
  38. function lottmobs.allow_put(inv, listname, index, stack, player)
  39. if listname == "payment" then
  40. return 99
  41. end
  42. return 0
  43. end
  44. function lottmobs.allow_take(inv, listname, index, stack, player)
  45. if listname == "takeaway" or
  46. listname == "payment" then
  47. return 99
  48. else
  49. return 0
  50. end
  51. end
  52. function lottmobs.on_put(inv, listname, index, stack)
  53. if listname == "payment" then
  54. lottmobs.update_takeaway(inv)
  55. end
  56. end
  57. function lottmobs.on_take(inv, listname, count, index, stack, player)
  58. if listname == "takeaway" then
  59. local amount = inv:get_stack("payment",1):get_count()
  60. local price = inv:get_stack("price",1):get_count()
  61. local thing = inv:get_stack("payment",1):get_name()
  62. inv.set_stack(inv,"selection",1,nil)
  63. inv.set_stack(inv,"price",1,nil)
  64. inv.set_stack(inv,"takeaway",1,nil)
  65. inv.set_stack(inv,"payment",1,thing .. " " .. amount-price)
  66. end
  67. if listname == "payment" then
  68. if lottmobs.check_pay(inv,false) then
  69. local selection = inv.get_stack(inv,"selection", 1)
  70. if selection ~= nil then
  71. inv.set_stack(inv,"takeaway",1,selection)
  72. end
  73. else
  74. inv.set_stack(inv,"takeaway",1,nil)
  75. end
  76. end
  77. end
  78. function lottmobs.update_takeaway(inv)
  79. if lottmobs.check_pay(inv,false) then
  80. local selection = inv.get_stack(inv,"selection", 1)
  81. if selection ~= nil then
  82. inv.set_stack(inv,"takeaway",1,selection)
  83. end
  84. else
  85. inv.set_stack(inv,"takeaway",1,nil)
  86. end
  87. end
  88. function lottmobs.check_pay(inv,paynow)
  89. local now_at_pay = inv.get_stack(inv,"payment",1)
  90. local count = now_at_pay.get_count(now_at_pay)
  91. local name = now_at_pay.get_name(now_at_pay)
  92. local price = inv.get_stack(inv,"price", 1)
  93. if price:get_name() == name then
  94. local price = price:get_count()
  95. if price > 0 and
  96. price <= count then
  97. if paynow then
  98. now_at_pay.take_item(now_at_pay,price)
  99. inv.set_stack(inv,"payment",1,now_at_pay)
  100. return true
  101. else
  102. return true
  103. end
  104. else
  105. if paynow then
  106. inv.set_stack(inv,"payment",1,nil)
  107. end
  108. end
  109. end
  110. return false
  111. end
  112. lottmobs.trader_inventories = {}
  113. function lottmobs.add_goods(entity, race)
  114. local goods_to_add = nil
  115. for i=1,15 do
  116. if same_race == true then
  117. if math.random(0, 100) > race.items_race[i][3] then
  118. lottmobs.trader_inventory.set_stack(lottmobs.trader_inventory,"goods", i, race.items_race[i][1])
  119. end
  120. else
  121. if math.random(0, 100) > race.items[i][3] then
  122. lottmobs.trader_inventory.set_stack(lottmobs.trader_inventory,"goods", i, race.items[i][1])
  123. end
  124. end
  125. end
  126. end
  127. function lottmobs.face_pos(self,pos)
  128. local s = self.object:getpos()
  129. local vec = {x=pos.x-s.x, y=pos.y-s.y, z=pos.z-s.z}
  130. local yaw = math.atan2(vec.z,vec.x)-math.pi/2
  131. if self.drawtype == "side" then
  132. yaw = yaw+(math.pi/2)
  133. end
  134. self.object:setyaw(yaw)
  135. return yaw
  136. end
  137. ----
  138. function lottmobs_trader(self, clicker, entity, race, image, priv)
  139. lottmobs.face_pos(self, clicker:getpos())
  140. local player = clicker:get_player_name()
  141. if self.id == 0 then
  142. self.id = (math.random(1, 1000) * math.random(1, 10000)) .. self.name .. (math.random(1, 1000) ^ 2)
  143. end
  144. if self.game_name == "mob" then
  145. self.game_name = tostring(race.names[math.random(1,#race.names)])
  146. --self.nametag = self.game_name
  147. end
  148. local unique_entity_id = self.id
  149. local is_inventory = minetest.get_inventory({type="detached", name=unique_entity_id})
  150. local same_race = false
  151. if minetest.get_player_privs(player)[priv] ~= nil then
  152. same_race = true
  153. end
  154. local move_put_take = {
  155. allow_move = lottmobs.allow_move,
  156. allow_put = lottmobs.allow_put,
  157. allow_take = lottmobs.allow_take,
  158. on_move = function(inventory, from_list, from_index, to_list, to_index, count, player)
  159. if from_list == "goods" and
  160. to_list == "selection" then
  161. local inv = inventory
  162. local moved = inv.get_stack(inv,to_list, to_index)
  163. local goodname = moved.get_name(moved)
  164. local elements = moved.get_count(moved)
  165. if( elements > count ) then
  166. -- remove the surplus parts
  167. inv.set_stack(inv,"selection", 1,goodname.." "..tostring( count ))
  168. -- the slot we took from is now free
  169. inv.set_stack(inv,"goods",from_index,
  170. goodname.." "..tostring( elements - count ))
  171. -- update the real amount of items in the slot now
  172. elements = count
  173. end
  174. local good = nil
  175. local good = nil
  176. if same_race == true then
  177. for i = 1,#race.items_race,1 do
  178. local stackstring = goodname .." " .. count
  179. if race.items_race[i][1] == stackstring then
  180. good = race.items_race[i]
  181. end
  182. end
  183. else
  184. for i = 1,#race.items,1 do
  185. local stackstring = goodname .." " .. count
  186. if race.items[i][1] == stackstring then
  187. good = race.items[i]
  188. end
  189. end
  190. end
  191. if good ~= nil then
  192. inventory.set_stack(inventory,"price", 1, good[2])
  193. else
  194. inventory.set_stack(inventory,"price", 1, nil)
  195. end
  196. lottmobs.update_takeaway(inv)
  197. end
  198. end,
  199. on_put = lottmobs.on_put,
  200. on_take = lottmobs.on_take
  201. }
  202. if is_inventory == nil then
  203. lottmobs.trader_inventory = minetest.create_detached_inventory(unique_entity_id, move_put_take)
  204. lottmobs.trader_inventory.set_size(lottmobs.trader_inventory,"goods",15)
  205. lottmobs.trader_inventory.set_size(lottmobs.trader_inventory,"takeaway",1)
  206. lottmobs.trader_inventory.set_size(lottmobs.trader_inventory,"selection",1)
  207. lottmobs.trader_inventory.set_size(lottmobs.trader_inventory,"price",1)
  208. lottmobs.trader_inventory.set_size(lottmobs.trader_inventory,"payment",1)
  209. lottmobs.add_goods(entity, race)
  210. end
  211. minetest.chat_send_player(player, "[NPC] <Trader " .. self.game_name .. "> Hello, " .. player .. ", have a look at my wares.")
  212. minetest.show_formspec(player, "trade",
  213. "size[8,10;]" ..
  214. "background[5,5;1,1;" .. image .. ";true]" ..
  215. "label[0,0;Trader " .. self.game_name .. "'s stock:]" ..
  216. "list[detached:" .. unique_entity_id .. ";goods;.5,.5;3,5;]" ..
  217. "label[4.5,0.5;Selection]" ..
  218. "list[detached:" .. unique_entity_id .. ";selection;4.5,1;5.5,2;]" ..
  219. "label[6,0.5;Price]" ..
  220. "list[detached:" .. unique_entity_id .. ";price;6,1;7,2;]" ..
  221. "label[4.5,3.5;Payment]" ..
  222. "list[detached:" .. unique_entity_id .. ";payment;4.5,4;5.5,5;]" ..
  223. "label[6,3.5;Brought items]" ..
  224. "list[detached:" .. unique_entity_id .. ";takeaway;6,4;7.5,5.5;]" ..
  225. "list[current_player;main;0,6;8,4;]"
  226. )
  227. end