diff --git a/shooter/README.txt b/shooter/README.txt index 5287bf4..2ec856a 100644 --- a/shooter/README.txt +++ b/shooter/README.txt @@ -13,11 +13,48 @@ to produce an accurate and server-firendly method of hit detection. By default this mod is configured to work only against other players in multiplayer mode and against Simple Mobs [mobs] in singleplayer mode. -Default configuration can be customised by adding a shooter.conf file to -the mod's main directory, see shooter.conf.example for more details. +Configuration +============= -This is still very much a work in progress which I eventually plan to use -as the base for a 'Spades' style FPS game using the minetest engine. +Override the following default settings by adding them to your minetest.conf file. + +-- Enable admin super weapons +-- This lets admins shoot guns automatically after 2 seconds without munition. +shooter_admin_weapons = false + +-- Enable node destruction with explosives +shooter_enable_blasting = true + +-- Enable Crafting +shooter_enable_crafting = true + +-- Enable particle effects +shooter_enable_particle_fx = true + +-- Enable protection mod support, requires a protection mod that utilizes +-- minetest.is_protected(), tested with TenPlus1's version of [protector] +shooter_enable_protection = false + +-- Particle texture used when a player or entity is hit +shooter_explosion = "shooter_hit.png" + +-- Allow node destruction +shooter_allow_nodes = true + +-- Allow entities in multiplayer mode +shooter_allow_entities = false + +-- Allow players in multiplayer mode +shooter_allow_players = true + +-- How often objects are fully reloaded +shooter_object_reload_time = 1 + +-- How often object positions are updated +shooter_object_update_time = 0.25 + +-- How often rounds are processed +shooter_rounds_update_time = 0.4 Crafting ======== diff --git a/shooter/api.lua b/shooter/api.lua index abc81bc..6ef2278 100644 --- a/shooter/api.lua +++ b/shooter/api.lua @@ -5,62 +5,28 @@ shooter = { shots = {}, update_time = 0, reload_time = 0, + player_offset = {x=0, y=1, z=0}, + entity_offset = {x=0, y=0, z=0}, } -SHOOTER_ADMIN_WEAPONS = false -SHOOTER_ENABLE_BLASTING = false -SHOOTER_ENABLE_CROSSBOW = true -SHOOTER_ENABLE_GUNS = true -SHOOTER_ENABLE_FLARES = true -SHOOTER_ENABLE_HOOK = true -SHOOTER_ENABLE_GRENADES = true -SHOOTER_ENABLE_ROCKETS = true -SHOOTER_ENABLE_TURRETS = true -SHOOTER_ENABLE_CRAFTING = true -SHOOTER_ENABLE_PARTICLE_FX = true -SHOOTER_ENABLE_PROTECTION = false -SHOOTER_EXPLOSION_TEXTURE = "shooter_hit.png" -SHOOTER_ALLOW_NODES = true -SHOOTER_ALLOW_ENTITIES = false -SHOOTER_ALLOW_PLAYERS = true -SHOOTER_OBJECT_RELOAD_TIME = 1 -SHOOTER_OBJECT_UPDATE_TIME = 0.25 -SHOOTER_ROUNDS_UPDATE_TIME = 0.4 -SHOOTER_PLAYER_OFFSET = {x=0, y=1, z=0} -SHOOTER_ENTITY_OFFSET = {x=0, y=0, z=0} -SHOOTER_ENTITIES = {} -for k, v in pairs(minetest.registered_entities) do - if string.find(k, "^mobs") then - table.insert(SHOOTER_ENTITIES, k) - end -end +shooter.config = { + admin_weapons = false, + enable_blasting = false, + enable_particle_fx = true, + enable_protection = false, + enable_crafting = true, + explosion_texture = "shooter_hit.png", + allow_nodes = true, + allow_entities = false, + allow_players = true, + object_reload_time = 1, + object_update_time = 0.25, + rounds_update_time = 0.4, +} +local config = shooter.config local singleplayer = minetest.is_singleplayer() -if singleplayer then - SHOOTER_ENABLE_BLASTING = true - SHOOTER_ALLOW_ENTITIES = true - SHOOTER_ALLOW_PLAYERS = false -end - -local modpath = minetest.get_modpath(minetest.get_current_modname()) -local worldpath = minetest.get_worldpath() -local input = io.open(modpath.."/shooter.conf", "r") -if input then - dofile(modpath.."/shooter.conf") - input:close() - input = nil -end -input = io.open(worldpath.."/shooter.conf", "r") -if input then - dofile(worldpath.."/shooter.conf") - input:close() - input = nil -end - local allowed_entities = {} -for _,v in ipairs(SHOOTER_ENTITIES) do - allowed_entities[v] = 1 -end local function get_dot_product(v1, v2) return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z @@ -70,10 +36,14 @@ local function get_particle_pos(p, v, d) return vector.add(p, vector.multiply(v, {x=d, y=d, z=d})) end +function shooter:set_shootable_entity(name) + allowed_entities[name] = 1 +end + function shooter:spawn_particles(pos, texture) - if SHOOTER_ENABLE_PARTICLE_FX == true then + if config.enable_particle_fx == true then if type(texture) ~= "string" then - texture = SHOOTER_EXPLOSION_TEXTURE + texture = config.explosion_texture end local spread = {x=0.1, y=0.1, z=0.1} minetest.add_particlespawner(15, 0.3, @@ -107,7 +77,7 @@ function shooter:punch_node(pos, def) if not item then return end - if SHOOTER_ENABLE_PROTECTION then + if config.enable_protection then if minetest.is_protected(pos, def.name) then return end @@ -132,9 +102,9 @@ end function shooter:is_valid_object(object) if object then if object:is_player() == true then - return SHOOTER_ALLOW_PLAYERS + return config.allow_players end - if SHOOTER_ALLOW_ENTITIES == true then + if config.allow_entities == true then local luaentity = object:get_luaentity() if luaentity then if luaentity.name then @@ -190,14 +160,14 @@ function shooter:process_round(round) local user = minetest.get_player_by_name(round.name) if user then target.object:punch(user, nil, round.def.tool_caps, v1) - shooter:spawn_particles(target.pos, SHOOTER_EXPLOSION_TEXTURE) + shooter:spawn_particles(target.pos, config.explosion_texture) end return 1 - elseif pos and SHOOTER_ALLOW_NODES == true then + elseif pos and config.allow_nodes == true then shooter:punch_node(pos, round.def) return 1 end - elseif SHOOTER_ALLOW_NODES == true then + elseif config.allow_nodes == true then local d = round.def.step local p2 = vector.add(p1, vector.multiply(v1, {x=d, y=d, z=d})) local success, pos = minetest.line_of_sight(p1, p2, 1) @@ -267,7 +237,7 @@ function shooter:fire_weapon(user, pointed_thing, def) {x=0, y=0, z=0}, 0.5, 0.25, false, def.particle ) - if pointed_thing.type == "node" and SHOOTER_ALLOW_NODES == true then + if pointed_thing.type == "node" and config.allow_nodes == true then local pos = minetest.get_pointed_thing_position(pointed_thing, false) shooter:punch_node(pos, def) elseif pointed_thing.type == "object" then @@ -277,7 +247,7 @@ function shooter:fire_weapon(user, pointed_thing, def) local p2 = object:getpos() local pp = get_particle_pos(p1, v1, vector.distance(p1, p2)) pp.y = pp.y + 1.75 - shooter:spawn_particles(pp, SHOOTER_EXPLOSION_TEXTURE) + shooter:spawn_particles(pp, config.explosion_texture) end else shooter:update_objects() @@ -293,7 +263,7 @@ end function shooter:load_objects() local objects = {} - if SHOOTER_ALLOW_PLAYERS == true then + if config.allow_players == true then local players = minetest.get_connected_players() for _,player in ipairs(players) do local pos = player:getpos() @@ -305,12 +275,12 @@ function shooter:load_objects() object = player, pos = pos, collisionbox = {-0.25,-1.0,-0.25, 0.25,0.8,0.25}, - offset = SHOOTER_PLAYER_OFFSET, + offset = shooter.player_offset, }) end end end - if SHOOTER_ALLOW_ENTITIES == true then + if config.allow_entities == true then for _,ref in pairs(minetest.luaentities) do if ref.object and ref.name then if allowed_entities[ref.name] then @@ -323,7 +293,7 @@ function shooter:load_objects() object = ref.object, pos = pos, collisionbox = def.collisionbox or {0,0,0, 0,0,0}, - offset = SHOOTER_ENTITY_OFFSET, + offset = shooter.entity_offset, }) end end @@ -339,9 +309,9 @@ function shooter:load_objects() end function shooter:update_objects() - if shooter.time - shooter.reload_time > SHOOTER_OBJECT_RELOAD_TIME then + if shooter.time - shooter.reload_time > config.object_reload_time then shooter:load_objects() - elseif shooter.time - shooter.update_time > SHOOTER_OBJECT_UPDATE_TIME then + elseif shooter.time - shooter.update_time > config.object_update_time then for i, ref in ipairs(shooter.objects) do if ref.object then local pos = ref.object:getpos() @@ -365,8 +335,8 @@ function shooter:blast(pos, radius, fleshy, distance, user) local p1 = vector.subtract(pos, radius) local p2 = vector.add(pos, radius) minetest.sound_play("tnt_explode", {pos=pos, gain=1}) - if SHOOTER_ALLOW_NODES and SHOOTER_ENABLE_BLASTING then - if SHOOTER_ENABLE_PROTECTION then + if config.allow_nodes and config.enable_blasting then + if config.enable_protection then if not minetest.is_protected(pos, name) then minetest.set_node(pos, {name="tnt:boom"}) end @@ -374,7 +344,7 @@ function shooter:blast(pos, radius, fleshy, distance, user) minetest.set_node(pos, {name="tnt:boom"}) end end - if SHOOTER_ENABLE_PARTICLE_FX == true then + if config.enable_particle_fx == true then minetest.add_particlespawner(50, 0.1, p1, p2, {x=-0, y=-0, z=-0}, {x=0, y=0, z=0}, {x=-0.5, y=5, z=-0.5}, {x=0.5, y=5, z=0.5}, @@ -383,8 +353,8 @@ function shooter:blast(pos, radius, fleshy, distance, user) end local objects = minetest.get_objects_inside_radius(pos, distance) for _,obj in ipairs(objects) do - if (obj:is_player() and SHOOTER_ALLOW_PLAYERS == true) or - (obj:get_luaentity() and SHOOTER_ALLOW_ENTITIES == true and + if (obj:is_player() and config.allow_players == true) or + (obj:get_luaentity() and config.allow_entities == true and obj:get_luaentity().name ~= "__builtin:item") then local obj_pos = obj:getpos() local dist = vector.distance(obj_pos, pos) @@ -401,7 +371,7 @@ function shooter:blast(pos, radius, fleshy, distance, user) end end end - if SHOOTER_ALLOW_NODES and SHOOTER_ENABLE_BLASTING then + if config.allow_nodes and config.enable_blasting then local pr = PseudoRandom(os.time()) local vm = VoxelManip() local min, max = vm:read_from_map(p1, p2) @@ -415,7 +385,7 @@ function shooter:blast(pos, radius, fleshy, distance, user) for x = -radius, radius do if (x * x) + (y * y) + (z * z) <= (radius * radius) + pr:next(-radius, radius) then - if SHOOTER_ENABLE_PROTECTION then + if config.enable_protection then if not minetest.is_protected(vp, name) then data[vi] = c_air end @@ -434,7 +404,7 @@ function shooter:blast(pos, radius, fleshy, distance, user) end end -if not singleplayer and SHOOTER_ADMIN_WEAPONS then +if not singleplayer and config.admin_weapons then local timer = 0 local shooting = false minetest.register_globalstep(function(dtime) diff --git a/shooter/init.lua b/shooter/init.lua index 894b12f..59ca8bb 100644 --- a/shooter/init.lua +++ b/shooter/init.lua @@ -1,7 +1,71 @@ -local modpath = minetest.get_modpath(minetest.get_current_modname()) +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) +local worldpath = minetest.get_worldpath() dofile(modpath.."/api.lua") +if minetest.is_singleplayer() then + shooter.config.enable_blasting = true + shooter.config.allow_entities = true + shooter.config.allow_players = false +end + +-- Legacy Config Support + +local input = io.open(modpath.."/shooter.conf", "r") +if input then + dofile(modpath.."/shooter.conf") + input:close() + input = nil +end +input = io.open(worldpath.."/shooter.conf", "r") +if input then + dofile(worldpath.."/shooter.conf") + input:close() + input = nil +end +for name, _ in pairs(shooter.config) do + local global = "SHOOTER_"..name:upper() + if minetest.global_exists(global) then + shooter.config[name] = _G[global] + end +end +if minetest.global_exists("SHOOTER_PLAYER_OFFSET") then + shooter.player_offset = SHOOTER_PLAYER_OFFSET +end +if minetest.global_exists("SHOOTER_ENTITY_OFFSET") then + shooter.entity_offset = SHOOTER_ENTITY_OFFSET +end +if minetest.global_exists("SHOOTER_ENTITIES") then + for _, name in pairs(SHOOTER_ENTITIES) do + shooter:set_shootable_entity(name) + end +end + +-- Simple Mobs Support + +for name, _ in pairs(minetest.registered_entities) do + if string.find(name, "^mobs") then + shooter:set_shootable_entity(name) + end +end + +-- Load Configuration + +for name, config in pairs(shooter.config) do + local setting = minetest.settings:get("shooter_"..name) + if type(config) == "number" then + setting = tonumber(setting) + elseif type(config) == "boolean" then + setting = minetest.settings:get_bool("shooter_"..name) + end + if setting ~= nil then + shooter.config[name] = setting + end +end + +-- Legacy Entity Support + minetest.register_entity("shooter:turret_entity", { visual = "sprite", textures = {"blank.png"}, diff --git a/shooter/shooter.conf.example b/shooter/shooter.conf.example deleted file mode 100644 index 89cc064..0000000 --- a/shooter/shooter.conf.example +++ /dev/null @@ -1,81 +0,0 @@ --- Simple Shooter config example - --- Global Constants (defaults) - --- Enable admin super weapons --- This lets admins shoot guns automatically after 2 seconds without munition. -SHOOTER_ADMIN_WEAPONS = false - --- Enable node destruction with explosives -SHOOTER_ENABLE_BLASTING = true - --- Enable Crossbow -SHOOTER_ENABLE_CROSSBOW = true - --- Enable basic guns (Pistol, Rifle, Shotgun, Machine Gun) -SHOOTER_ENABLE_GUNS = true - --- Enable Flare Gun -SHOOTER_ENABLE_FLARES = true - --- Enable Grappling Hook -SHOOTER_ENABLE_HOOK = true - --- Enable Grenades -SHOOTER_ENABLE_GRENADES = true - --- Enable Rocket Gun -SHOOTER_ENABLE_ROCKETS = true - --- Enable Turrret Gun -SHOOTER_ENABLE_TURRETS = true - --- Enable Crafting -SHOOTER_ENABLE_CRAFTING = true - --- Enable particle effects -SHOOTER_ENABLE_PARTICLE_FX = true - --- Enable protection mod support, requires a protection mod that utilizes --- minetest.is_protected(), tested with TenPlus1's version of [protector] -SHOOTER_ENABLE_PROTECTION = false - --- Particle texture used when a player or entity is hit -SHOOTER_EXPLOSION_TEXTURE = "shooter_hit.png" - --- Allow node destruction -SHOOTER_ALLOW_NODES = true - --- Allow entities in multiplayer mode -SHOOTER_ALLOW_ENTITIES = false - --- Allow players in multiplayer mode -SHOOTER_ALLOW_PLAYERS = true - --- How often objects are fully reloaded -SHOOTER_OBJECT_RELOAD_TIME = 1 - --- How often object positions are updated -SHOOTER_OBJECT_UPDATE_TIME = 0.25 - --- How often rounds are processed -SHOOTER_ROUNDS_UPDATE_TIME = 0.4 - --- Player collision box offset (may require adjustment for some games) -SHOOTER_PLAYER_OFFSET = {x=0, y=1, z=0} - --- Entity collision box offset (may require adjustment for other mobs) -SHOOTER_ENTITY_OFFSET = {x=0, y=0, z=0} - --- Shootable entities (default support for Simple Mobs) -SHOOTER_ENTITIES = { - "mobs:dirt_monster", - "mobs:stone_monster", - "mobs:sand_monster", - "mobs:tree_monster", - "mobs:sheep", - "mobs:rat", - "mobs:oerkki", - "mobs:dungeon_master", -} - diff --git a/shooter_crossbow/init.lua b/shooter_crossbow/init.lua index 3c625ac..c01c33d 100644 --- a/shooter_crossbow/init.lua +++ b/shooter_crossbow/init.lua @@ -1,12 +1,31 @@ -SHOOTER_CROSSBOW_USES = 50 -SHOOTER_ARROW_TOOL_CAPS = {damage_groups={fleshy=2}} -SHOOTER_ARROW_LIFETIME = 180 -- 3 minutes +local config = { + crossbow_uses = 50, + arrow_lifetime = 180, +} + +-- Legacy Config Support + +for name, _ in pairs(config) do + local global = "SHOOTER_"..name:upper() + if minetest.global_exists(global) then + config[name] = _G[global] + end + local setting = minetest.settings:get("shooter_"..name) + if type(setting) == "string" then + config[name] = tonumber(setting) + end +end + +local arrow_tool_caps = {damage_groups={fleshy=2}} +if minetest.global_exists("SHOOTER_ARROW_TOOL_CAPS") then + arrow_tool_caps = table.copy(SHOOTER_ARROW_TOOL_CAPS) +end minetest.register_alias("shooter_crossbow:arrow", "shooter_crossbow:arrow_white") minetest.register_alias("shooter:crossbow_loaded", "shooter:crossbow_loaded_white") local dye_basecolors = (dye and dye.basecolors) or - {"white", "grey", "black", "red", "yellow", "green", "cyan", "blue", "magenta"} + {"white", "grey", "black", "red", "yellow", "green", "cyan", "blue", "magenta"} local function get_animation_frame(dir) local angle = math.atan(dir.y) @@ -40,7 +59,7 @@ minetest.register_entity("shooter_crossbow:arrow_entity", { }, color = "white", timer = 0, - lifetime = SHOOTER_ARROW_LIFETIME, + lifetime = config.arrow_lifetime, player = nil, state = "init", node_pos = nil, @@ -69,8 +88,8 @@ minetest.register_entity("shooter_crossbow:arrow_entity", { local p1 = puncher:getpos() local p2 = object:getpos() local tpos = get_target_pos(p1, p2, dir, 0) - shooter:spawn_particles(tpos, SHOOTER_EXPLOSION_TEXTURE) - object:punch(puncher, nil, SHOOTER_ARROW_TOOL_CAPS, dir) + shooter:spawn_particles(tpos, shooter.config.explosion_texture) + object:punch(puncher, nil, arrow_tool_caps, dir) end end self:stop(object:getpos()) @@ -132,9 +151,9 @@ minetest.register_entity("shooter_crossbow:arrow_entity", { for _,obj in ipairs(objects) do if shooter:is_valid_object(obj) and obj ~= self.player then local collisionbox = {-0.25,-1.0,-0.25, 0.25,0.8,0.25} - local offset = SHOOTER_PLAYER_OFFSET + local offset = shooter.player_offset if not obj:is_player() then - offset = SHOOTER_ENTITY_OFFSET + offset = shooter.entity_offset local ent = obj:get_luaentity() if ent then local def = minetest.registered_entities[ent.name] @@ -180,7 +199,7 @@ for _, color in pairs(dye_basecolors) do on_use = function(itemstack, user, pointed_thing) minetest.sound_play("shooter_click", {object=user}) if not minetest.setting_getbool("creative_mode") then - itemstack:add_wear(65535/SHOOTER_CROSSBOW_USES) + itemstack:add_wear(65535/config.crossbow_uses) end itemstack = "shooter_crossbow:crossbow 1 "..itemstack:get_wear() local pos = user:getpos() @@ -262,7 +281,7 @@ minetest.register_tool("shooter_crossbow:crossbow", { end, }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_crossbow:crossbow", recipe = { diff --git a/shooter_flaregun/init.lua b/shooter_flaregun/init.lua index 8126afe..7cd9270 100644 --- a/shooter_flaregun/init.lua +++ b/shooter_flaregun/init.lua @@ -129,7 +129,7 @@ minetest.register_tool("shooter_flaregun:flaregun", { end, }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_flaregun:flare", recipe = { @@ -145,7 +145,6 @@ if SHOOTER_ENABLE_CRAFTING == true then }) end - --Backwards compatibility minetest.register_alias("shooter:flaregun", "shooter_flaregun:flaregun") minetest.register_alias("shooter:flare", "shooter_flaregun:flare") diff --git a/shooter_grenade/init.lua b/shooter_grenade/init.lua index 90f5bb4..e674be3 100644 --- a/shooter_grenade/init.lua +++ b/shooter_grenade/init.lua @@ -69,7 +69,7 @@ minetest.register_tool("shooter_grenade:grenade", { end, }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_grenade:grenade", recipe = { @@ -78,6 +78,5 @@ if SHOOTER_ENABLE_CRAFTING == true then }) end - --Backwards compatibility minetest.register_alias("shooter:grenade", "shooter_grenade:grenade") diff --git a/shooter_guns/init.lua b/shooter_guns/init.lua index 5def56a..85d06c4 100644 --- a/shooter_guns/init.lua +++ b/shooter_guns/init.lua @@ -60,7 +60,7 @@ minetest.register_craftitem("shooter_guns:ammo", { inventory_image = "shooter_ammo.png", }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_guns:pistol 1 65535", recipe = { @@ -104,7 +104,7 @@ local rounds_update_time = 0 minetest.register_globalstep(function(dtime) shooter.time = shooter.time + dtime - if shooter.time - rounds_update_time > SHOOTER_ROUNDS_UPDATE_TIME then + if shooter.time - rounds_update_time > shooter.config.rounds_update_time then for i, round in ipairs(shooter.rounds) do if shooter:process_round(round) or round.dist > round.def.range then table.remove(shooter.rounds, i) diff --git a/shooter_hook/init.lua b/shooter_hook/init.lua index 1372ae9..671f6d7 100644 --- a/shooter_hook/init.lua +++ b/shooter_hook/init.lua @@ -112,7 +112,7 @@ minetest.register_tool("shooter_hook:grapple_gun_loaded", { end, }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_hook:grapple_hook", recipe = { diff --git a/shooter_rocket/init.lua b/shooter_rocket/init.lua index c98e9e5..45d1bcc 100644 --- a/shooter_rocket/init.lua +++ b/shooter_rocket/init.lua @@ -96,7 +96,7 @@ minetest.register_tool("shooter_rocket:rocket_gun", { end, }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_rocket:rocket_gun", recipe = { diff --git a/shooter_turret/init.lua b/shooter_turret/init.lua index 9d7335e..645e828 100644 --- a/shooter_turret/init.lua +++ b/shooter_turret/init.lua @@ -171,7 +171,7 @@ minetest.register_entity("shooter_turret:turret_entity", { obj:setacceleration({x=dir.x * -3, y=-10, z=dir.z * -3}) end end - if SHOOTER_ENABLE_PARTICLE_FX == true then + if shooter.config.enable_particle_fx == true then minetest.add_particlespawner(10, 0.1, {x=pos.x - 1, y=pos.y - 1, z=pos.z - 1}, {x=pos.x + 1, y=pos.y + 1, z=pos.z + 1}, @@ -264,7 +264,7 @@ minetest.register_abm({ end }) -if SHOOTER_ENABLE_CRAFTING == true then +if shooter.config.enable_crafting == true then minetest.register_craft({ output = "shooter_turret:turret", recipe = { @@ -275,7 +275,6 @@ if SHOOTER_ENABLE_CRAFTING == true then }) end - --Backward compatibility minetest.register_alias("shooter:turret", "shooter_turret:turret")