diff --git a/api.lua b/api.lua index 8a8177b..8f839c2 100644 --- a/api.lua +++ b/api.lua @@ -44,6 +44,10 @@ function projectile.register_weapon(name, def) def.on_cancel(wep, user) end + if projectile.charge_levels[user:get_player_name()] and projectile.charge_levels[user:get_player_name()].sound then + minetest.sound_stop(projectile.charge_levels[user:get_player_name()].sound) + end + --Delete charge data. projectile.charge_levels[user:get_player_name()] = nil @@ -77,6 +81,11 @@ function projectile.register_weapon(name, def) --I originally wanted the item to be shown loaded with specific ammo, but it doesn't seem to be possible. wep = ItemStack({name = name.."_2", wear = wep:get_wear()}) + --If a callback is defined to do something when a charge begins, call it now. + if def.on_charge_begin then + def.on_charge_begin(wep, user) + end + --Once ammo is found, the search can be stopped. break end @@ -86,6 +95,7 @@ function projectile.register_weapon(name, def) --Otherwise, if there is charge data... else + --If a callback is defined to do something right before firing, call it now. if def.on_fire then def.on_fire(wep, user) end @@ -93,6 +103,7 @@ function projectile.register_weapon(name, def) --Shoot out the projectile projectile.shoot(wep, user, projectile.charge_levels[pname].charge) + --If a callback is defined to do something right after firing, call it now. if def.after_fire then def.after_fire(wep, user) end @@ -219,6 +230,14 @@ function projectile.register_projectile(name, usable_by, ammo, def) if c.type == "node" then hit = true + --Get the definition of the node that was hit... + local ndef = minetest.registered_nodes[minetest.get_node(c.node_pos).name] + --If the definition exists and defines a sound for being dug... + if ndef and ndef.sounds and ndef.sounds.dug then + --Play that sound + minetest.sound_play(ndef.sounds.dug, {gain = 1.0, pos = c.node_pos}, true) + end + --If it's an object... else --As long as that object isn't the player who fired this projectile and the target isn't already dead... @@ -245,6 +264,15 @@ function projectile.register_projectile(name, usable_by, ammo, def) self:on_impact(info.collisions) end + if node_damage and minetest.settings:get_bool("placeable_impacts_damage_nodes") then + for _, c in pairs(info.collisions) do + if c.type == "node" then + node_damage.damage(c.node_pos) + break + end + end + end + --Make the projectile destroy itself. selfo:remove() end diff --git a/api.txt b/api.txt index 9fd979d..c1cb8e0 100644 --- a/api.txt +++ b/api.txt @@ -68,6 +68,14 @@ projectile.register_weapon(name, definition) --Can't be used to negate the need for ammo. --Defaults to always return true. + on_charge_begin = function(wep, user) + --This function is called just after the user right-clicks to start charging the weapon. + --Has no return value. + + on_charge_full = function(wep, user) + --This function is called the moment that the weapon becomes fully charged. + --Has no return value. + on_cancel = function(weapon, user) --This function is called whenever a charge is cut short, either by left-clicking, switching the selected hotbar index, or leaving the game. --Has no return value. diff --git a/changelog.txt b/changelog.txt index 8c56764..8555a28 100644 --- a/changelog.txt +++ b/changelog.txt @@ -40,3 +40,14 @@ v1.1.2: Fixes: -Slingshots crashing the game when used + +v1.1.3: + New: + +Added sounds for weapons being charged and fired, and for projectiles impacting nodes. + *Charging and firing sounds come from freesound.org, so their file names include the names of the original uploaders of these sounds. + +Added on_charge_begin and on_charge_full callbacks to the api + +A second optional feature when using with the node_damage mod, where projectiles damage nodes that they impact. + *The above option is disabled by default, even with node_damage included, because it can be annoying, especially with shotguns. + + Fixes: + -A crash that could occur from pulverizing a charging weapon. diff --git a/init.lua b/init.lua index b382710..2e008d4 100644 --- a/init.lua +++ b/init.lua @@ -51,8 +51,14 @@ local function uncharge_player(player) --Get the projectile weapon. get_wielded_item() can't be used, since the weapon may no longer be held. local wep = player:get_inventory():get_stack("main", old_slot) - --Call the weapon's on_use function, which will cancel it. - wep:get_definition().on_use(wep, player, true) + --If the weapon was /pulverized or otherwise deleted without triggering a callback... + if wep:is_empty() then + --Delete the entry directly, which normally happens inside the weapon's on_use function. + projectile.charge_levels[pname] = nil + else + --Call the weapon's on_use function, which will cancel it. + wep:get_definition().on_use(wep, player, true) + end --Update the player's inventory with any modifications. player:get_inventory():set_stack("main", old_slot, wep) @@ -68,8 +74,8 @@ minetest.register_globalstep(function(dtime) --If this player is currently charging a projectile weapon... if projectile.charge_levels[pname] then - --If the player's selected hotbar slot changed... - if player:get_wield_index() ~= projectile.charge_levels[pname].slot then + --If the player's selected hotbar slot changed or their weapon was deleted somehow... + if player:get_wield_index() ~= projectile.charge_levels[pname].slot or player:get_wielded_item():is_empty() then --Cancel their charge. uncharge_player(player) @@ -88,6 +94,11 @@ minetest.register_globalstep(function(dtime) --Once this happens, replace the weapon with a fully charged sprite version. wep:set_name(def.full_charge_name) player:set_wielded_item(wep) + + --Enable a callback that can occur when the weapon is fully charged + if def.on_charge_full then + def.on_charge_full(wep, player) + end end end end @@ -129,7 +140,15 @@ projectile.register_weapon("projectile:slingshot", { durability = 75, rw_category = "slingshot", charge = true, - fire_while_charging = true + fire_while_charging = true, + + on_charge_begin = function(wep, user) + projectile.charge_levels[user:get_player_name()].sound = minetest.sound_play("projectile_slingshot_drawn_adam-n", {gain = 1.0, object = user}) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_bow_release_porkmuncher", {gain = 1.0, pos = user:get_pos()}, true) + end }) --An upgraded slingshot, which fires faster and harder, but is slightly harder to charge up. Metal wire is stiffer than string, after all. @@ -144,7 +163,15 @@ projectile.register_weapon("projectile:steel_slingshot", { fire_while_charging = true, charge_time = 1.1, damage = 1.25, - speed = 1.75 + speed = 1.75, + + on_charge_begin = function(wep, user) + projectile.charge_levels[user:get_player_name()].sound = minetest.sound_play("projectile_slingshot_drawn_adam-n", {gain = 1.0, object = user}) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_bow_release_porkmuncher", {gain = 1.0, pos = user:get_pos()}, true) + end }) --The basic bow. It is more powerful than a slingshot, but it takes way longer to charge and ammunition is harder to get. @@ -157,7 +184,15 @@ projectile.register_weapon("projectile:bow", { rw_category = "bow", charge = true, fire_while_charging = true, - charge_time = 2 + charge_time = 2, + + on_charge_begin = function(wep, user) + projectile.charge_levels.sound = minetest.sound_play("projectile_bow_drawn_paveroux", {gain = 1.0, object = user}) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_bow_release_porkmuncher", {gain = 1.0, pos = user:get_pos()}, true) + end }) --An upgraded bow, which fires faster and harder, but is slightly harder to charge up. Metal wire is stiffer than string, after all. @@ -172,7 +207,15 @@ projectile.register_weapon("projectile:steel_bow", { fire_while_charging = true, charge_time = 2.1, damage = 1.5, - speed = 1.9 + speed = 1.9, + + on_charge_begin = function(wep, user) + projectile.charge_levels[user:get_player_name()].sound = minetest.sound_play("projectile_bow_drawn_paveroux", {gain = 1.0, object = user}) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_bow_release_porkmuncher", {gain = 1.0, pos = user:get_pos()}, true) + end }) --The basic flintlock weapon, which can fire fairly often and has fair damage, but can't be fired before it is fully loaded. @@ -187,7 +230,19 @@ projectile.register_weapon("projectile:flintlock_pistol", { charge_time = 0.667, can_fire = projectile.needs_gunpowder, - on_cancel = projectile.return_gunpowder + on_cancel = projectile.return_gunpowder, + + on_charge_begin = function(wep, user) + minetest.sound_play("projectile_metal_click_mkoenig", {gain = 1.0, pos = user:get_pos()}, true) + end, + + on_charge_full = function(wep, user) + minetest.sound_play("projectile_metal_click_mkoenig", {gain = 1.0, pos = user:get_pos()}, true) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_musket_shot_aaronsiler", {gain = 0.75, pos = user:get_pos(), max_hear_distance = 48}, true) + end, }) --A slowler, more powerful flintlock weapon. @@ -204,7 +259,19 @@ projectile.register_weapon("projectile:musket", { speed = 1.1, can_fire = projectile.needs_gunpowder, - on_cancel = projectile.return_gunpowder + on_cancel = projectile.return_gunpowder, + + on_charge_begin = function(wep, user) + minetest.sound_play("projectile_metal_click_mkoenig", {gain = 1.0, pos = user:get_pos()}, true) + end, + + on_charge_full = function(wep, user) + minetest.sound_play("projectile_metal_click_mkoenig", {gain = 1.0, pos = user:get_pos()}, true) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_musket_shot_aaronsiler", {gain = 1.0, pos = user:get_pos(), max_hear_distance = 96}, true) + end, }) --A flintlock weapon that fires bursts of shot, rather than individual musket balls. @@ -219,7 +286,19 @@ projectile.register_weapon("projectile:blunderbuss", { charge_time = 1, can_fire = projectile.needs_gunpowder, - on_cancel = projectile.return_gunpowder + on_cancel = projectile.return_gunpowder, + + on_charge_begin = function(wep, user) + minetest.sound_play("projectile_metal_click_mkoenig", {gain = 1.0, pos = user:get_pos()}, true) + end, + + on_charge_full = function(wep, user) + minetest.sound_play("projectile_metal_click_mkoenig", {gain = 1.0, pos = user:get_pos()}, true) + end, + + after_fire = function(wep, user) + minetest.sound_play("projectile_musket_shot_aaronsiler", {gain = 1.0, pos = user:get_pos(), max_hear_distance = 96}, true) + end, }) diff --git a/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..f824216 --- /dev/null +++ b/settingtypes.txt @@ -0,0 +1 @@ +placeable_impacts_damage_nodes (Allow projectile impacts to damage nodes using the node_damage mod) bool false diff --git a/sounds/projectile_bow_drawn_paveroux.ogg b/sounds/projectile_bow_drawn_paveroux.ogg new file mode 100644 index 0000000..bd8a22a Binary files /dev/null and b/sounds/projectile_bow_drawn_paveroux.ogg differ diff --git a/sounds/projectile_bow_release_porkmuncher.ogg b/sounds/projectile_bow_release_porkmuncher.ogg new file mode 100644 index 0000000..316c00c Binary files /dev/null and b/sounds/projectile_bow_release_porkmuncher.ogg differ diff --git a/sounds/projectile_metal_click_mkoenig.ogg b/sounds/projectile_metal_click_mkoenig.ogg new file mode 100644 index 0000000..09fa30f Binary files /dev/null and b/sounds/projectile_metal_click_mkoenig.ogg differ diff --git a/sounds/projectile_musket_shot_aaronsiler.ogg b/sounds/projectile_musket_shot_aaronsiler.ogg new file mode 100644 index 0000000..03d6b75 Binary files /dev/null and b/sounds/projectile_musket_shot_aaronsiler.ogg differ diff --git a/sounds/projectile_slingshot_drawn_adam-n.ogg b/sounds/projectile_slingshot_drawn_adam-n.ogg new file mode 100644 index 0000000..f8b8b4b Binary files /dev/null and b/sounds/projectile_slingshot_drawn_adam-n.ogg differ diff --git a/textures/projectile_dot.png b/textures/projectile_dot.png index 7e9e820..2177fa5 100644 Binary files a/textures/projectile_dot.png and b/textures/projectile_dot.png differ diff --git a/textures/projectile_ebonite_block.png b/textures/projectile_ebonite_block.png new file mode 100644 index 0000000..5591d06 Binary files /dev/null and b/textures/projectile_ebonite_block.png differ diff --git a/textures/projectile_ebonite_ingot.png b/textures/projectile_ebonite_ingot.png new file mode 100644 index 0000000..bee6d89 Binary files /dev/null and b/textures/projectile_ebonite_ingot.png differ diff --git a/textures/projectile_pistol.png b/textures/projectile_pistol.png new file mode 100644 index 0000000..524bffa Binary files /dev/null and b/textures/projectile_pistol.png differ diff --git a/textures/projectile_pistol_charged.png b/textures/projectile_pistol_charged.png new file mode 100644 index 0000000..8ae885e Binary files /dev/null and b/textures/projectile_pistol_charged.png differ