ShadowNinja
2013-07-12 4f35f407cebb32cf126a791b610a0bd379366dd0
commit | author | age
9a0d3f 1 -- Forcefield mod by ShadowNinja
K 2 -- Modified by kpoppel
3 --
4 -- Forcefields are powerful barriers but they consume huge amounts of power.
5 -- Forcefield Generator is a HV machine.
c6da0a 6
73209c 7 -- How expensive is the generator? Leaves room for upgrades lowering the power drain?
30361a 8 local forcefield_power_drain     = 10
4f35f4 9 local forcefield_step_interval = 1
c6da0a 10
R 11 minetest.register_craft({
12     output = 'technic:forcefield_emitter_off',
13     recipe = {
14             {'default:mese',         'technic:deployer_off', 'default:mese'        },
15             {'technic:deployer_off', 'technic:motor',        'technic:deployer_off'},
16             {'default:mese',         'technic:deployer_off', 'default:mese'        },
17     }
18 })
19
30361a 20
9a0d3f 21 -- Idea: Let forcefields have different colors by upgrade slot.
K 22 -- Idea: Let forcefields add up by detecting if one hits another.
23 --    ___   __
24 --   /   \/   \
25 --  |          |
26 --   \___/\___/
30361a 27
4f35f4 28 local function update_forcefield(pos, range, active)
S 29     local vm = VoxelManip()
30     local p1 = {x = pos.x-range, y = pos.y-range, z = pos.z-range}
31     local p2 = {x = pos.x+range, y = pos.y+range, z = pos.z+range}
32     local MinEdge, MaxEdge = vm:read_from_map(p1, p2)
33     local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
34     local data = vm:get_data()
30361a 35
4f35f4 36     local c_air   = minetest.get_content_id("air")
S 37     local c_field = minetest.get_content_id("technic:forcefield")
38
39     for z=-range, range do
40     for y=-range, range do
41     local vi = area:index(pos.x+(-range), pos.y+y, pos.z+z)
42     for x=-range, range do
43         if x*x+y*y+z*z <= range     *  range    +  range    and
44            x*x+y*y+z*z >= (range-1) * (range-1) + (range-1) and
45            ((active and data[vi] == c_air) or ((not active) and data[vi] == c_field)) then
46                if active then
47                 data[vi] = c_field
48             else
49                 data[vi] = c_air
c6da0a 50             end
R 51         end
4f35f4 52         vi = vi + 1
c6da0a 53     end
R 54     end
55     end
56
4f35f4 57     vm:set_data(data)
S 58     vm:update_liquids()
59     vm:write_to_map()
60     vm:update_map()
c6da0a 61 end
R 62
9a0d3f 63 local get_forcefield_formspec = function(range)
K 64     return "invsize[3,4;]"..
30361a 65         "label[0,0;Forcefield emitter]"..
S 66         "label[1,1;Range]"..
67         "label[1,2;"..range.."]"..
68         "button[0,2;1,1;subtract;-]"..
69         "button[2,2;1,1;add;+]"..
70         "button[0,3;3,1;toggle;Enable/Disable]"
c6da0a 71 end
R 72
9a0d3f 73 local forcefield_receive_fields = function(pos, formname, fields, sender)
30361a 74     local meta = minetest.env:get_meta(pos)
S 75     local range = meta:get_int("range")
9a0d3f 76
30361a 77     if fields.add then range = range + 1 end
S 78     if fields.subtract then range = range - 1 end
79     if fields.toggle then
80         if meta:get_int("enabled") == 1 then
81            meta:set_int("enabled", 0)
82         else
83            meta:set_int("enabled", 1)
84         end
85     end
86
87     -- Smallest field is 5. Anything less is asking for trouble.
88     -- Largest is 20. It is a matter of pratical node handling.
89     if range < 5  then range = 5 end
90     if range > 20 then range = 20 end
91
92     if range <= 20 and range >= 5 and meta:get_int("range") ~= range then
4f35f4 93         update_forcefield(pos, meta:get_int("range"), false)
30361a 94         meta:set_int("range", range)
S 95         meta:set_string("formspec", get_forcefield_formspec(range))
96     end
97 end
c6da0a 98
4f35f4 99 local function forcefield_step(pos)
30361a 100     local meta = minetest.env:get_meta(pos)
S 101     local node = minetest.env:get_node(pos)
102     local eu_input   = meta:get_int("HV_EU_input")
103     local eu_demand  = meta:get_int("HV_EU_demand")
104     local enabled    = meta:get_int("enabled")
c6da0a 105
30361a 106     -- Power off automatically if no longer connected to a switching station
S 107     technic.switching_station_timeout_count(pos, "HV")
c6da0a 108
30361a 109     local power_requirement = 0
S 110     if enabled == 1 then
111         power_requirement = math.floor(
112                 4 * math.pi * math.pow(meta:get_int("range"), 2)
113             ) * forcefield_power_drain
114     else
115         power_requirement = eu_demand
e5d48e 116     end
30361a 117
S 118     if meta:get_int("enabled") == 0 then
119         if node.name == "technic:forcefield_emitter_on" then
4f35f4 120             update_forcefield(pos, meta:get_int("range"), false)
30361a 121             hacky_swap_node(pos, "technic:forcefield_emitter_off")
S 122             meta:set_int("HV_EU_demand", 100)
123             meta:set_string("infotext", "Forcefield Generator Disabled")
124         end
125     elseif eu_input < power_requirement then
126         meta:set_string("infotext", "Forcefield Generator Unpowered")
127         if node.name == "technic:forcefield_emitter_on" then
4f35f4 128             update_forcefield(pos, meta:get_int("range"), false)
30361a 129             hacky_swap_node(pos, "technic:forcefield_emitter_off")
S 130         end
131     elseif eu_input >= power_requirement then
132         if node.name == "technic:forcefield_emitter_off" then
133             hacky_swap_node(pos, "technic:forcefield_emitter_on")
134             meta:set_string("infotext", "Forcefield Generator Active")
135         end
4f35f4 136         update_forcefield(pos, meta:get_int("range"), true)
30361a 137     end
S 138     meta:set_int("HV_EU_demand", power_requirement)
139     return true
140 end
141
142 local mesecons = {
143     effector = {
144         action_on = function(pos, node)
145             minetest.env:get_meta(pos):set_int("enabled", 0)
146         end,
147         action_off = function(pos, node)
148             minetest.env:get_meta(pos):set_int("enabled", 1)
149         end
150     }
151 }
c6da0a 152
R 153 minetest.register_node("technic:forcefield_emitter_off", {
154     description = "Forcefield emitter",
155     inventory_image = minetest.inventorycube("technic_forcefield_emitter_off.png"),
156     tiles = {"technic_forcefield_emitter_off.png"},
157     is_ground_content = true,
158     groups = {cracky = 1},
4f35f4 159     on_timer = forcefield_step,
c6da0a 160     on_receive_fields = forcefield_receive_fields,
R 161     on_construct = function(pos)
4f35f4 162         minetest.env:get_node_timer(pos):start(forcefield_step_interval)
c6da0a 163         local meta = minetest.env:get_meta(pos)
9a0d3f 164         meta:set_float("technic_hv_power_machine", 1)
K 165         meta:set_int("HV_EU_input", 0)
166         meta:set_int("HV_EU_demand", 0)
c6da0a 167         meta:set_int("range", 10)
9a0d3f 168         meta:set_int("enabled", 0)
K 169         meta:set_string("formspec", get_forcefield_formspec(meta:get_int("range")))
c6da0a 170         meta:set_string("infotext", "Forcefield emitter");
R 171     end,
e5d48e 172     mesecons = mesecons
c6da0a 173 })
R 174
175 minetest.register_node("technic:forcefield_emitter_on", {
176     description = "Forcefield emitter on (you hacker you)",
177     tiles = {"technic_forcefield_emitter_on.png"},
178     is_ground_content = true,
179     groups = {cracky = 1, not_in_creative_inventory=1},
180     drop='"technic:forcefield_emitter_off" 1',
4f35f4 181     on_timer = forcefield_step,
c6da0a 182     on_receive_fields = forcefield_receive_fields,
R 183     on_construct = function(pos) 
4f35f4 184         minetest.env:get_node_timer(pos):start(forcefield_step_interval)
c6da0a 185         local meta = minetest.env:get_meta(pos)
9a0d3f 186 --        meta:set_float("technic_hv_power_machine", 1)
K 187 --        meta:set_float("HV_EU_input", 0)
188 --        meta:set_float("HV_EU_demand", 0)
189 --        meta:set_int("range", 10)
190 --        meta:set_int("enabled", 1)
191         meta:set_string("formspec", get_forcefield_formspec(meta:get_int("range")))
192 --        meta:set_string("infotext", "Forcefield emitter");
c6da0a 193     end,
4f35f4 194     on_dig = function(pos, node, digger)
S 195         update_forcefield(pos, minetest.env:get_meta(pos):get_int("range"), false)
c6da0a 196         return minetest.node_dig(pos, node, digger)
R 197     end,
e5d48e 198     mesecons = mesecons
c6da0a 199 })
R 200
201 minetest.register_node("technic:forcefield", {
202     description = "Forcefield (you hacker you)",
203     sunlight_propagates = true,
204     drop = '',
9a0d3f 205         light_source = 8,
30361a 206     tiles = {{
S 207         name = "technic_forcefield_animated.png",
208         animation = {
209             type = "vertical_frames",
210             aspect_w=16,
211             aspect_h=16,
212             length=2.0,
213         },
214     }},
c6da0a 215     is_ground_content = true,
30361a 216     groups = { not_in_creative_inventory=1, unbreakable=1 },
c6da0a 217     paramtype = "light",
R 218     drawtype = "nodebox",
219     node_box = {  --hacky way to get the field blue and not see through the ground
220         type = "fixed",
221         fixed={
222             {-.5,-.5,-.5,.5,.5,.5},
223         },
224     },
225 })
226
30361a 227 technic.register_HV_machine("technic:forcefield_emitter_on", "RE")
S 228 technic.register_HV_machine("technic:forcefield_emitter_off", "RE")