update gunslinger
added bloom, reloading delay, damage reduction with range, a weapon entity that is attached when you have the weapon in your inv, and making your inventory smaller when you have large weapons
This commit is contained in:
parent
05aa97769b
commit
e5976cebe0
50
api.lua
50
api.lua
@ -13,6 +13,7 @@ local types = {}
|
||||
local automatic = {}
|
||||
local scope_overlay = {}
|
||||
local interval = {}
|
||||
local bloom = {}
|
||||
|
||||
--
|
||||
-- Internal API functions
|
||||
@ -100,6 +101,7 @@ local function reload(stack, player, ammo)
|
||||
if not ammo then
|
||||
return stack
|
||||
end
|
||||
local playername = player:get_player_name()
|
||||
local is_mag = minetest.get_item_group(ammo, "gunslinger_magazine") > 0
|
||||
local inv = player:get_inventory()
|
||||
if inv:contains_item("main", ammo) then
|
||||
@ -124,6 +126,15 @@ local function reload(stack, player, ammo)
|
||||
stack:set_wear(0)
|
||||
inv:remove_item("main", ammo)
|
||||
end
|
||||
local def = gunslinger.get_def(stack:get_name())
|
||||
interval[playername] = def.unit_time-1
|
||||
minetest.after(-interval[playername], function()
|
||||
minetest.sound_play("gunslinger_charge", {
|
||||
object = player,
|
||||
max_hear_distance = 30,
|
||||
pitch = math.random(70,90)*.01
|
||||
})
|
||||
end)
|
||||
minetest.sound_play("gunslinger_loadmag", {
|
||||
object = player,
|
||||
max_hear_distance = 30,
|
||||
@ -211,6 +222,25 @@ local function fire(stack, player, base_spread, max_spread, pellets)
|
||||
end
|
||||
--a little calculation. speed divided by max speed should always be a value between 0 and 1.
|
||||
base_spread = base_spread + max_spread*(speed/max_speed)
|
||||
--add bloom
|
||||
local bloomref = bloom[player:get_player_name()]
|
||||
if bloomref then
|
||||
base_spread = base_spread + bloomref.time or 0
|
||||
bloomref.time = bloomref.time + def.bloom_amount or 0
|
||||
if bloomref.time > def.bloom_amount*4 then
|
||||
bloomref.time = def.bloom_amount*4
|
||||
end
|
||||
elseif def.bloom_amount then
|
||||
bloomref = {}
|
||||
bloomref.time = def.bloom_amount
|
||||
bloomref.multiplier = (def.bloom_decay or 1)*def.bloom_amount
|
||||
end
|
||||
|
||||
--don't allow spread to go beyond the maximum for the gun.
|
||||
if base_spread > max_spread then
|
||||
base_spread = max_spread
|
||||
end
|
||||
bloom[player:get_player_name()] = bloomref
|
||||
end
|
||||
if not pellets then pellets = 1 end
|
||||
for i = 1, pellets do
|
||||
@ -255,9 +285,9 @@ local function fire(stack, player, base_spread, max_spread, pellets)
|
||||
local target = pointed.ref
|
||||
local point = pointed.intersection_point
|
||||
local dmg = def.base_dmg * def.dmg_mult
|
||||
|
||||
local targetpos = target:get_pos()
|
||||
-- Add 50% damage if headshot
|
||||
if point.y > target:get_pos().y + 1.5 then
|
||||
if point.y > targetpos.y + 1.5 then
|
||||
dmg = dmg * 1.5
|
||||
end
|
||||
|
||||
@ -265,7 +295,9 @@ local function fire(stack, player, base_spread, max_spread, pellets)
|
||||
if scope_overlay[player:get_player_name()] then
|
||||
dmg = dmg * 1.2
|
||||
end
|
||||
|
||||
local distmulti = -(vector.distance(p1, targetpos)/def.range)^2+1
|
||||
dmg = dmg*distmulti
|
||||
if dmg < 0 then dmg = 0 end
|
||||
target:punch(player, nil, {damage_groups={fleshy=dmg}})
|
||||
end
|
||||
end
|
||||
@ -363,8 +395,9 @@ local function on_rclick(stack, player)
|
||||
end
|
||||
|
||||
local function on_q(itemstack, dropper, pos)
|
||||
local playername = dropper:get_player_name()
|
||||
local name = itemstack:get_name()
|
||||
if dropper:get_wielded_item():get_name() ~= name or not minetest.get_player_by_name(dropper:get_player_name()) then return end
|
||||
if dropper:get_wielded_item():get_name() ~= name or not playername then return end
|
||||
local def = gunslinger.get_def(name)
|
||||
local inv = dropper:get_inventory()
|
||||
minetest.sound_play("gunslinger_dropmag", {
|
||||
@ -383,6 +416,10 @@ end
|
||||
--------------------------------
|
||||
|
||||
local function on_step(dtime)
|
||||
for name, data in pairs(bloom) do
|
||||
bloom[name].time = data.time - dtime*data.multiplier or 1
|
||||
if data.time <= 0 then bloom[name] = nil end
|
||||
end
|
||||
for name in pairs(interval) do
|
||||
interval[name] = interval[name] + dtime
|
||||
end
|
||||
@ -418,7 +455,8 @@ end
|
||||
--
|
||||
|
||||
function gunslinger.get_def(name)
|
||||
return guns[name]
|
||||
if not name then return guns end
|
||||
return guns[name:gsub("%_empty", "")]
|
||||
end
|
||||
|
||||
function gunslinger.register_type(name, def)
|
||||
@ -519,7 +557,7 @@ function gunslinger.register_magazine(magazine, ammunition, size)
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = magazine,
|
||||
recipe = {magazine, ammunition},
|
||||
recipe = {magazine, ammunition.." "..size},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
|
176
invspace.lua
Normal file
176
invspace.lua
Normal file
@ -0,0 +1,176 @@
|
||||
local gunitems = {}
|
||||
local invsize = 8*4
|
||||
|
||||
minetest.register_entity("gunslinger:gunitem",{
|
||||
hp_max = 1,
|
||||
visual="wielditem",
|
||||
visual_size={x=.4,y=.4},
|
||||
collisionbox = {0,0,0,0,0,0},
|
||||
physical=false,
|
||||
textures={"air"},
|
||||
on_activate = function(self, staticdata)
|
||||
if not staticdata or staticdata == "" then self.object:remove() return end
|
||||
local data = minetest.deserialize(staticdata)
|
||||
if not data or not data.owner or not data.item then self.object:remove() return end
|
||||
local player = minetest.get_player_by_name(data.owner)
|
||||
if not player then gunitems[data.owner] = nil self.object:remove() return end
|
||||
self.object:set_attach(player, "Body", {x=0,y=4,z=1.5}, {x=0,y=0,z=0})
|
||||
self.object:set_properties({textures = { data.item }})
|
||||
end
|
||||
})
|
||||
|
||||
local function get_weapons(player)
|
||||
local name = player:get_player_name()
|
||||
local inv = player:get_inventory()
|
||||
local lists = inv:get_lists()
|
||||
local weapons = {}
|
||||
for list, data in pairs(lists) do
|
||||
local size = inv:get_size(list)
|
||||
for i = 1, size do
|
||||
|
||||
local stack = inv:get_stack(list, i)
|
||||
local stackname = stack:get_name()
|
||||
if stackname then
|
||||
stacksub = stackname
|
||||
if gunslinger.get_def(stacksub) and not gunslinger.get_def(stacksub).concealed then
|
||||
if (wieldview or wield3d) and list == "main" and player:get_wield_index() == i then
|
||||
weapons["wield"] = stackname
|
||||
else
|
||||
table.insert(weapons, stackname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return weapons
|
||||
end
|
||||
|
||||
local function get_largest(weapons)
|
||||
local size = 0
|
||||
local bigindex
|
||||
for index, weapon in pairs(weapons) do
|
||||
if index ~= "wield" then
|
||||
local gunsize = gunslinger.get_def(weapon).space
|
||||
if gunsize and gunsize > size then size = gunsize bigindex = index end
|
||||
end
|
||||
end
|
||||
return bigindex or 1
|
||||
end
|
||||
|
||||
local function update_weapon(player)
|
||||
local weapons = get_weapons(player)
|
||||
local weapon = weapons[get_largest(weapons)]
|
||||
local name = player:get_player_name()
|
||||
local gunspace = 0
|
||||
for index, gun in pairs(weapons) do
|
||||
gun = gun
|
||||
local def = gunslinger.get_def(gun)
|
||||
if def and def.space then
|
||||
gunspace = gunspace + def.space-1
|
||||
end
|
||||
end
|
||||
local player_inv = player:get_inventory()
|
||||
if invsize-gunspace ~= player_inv:get_size("main") then
|
||||
for i = invsize-gunspace+1, invsize do
|
||||
minetest.item_drop(player_inv:get_stack("main", i), player, player:get_pos())
|
||||
end
|
||||
player_inv:set_size("main", invsize-gunspace)
|
||||
end
|
||||
if not weapon then
|
||||
if gunitems[name] then
|
||||
gunitems[name]:remove()
|
||||
gunitems[name] = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
if not gunitems[name] then
|
||||
gunitems[name] = minetest.add_entity(player:get_pos(), "gunslinger:gunitem", minetest.serialize({owner = name, item = weapon}))
|
||||
else
|
||||
gunitems[name]:set_properties({textures = { weapon }})
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
|
||||
--minetest.chat_send_all("oi")
|
||||
--return 0
|
||||
end)
|
||||
--[[ * Determines how much of a stack may be taken, put or moved to a
|
||||
player inventory.
|
||||
* `player` (type `ObjectRef`) is the player who modified the inventory
|
||||
`inventory` (type `InvRef`).
|
||||
* List of possible `action` (string) values and their
|
||||
`inventory_info` (table) contents:
|
||||
* `move`: `{from_list=string, to_list=string, from_index=number, to_index=number, count=number}`
|
||||
* `put`: `{listname=string, index=number, stack=ItemStack}`
|
||||
* `take`: Same as `put`
|
||||
* Return a numeric value to limit the amount of items to be taken, put or
|
||||
moved. A value of `-1` for `take` will make the source stack infinite.--]]
|
||||
|
||||
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
|
||||
local stack = inventory_info.stack
|
||||
if not stack and action == "move" then
|
||||
stack = inventory:get_stack(inventory_info.to_list, inventory_info.to_index)
|
||||
if not stack or not gunslinger.get_def(stack:get_name()) then
|
||||
stack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index)
|
||||
end
|
||||
end
|
||||
if stack and gunslinger.get_def(stack:get_name()) then
|
||||
update_weapon(player)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_joinplayer(function(player, last_login)
|
||||
update_weapon(player)
|
||||
end)
|
||||
minetest.register_on_leaveplayer(function(player, last_login)
|
||||
local name = player:get_player_name()
|
||||
if gunitems[name] then
|
||||
gunitems[name]:remove()
|
||||
gunitems[name] = nil
|
||||
end
|
||||
end)
|
||||
minetest.register_on_respawnplayer(function(player, last_login)
|
||||
local name = player:get_player_name()
|
||||
if gunitems[name] then
|
||||
gunitems[name]:remove()
|
||||
gunitems[name] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
if armor then
|
||||
local origfunc = armor.update_player_visuals
|
||||
armor.update_player_visuals = function(self, player)
|
||||
minetest.after(0, update_weapon, player)
|
||||
return origfunc(self, player)
|
||||
end
|
||||
else
|
||||
local wieldtimer = 0
|
||||
local lastwield = {}
|
||||
minetest.register_globalstep(function(dtime)
|
||||
wieldtimer = wieldtimer + dtime
|
||||
if wieldtimer > .5 then
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local wielditem = player:get_wielded_item():get_name()
|
||||
if not lastwield[name] then lastwield[name] = wielditem else
|
||||
if wielditem ~= lastwield[name] then
|
||||
update_weapon(player)
|
||||
end
|
||||
lastwield[name] = wielditem
|
||||
end
|
||||
end
|
||||
wieldtimer = 0
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function reattach()
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
if gunitems[name] then
|
||||
gunitems[name]:set_attach(player, "Body", {x=0,y=4,z=1.5}, {x=0,y=0,z=0})
|
||||
end
|
||||
end
|
||||
minetest.after(5, reattach)
|
||||
end
|
||||
--minetest.after(5, reattach) --uncomment if you have issues with item getting detached in multiplayer
|
Loading…
x
Reference in New Issue
Block a user