trader.lua 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. local S = mobs.intllib
  2. -- define table containing names for use and shop items for sale
  3. mobs.human = {
  4. names = {
  5. "Bob", "Duncan", "Bill", "Tom", "James", "Ian", "Lenny",
  6. "Dylan", "Ethan"
  7. },
  8. items = {
  9. --{item for sale, price, chance of appearing in trader's inventory}
  10. {"default:apple 10", "default:gold_ingot 2", 10},
  11. {"farming:bread 10", "default:gold_ingot 4", 5},
  12. {"default:clay 10", "default:gold_ingot 2", 12},
  13. {"default:brick 10", "default:gold_ingot 4", 17},
  14. {"default:glass 10", "default:gold_ingot 4", 17},
  15. {"default:obsidian 10", "default:gold_ingot 15", 50},
  16. {"default:diamond 1", "default:gold_ingot 5", 40},
  17. {"farming:wheat 10", "default:gold_ingot 2", 17},
  18. {"default:tree 5", "default:gold_ingot 4", 20},
  19. {"default:stone 10", "default:gold_ingot 8", 17},
  20. {"default:desert_stone 10", "default:gold_ingot 8", 27},
  21. {"default:sapling 1", "default:gold_ingot 1", 7},
  22. {"default:pick_steel 1", "default:gold_ingot 2", 7},
  23. {"default:sword_steel 1", "default:gold_ingot 2", 17},
  24. {"default:shovel_steel 1", "default:gold_ingot 1", 17},
  25. {"default:cactus 2", "default:gold_ingot 2", 40},
  26. {"default:papyrus 2", "default:gold_ingot 2", 40},
  27. {"default:mese_crystal_fragment 1", "default:dirt_with_grass 10", 90},
  28. {"default:mese_crystal_fragment 1", "default:gold_ingot 5", 90},
  29. }
  30. }
  31. -- Trader ( same as NPC but with right-click shop )
  32. mobs:register_mob("mobs_npc:trader", {
  33. type = "npc",
  34. passive = false,
  35. damage = 3,
  36. attack_type = "dogfight",
  37. attacks_monsters = true,
  38. attack_animals = false,
  39. attack_npcs = false,
  40. pathfinding = false,
  41. hp_min = 10,
  42. hp_max = 20,
  43. armor = 100,
  44. collisionbox = {-0.35,-1.0,-0.35, 0.35,0.8,0.35},
  45. visual = "mesh",
  46. mesh = "mobs_character.b3d",
  47. textures = {
  48. {"mobs_trader.png"}, -- by Frerin
  49. {"mobs_trader2.png"},
  50. {"mobs_trader3.png"},
  51. },
  52. makes_footstep_sound = true,
  53. sounds = {},
  54. walk_velocity = 2,
  55. run_velocity = 3,
  56. jump = false,
  57. drops = {},
  58. water_damage = 0,
  59. lava_damage = 4,
  60. light_damage = 0,
  61. follow = {"default:diamond"},
  62. view_range = 15,
  63. owner = "",
  64. order = "stand",
  65. fear_height = 3,
  66. animation = {
  67. speed_normal = 30,
  68. speed_run = 30,
  69. stand_start = 0,
  70. stand_end = 79,
  71. walk_start = 168,
  72. walk_end = 187,
  73. run_start = 168,
  74. run_end = 187,
  75. punch_start = 200,
  76. punch_end = 219,
  77. },
  78. on_rightclick = function(self, clicker)
  79. self.attack = nil
  80. mobs_trader(self, clicker, mobs.human)
  81. end,
  82. on_spawn = function(self)
  83. self.nametag = S("Trader")
  84. self.object:set_properties({
  85. nametag = self.nametag,
  86. nametag_color = "#FFFFFF"
  87. })
  88. return true -- return true so on_spawn is run once only
  89. end,
  90. })
  91. --This code comes almost exclusively from the trader and inventory of mobf, by Sapier.
  92. --The copyright notice below is from mobf:
  93. -------------------------------------------------------------------------------
  94. -- Mob Framework Mod by Sapier
  95. --
  96. -- You may copy, use, modify or do nearly anything except removing this
  97. -- copyright notice.
  98. -- And of course you are NOT allow to pretend you have written it.
  99. --
  100. --! @file inventory.lua
  101. --! @brief component containing mob inventory related functions
  102. --! @copyright Sapier
  103. --! @author Sapier
  104. --! @date 2013-01-02
  105. --
  106. --! @defgroup Inventory Inventory subcomponent
  107. --! @brief Component handling mob inventory
  108. --! @ingroup framework_int
  109. --! @{
  110. --
  111. -- Contact sapier a t gmx net
  112. -------------------------------------------------------------------------------
  113. -- This code has been heavily modified by isaiah658.
  114. -- Trades are saved in entity metadata so they always stay the same after
  115. -- initially being chosen. Also the formspec uses item image buttons instead of
  116. -- inventory slots.
  117. function mobs.add_goods(self, race)
  118. local trade_index = 1
  119. local trades_already_added = {}
  120. local trader_pool_size = 10
  121. local item_pool_size = #race.items -- get number of items on list
  122. self.trades = {}
  123. if item_pool_size < trader_pool_size then
  124. trader_pool_size = item_pool_size
  125. end
  126. for i = 1, trader_pool_size do
  127. -- If there are more trades than the amount being added, they are
  128. -- randomly selected. If they are equal, there is no reason to randomly
  129. -- select them
  130. local random_trade = nil
  131. if item_pool_size == trader_pool_size then
  132. random_trade = i
  133. else
  134. while random_trade == nil do
  135. local num = math.random(item_pool_size)
  136. if trades_already_added[num] == nil then
  137. trades_already_added[num] = true
  138. random_trade = num
  139. end
  140. end
  141. end
  142. if math.random(0, 100) > race.items[random_trade][3] then
  143. self.trades[trade_index] = {
  144. race.items[random_trade][1],
  145. race.items[random_trade][2]
  146. }
  147. trade_index = trade_index + 1
  148. end
  149. end
  150. end
  151. function mobs_trader(self, clicker, race)
  152. if not self.id then
  153. self.id = (math.random(1, 1000) * math.random(1, 10000))
  154. .. self.name .. (math.random(1, 1000) ^ 2)
  155. end
  156. if not self.game_name then
  157. self.game_name = tostring(race.names[math.random(1, #race.names)])
  158. self.nametag = S("Trader @1", self.game_name)
  159. self.object:set_properties({
  160. nametag = self.nametag,
  161. nametag_color = "#00FF00"
  162. })
  163. end
  164. if self.trades == nil then
  165. mobs.add_goods(self, race)
  166. end
  167. local player = clicker:get_player_name() or ""
  168. minetest.chat_send_player(player,
  169. S("[NPC] <Trader @1> Hello, @2, have a look at my wares.",
  170. self.game_name, player))
  171. -- Make formspec trade list
  172. local formspec_trade_list = ""
  173. local x, y
  174. for i = 1, 10 do
  175. if self.trades[i] and self.trades[i] ~= "" then
  176. if i < 6 then
  177. x = 0.5
  178. y = i - 0.5
  179. else
  180. x = 4.5
  181. y = i - 5.5
  182. end
  183. formspec_trade_list = formspec_trade_list
  184. .. "item_image_button[".. x ..",".. y ..";1,1;"
  185. .. self.trades[i][2] .. ";prices#".. i .."#".. self.id ..";]"
  186. .. "item_image_button[".. x + 2 ..",".. y ..";1,1;"
  187. .. self.trades[i][1] .. ";goods#".. i .."#".. self.id ..";]"
  188. .. "image[".. x + 1 ..",".. y ..";1,1;gui_arrow_blank.png]"
  189. end
  190. end
  191. minetest.show_formspec(player, "mobs_npc:trade", "size[8,10]"
  192. .. default.gui_bg_img
  193. .. default.gui_slots
  194. .. "label[0.5,-0.1;" .. S("Trader @1's stock:", self.game_name) .. "]"
  195. .. formspec_trade_list
  196. .. "list[current_player;main;0,6;8,4;]"
  197. )
  198. end
  199. minetest.register_on_player_receive_fields(function(player, formname, fields)
  200. if formname ~= "mobs_npc:trade" then return end
  201. if fields then
  202. local trade = ""
  203. for k, v in pairs(fields) do
  204. trade = tostring(k)
  205. end
  206. local id = trade:split("#")[3]
  207. local self = nil
  208. if id ~= nil then
  209. for k, v in pairs(minetest.luaentities) do
  210. if v.object and v.id and v.id == id then
  211. self = v
  212. break
  213. end
  214. end
  215. end
  216. if self ~= nil then
  217. local trade_number = tonumber(trade:split("#")[2])
  218. if trade_number ~= nil and self.trades[trade_number] ~= nil then
  219. local price = self.trades[trade_number][2]
  220. local goods = self.trades[trade_number][1]
  221. local inv = player:get_inventory()
  222. if inv:contains_item("main", price) then
  223. inv:remove_item("main", price)
  224. local leftover = inv:add_item("main", goods)
  225. if leftover:get_count() > 0 then
  226. -- drop item(s) in front of player
  227. local droppos = player:get_pos()
  228. local dir = player:get_look_dir()
  229. droppos.x = droppos.x + dir.x
  230. droppos.z = droppos.z + dir.z
  231. minetest.add_item(droppos, leftover)
  232. end
  233. end
  234. end
  235. end
  236. end
  237. end)
  238. mobs:register_egg("mobs_npc:trader", S("Trader"), "default_sandstone.png", 1)
  239. -- compatibility
  240. mobs:alias_mob("mobs:trader", "mobs_npc:trader")