Zefram
2014-08-17 d0efa15b983f7a0a96e1a7abcdad713715dfeeeb
commit | author | age
ee0765 1 -- Forcefield mod by ShadowNinja
S 2 -- Modified by kpoppel
3 --
4 -- Forcefields are powerful barriers but they consume huge amounts of power.
5 -- Forcefield Generator is a HV machine.
6
7 -- How expensive is the generator?
8 -- Leaves room for upgrades lowering the power drain?
9 local forcefield_power_drain   = 10
10 local forcefield_step_interval = 1
11
be2f30 12 local S = technic.getter
S 13
ee0765 14 minetest.register_craft({
S 15     output = 'technic:forcefield_emitter_off',
16     recipe = {
e8a5a6 17             {'default:mese',         'technic:motor',          'default:mese'        },
Z 18             {'technic:deployer_off', 'technic:machine_casing', 'technic:deployer_off'},
68ea0a 19             {'default:mese',         'technic:hv_cable0',      'default:mese'        },
ee0765 20     }
S 21 })
22
23
24 -- Idea: Let forcefields have different colors by upgrade slot.
25 -- Idea: Let forcefields add up by detecting if one hits another.
26 --    ___   __
27 --   /   \/   \
28 --  |          |
29 --   \___/\___/
30
830de4 31 local function update_forcefield(pos, meta, active)
Z 32     local shape = meta:get_int("shape")
33     local range = meta:get_int("range")
ee0765 34     local vm = VoxelManip()
S 35     local p1 = {x = pos.x-range, y = pos.y-range, z = pos.z-range}
36     local p2 = {x = pos.x+range, y = pos.y+range, z = pos.z+range}
37     local MinEdge, MaxEdge = vm:read_from_map(p1, p2)
38     local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
39     local data = vm:get_data()
40
41     local c_air   = minetest.get_content_id("air")
42     local c_field = minetest.get_content_id("technic:forcefield")
43
44     for z=-range, range do
45     for y=-range, range do
46     local vi = area:index(pos.x+(-range), pos.y+y, pos.z+z)
47     for x=-range, range do
830de4 48         local relevant
Z 49         if shape == 0 then
50             relevant =
51                x*x+y*y+z*z <= range     *  range    +  range    and
52                x*x+y*y+z*z >= (range-1) * (range-1) + (range-1)
53         else
54             relevant =
55                 x == -range or x == range or
56                 y == -range or y == range or
57                 z == -range or z == range
58         end
59         if relevant then
ee0765 60             if active and data[vi] == c_air then
S 61                 data[vi] = c_field
62             elseif not active and data[vi] == c_field then
63                 data[vi] = c_air
64             end
65         end
66         vi = vi + 1
67     end
68     end
69     end
70
71     vm:set_data(data)
72     vm:update_liquids()
73     vm:write_to_map()
74     vm:update_map()
75 end
76
2d6f34 77 local function set_forcefield_formspec(meta)
cca72f 78     local formspec = "size[5,2.25]"..
830de4 79         "field[0.3,0.5;2,1;range;"..S("Range")..";"..meta:get_int("range").."]"
cca72f 80     -- The names for these toggle buttons are explicit about which
Z 81     -- state they'll switch to, so that multiple presses (arising
82     -- from the ambiguity between lag and a missed press) only make
83     -- the single change that the user expects.
830de4 84     if meta:get_int("shape") == 0 then
Z 85         formspec = formspec.."button[3,0.2;2,1;shape1;"..S("Sphere").."]"
86     else
87         formspec = formspec.."button[3,0.2;2,1;shape0;"..S("Cube").."]"
88     end
6a4cb1 89     if meta:get_int("mesecon_mode") == 0 then
cca72f 90         formspec = formspec.."button[0,1;5,1;mesecon_mode_1;"..S("Ignoring Mesecon Signal").."]"
2d6f34 91     else
cca72f 92         formspec = formspec.."button[0,1;5,1;mesecon_mode_0;"..S("Controlled by Mesecon Signal").."]"
6a4cb1 93     end
Z 94     if meta:get_int("enabled") == 0 then
cca72f 95         formspec = formspec.."button[0,1.75;5,1;enable;"..S("%s Disabled"):format(S("%s Forcefield Emitter"):format("HV")).."]"
6a4cb1 96     else
cca72f 97         formspec = formspec.."button[0,1.75;5,1;disable;"..S("%s Enabled"):format(S("%s Forcefield Emitter"):format("HV")).."]"
2d6f34 98     end
Z 99     meta:set_string("formspec", formspec)
ee0765 100 end
S 101
102 local forcefield_receive_fields = function(pos, formname, fields, sender)
103     local meta = minetest.get_meta(pos)
830de4 104     local range = nil
2d6f34 105     if fields.range then
830de4 106         range = tonumber(fields.range) or 0
2d6f34 107         -- Smallest field is 5. Anything less is asking for trouble.
Z 108         -- Largest is 20. It is a matter of pratical node handling.
109         -- At the maximim range updating the forcefield takes about 0.2s
110         range = math.max(range, 5)
111         range = math.min(range, 20)
830de4 112         if range == meta:get_int("range") then range = nil end
ee0765 113     end
830de4 114     if fields.shape0 or fields.shape1 or range then
Z 115         update_forcefield(pos, meta, false)
116     end
117     if range then meta:set_int("range", range) end
118     if fields.shape0 then meta:set_int("shape", 0) end
119     if fields.shape1 then meta:set_int("shape", 1) end
2d6f34 120     if fields.enable then meta:set_int("enabled", 1) end
Z 121     if fields.disable then meta:set_int("enabled", 0) end
6a4cb1 122     if fields.mesecon_mode_0 then meta:set_int("mesecon_mode", 0) end
Z 123     if fields.mesecon_mode_1 then meta:set_int("mesecon_mode", 1) end
2d6f34 124     set_forcefield_formspec(meta)
ee0765 125 end
S 126
127 local mesecons = {
128     effector = {
129         action_on = function(pos, node)
6a4cb1 130             minetest.get_meta(pos):set_int("mesecon_effect", 1)
ee0765 131         end,
S 132         action_off = function(pos, node)
6a4cb1 133             minetest.get_meta(pos):set_int("mesecon_effect", 0)
ee0765 134         end
S 135     }
136 }
137
563a4c 138 local run = function(pos, node, active_object_count, active_object_count_wider)
N 139     local meta = minetest.get_meta(pos)
140     local eu_input   = meta:get_int("HV_EU_input")
cca72f 141     local enabled = meta:get_int("enabled") ~= 0 and (meta:get_int("mesecon_mode") == 0 or meta:get_int("mesecon_effect") ~= 0)
563a4c 142     local machine_name = S("%s Forcefield Emitter"):format("HV")
N 143
830de4 144     local range = meta:get_int("range")
Z 145     local power_requirement
146     if meta:get_int("shape") == 0 then
147         power_requirement = math.floor(4 * math.pi * range * range)
148     else
149         power_requirement = 24 * range * range
150     end
151     power_requirement = power_requirement * forcefield_power_drain
563a4c 152
6a4cb1 153     if not enabled then
563a4c 154         if node.name == "technic:forcefield_emitter_on" then
830de4 155             update_forcefield(pos, meta, false)
563a4c 156             technic.swap_node(pos, "technic:forcefield_emitter_off")
N 157             meta:set_string("infotext", S("%s Disabled"):format(machine_name))
158         end
849526 159         meta:set_int("HV_EU_demand", 0)
Z 160         return
161     end
162     meta:set_int("HV_EU_demand", power_requirement)
163     if eu_input < power_requirement then
563a4c 164         meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
N 165         if node.name == "technic:forcefield_emitter_on" then
830de4 166             update_forcefield(pos, meta, false)
563a4c 167             technic.swap_node(pos, "technic:forcefield_emitter_off")
N 168         end
169     elseif eu_input >= power_requirement then
170         if node.name == "technic:forcefield_emitter_off" then
171             technic.swap_node(pos, "technic:forcefield_emitter_on")
172             meta:set_string("infotext", S("%s Active"):format(machine_name))
173         end
830de4 174         update_forcefield(pos, meta, true)
563a4c 175     end
N 176 end
177
ee0765 178 minetest.register_node("technic:forcefield_emitter_off", {
7c4b70 179     description = S("%s Forcefield Emitter"):format("HV"),
ee0765 180     tiles = {"technic_forcefield_emitter_off.png"},
563a4c 181     groups = {cracky = 1, technic_machine = 1},
ee0765 182     on_receive_fields = forcefield_receive_fields,
S 183     on_construct = function(pos)
184         local meta = minetest.get_meta(pos)
185         meta:set_int("HV_EU_input", 0)
186         meta:set_int("HV_EU_demand", 0)
187         meta:set_int("range", 10)
188         meta:set_int("enabled", 0)
6a4cb1 189         meta:set_int("mesecon_mode", 0)
Z 190         meta:set_int("mesecon_effect", 0)
7c4b70 191         meta:set_string("infotext", S("%s Forcefield Emitter"):format("HV"))
2d6f34 192         set_forcefield_formspec(meta)
ee0765 193     end,
563a4c 194     mesecons = mesecons,
N 195     technic_run = run,
ee0765 196 })
S 197
198 minetest.register_node("technic:forcefield_emitter_on", {
7c4b70 199     description = S("%s Forcefield Emitter"):format("HV"),
ee0765 200     tiles = {"technic_forcefield_emitter_on.png"},
563a4c 201     groups = {cracky = 1, technic_machine = 1, not_in_creative_inventory=1},
ee0765 202     drop = "technic:forcefield_emitter_off",
S 203     on_receive_fields = forcefield_receive_fields,
204     on_destruct = function(pos)
205         local meta = minetest.get_meta(pos)
830de4 206         update_forcefield(pos, meta, false)
ee0765 207     end,
563a4c 208     mesecons = mesecons,
N 209     technic_run = run,
2a7ee1 210     technic_on_disable = function (pos, node)
Z 211         local meta = minetest.get_meta(pos)
830de4 212         update_forcefield(pos, meta, false)
2a7ee1 213         technic.swap_node(pos, "technic:forcefield_emitter_off")
Z 214     end,
ee0765 215 })
S 216
217 minetest.register_node("technic:forcefield", {
7c4b70 218     description = S("%s Forcefield"):format("HV"),
ee0765 219     sunlight_propagates = true,
S 220     drawtype = "glasslike",
221     groups = {not_in_creative_inventory=1, unbreakable=1},
222     paramtype = "light",
223         light_source = 15,
224     drop = '',
225     tiles = {{
226         name = "technic_forcefield_animated.png",
227         animation = {
228             type = "vertical_frames",
229             aspect_w = 16,
230             aspect_h = 16,
231             length = 1.0,
232         },
233     }},
234 })
235
236
237 if minetest.get_modpath("mesecons_mvps") then
238     mesecon:register_mvps_stopper("technic:forcefield")
239 end
240
241 technic.register_machine("HV", "technic:forcefield_emitter_on",  technic.receiver)
242 technic.register_machine("HV", "technic:forcefield_emitter_off", technic.receiver)
243