From 9dc9c12f29e12158fddc56f12811a4327391d1cb Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Thu, 30 Jan 2020 22:05:18 +0100 Subject: [PATCH] Implement TNT minecart --- mods/ENTITIES/mcl_minecarts/init.lua | 121 +++++++++++++++++- mods/ENTITIES/mcl_minecarts/rails.lua | 15 +++ .../textures/mcl_minecarts_minecart_tnt.png | Bin 249 -> 257 bytes mods/ITEMS/mcl_tnt/init.lua | 33 +++-- 4 files changed, 150 insertions(+), 19 deletions(-) diff --git a/mods/ENTITIES/mcl_minecarts/init.lua b/mods/ENTITIES/mcl_minecarts/init.lua index 06f817e420..104846627e 100644 --- a/mods/ENTITIES/mcl_minecarts/init.lua +++ b/mods/ENTITIES/mcl_minecarts/init.lua @@ -8,10 +8,29 @@ mcl_minecarts.check_float_time = 15 dofile(mcl_minecarts.modpath.."/functions.lua") dofile(mcl_minecarts.modpath.."/rails.lua") +local function activate_tnt_minecart(self) + if self._boomtimer then + return + end + self.object:set_armor_groups({immortal=1}) + self._boomtimer = tnt.BOOMTIMER + self.object:set_properties({textures = { + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_minecarts_minecart.png", + }}) + self._blinktimer = tnt.BLINKTIMER + minetest.sound_play("tnt_ignite", {pos = self.object:get_pos(), gain = 1.0, max_hear_distance = 15}) +end + -- Table for item-to-entity mapping. Keys: itemstring, Values: Corresponding entity ID local entity_mapping = {} -local function register_entity(entity_id, mesh, textures, drop, on_rightclick) +local function register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail) local cart = { physical = false, collisionbox = {-10/16., -0.5, -10/16, 10/16, 0.25, 10/16}, @@ -28,6 +47,9 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) _start_pos = nil, -- Used to calculate distance for “On A Rail” achievement _last_float_check = nil, -- timestamp of last time the cart was checked to be still on a rail _fueltime = nil, -- how many seconds worth of fuel is left. Only used by minecart with furnace + _boomtimer = nil, -- how many seconds are left before exploding + _blinktimer = nil, -- how many seconds are left before TNT blinking + _blink = false, -- is TNT blink texture active? _old_dir = {x=0, y=0, z=0}, _old_pos = nil, _old_vel = {x=0, y=0, z=0}, @@ -36,11 +58,21 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) } function cart:on_activate(staticdata, dtime_s) + -- Initialize local data = minetest.deserialize(staticdata) if type(data) == "table" then self._railtype = data._railtype end self.object:set_armor_groups({immortal=1}) + + -- Activate cart if on activator rail + if self.on_activate_by_rail then + local pos = self.object:get_pos() + local node = minetest.get_node(vector.floor(pos)) + if node.name == "mcl_minecarts:activator_rail_on" then + self:on_activate_by_rail() + end + end end function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) @@ -61,7 +93,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) return end - if puncher:get_player_control().sneak then + -- Punch+sneak: Pick up minecart (unless TNT was ignited) + if puncher:get_player_control().sneak and not self._boomtimer then if self._driver then if self._old_pos then self.object:set_pos(self._old_pos) @@ -123,6 +156,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) self._punched = true end + cart.on_activate_by_rail = on_activate_by_rail + function cart:on_step(dtime) local vel = self.object:get_velocity() local update = {} @@ -152,8 +187,15 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) end end + -- Explode if already ignited + if self._boomtimer then + self.object:remove() + tnt.boom(pos) + return + end + -- Drop items and remove cart entity - if not minetest.settings:get_bool("creative_mode") then + if not minetest.settings:get_bool("creative_mode") then for d=1, #drop do minetest.add_item(self.object:get_pos(), drop[d]) end @@ -165,7 +207,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) self._last_float_check = 0 end - -- Update furnace texture if out of fuel + -- Update furnace stuff if self._fueltime and self._fueltime > 0 then self._fueltime = self._fueltime - dtime if self._fueltime <= 0 then @@ -184,6 +226,50 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) end local has_fuel = self._fueltime and self._fueltime > 0 + -- Update TNT stuff + if self._boomtimer then + -- Explode + self._boomtimer = self._boomtimer - dtime + local pos = self.object:get_pos() + if self._boomtimer <= 0 then + self.object:remove() + tnt.boom(pos) + return + else + tnt.smoke_step(pos) + end + end + if self._blinktimer then + self._blinktimer = self._blinktimer - dtime + if self._blinktimer <= 0 then + self._blink = not self._blink + if self._blink then + self.object:set_properties({textures = + { + "default_tnt_top.png", + "default_tnt_bottom.png", + "default_tnt_side.png", + "default_tnt_side.png", + "default_tnt_side.png", + "default_tnt_side.png", + "mcl_minecarts_minecart.png", + }}) + else + self.object:set_properties({textures = + { + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_tnt_blink.png", + "mcl_minecarts_minecart.png", + }}) + end + self._blinktimer = tnt.BLINKTIMER + end + end + if self._punched then vel = vector.add(vel, self._velocity) self.object:set_velocity(vel) @@ -224,6 +310,10 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick) minetest.swap_node(rou_old, newnode) mesecon.receptor_off(rou_old) end + -- Activate minecart if on activator rail + if node_old.name == "mcl_minecarts:activator_rail_on" and self.on_activate_by_rail then + self:on_activate_by_rail() + end end local ctrl, player = nil, nil @@ -483,7 +573,7 @@ Register a minecart * creative: If false, don't show in Creative Inventory ]] local function register_minecart(itemstring, entity_id, description, longdesc, usagehelp, mesh, textures, icon, drop, on_rightclick, on_activate_by_rail, creative) - register_entity(entity_id, mesh, textures, drop, on_rightclick) + register_entity(entity_id, mesh, textures, drop, on_rightclick, on_activate_by_rail) register_craftitem(itemstring, entity_id, description, longdesc, usagehelp, icon, creative) if minetest.get_modpath("doc_identifier") ~= nil then doc.sub.identifier.register_object(entity_id, "craftitems", itemstring) @@ -651,8 +741,25 @@ register_minecart( }, "mcl_minecarts_minecart_tnt.png", {"mcl_minecarts:minecart", "mcl_tnt:tnt"}, - nil, nil, false -) + -- Ingite + function(self, clicker) + if not clicker or not clicker:is_player() then + return + end + if self._boomtimer then + return + end + local held = clicker:get_wielded_item() + if held:get_name() == "mcl_fire:flint_and_steel" then + if not minetest.settings:get_bool("creative_mode") then + held:add_wear(65535/65) -- 65 uses + local index = clicker:get_wielded_index() + local inv = clicker:get_inventory() + inv:set_stack("main", index, held) + end + activate_tnt_minecart(self) + end + end, activate_tnt_minecart, false) minetest.register_craft({ diff --git a/mods/ENTITIES/mcl_minecarts/rails.lua b/mods/ENTITIES/mcl_minecarts/rails.lua index cf1ebacf15..bc94e54be2 100644 --- a/mods/ENTITIES/mcl_minecarts/rails.lua +++ b/mods/ENTITIES/mcl_minecarts/rails.lua @@ -129,6 +129,7 @@ register_rail("mcl_minecarts:activator_rail", offstate = "mcl_minecarts:activator_rail", onstate = "mcl_minecarts:activator_rail_on", rules = rail_rules_long, + }, }, }, @@ -149,6 +150,20 @@ register_rail("mcl_minecarts:activator_rail_on", onstate = "mcl_minecarts:activator_rail_on", rules = rail_rules_long, }, + effector = { + -- Activate minecarts + action_on = function(pos, node) + local pos2 = { x = pos.x, y =pos.y + 1, z = pos.z } + local objs = minetest.get_objects_inside_radius(pos2, 1) + for _, o in pairs(objs) do + local l = o:get_luaentity() + if l and string.sub(l.name, 1, 14) == "mcl_minecarts:" and l.on_activate_by_rail then + l:on_activate_by_rail() + end + end + end, + }, + }, drop = "mcl_minecarts:activator_rail", }, diff --git a/mods/ENTITIES/mcl_minecarts/textures/mcl_minecarts_minecart_tnt.png b/mods/ENTITIES/mcl_minecarts/textures/mcl_minecarts_minecart_tnt.png index cbd312804541e75c6b6d2e9d3e97826b1fa99fd8..246d36328c86e97f58f3042505429ea3a41f7b8c 100644 GIT binary patch delta 241 zcmey#*vK?NqMn7Bfq~)e-A6${N-Mx8#P$FG|H{hB_4<|*O>DMXSln>3($UcYipa>w zT-dW@@2VNLwzi(0o}^Oim)Ii8;CkuO_V6wF2^sm`x3|@@2l!T3RsGu5CCkH;e(sH3aaB1pbBOq1RmdKI;Vst07&&&{{R30 delta 233 zcmV)-7K8rX0obJv7!3J7UuEjW00000NkvXXu0mjfZ1G?i diff --git a/mods/ITEMS/mcl_tnt/init.lua b/mods/ITEMS/mcl_tnt/init.lua index 342e0c58a7..62f3710ae8 100644 --- a/mods/ITEMS/mcl_tnt/init.lua +++ b/mods/ITEMS/mcl_tnt/init.lua @@ -48,6 +48,23 @@ tnt.ignite = function(pos) core.check_for_falling(pos) end +-- Add smoke particle of entity at pos. +-- Intended to be called every step +tnt.smoke_step = function(pos) + minetest.add_particle({ + pos = {x=pos.x,y=pos.y+0.5,z=pos.z}, + velocity = vector.new(math.random() * 0.2 - 0.1, 1.0 + math.random(), math.random() * 0.2 - 0.1), + acceleration = vector.new(0, -0.1, 0), + expirationtime = 0.15 + math.random() * 0.25, + size = 1.0 + math.random(), + collisiondetection = false, + texture = "tnt_smoke.png" + }) +end + +tnt.BOOMTIMER = 4 +tnt.BLINKTIMER = 0.25 + local TNT_RANGE = 3 local sounds @@ -162,19 +179,11 @@ end function TNT:on_step(dtime) local pos = self.object:get_pos() - minetest.add_particle({ - pos = {x=pos.x,y=pos.y+0.5,z=pos.z}, - velocity = vector.new(math.random() * 0.2 - 0.1, 1.0 + math.random(), math.random() * 0.2 - 0.1), - acceleration = vector.new(0, -0.1, 0), - expirationtime = 0.15 + math.random() * 0.25, - size = 1.0 + math.random(), - collisiondetection = false, - texture = "tnt_smoke.png" - }) + tnt.smoke_step(pos) self.timer = self.timer + dtime self.blinktimer = self.blinktimer + dtime - if self.blinktimer > 0.25 then - self.blinktimer = self.blinktimer - 0.25 + if self.blinktimer > tnt.BLINKTIMER then + self.blinktimer = self.blinktimer - tnt.BLINKTIMER if self.blinkstatus then self.object:set_texture_mod("") else @@ -182,7 +191,7 @@ function TNT:on_step(dtime) end self.blinkstatus = not self.blinkstatus end - if self.timer > 4 then + if self.timer > tnt.BOOMTIMER then tnt.boom(self.object:get_pos()) self.object:remove() end