ringcraft.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. --Function for random breakages!
  2. local function random_break(pos, chance, output, src_time)
  3. local inv = minetest.get_meta(pos):get_inventory()
  4. if math.random(8) > chance then
  5. if inv:room_for_item("output", output) then
  6. inv:add_item("output", output)
  7. for i = 1, 2 do
  8. local s = inv:get_stack("input", i)
  9. local n = s:get_name()
  10. local c = s:get_count()
  11. inv:set_stack("input", i, n .. " " .. c - 1)
  12. end
  13. src_time = 0
  14. end
  15. else
  16. for i = 1, 2 do
  17. local s = inv:get_stack("input", i)
  18. local n = s:get_name()
  19. local c = s:get_count()
  20. inv:set_stack("input", i, n .. " " .. c - 1)
  21. end
  22. src_time = 0
  23. end
  24. return src_time
  25. end
  26. --------------------
  27. -- Forming a ring --
  28. --------------------
  29. minetest.register_craftitem("lottother:quarter_ring", {
  30. description = "Quarter Ring",
  31. inventory_image = "lottother_quarter_ring.png",
  32. groups = {forbidden=1},
  33. })
  34. minetest.register_craftitem("lottother:half_ring", {
  35. description = "Half Ring",
  36. inventory_image = "lottother_half_ring.png",
  37. groups = {forbidden=1},
  38. })
  39. minetest.register_craftitem("lottother:ring", {
  40. description = "Plain Ring",
  41. inventory_image = "lottother_ring.png",
  42. groups = {forbidden=1},
  43. })
  44. lottblocks.crafting.add_craft("lottother:quarter_ring", {
  45. recipe = {"lottother:ringsilver", "lottother:ringsilver"},
  46. type = "dualfurn",
  47. time = 7,
  48. func = function(pos, output, src_time)
  49. return random_break(pos, 1, output, src_time)
  50. end,
  51. })
  52. lottblocks.crafting.add_craft("lottother:half_ring", {
  53. recipe = {"lottother:quarter_ring", "lottother:quarter_ring"},
  54. type = "dualfurn",
  55. time = 14,
  56. func = function(pos, output, src_time)
  57. return random_break(pos, 2, output, src_time)
  58. end,
  59. })
  60. lottblocks.crafting.add_craft("lottother:ring", {
  61. recipe = {"lottother:half_ring", "lottother:half_ring"},
  62. type = "dualfurn",
  63. time = 28,
  64. func = function(pos, output, src_time)
  65. return random_break(pos, 3, output, src_time)
  66. end
  67. })
  68. ---------------------------------
  69. -- Attaching a gem to the ring --
  70. ---------------------------------
  71. -- Preparing the ring
  72. minetest.register_craftitem("lottother:pin", {
  73. description = "Pin",
  74. inventory_image = "lottother_pin.png",
  75. groups = {forbidden=1},
  76. })
  77. minetest.register_craftitem("lottother:prepared_ring", {
  78. description = "Prepared Ring",
  79. inventory_image = "lottother_prepared_ring.png",
  80. groups = {forbidden=1},
  81. })
  82. minetest.register_craft({
  83. output = "lottother:pin 2",
  84. type = "shapeless",
  85. recipe = {"lottother:ringsilver"},
  86. })
  87. minetest.register_craft({
  88. output = "lottother:prepared_ring",
  89. recipe = {
  90. {"lottother:pin", "", "lottother:pin"},
  91. {"", "lottother:ring", ""},
  92. }
  93. })
  94. -- The basic gemed rings.
  95. minetest.register_craftitem("lottother:blue_gem_ring", {
  96. description = "Sapphire Ring.",
  97. inventory_image = "lottother_bluegem_ring.png",
  98. groups = {forbidden=1},
  99. })
  100. minetest.register_craftitem("lottother:red_gem_ring", {
  101. description = "Ruby Ring",
  102. inventory_image = "lottother_redgem_ring.png",
  103. groups = {forbidden=1},
  104. })
  105. minetest.register_craftitem("lottother:purple_gem_ring", {
  106. description = "Amethyst Ring",
  107. inventory_image = "lottother_purplegem_ring.png",
  108. groups = {forbidden=1},
  109. })
  110. minetest.register_craftitem("lottother:white_gem_ring", {
  111. description = "Adamant Ring",
  112. inventory_image = "lottother_whitegem_ring.png",
  113. groups = {forbidden=1},
  114. })
  115. lottblocks.crafting.add_craft("lottother:blue_gem_ring", {
  116. recipe = {"lottother:prepared_ring", "lottother:blue_gem"},
  117. type = "dualfurn",
  118. time = 60,
  119. func = function(pos, output, src_time)
  120. return random_break(pos, 2, output, src_time)
  121. end
  122. })
  123. lottblocks.crafting.add_craft("lottother:red_gem_ring", {
  124. recipe = {"lottother:prepared_ring", "lottother:red_gem"},
  125. type = "dualfurn",
  126. time = 60,
  127. func = function(pos, output, src_time)
  128. return random_break(pos, 2, output, src_time)
  129. end
  130. })
  131. lottblocks.crafting.add_craft("lottother:purple_gem_ring", {
  132. recipe = {"lottother:prepared_ring", "lottother:purple_gem"},
  133. type = "dualfurn",
  134. time = 60,
  135. func = function(pos, output, src_time)
  136. return random_break(pos, 2, output, src_time)
  137. end
  138. })
  139. lottblocks.crafting.add_craft("lottother:white_gem_ring", {
  140. recipe = {"lottother:prepared_ring", "lottother:white_gem"},
  141. type = "dualfurn",
  142. time = 60,
  143. func = function(pos, output, src_time)
  144. return random_break(pos, 2, output, src_time)
  145. end
  146. })
  147. ---------------------------------
  148. -- Imbuing the ring with power --
  149. ---------------------------------
  150. -- First add a rough rock coating
  151. minetest.register_craftitem("lottother:blue_rr_ring", {
  152. description = "Coated Sapphire Ring",
  153. inventory_image = "lottother_bluegem_rr_ring.png",
  154. groups = {forbidden=1, ring = 1},
  155. stack_max = 1,
  156. })
  157. minetest.register_craftitem("lottother:red_rr_ring", {
  158. description = "Coated Ruby Ring",
  159. inventory_image = "lottother_redgem_rr_ring.png",
  160. groups = {forbidden=1, ring = 1},
  161. stack_max = 1,
  162. })
  163. minetest.register_craftitem("lottother:purple_rr_ring", {
  164. description = "Coated Amethyst Ring",
  165. inventory_image = "lottother_purplegem_rr_ring.png",
  166. groups = {forbidden=1, ring = 1},
  167. stack_max = 1,
  168. })
  169. minetest.register_craftitem("lottother:white_rr_ring", {
  170. description = "Coated Adamant Ring",
  171. inventory_image = "lottother_whitegem_rr_ring.png",
  172. groups = {forbidden=1, ring = 1},
  173. stack_max = 1,
  174. })
  175. minetest.register_craft({
  176. output = "lottother:blue_rr_ring",
  177. recipe = {
  178. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  179. {"lottores:rough_rock_lump", "lottother:blue_gem_ring", "lottores:rough_rock_lump"},
  180. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  181. },
  182. })
  183. minetest.register_craft({
  184. output = "lottother:red_rr_ring",
  185. recipe = {
  186. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  187. {"lottores:rough_rock_lump", "lottother:red_gem_ring", "lottores:rough_rock_lump"},
  188. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  189. },
  190. })
  191. minetest.register_craft({
  192. output = "lottother:purple_rr_ring",
  193. recipe = {
  194. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  195. {"lottores:rough_rock_lump", "lottother:purple_gem_ring", "lottores:rough_rock_lump"},
  196. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  197. },
  198. })
  199. minetest.register_craft({
  200. output = "lottother:white_rr_ring",
  201. recipe = {
  202. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  203. {"lottores:rough_rock_lump", "lottother:white_gem_ring", "lottores:rough_rock_lump"},
  204. {"lottores:rough_rock_lump", "lottores:rough_rock_lump", "lottores:rough_rock_lump"},
  205. },
  206. })
  207. -- Then cook in a special furnace!
  208. -- It's hard-coded, but has only one purpose (and, ofc, gets destroyed when used, 100% chance!)
  209. local formspec = "size[8,8]"..
  210. "background[-0.5,-0.65;9,9.35;gui_elfbg.png]"..
  211. "list[current_player;main;0,3.75;8,1;]"..
  212. "list[current_player;main;0,5;8,3;8]"..
  213. "list[context;ring;3.5,1.5;1,1;]"..
  214. "label[2.25,0.7;Galvorn]"..
  215. "list[context;galvorn;3.5,0.5;1,1;]"..
  216. "label[1.5,1.7;Mithril]"..
  217. "list[context;mithril;2.5,1.5;1,1;]"..
  218. "label[5.5,1.7;Tilkal]"..
  219. "list[context;tilkal;4.5,1.5;1,1;]"..
  220. "label[2.5,2.7;Fuel]"..
  221. "list[context;fuel;3.5,2.5;1,1;]"..
  222. "image[4.5,2.5;1,1;default_furnace_fire_bg.png]"..
  223. "image[5.5,2.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"
  224. local function can_dig(pos, player)
  225. local meta = minetest.get_meta(pos);
  226. local inv = meta:get_inventory()
  227. return inv:is_empty("goldsilver") and inv:is_empty("mithril")
  228. and inv:is_empty("roughrock") and inv:is_empty("fuel")
  229. end
  230. local function check_nodes(pos)
  231. for x = -1, 1 do
  232. for z = -1, 1 do
  233. local npos = {x = pos.x + x, y = pos.y - 1, z = pos.z + z}
  234. if minetest.get_node(npos).name ~= "default:lava_source" then
  235. return false
  236. end
  237. end
  238. end
  239. return true
  240. end
  241. local function is_cookable(inv)
  242. if inv:contains_item("mithril", "lottores:mithril_block")
  243. and inv:contains_item("tilkal", "lottores:tilkal")
  244. and inv:contains_item("galvorn", "lottores:galvorn_block") then
  245. if inv:contains_item("ring", "lottother:blue_rr_ring") then
  246. return true, "vilya"
  247. elseif inv:contains_item("ring", "lottother:red_rr_ring") then
  248. return true, "narya"
  249. elseif inv:contains_item("ring", "lottother:white_rr_ring") then
  250. return true, "nenya"
  251. elseif inv:contains_item("ring", "lottother:purple_rr_ring") then
  252. return true, "dwarf_ring"
  253. end
  254. end
  255. return false
  256. end
  257. local function take_items(inv)
  258. local c = inv:get_stack("mithril", 1):get_count() - 1
  259. inv:set_stack("mithril", 1, "lottores:mithril_block " .. c)
  260. c = inv:get_stack("goldsilver", 1):get_count() - 1
  261. inv:set_stack("tilkal", 1, "lottores:tilkal " .. c)
  262. c = inv:get_stack("galvorn", 1):get_count() - 1
  263. inv:set_stack("galvorn", 1, "lottores:galvorn_block " .. c)
  264. inv:set_stack("ring", 1, "")
  265. end
  266. local function swap_node(pos, name)
  267. local node = minetest.get_node(pos)
  268. if node.name == name then
  269. return
  270. end
  271. node.name = name
  272. minetest.swap_node(pos, node)
  273. end
  274. local function furnace_node_timer(pos, elapsed)
  275. local meta = minetest.get_meta(pos)
  276. local fuel_time = meta:get_float("fuel_time") or 0
  277. local src_time = meta:get_float("src_time") or 0
  278. local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
  279. local time = 1800
  280. local inv = meta:get_inventory()
  281. local fuel = inv:get_list("fuel")
  282. local cookable, ring = is_cookable(inv)
  283. -- Check if we have enough fuel to burn
  284. if fuel_time < fuel_totaltime then
  285. -- The furnace is currently active and has enough fuel
  286. fuel_time = fuel_time + 1
  287. -- If there is a cookable item then check if it is ready yet
  288. if cookable then
  289. src_time = src_time + 1
  290. if src_time % 50 == 0 then
  291. if check_nodes(pos) == false then
  292. default.explode(pos, 0, 4, 20)
  293. end
  294. end
  295. if src_time >= time then
  296. take_items(inv)
  297. if math.random(1,3) ~= 1 then
  298. local item = minetest.add_item({x=pos.x, y=pos.y+1, z=pos.z},
  299. "lottother:" .. ring)
  300. item:setvelocity({x=0, y=15, z=0})
  301. item:set_properties({automatic_rotate = 20})
  302. minetest.add_particlespawner({
  303. amount = 250,
  304. time = 5,
  305. minvel = {x=-3, y=3, z=-3},
  306. maxvel = {x=3, y=7, z=3},
  307. minacc = {x=-2, y=1, z=-2},
  308. maxacc = {x=2, y=5, z=2},
  309. minexptime = 1,
  310. maxexptime = 4,
  311. attached = item,
  312. glow = 14,
  313. texture = "fire_basic_flame.png",
  314. })
  315. local pn = meta:get_string("player_name")
  316. if pn and pn ~= "" then
  317. lottachievements.unlock(pn, "ring_smith")
  318. end
  319. default.explode(pos, 0, 10, 5)
  320. else
  321. default.explode(pos, 0, 5, 40)
  322. end
  323. src_time = 0
  324. end
  325. end
  326. else
  327. -- Furnace ran out of fuel
  328. if cookable then
  329. -- We need to get new fuel
  330. local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuel})
  331. if fuel.time == 0 then
  332. -- No valid fuel in fuel list
  333. fuel_totaltime = 0
  334. fuel_time = 0
  335. src_time = 0
  336. else
  337. -- Take fuel from fuel list
  338. inv:set_stack("fuel", 1, afterfuel.items[1])
  339. fuel_totaltime = fuel.time
  340. fuel_time = 0
  341. end
  342. else
  343. -- We don't need to get new fuel since there is no cookable item
  344. fuel_totaltime = 0
  345. fuel_time = 0
  346. src_time = 0
  347. end
  348. end
  349. --
  350. -- Update formspec, infotext and node
  351. --
  352. local item_state = ""
  353. local fuel_state = "Empty"
  354. local active = "inactive "
  355. local result = false
  356. local item_percent = 0
  357. local new_formspec = formspec
  358. if time then
  359. item_percent = math.floor(src_time / time * 100)
  360. end
  361. if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then
  362. swap_node(pos, "lottother:ring_furnace_active")
  363. result = true
  364. local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
  365. new_formspec = new_formspec ..
  366. "image[5.5,2.5;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
  367. (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
  368. "image[4.5,2.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
  369. (100-fuel_percent)..":default_furnace_fire_fg.png]"
  370. else
  371. swap_node(pos, "lottother:ring_furnace_inactive")
  372. local timer = minetest.get_node_timer(pos)
  373. timer:stop()
  374. end
  375. --
  376. -- Set meta values
  377. --
  378. meta:set_float("fuel_totaltime", fuel_totaltime)
  379. meta:set_float("fuel_time", fuel_time)
  380. meta:set_float("src_time", src_time)
  381. meta:set_string("formspec", new_formspec)
  382. return result
  383. end
  384. --
  385. -- Node definitions
  386. --
  387. for _, status in pairs({"active", "inactive"}) do
  388. local groups = {forbidden=1, very_hard=1, creative=1}
  389. if status == "active" then
  390. groups.not_in_creative_inventory = 1
  391. end
  392. minetest.register_node("lottother:ring_furnace_" .. status, {
  393. description = "Ring Furnace",
  394. tiles = {
  395. "lottother_ring_furnace_side.png",
  396. "lottother_ring_furnace_side.png",
  397. "lottother_ring_furnace_side.png",
  398. "lottother_ring_furnace_side.png",
  399. "lottother_ring_furnace_side.png",
  400. "lottother_ring_furnace_front_" .. status .. ".png"
  401. },
  402. paramtype2 = "facedir",
  403. groups = groups,
  404. drop = "lottother:ring_furnace_inactive",
  405. legacy_facedir_simple = true,
  406. is_ground_content = false,
  407. can_dig = can_dig,
  408. on_timer = furnace_node_timer,
  409. on_construct = function(pos)
  410. local meta = minetest.get_meta(pos)
  411. local inv = meta:get_inventory()
  412. inv:set_size("tilkal", 1)
  413. inv:set_size("mithril", 1)
  414. inv:set_size("galvorn", 1)
  415. inv:set_size("ring", 1)
  416. inv:set_size("fuel", 1)
  417. meta:set_string("infotext", "Ringsilver Furnace")
  418. meta:set_string("formspec", formspec)
  419. end,
  420. on_metadata_inventory_move = function(pos)
  421. local timer = minetest.get_node_timer(pos)
  422. timer:start(1.0)
  423. end,
  424. on_metadata_inventory_put = function(pos, _, _, _, player)
  425. -- start timer function, it will sort out whether furnace can burn or not.
  426. local meta = minetest.get_meta(pos)
  427. meta:set_string("player_name", player:get_player_name())
  428. local timer = minetest.get_node_timer(pos)
  429. timer:start(1.0)
  430. end,
  431. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  432. if listname == "fuel" then
  433. if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
  434. return stack:get_count()
  435. end
  436. elseif listname == "galvorn" then
  437. if stack:get_name() == "lottores:galvorn_block" then
  438. return 1
  439. end
  440. elseif listname == "tilkal" then
  441. if stack:get_name() == "lottores:tilkal" then
  442. return 1
  443. end
  444. elseif listname == "mithril" then
  445. if stack:get_name() == "lottores:mithril_block" then
  446. return 1
  447. end
  448. elseif listname == "ring" then
  449. if stack:get_definition().groups.ring == 1 then
  450. return 1
  451. end
  452. end
  453. return 0
  454. end,
  455. allow_metadata_inventory_move = function()
  456. return 0
  457. end,
  458. on_place = function(itemstack, placer, pointed_thing)
  459. if check_nodes(pointed_thing.above) == false then
  460. minetest.chat_send_player(placer:get_player_name(),
  461. "This area is not hot enough for a ringsilver furnace.")
  462. return
  463. end
  464. return minetest.item_place(itemstack, placer, pointed_thing)
  465. end,
  466. })
  467. end
  468. minetest.register_craft({
  469. output = "lottother:ring_furnace_inactive",
  470. recipe = {
  471. {"lottores:galvorn_block", "lottores:mithril_block", "lottores:galvorn_block"},
  472. {"default:steelblock", "lottother:ringsilver_furnace_inactive", "default:steelblock"},
  473. {"lottores:tilkal", "lottores:mithril_block", "lottores:tilkal"},
  474. },
  475. })