initial commit
|
@ -0,0 +1 @@
|
||||||
|
.DS_Store
|
|
@ -0,0 +1,20 @@
|
||||||
|
unused_args = false
|
||||||
|
allow_defined_top = true
|
||||||
|
|
||||||
|
globals = {
|
||||||
|
"minetest",
|
||||||
|
"tnt",
|
||||||
|
"explosions"
|
||||||
|
}
|
||||||
|
|
||||||
|
read_globals = {
|
||||||
|
string = {fields = {"split"}},
|
||||||
|
table = {fields = {"copy", "getn"}},
|
||||||
|
|
||||||
|
-- Builtin
|
||||||
|
"vector", "ItemStack",
|
||||||
|
"dump", "DIR_DELIM", "VoxelArea", "Settings",
|
||||||
|
|
||||||
|
-- MTG
|
||||||
|
"default", "sfinv", "creative",
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
# LICENSE
|
||||||
|
|
||||||
|
- Code: GPLv3.0
|
||||||
|
- Textures: CC BY-SA 4.0
|
||||||
|
- Sounds: They have different licenses, see below.
|
||||||
|
|
||||||
|
## Sounds
|
||||||
|
|
||||||
|
### Draw Bow
|
||||||
|
- farbows_draw_bow.ogg
|
||||||
|
- Author: Mike Koenig
|
||||||
|
- http://soundbible.com/2107-Drawing-Bow-Back.html
|
||||||
|
- License: Attribution 3.0
|
||||||
|
|
||||||
|
### Fire Arrow
|
||||||
|
- farbows_fire_arrow.ogg
|
||||||
|
- Author: Mike Koenig
|
||||||
|
- http://soundbible.com/2108-Shoot-Arrow.html
|
||||||
|
- License: Attribution 3.0
|
||||||
|
|
||||||
|
### Hit Arrow
|
||||||
|
- farbows_hit_arrow.ogg
|
||||||
|
- Author: runs
|
||||||
|
- GPLv3.0
|
|
@ -0,0 +1,198 @@
|
||||||
|
# RCBOWS
|
||||||
|
|
||||||
|
## function rcbows.register_arrow(name, def)
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
rcbows.register_arrow("farbows:e_arrow", {
|
||||||
|
damage = 5,
|
||||||
|
inventory_arrow = {
|
||||||
|
name = "farbows:inv_arrow",
|
||||||
|
description = S("Arrow"),
|
||||||
|
inventory_image = "farbows_arrow.png",
|
||||||
|
stack_max = 64, --optional, 99 by default
|
||||||
|
}
|
||||||
|
sounds = {
|
||||||
|
max_hear_distance = 10,
|
||||||
|
gain = 0.4,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
## function rcbows.register_bow(name, def)
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
rcbows.register_bow("farbows:bow_wood", {
|
||||||
|
description = S("Wooden Bow"),
|
||||||
|
image = "farbows_bow_wood.png",
|
||||||
|
strength = 30,
|
||||||
|
uses = 150,
|
||||||
|
charge_time = 0.5,
|
||||||
|
recipe = {
|
||||||
|
{"", "group:wood", "farming:string"},
|
||||||
|
{"group:wood", "", "farming:string"},
|
||||||
|
{"", "group:wood", "farming:string"},
|
||||||
|
},
|
||||||
|
base_texture = "farbows_base_bow_wood.png",
|
||||||
|
overlay_empty = "farbows_overlay_empty.png",
|
||||||
|
overlay_charged = "farbows_overlay_charged.png",
|
||||||
|
arrows = "farbows:e_arrow",
|
||||||
|
sounds = {
|
||||||
|
max_hear_distance = 10,
|
||||||
|
gain = 0.4,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arrows
|
||||||
|
|
||||||
|
You can define "arrows" as a single arrow (string) or a table of arrows.
|
||||||
|
|
||||||
|
In this case the order matters. The first ones have preference over the last ones when charging the bow.
|
||||||
|
|
||||||
|
I.e:
|
||||||
|
```
|
||||||
|
arrows = {"farbows:e_arrow", ""farbows:ice_arrow""},
|
||||||
|
```
|
||||||
|
|
||||||
|
### Viewfinder
|
||||||
|
|
||||||
|
You can define a viewfinder for a bow. This produces a zoom effect.
|
||||||
|
|
||||||
|
```
|
||||||
|
viewfinder = {
|
||||||
|
zoom = 15, --level of zoom; by default 15.
|
||||||
|
texture = "" --optional
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- When the bow charged, toogle the viewfinder with the secondary use (right-click).
|
||||||
|
- You can define an optional texture to being showed. If you define texture as empty (""), you get the default rcbows viewfinder texture.
|
||||||
|
|
||||||
|
## Audio
|
||||||
|
|
||||||
|
1. If you define ``sounds={}``, you get the default sounds.
|
||||||
|
|
||||||
|
For no sound at all do not declare 'sounds'.
|
||||||
|
|
||||||
|
Also you can set the sound parameters 'max_hear_distance' and 'gain'.
|
||||||
|
|
||||||
|
In example:
|
||||||
|
```
|
||||||
|
sounds = {
|
||||||
|
max_hear_distance = 10,
|
||||||
|
gain = 0.4,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. You also can define your own soundfiles.
|
||||||
|
|
||||||
|
You can set "soundfile_draw_bow" and/or "soundfile_fire_arrow" for bows, and "soundfile_hit_arrow" for arrows.
|
||||||
|
|
||||||
|
In example for a Bow:
|
||||||
|
```
|
||||||
|
sounds = {
|
||||||
|
soundfile_draw_bow = "my_draw_bow"
|
||||||
|
soundfile_fire_arrow = "my_fire_arrow"
|
||||||
|
max_hear_distance = 5,
|
||||||
|
--set the gain by default (0.5)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In example for a Arrow:
|
||||||
|
```
|
||||||
|
sounds = {
|
||||||
|
soundfile_hit_arrow = "my_hit_arrow"
|
||||||
|
max_hear_distance = 5,
|
||||||
|
--set the gain by default (0.5)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Drop
|
||||||
|
|
||||||
|
By default the arrow drops the inventory_arrow when reachs a solid node.
|
||||||
|
|
||||||
|
If you want to define another item to drop, define it with 'drop':
|
||||||
|
```
|
||||||
|
rcbows.register_arrow("farbows:e_arrow", {
|
||||||
|
damage = 5,
|
||||||
|
inventory_arrow = {
|
||||||
|
name = "farbows:inv_arrow",
|
||||||
|
description = S("Arrow"),
|
||||||
|
inventory_image = "farbows_arrow.png",
|
||||||
|
}
|
||||||
|
drop = "farbows_drop_arrow"
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want not any drop at all, add:
|
||||||
|
```
|
||||||
|
drop = "",
|
||||||
|
```
|
||||||
|
|
||||||
|
## Arrow Effects
|
||||||
|
You can define some arrow effects
|
||||||
|
### replace_node
|
||||||
|
Replace the hit node for this one.
|
||||||
|
### trail_particle
|
||||||
|
Particle texture to create an arrow trail.
|
||||||
|
|
||||||
|
It can be a string with "texture" only, or a table for animated textures: {texture = "texture", animation = "animation"}.
|
||||||
|
### explosion
|
||||||
|
It requires "tnt" or "explosion" mods as an optional dependency.
|
||||||
|
|
||||||
|
It is a table in where to define:
|
||||||
|
- mod = "tnt" or "explosions",
|
||||||
|
- radius
|
||||||
|
- damage = It is "damage_radius" for the "tnt" mod or "strength" for "explosions"
|
||||||
|
|
||||||
|
|
||||||
|
In example:
|
||||||
|
```
|
||||||
|
rcbows.register_arrow("farbows:fire_arrow", {
|
||||||
|
damage = 7,
|
||||||
|
inventory_arrow = {
|
||||||
|
name = "farbows:inv_fire_arrow",
|
||||||
|
description = S("Fire Arrow"),
|
||||||
|
inventory_image = "farbows_arrow_fire.png",
|
||||||
|
},
|
||||||
|
drop = "farbows:inv_arrow",
|
||||||
|
effects = {
|
||||||
|
replace_node = "fire:basic_flame",
|
||||||
|
trail_particle = "farbows_particle_fire.png",
|
||||||
|
explosion = {
|
||||||
|
mod = "tnt",
|
||||||
|
radius= 10,
|
||||||
|
damage = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
### water
|
||||||
|
An effect that extinguishes the flames.
|
||||||
|
|
||||||
|
It requires "fire" mod as an optional dependency.
|
||||||
|
|
||||||
|
It is a table in where to define:
|
||||||
|
- flame_node = The name of the flame node to extinguish
|
||||||
|
- radius
|
||||||
|
- particles = A water particles effect [optional]
|
||||||
|
|
||||||
|
```
|
||||||
|
rcbows.register_arrow("farbows:water_arrow", {
|
||||||
|
projectile_texture = "farbows_water_arrow",
|
||||||
|
damage = 2,
|
||||||
|
inventory_arrow = {
|
||||||
|
name = "farbows:inv_water_arrow",
|
||||||
|
description = S("Water Arrow"),
|
||||||
|
inventory_image = "farbows_arrow_water.png",
|
||||||
|
},
|
||||||
|
drop = "bucket:bucket_empty",
|
||||||
|
effects = {
|
||||||
|
trail_particle = "default_water.png",
|
||||||
|
water = {
|
||||||
|
radius = 5,
|
||||||
|
flame_node = "fire:basic_flame",
|
||||||
|
particles = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
|
@ -0,0 +1,449 @@
|
||||||
|
rcbows = {}
|
||||||
|
|
||||||
|
local S = minetest.get_translator(minetest.get_current_modname())
|
||||||
|
|
||||||
|
--CONSTANTS
|
||||||
|
local DEFAULT_MAX_HEAR_DISTANCE = 10
|
||||||
|
local DEFAULT_GAIN = 0.5
|
||||||
|
|
||||||
|
function rcbows.spawn_arrow(user, strength, itemstack)
|
||||||
|
local pos = user:get_pos()
|
||||||
|
pos.y = pos.y + 1.5 -- camera offset
|
||||||
|
local dir = user:get_look_dir()
|
||||||
|
local yaw = user:get_look_horizontal()
|
||||||
|
local meta = itemstack:get_meta()
|
||||||
|
local arrow = meta:get_string("rcbows:charged_arrow")
|
||||||
|
local obj = nil
|
||||||
|
if pos and arrow then
|
||||||
|
obj = minetest.add_entity(pos, arrow)
|
||||||
|
end
|
||||||
|
if not obj then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local lua_ent = obj:get_luaentity()
|
||||||
|
lua_ent.shooter_name = user:get_player_name()
|
||||||
|
obj:set_yaw(yaw - 0.5 * math.pi)
|
||||||
|
local velocity = vector.multiply(dir, strength)
|
||||||
|
obj:set_velocity(velocity)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function rcbows.launch_arrow(user, name, def, itemstack)
|
||||||
|
if not rcbows.spawn_arrow(user, def.strength, itemstack) then --throw arrow (spawn arrow entity)
|
||||||
|
return -- something failed
|
||||||
|
end
|
||||||
|
if def.sounds then
|
||||||
|
local user_pos = user:get_pos()
|
||||||
|
if not def.sounds.soundfile_fire_arrow then
|
||||||
|
def.sounds.soundfile_fire_arrow = "rcbows_fire_arrow"
|
||||||
|
end
|
||||||
|
rcbows.make_sound("pos", user_pos, def.sounds.soundfile_fire_arrow, DEFAULT_GAIN, DEFAULT_MAX_HEAR_DISTANCE)
|
||||||
|
end
|
||||||
|
itemstack:set_name(name)
|
||||||
|
itemstack:set_wear(itemstack:get_wear() + 0x10000 / def.uses)
|
||||||
|
if def.viewfinder then --reset the viewfinder-zoom
|
||||||
|
if not(user:get_fov() == 0) then
|
||||||
|
user:set_fov(0)
|
||||||
|
remove_viewfinder(user, itemstack:get_meta():get_int( "rcbows:viewfinder_id"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
local function show_viewfinder(player, texture)
|
||||||
|
local hud_id = player:hud_add({
|
||||||
|
hud_elem_type = "image",
|
||||||
|
text = texture,
|
||||||
|
position = {x=0, y=0},
|
||||||
|
scale = {x=-100, y=-100},
|
||||||
|
alignment = {x=1, y=1},
|
||||||
|
offset = {x=0, y=0}
|
||||||
|
})
|
||||||
|
return hud_id
|
||||||
|
end
|
||||||
|
|
||||||
|
function remove_viewfinder(player, hud_id)
|
||||||
|
if hud_id then
|
||||||
|
player:hud_remove(hud_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function rcbows.register_bow(name, def)
|
||||||
|
assert(type(def.description) == "string")
|
||||||
|
assert(type(def.image) == "string")
|
||||||
|
assert(type(def.strength) == "number")
|
||||||
|
assert(def.uses > 0)
|
||||||
|
|
||||||
|
local function reload_bow(itemstack, user, pointed_thing)
|
||||||
|
local inv = user:get_inventory()
|
||||||
|
local arrow, inventory_arrows, inventory_arrow, inv_arrow_name
|
||||||
|
local inv_list = inv:get_list("main")
|
||||||
|
if type(def.arrows) == 'table' then --more than one arrow?
|
||||||
|
for i = 1, #def.arrows do
|
||||||
|
arrow = def.arrows[i]
|
||||||
|
inv_arrow_name = minetest.registered_entities[arrow].inventory_arrow_name
|
||||||
|
if inv:contains_item("main", inv_arrow_name) then
|
||||||
|
if not inventory_arrows then
|
||||||
|
inventory_arrows = {}
|
||||||
|
end
|
||||||
|
inventory_arrows[#inventory_arrows+1] = {arrow = arrow, inv_arrow_name = inv_arrow_name}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
arrow = def.arrows
|
||||||
|
inventory_arrow = minetest.registered_entities[def.arrows].inventory_arrow_name
|
||||||
|
end
|
||||||
|
if not inventory_arrow and not inventory_arrows then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if inventory_arrows then --more than one arrow?
|
||||||
|
for i = 1, #inv_list do
|
||||||
|
if inventory_arrow then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
for j = 1, #inventory_arrows do
|
||||||
|
local inv_arrow = inventory_arrows[j]
|
||||||
|
if inv_list[i]:get_name() == inv_arrow.inv_arrow_name then
|
||||||
|
arrow = inv_arrow.arrow
|
||||||
|
inventory_arrow = inv_arrow.inv_arrow_name
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not inventory_arrow then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not inv:remove_item("main", inventory_arrow):is_empty() then
|
||||||
|
minetest.after(def.charge_time or 0, function(v_user, v_name)
|
||||||
|
local wielded_item = v_user:get_wielded_item()
|
||||||
|
local wielded_item_name = wielded_item:get_name()
|
||||||
|
if wielded_item_name == v_name then
|
||||||
|
local meta = wielded_item:get_meta()
|
||||||
|
meta:set_string("rcbows:charged_arrow", arrow) --save the arrow in the meta
|
||||||
|
wielded_item:set_name(v_name .. "_charged")
|
||||||
|
v_user:set_wielded_item(wielded_item)
|
||||||
|
end
|
||||||
|
end, user, name)
|
||||||
|
if def.sounds then
|
||||||
|
local user_pos = user:get_pos()
|
||||||
|
if not def.sounds.soundfile_draw_bow then
|
||||||
|
def.sounds.soundfile_draw_bow = "rcbows_draw_bow"
|
||||||
|
end
|
||||||
|
rcbows.make_sound("pos", user_pos, def.sounds.soundfile_draw_bow, DEFAULT_GAIN, DEFAULT_MAX_HEAR_DISTANCE)
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_tool(name, {
|
||||||
|
description = def.description .. " ".. S("(place to reload)"),
|
||||||
|
inventory_image = def.image .. "^" .. def.overlay_empty,
|
||||||
|
|
||||||
|
on_use = function() end,
|
||||||
|
on_place = reload_bow,
|
||||||
|
on_secondary_use = reload_bow,
|
||||||
|
})
|
||||||
|
|
||||||
|
if def.recipe then
|
||||||
|
minetest.register_craft({
|
||||||
|
output = name,
|
||||||
|
recipe = def.recipe
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local charged_name = name .. "_charged"
|
||||||
|
|
||||||
|
minetest.register_tool(charged_name, {
|
||||||
|
description = def.description .. " " .. S("(use to fire)"),
|
||||||
|
inventory_image = def.base_texture .. "^" ..def.overlay_charged,
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
return rcbows.launch_arrow(user, name, def, itemstack)
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_secondary_use = function(itemstack, user, pointed_thing) --viewfinder
|
||||||
|
if not def.viewfinder then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if user:get_fov() == 0 then
|
||||||
|
user:set_fov(def.viewfinder.zoom or 15)
|
||||||
|
if def.viewfinder.texture then
|
||||||
|
local viewfinder_texture = def.viewfinder.texture
|
||||||
|
if viewfinder_texture == "" then
|
||||||
|
viewfinder_texture = "rcbows_viewfinder.png"
|
||||||
|
end
|
||||||
|
itemstack:get_meta():set_int("rcbows:viewfinder_id", show_viewfinder(user, viewfinder_texture))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
user:set_fov(0)
|
||||||
|
if def.viewfinder.texture then
|
||||||
|
remove_viewfinder(user, itemstack:get_meta():get_int( "rcbows:viewfinder_id"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function rcbows.register_arrow(name, def)
|
||||||
|
minetest.register_entity(name, {
|
||||||
|
hp_max = 4, -- possible to catch the arrow (pro skills)
|
||||||
|
physical = false, -- use Raycast
|
||||||
|
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
|
||||||
|
visual = "wielditem",
|
||||||
|
textures = {def.inventory_arrow.name},
|
||||||
|
visual_size = {x = 0.2, y = 0.15},
|
||||||
|
old_pos = nil,
|
||||||
|
velocity = nil,
|
||||||
|
liquidflag = nil,
|
||||||
|
shooter_name = "",
|
||||||
|
waiting_for_removal = false,
|
||||||
|
inventory_arrow_name = def.inventory_arrow.name,
|
||||||
|
groups = {arrow = 1},
|
||||||
|
|
||||||
|
on_activate = function(self)
|
||||||
|
self.object:set_acceleration({x = 0, y = -9.81, z = 0})
|
||||||
|
end,
|
||||||
|
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
if self.waiting_for_removal then
|
||||||
|
self.object:remove()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
self.old_pos = self.old_pos or pos
|
||||||
|
local velocity = self.object:get_velocity()
|
||||||
|
if def.sounds and not(def.sounds.soundfile_hit_arrow) then
|
||||||
|
def.sounds.soundfile_hit_arrow = "rcbows_hit_arrow"
|
||||||
|
end
|
||||||
|
local cast = minetest.raycast(self.old_pos, pos, true, true)
|
||||||
|
local thing = cast:next()
|
||||||
|
while thing do
|
||||||
|
if thing.type == "object" and thing.ref ~= self.object then
|
||||||
|
if not thing.ref:is_player() or thing.ref:get_player_name() ~= self.shooter_name then
|
||||||
|
thing.ref:punch(self.object, 1.0, {
|
||||||
|
full_punch_interval = 0.5,
|
||||||
|
damage_groups = {fleshy = def.damage or 1}
|
||||||
|
})
|
||||||
|
self.waiting_for_removal = true
|
||||||
|
self.object:remove()
|
||||||
|
if def.sounds then
|
||||||
|
local thing_pos = thing.ref:get_pos()
|
||||||
|
if thing_pos then
|
||||||
|
rcbows.make_sound("pos", thing_pos, def.sounds.soundfile_hit_arrow, DEFAULT_GAIN, DEFAULT_MAX_HEAR_DISTANCE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- no effects or not owner, nothing to do.
|
||||||
|
-- some effects should also happen if hitting an other object. like tnt, water etc.
|
||||||
|
if not def.effects or minetest.is_protected(pos, self.shooter_name) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
rcbows.boom_effect(def, pos) -- BOOM
|
||||||
|
rcbows.water_effect(def, pos) -- water - extinguish fires
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
elseif thing.type == "node" then
|
||||||
|
local node_name = minetest.get_node(thing.under).name
|
||||||
|
local drawtype = minetest.registered_nodes[node_name]["drawtype"]
|
||||||
|
if drawtype == 'liquid' then
|
||||||
|
if not self.liquidflag then
|
||||||
|
self.velocity = velocity
|
||||||
|
self.liquidflag = true
|
||||||
|
local liquidviscosity = minetest.registered_nodes[node_name]["liquid_viscosity"]
|
||||||
|
local drag = 1/(liquidviscosity*6)
|
||||||
|
self.object:set_velocity(vector.multiply(velocity, drag))
|
||||||
|
self.object:set_acceleration({x = 0, y = -1.0, z = 0})
|
||||||
|
rcbows.splash(self.old_pos, "rcbows_bubble.png")
|
||||||
|
end
|
||||||
|
elseif self.liquidflag then
|
||||||
|
self.liquidflag = false
|
||||||
|
if self.velocity then
|
||||||
|
self.object:set_velocity(self.velocity)
|
||||||
|
end
|
||||||
|
self.object:set_acceleration({x = 0, y = -9.81, z = 0})
|
||||||
|
end
|
||||||
|
if minetest.registered_items[node_name].walkable then
|
||||||
|
if not(def.drop) then
|
||||||
|
minetest.item_drop(ItemStack(def.inventory_arrow), nil, vector.round(self.old_pos))
|
||||||
|
else
|
||||||
|
if not(def.drop == "") then
|
||||||
|
minetest.item_drop(ItemStack(def.drop), nil, vector.round(self.old_pos))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.waiting_for_removal = true
|
||||||
|
self.object:remove()
|
||||||
|
|
||||||
|
if def.sounds then
|
||||||
|
if pos then
|
||||||
|
rcbows.make_sound("pos", pos, def.sounds.soundfile_hit_arrow, DEFAULT_GAIN, DEFAULT_MAX_HEAR_DISTANCE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- no effects or not owner, nothing to do.
|
||||||
|
if not def.effects or minetest.is_protected(pos, self.shooter_name) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--replace node
|
||||||
|
if def.effects.replace_node then
|
||||||
|
minetest.set_node(pos, {name = def.effects.replace_node})
|
||||||
|
end
|
||||||
|
|
||||||
|
rcbows.boom_effect(def, pos) -- BOOM
|
||||||
|
rcbows.water_effect(def, pos) -- water - extinguish fires
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
thing = cast:next()
|
||||||
|
end
|
||||||
|
if def.effects and def.effects.trail_particle then
|
||||||
|
rcbows.trail(self.old_pos, pos, def.effects.trail_particle)
|
||||||
|
end
|
||||||
|
self.old_pos = pos
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_craftitem(def.inventory_arrow.name, {
|
||||||
|
description = def.inventory_arrow.description,
|
||||||
|
inventory_image = def.inventory_arrow.inventory_image,
|
||||||
|
stack_max = def.stack_max or 99,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--SOUND SYSTEM
|
||||||
|
|
||||||
|
function rcbows.make_sound(dest_type, dest, soundfile, gain, max_hear_distance)
|
||||||
|
if dest_type == "object" then
|
||||||
|
minetest.sound_play(soundfile, {object = dest, gain = gain or DEFAULT_GAIN, max_hear_distance = max_hear_distance or DEFAULT_MAX_HEAR_DISTANCE,})
|
||||||
|
elseif dest_type == "player" then
|
||||||
|
local player_name = dest:get_player_name()
|
||||||
|
minetest.sound_play(soundfile, {to_player = player_name, gain = gain or DEFAULT_GAIN, max_hear_distance = max_hear_distance or DEFAULT_MAX_HEAR_DISTANCE,})
|
||||||
|
elseif dest_type == "pos" then
|
||||||
|
minetest.sound_play(soundfile, {pos = dest, gain = gain or DEFAULT_GAIN, max_hear_distance = max_hear_distance or DEFAULT_MAX_HEAR_DISTANCE,})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--ARROW EFFECTS
|
||||||
|
|
||||||
|
function rcbows.boom_effect(def, pos)
|
||||||
|
if def.effects.explosion and def.effects.explosion.mod then
|
||||||
|
local mod_name = def.effects.explosion.mod
|
||||||
|
if minetest.get_modpath(mod_name) ~= nil then
|
||||||
|
if mod_name == "tnt" then
|
||||||
|
tnt.boom(pos, {radius = def.effects.explosion.radius, damage_radius = def.effects.explosion.damage})
|
||||||
|
elseif mod_name == "explosions" then
|
||||||
|
explosions.explode(pos, {radius = def.effects.explosion.radius, strength = def.effects.explosion.damage})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function rcbows.water_effect(def, pos)
|
||||||
|
if def.effects.water then
|
||||||
|
if def.effects.water.particles then
|
||||||
|
rcbows.splash(pos, "rcbows_water.png")
|
||||||
|
end
|
||||||
|
local radius = def.effects.water.radius or 5
|
||||||
|
local flames = minetest.find_nodes_in_area({x=pos.x -radius, y=pos.y -radius, z=pos.z -radius}, {x=pos.x+radius, y=pos.y+radius, z=pos.z+radius}, {def.effects.water.flame_node})
|
||||||
|
if flames and #flames > 0 then
|
||||||
|
for i=1, #flames do
|
||||||
|
minetest.set_node(flames[i], {name="air"})
|
||||||
|
if def.effects.water.particles then
|
||||||
|
rcbows.splash(flames[i], "rcbows_water.png")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--PARTICLES EFFECTS
|
||||||
|
|
||||||
|
function rcbows.trail(old_pos, pos, trail_particle)
|
||||||
|
local texture, animation
|
||||||
|
if type(trail_particle) == 'table' then
|
||||||
|
texture = trail_particle.texture
|
||||||
|
animation = trail_particle.animation
|
||||||
|
else
|
||||||
|
texture = trail_particle
|
||||||
|
animation = ""
|
||||||
|
end
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
texture = texture,
|
||||||
|
amount = 20,
|
||||||
|
time = 0.2,
|
||||||
|
minpos = old_pos,
|
||||||
|
maxpos = pos,
|
||||||
|
--minvel = {x=1, y=0, z=1},
|
||||||
|
--maxvel = {x=1, y=0, z=1},
|
||||||
|
--minacc = {x=1, y=0, z=1},
|
||||||
|
--maxacc = {x=1, y=0, z=1},
|
||||||
|
minexptime = 0.2,
|
||||||
|
maxexptime = 0.5,
|
||||||
|
minsize = 0.5,
|
||||||
|
maxsize = 1.5,
|
||||||
|
collisiondetection = false,
|
||||||
|
vertical = false,
|
||||||
|
glow = 14,
|
||||||
|
animation = animation,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function rcbows.splash(old_pos, splash_particle)
|
||||||
|
minetest.add_particlespawner({
|
||||||
|
amount = 5,
|
||||||
|
time = 1,
|
||||||
|
minpos = old_pos,
|
||||||
|
maxpos = old_pos,
|
||||||
|
minvel = {x=1, y=1, z=0},
|
||||||
|
maxvel = {x=1, y=1, z=0},
|
||||||
|
minacc = {x=1, y=1, z=1},
|
||||||
|
maxacc = {x=1, y=1, z=1},
|
||||||
|
minexptime = 0.2,
|
||||||
|
maxexptime = 0.5,
|
||||||
|
minsize = 1,
|
||||||
|
maxsize = 1,
|
||||||
|
collisiondetection = false,
|
||||||
|
vertical = false,
|
||||||
|
texture = splash_particle,
|
||||||
|
playername = "singleplayer"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
rcbows.register_bow("rcbows:bow_wood", {
|
||||||
|
description = S("Wooden Bow"),
|
||||||
|
image = "rcbows_pulling_0.png",
|
||||||
|
strength = 30,
|
||||||
|
uses = 150,
|
||||||
|
charge_time = 0.5,
|
||||||
|
recipe = {
|
||||||
|
{"", "group:wood", "farming:string"},
|
||||||
|
{"group:wood", "", "farming:string"},
|
||||||
|
{"", "group:wood", "farming:string"},
|
||||||
|
},
|
||||||
|
base_texture = "rcbows_pulling_0.png",
|
||||||
|
overlay_empty = "rcbows_standby.png",
|
||||||
|
overlay_charged = "rcbows_pulling_2.png",
|
||||||
|
arrows = "rcbows:arrow",
|
||||||
|
sounds = {
|
||||||
|
max_hear_distance = 10,
|
||||||
|
gain = 0.4,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
rcbows.register_arrow("rcbows:arrow", {
|
||||||
|
damage = 5,
|
||||||
|
inventory_arrow = {
|
||||||
|
name = "rcbows:inv_arrow",
|
||||||
|
description = S("Arrow"),
|
||||||
|
inventory_image = "rcbows_arrow.png"
|
||||||
|
},
|
||||||
|
sounds = {
|
||||||
|
max_hear_distance = 10,
|
||||||
|
gain = 0.4,
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,3 @@
|
||||||
|
# textdomain: rcbows
|
||||||
|
(place to reload)=(dcha. ratón para recargar)
|
||||||
|
(use to fire)=(izda. ratón para usar)
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = rcbows
|
||||||
|
depends =
|
||||||
|
optional_depends = tnt, explosions
|
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 333 B |
After Width: | Height: | Size: 341 B |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 666 B |