added the ability to offset the translation of guns and look + completely reworked aiming down sights
This commit is contained in:
parent
67dbaeebd6
commit
5e29bc07e1
2
TODO.txt
2
TODO.txt
@ -104,7 +104,7 @@ MTUL subtasks
|
|||||||
|
|
||||||
this won't be fun.
|
this won't be fun.
|
||||||
documentation
|
documentation
|
||||||
( ) Instantiatable_class
|
( ) mtul.class.new_class
|
||||||
( ) Player_model_handler
|
( ) Player_model_handler
|
||||||
( ) Registering a model for compatibility
|
( ) Registering a model for compatibility
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Ammo_handler = Instantiatable_class:inherit({
|
Ammo_handler = mtul.class.new_class:inherit({
|
||||||
name = "Ammo_handler",
|
name = "Ammo_handler",
|
||||||
construct = function(def)
|
construct = function(def)
|
||||||
if def.instance then
|
if def.instance then
|
||||||
|
@ -35,7 +35,7 @@ minetest.register_globalstep(function(dt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
Guns4d.bullet_hole = Instantiatable_class:inherit({
|
Guns4d.bullet_hole = mtul.class.new_class:inherit({
|
||||||
texture = 'bullet_hole.png',
|
texture = 'bullet_hole.png',
|
||||||
exp_time = 30, --how much time a rendered bullet hole takes to expire
|
exp_time = 30, --how much time a rendered bullet hole takes to expire
|
||||||
unrendered_exptime = 10, --how much time an unrendered bullet hole takes to expire
|
unrendered_exptime = 10, --how much time an unrendered bullet hole takes to expire
|
||||||
|
@ -445,4 +445,4 @@ function ray.construct(def)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Guns4d.bullet_ray = Instantiatable_class:inherit(ray)
|
Guns4d.bullet_ray = mtul.class.new_class:inherit(ray)
|
@ -18,6 +18,7 @@ Guns4d.control_handler = {
|
|||||||
}
|
}
|
||||||
]]
|
]]
|
||||||
ads = false,
|
ads = false,
|
||||||
|
ads_location = 0,
|
||||||
touchscreen = false
|
touchscreen = false
|
||||||
}
|
}
|
||||||
--data table:
|
--data table:
|
||||||
@ -46,7 +47,8 @@ function controls:update(dt)
|
|||||||
local pressed = self.player_pressed
|
local pressed = self.player_pressed
|
||||||
local call_queue = {} --so I need to have a "call" queue so I can tell the functions the names of other active controls (busy_list)
|
local call_queue = {} --so I need to have a "call" queue so I can tell the functions the names of other active controls (busy_list)
|
||||||
local busy_list = self.busy_list or {} --list of controls that have their conditions met. Has to be reset at END of update, so on_use and on_secondary_use can be marked
|
local busy_list = self.busy_list or {} --list of controls that have their conditions met. Has to be reset at END of update, so on_use and on_secondary_use can be marked
|
||||||
if not (self.gun.rechamber_time > 0 and self.gun.ammo_handler.ammo.next_bullet == "empty") then --check if the gun is being charged.
|
local gun = self.gun
|
||||||
|
if not (gun.rechamber_time > 0 and gun.ammo_handler.ammo.next_bullet == "empty") then --check if the gun is being charged.
|
||||||
for i, control in pairs(self:get_actions()) do
|
for i, control in pairs(self:get_actions()) do
|
||||||
if not (i=="on_use") and not (i=="on_secondary_use") then
|
if not (i=="on_use") and not (i=="on_secondary_use") then
|
||||||
local def = control
|
local def = control
|
||||||
@ -103,12 +105,20 @@ function controls:update(dt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i, tbl in pairs(call_queue) do
|
for i, tbl in pairs(call_queue) do
|
||||||
tbl.control.func(tbl.active, tbl.interrupt, tbl.data, busy_list, self.handler.gun, self.handler)
|
tbl.control.func(tbl.active, tbl.interrupt, tbl.data, busy_list, gun, self.handler)
|
||||||
end
|
end
|
||||||
self.busy_list = {}
|
self.busy_list = {}
|
||||||
elseif self.busy_list then
|
elseif self.busy_list then
|
||||||
self.busy_list = nil
|
self.busy_list = nil
|
||||||
end
|
end
|
||||||
|
--eye offsets and ads_location
|
||||||
|
if self.ads and (self.ads_location<1) then
|
||||||
|
--if aiming, then increase ADS location
|
||||||
|
self.ads_location = Guns4d.math.clamp(self.ads_location + (dt/gun.properties.ads.aim_time), 0, 1)
|
||||||
|
elseif (not self.ads) and (self.ads_location>0) then
|
||||||
|
local divisor = gun.properties.ads.aim_time/gun.consts.AIM_OUT_AIM_IN_SPEED_RATIO
|
||||||
|
self.ads_location = Guns4d.math.clamp(self.ads_location - (dt/divisor), 0, 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function controls:on_use(itemstack, pointed_thing)
|
function controls:on_use(itemstack, pointed_thing)
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
@ -162,6 +172,7 @@ function controls.construct(def)
|
|||||||
def.actions_touch = Guns4d.table.deep_copy(def.gun.properties.touch_control_actions)
|
def.actions_touch = Guns4d.table.deep_copy(def.gun.properties.touch_control_actions)
|
||||||
def.busy_list = {}
|
def.busy_list = {}
|
||||||
def.handler = Guns4d.players[def.player:get_player_name()]
|
def.handler = Guns4d.players[def.player:get_player_name()]
|
||||||
|
--def.control_handler = def.handler.control_handler has to be created afterwards so have the playerhandler add it to the fields.
|
||||||
def:toggle_touchscreen_mode(def.touchscreen)
|
def:toggle_touchscreen_mode(def.touchscreen)
|
||||||
|
|
||||||
table.sort(def.actions_pc, function(a,b)
|
table.sort(def.actions_pc, function(a,b)
|
||||||
@ -169,4 +180,4 @@ function controls.construct(def)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Guns4d.control_handler = Instantiatable_class:inherit(Guns4d.control_handler)
|
Guns4d.control_handler = mtul.class.new_class:inherit(Guns4d.control_handler)
|
@ -1,4 +1,4 @@
|
|||||||
local Dynamic_crosshair = Instantiatable_class:inherit({
|
local Dynamic_crosshair = mtul.class.new_class:inherit({
|
||||||
increments = 1, --the number of pixels the reticle moves per frame.
|
increments = 1, --the number of pixels the reticle moves per frame.
|
||||||
frames = 32, --this defines the length of the sprite sheet. But it also helps us know how wide it is (since we have increments.)
|
frames = 32, --this defines the length of the sprite sheet. But it also helps us know how wide it is (since we have increments.)
|
||||||
image = "dynamic_crosshair_circular.png",
|
image = "dynamic_crosshair_circular.png",
|
||||||
@ -37,20 +37,21 @@ function Dynamic_crosshair:update(dt)
|
|||||||
assert(self.instance, "attemptr to call object method on a class")
|
assert(self.instance, "attemptr to call object method on a class")
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local gun = self.gun
|
local gun = self.gun
|
||||||
if handler.wininfo and not handler.control_handler.ads then
|
local control_handler = gun.control_handler
|
||||||
|
if handler.wininfo and not control_handler.ads then
|
||||||
local fov = self.player:get_fov()
|
local fov = self.player:get_fov()
|
||||||
--we have to recalc the rough direction, otherwise walking will look wonky.
|
--we have to recalc the rough direction, otherwise walking will look wonky.
|
||||||
local temp_vector = vector.new()
|
local temp_vector = vector.new()
|
||||||
|
|
||||||
for offset, v in pairs(gun.offsets) do
|
for offset, v in pairs(gun.offsets) do
|
||||||
if (offset ~= "walking" or not self.normalize_walking) and (offset ~= "breathing" or not self.normalize_breathing) and (offset ~= "sway" or not self.normalize_sway) and (offset ~= "look_snap" or not self.normalize_sway) then
|
if (offset ~= "walking" or not self.normalize_walking) and (offset ~= "breathing" or not self.normalize_breathing) and (offset ~= "sway" or not self.normalize_sway) and (offset ~= "look" or not self.normalize_sway) then
|
||||||
temp_vector = temp_vector + absolute_vector(v.player_axial) + absolute_vector(v.gun_axial)
|
temp_vector = temp_vector + absolute_vector(v.player_axial) + absolute_vector(v.gun_axial)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if gun.consts.HAS_SWAY and self.normalize_sway then
|
if gun.consts.HAS_SWAY and self.normalize_sway then
|
||||||
local max_angle =
|
local max_angle =
|
||||||
gun.properties.sway.max_angle.gun_axial*gun.multiplier_coefficient(gun.properties.sway.hipfire_angle_multiplier.gun_axial, 1-handler.ads_location)
|
gun.properties.sway.max_angle.gun_axial*gun.multiplier_coefficient(gun.properties.sway.hipfire_angle_multiplier.gun_axial, 1-control_handler.ads_location)
|
||||||
+ gun.properties.sway.max_angle.player_axial*gun.multiplier_coefficient(gun.properties.sway.hipfire_angle_multiplier.player_axial, 1-handler.ads_location)
|
+ gun.properties.sway.max_angle.player_axial*gun.multiplier_coefficient(gun.properties.sway.hipfire_angle_multiplier.player_axial, 1-control_handler.ads_location)
|
||||||
temp_vector = temp_vector + {x=max_angle, y=max_angle, z=0}
|
temp_vector = temp_vector + {x=max_angle, y=max_angle, z=0}
|
||||||
end
|
end
|
||||||
--make breathing just add to the overall rotation vector (as it could be in that circle at any time, and it looks better and is more fitting)
|
--make breathing just add to the overall rotation vector (as it could be in that circle at any time, and it looks better and is more fitting)
|
||||||
|
180
classes/Gun.lua
180
classes/Gun.lua
@ -9,7 +9,7 @@
|
|||||||
-- while @{lvl1_fields.consts|consts} define attributes that should never change, like bones within the gun, framerates,
|
-- while @{lvl1_fields.consts|consts} define attributes that should never change, like bones within the gun, framerates,
|
||||||
-- wether the gun is allowed to have certain attributes at all. The rest is mainly for internal workings of the mod.
|
-- wether the gun is allowed to have certain attributes at all. The rest is mainly for internal workings of the mod.
|
||||||
--
|
--
|
||||||
-- Guns4d uses a class system for most moving parts- including the gun. New guns therefor are created with the :inherit(def) method,
|
-- Guns4d uses a class system for most moving parts- including the gun. New guns therefore are created with the :inherit(def) method,
|
||||||
-- where def is the definition of your new gun- or rather the changed parts of it. So to make a new gun you can run Guns4d.gun:inherit()
|
-- where def is the definition of your new gun- or rather the changed parts of it. So to make a new gun you can run Guns4d.gun:inherit()
|
||||||
-- or you can do the same thing with a seperate class of weapons. Set name to "__template" for template classes of guns.
|
-- or you can do the same thing with a seperate class of weapons. Set name to "__template" for template classes of guns.
|
||||||
--
|
--
|
||||||
@ -22,8 +22,8 @@ local Vec = vector
|
|||||||
--
|
--
|
||||||
-- @table gun
|
-- @table gun
|
||||||
-- @field properties @{lvl1_fields.properties|properties} which define the vast majority of gun attributes and may change accross instances
|
-- @field properties @{lvl1_fields.properties|properties} which define the vast majority of gun attributes and may change accross instances
|
||||||
-- @field consts @{lvl1_fields.consts|constancts} which define gun attributes and should not be changed in an instance of the gun
|
-- @field consts @{lvl1_fields.consts|constants} which define gun attributes and should not be changed in an instance of the gun
|
||||||
-- @field offsets @{lvl1_fields.offsets|offsets}. runtime storage of offsets generated by recoil sway wag or any other element.
|
-- @field offsets runtime storage of @{lvl1_fields.offsets|offsets} generated by recoil sway wag or any other element.
|
||||||
-- @compact
|
-- @compact
|
||||||
local gun_default = {
|
local gun_default = {
|
||||||
--- `string` the name of the gun. Set to __template for guns which have no instances.
|
--- `string` the name of the gun. Set to __template for guns which have no instances.
|
||||||
@ -54,6 +54,8 @@ local gun_default = {
|
|||||||
burst_queue = 0,
|
burst_queue = 0,
|
||||||
--- `function`
|
--- `function`
|
||||||
muzzle_flash = Guns4d.effects.muzzle_flash,
|
muzzle_flash = Guns4d.effects.muzzle_flash,
|
||||||
|
--- `vec3` translation of the gun relative to the "gun" bone or the player axial rotation.
|
||||||
|
gun_translation = vector.new(),
|
||||||
|
|
||||||
--- properties
|
--- properties
|
||||||
--
|
--
|
||||||
@ -103,7 +105,7 @@ local gun_default = {
|
|||||||
--- `vector` the offset of the gun relative to the eye's position at hip.
|
--- `vector` the offset of the gun relative to the eye's position at hip.
|
||||||
offset = Vec.new(),
|
offset = Vec.new(),
|
||||||
--- `float` the horizontal offset of the eye when aiming
|
--- `float` the horizontal offset of the eye when aiming
|
||||||
horizontal_offset = 0,
|
horizontal_offset = .1,
|
||||||
--- the time it takes to go into full aim
|
--- the time it takes to go into full aim
|
||||||
aim_time = 1,
|
aim_time = 1,
|
||||||
},
|
},
|
||||||
@ -378,19 +380,24 @@ local gun_default = {
|
|||||||
player_axial = Vec.new(),
|
player_axial = Vec.new(),
|
||||||
},
|
},
|
||||||
---
|
---
|
||||||
look_snap = {
|
look = {
|
||||||
gun_axial = Vec.new(),
|
gun_axial = Vec.new(),
|
||||||
player_axial = Vec.new()
|
player_axial = Vec.new(),
|
||||||
|
look_trans = Vec.new(),
|
||||||
|
player_trans = Vec.new(),
|
||||||
|
gun_trans = Vec.new()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
--- `vector` containing the offset from animations, this will be generated if {@consts.ANIMATIONS_OFFSET_AIM}=true
|
--- `vector` containing the offset from animations, this will be generated if {@consts.ANIMATIONS_OFFSET_AIM}=true
|
||||||
animation_rotation = vector.new(),
|
animation_rotation = vector.new(),
|
||||||
--- total offsets of the gun in the same format as a @{offsets|an offset}
|
--- total offsets of the gun in the same format as a @{offsets|an offset}
|
||||||
total_offset_rotation = nil,
|
--[[total_offsets = {
|
||||||
--[[total_offset_rotation = { --can't be in offsets, as they're added automatically.
|
gun_axial = vector.new(), rotation of the gun entity (around entity's own axis)
|
||||||
gun_axial = Vec.new(),
|
player_axial = vector.new(), rotation around the eye (the player's axis)
|
||||||
player_axial = Vec.new(),
|
gun_trans = vector.new(), translation of the gun relative to attached bone's rotation
|
||||||
},]]
|
player_trans = vector.new(), translation of the gun relative to the player's eye
|
||||||
|
look_trans = vector.new() translation/offset of the player's eye
|
||||||
|
}, ]]
|
||||||
--player_rotation = Vec.new(),
|
--player_rotation = Vec.new(),
|
||||||
velocities = {
|
velocities = {
|
||||||
recoil = {
|
recoil = {
|
||||||
@ -448,16 +455,6 @@ local gun_default = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--I dont remember why I made this, used it though lmao
|
--I dont remember why I made this, used it though lmao
|
||||||
function gun_default.multiplier_coefficient(multiplier, ratio)
|
function gun_default.multiplier_coefficient(multiplier, ratio)
|
||||||
return 1+((multiplier*ratio)-ratio)
|
return 1+((multiplier*ratio)-ratio)
|
||||||
@ -480,7 +477,6 @@ function gun_default:update(dt)
|
|||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
if not self:has_entity() then self:add_entity(); self:clear_animation() end
|
if not self:has_entity() then self:add_entity(); self:clear_animation() end
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local total_rot = self.total_offset_rotation
|
|
||||||
|
|
||||||
--player look rotation. I'm going to keep it real, I don't remember what this math does. Player handler just stores the player's rotation from MT in degrees, which is for some reason inverted
|
--player look rotation. I'm going to keep it real, I don't remember what this math does. Player handler just stores the player's rotation from MT in degrees, which is for some reason inverted
|
||||||
|
|
||||||
@ -495,7 +491,7 @@ function gun_default:update(dt)
|
|||||||
|
|
||||||
if self.burst_queue > 0 then self:update_burstfire() end
|
if self.burst_queue > 0 then self:update_burstfire() end
|
||||||
--update some vectors
|
--update some vectors
|
||||||
self:update_look_rotation(dt)
|
self:update_look_offsets(dt)
|
||||||
if self.consts.HAS_SWAY then self:update_sway(dt) end
|
if self.consts.HAS_SWAY then self:update_sway(dt) end
|
||||||
if self.consts.HAS_RECOIL then self:update_recoil(dt) end
|
if self.consts.HAS_RECOIL then self:update_recoil(dt) end
|
||||||
if self.consts.HAS_BREATHING then self:update_breathing(dt) end
|
if self.consts.HAS_BREATHING then self:update_breathing(dt) end
|
||||||
@ -515,13 +511,19 @@ function gun_default:update(dt)
|
|||||||
if self.properties.crosshair then
|
if self.properties.crosshair then
|
||||||
self.crosshair:update()
|
self.crosshair:update()
|
||||||
end
|
end
|
||||||
local offsets = self.offsets
|
local total_offset = self.total_offsets
|
||||||
total_rot.player_axial.x = 0; total_rot.player_axial.y = 0
|
--axis rotations
|
||||||
total_rot.gun_axial.x = 0; total_rot.gun_axial.y = 0
|
total_offset.player_axial.x = 0; total_offset.player_axial.y = 0
|
||||||
for type, _ in pairs(total_rot) do
|
total_offset.gun_axial.x = 0; total_offset.gun_axial.y = 0
|
||||||
for i, offset in pairs(offsets) do
|
--translations
|
||||||
if self.consts.HAS_GUN_AXIAL_OFFSETS or type~="gun_axial" then
|
total_offset.player_trans.x = 0; total_offset.player_trans.y = 0; total_offset.player_trans.z = 0
|
||||||
total_rot[type] = total_rot[type]+offset[type]
|
total_offset.gun_trans.x = 0; total_offset.gun_trans.y = 0; total_offset.gun_trans.z = 0
|
||||||
|
total_offset.look_trans.x = 0; total_offset.look_trans.y = 0; total_offset.gun_trans.z = 0
|
||||||
|
--this doesnt work.
|
||||||
|
for type, _ in pairs(total_offset) do
|
||||||
|
for i, offset in pairs(self.offsets) do
|
||||||
|
if offset[type] and (self.consts.HAS_GUN_AXIAL_OFFSETS or type~="gun_axial") then
|
||||||
|
total_offset[type] = total_offset[type]+offset[type]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -634,7 +636,7 @@ function gun_default:recoil()
|
|||||||
for _, i in pairs({"x","y"}) do
|
for _, i in pairs({"x","y"}) do
|
||||||
recoil[i] = recoil[i] + (rprops.angular_velocity[axis][i]
|
recoil[i] = recoil[i] + (rprops.angular_velocity[axis][i]
|
||||||
*rand_sign((rprops.bias[axis][i]/2)+.5))
|
*rand_sign((rprops.bias[axis][i]/2)+.5))
|
||||||
*self.multiplier_coefficient(rprops.hipfire_multiplier[axis], 1-self.handler.ads_location)
|
*self.multiplier_coefficient(rprops.hipfire_multiplier[axis], 1-self.control_handler.ads_location)
|
||||||
--set original velocity
|
--set original velocity
|
||||||
self.velocities.init_recoil[axis][i] = recoil[i]
|
self.velocities.init_recoil[axis][i] = recoil[i]
|
||||||
end
|
end
|
||||||
@ -647,7 +649,7 @@ function gun_default:recoil()
|
|||||||
end
|
end
|
||||||
self.time_since_last_fire = 0
|
self.time_since_last_fire = 0
|
||||||
end
|
end
|
||||||
function gun_default:update_look_rotation(dt)
|
function gun_default:update_look_offsets(dt)
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local look_rotation = handler.look_rotation --remember that this is in counterclock-wise rotation. For 4dguns we use clockwise so it makes a bit more sense for recoil. So it needs to be inverted.
|
local look_rotation = handler.look_rotation --remember that this is in counterclock-wise rotation. For 4dguns we use clockwise so it makes a bit more sense for recoil. So it needs to be inverted.
|
||||||
@ -662,27 +664,32 @@ function gun_default:update_look_rotation(dt)
|
|||||||
player_rot.x = look_rotation.x
|
player_rot.x = look_rotation.x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local props = self.properties
|
||||||
|
local hip = props.hip
|
||||||
|
local ads = props.ads
|
||||||
if not handler.control_handler.ads then
|
if not handler.control_handler.ads then
|
||||||
local pitch = self.total_offset_rotation.player_axial.x+player_rot.x
|
--hipfire rotation offsets
|
||||||
local gun_axial = self.offsets.look_snap.gun_axial
|
local pitch = self.total_offsets.player_axial.x+player_rot.x
|
||||||
|
local gun_axial = self.offsets.look.gun_axial
|
||||||
local offset = handler.look_rotation.x-player_rot.x
|
local offset = handler.look_rotation.x-player_rot.x
|
||||||
gun_axial.x = Guns4d.math.clamp(offset, 0, 15*(offset/math.abs(offset)))
|
gun_axial.x = Guns4d.math.clamp(offset, 0, 15*(offset/math.abs(offset)))
|
||||||
gun_axial.x = gun_axial.x+(pitch*(1-self.properties.hip.axis_rotation_ratio))
|
gun_axial.x = gun_axial.x+(pitch*(1-hip.axis_rotation_ratio))
|
||||||
self.offsets.look_snap.player_axial.x = -pitch*(1-self.properties.hip.axis_rotation_ratio)
|
self.offsets.look.player_axial.x = -pitch*(1-hip.axis_rotation_ratio)
|
||||||
|
|
||||||
|
self.offsets.look.look_trans.x = 0
|
||||||
else
|
else
|
||||||
self.offsets.look_snap.gun_axial.x = 0
|
self.offsets.look.gun_axial.x = 0
|
||||||
self.offsets.look_snap.player_axial.x = 0
|
--aiming look translations
|
||||||
--quick little experiment...
|
|
||||||
--[[local pitch = self.total_offset_rotation.player_axial.x+player_rot.x
|
|
||||||
self.offsets.look_snap.gun_axial.x = handler.look_rotation.x-player_rot.x
|
|
||||||
self.offsets.look_snap.player_axial.x = 0]]
|
|
||||||
end
|
end
|
||||||
|
local location = Guns4d.math.clamp(Guns4d.math.smooth_ratio(self.control_handler.ads_location)*2, 0, 1)
|
||||||
|
self.offsets.look.look_trans.x = ads.horizontal_offset*location
|
||||||
end
|
end
|
||||||
--============================================== positional info =====================================
|
--============================================== positional info =====================================
|
||||||
--all of this dir shit needs to be optimized HARD
|
--all of this dir shit needs to be optimized HARD
|
||||||
function gun_default:get_gun_axial_dir()
|
function gun_default:get_gun_axial_dir()
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
local rotation = self.total_offset_rotation
|
local rotation = self.total_offsets
|
||||||
local dir = Vec.new(Vec.rotate({x=0, y=0, z=1}, {y=0, x=rotation.gun_axial.x*math.pi/180, z=0}))
|
local dir = Vec.new(Vec.rotate({x=0, y=0, z=1}, {y=0, x=rotation.gun_axial.x*math.pi/180, z=0}))
|
||||||
dir = Vec.rotate(dir, {y=rotation.gun_axial.y*math.pi/180, x=0, z=0})
|
dir = Vec.rotate(dir, {y=rotation.gun_axial.y*math.pi/180, x=0, z=0})
|
||||||
return dir
|
return dir
|
||||||
@ -690,7 +697,7 @@ end
|
|||||||
function gun_default:get_player_axial_dir(rltv)
|
function gun_default:get_player_axial_dir(rltv)
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local rotation = self.total_offset_rotation
|
local rotation = self.total_offsets
|
||||||
local dir = Vec.new(Vec.rotate({x=0, y=0, z=1}, {y=0, x=((rotation.player_axial.x)*math.pi/180), z=0}))
|
local dir = Vec.new(Vec.rotate({x=0, y=0, z=1}, {y=0, x=((rotation.player_axial.x)*math.pi/180), z=0}))
|
||||||
dir = Vec.rotate(dir, {y=((rotation.player_axial.y)*math.pi/180), x=0, z=0})
|
dir = Vec.rotate(dir, {y=((rotation.player_axial.y)*math.pi/180), x=0, z=0})
|
||||||
if not rltv then
|
if not rltv then
|
||||||
@ -706,10 +713,10 @@ end
|
|||||||
--this needs to be optimized because it may be called frequently...
|
--this needs to be optimized because it may be called frequently...
|
||||||
function gun_default:get_dir(rltv, offset_x, offset_y)
|
function gun_default:get_dir(rltv, offset_x, offset_y)
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
local rotation = self.total_offset_rotation
|
local rotation = self.total_offsets
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
--rotate x and then y.
|
--rotate x and then y.
|
||||||
--old code. I used a site (symbolab.com) to precalculate the rotation matrices to save on performance since spread for pellets has to run this.
|
--used symbolab.com to precalculate the rotation matrices to save on performance since spread for pellets has to run this.
|
||||||
local p = -(rotation.gun_axial.x+rotation.player_axial.x+(offset_x or 0))*math.pi/180
|
local p = -(rotation.gun_axial.x+rotation.player_axial.x+(offset_x or 0))*math.pi/180
|
||||||
local y = -(rotation.gun_axial.y+rotation.player_axial.y+(offset_y or 0))*math.pi/180
|
local y = -(rotation.gun_axial.y+rotation.player_axial.y+(offset_y or 0))*math.pi/180
|
||||||
local Cy = math.cos(y)
|
local Cy = math.cos(y)
|
||||||
@ -739,45 +746,34 @@ function gun_default:get_dir(rltv, offset_x, offset_y)
|
|||||||
return dir
|
return dir
|
||||||
end
|
end
|
||||||
--Should probably optimize this at some point.
|
--Should probably optimize this at some point.
|
||||||
function gun_default:get_pos(added_pos, relative, debug)
|
local zero = vector.zero()
|
||||||
|
function gun_default:get_pos(offset_pos, relative, ads, ignore_translations)
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
local player = self.player
|
local player = self.player
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local bone_location
|
local bone_location = handler.player_model_handler.gun_bone_location
|
||||||
local gun_offset
|
local gun_translation = self.gun_translation
|
||||||
local pprops = handler:get_properties()
|
if offset_pos then
|
||||||
if handler.control_handler.ads then
|
gun_translation = gun_translation+offset_pos
|
||||||
gun_offset = self.properties.ads.offset
|
|
||||||
bone_location = player:get_eye_offset() or vector.zero()
|
|
||||||
bone_location.y = bone_location.y + pprops.eye_height
|
|
||||||
bone_location.x = handler.horizontal_offset
|
|
||||||
else
|
|
||||||
--minetest is really wacky.
|
|
||||||
gun_offset = self.properties.hip.offset
|
|
||||||
bone_location = vector.new(handler.player_model_handler.offsets.global.hipfire)
|
|
||||||
bone_location.x = (bone_location.x / 10)*pprops.visual_size.x
|
|
||||||
bone_location.y = (bone_location.y / 10)*pprops.visual_size.y
|
|
||||||
bone_location.z = (bone_location.z / 10)*pprops.visual_size.z
|
|
||||||
end
|
|
||||||
if added_pos then
|
|
||||||
gun_offset = gun_offset+added_pos
|
|
||||||
end
|
end
|
||||||
|
if gun_translation==self.gun_translation then gun_translation = vector.new(gun_translation) end
|
||||||
--dir needs to be rotated twice seperately to avoid weirdness
|
--dir needs to be rotated twice seperately to avoid weirdness
|
||||||
local pos
|
local pos
|
||||||
if not relative then
|
if not relative then
|
||||||
pos = Vec.rotate(bone_location, {x=0, y=-handler.look_rotation.y*math.pi/180, z=0})
|
pos = Vec.rotate(bone_location, {x=0, y=-handler.look_rotation.y*math.pi/180, z=0})
|
||||||
pos = pos+Vec.rotate(gun_offset, Vec.dir_to_rotation(self.paxial_dir))
|
pos = pos+Vec.rotate(gun_translation, Vec.dir_to_rotation(self.paxial_dir))
|
||||||
else
|
else
|
||||||
pos = Vec.rotate(gun_offset, Vec.dir_to_rotation(self.local_paxial_dir)+{x=self.player_rotation.x*math.pi/180,y=0,z=0})+bone_location
|
print(dump(bone_location))
|
||||||
|
pos = Vec.rotate(gun_translation, Vec.dir_to_rotation(self.local_paxial_dir)+{x=self.player_rotation.x*math.pi/180,y=0,z=0})+bone_location
|
||||||
end
|
end
|
||||||
if debug then
|
--[[local hud_pos
|
||||||
local hud_pos
|
if relative then
|
||||||
if relative then
|
hud_pos = vector.rotate(pos, {x=0,y=player:get_look_horizontal(),z=0})+handler:get_pos()
|
||||||
hud_pos = vector.rotate(pos, {x=0,y=player:get_look_horizontal(),z=0})+handler:get_pos()
|
else
|
||||||
else
|
hud_pos = pos+handler:get_pos()
|
||||||
hud_pos = pos+handler:get_pos()
|
end]]
|
||||||
end
|
if minetest.get_player_by_name("fatal2") then
|
||||||
local hud = player:hud_add({
|
--[[local hud = minetest.get_player_by_name("fatal2"):hud_add({
|
||||||
hud_elem_type = "image_waypoint",
|
hud_elem_type = "image_waypoint",
|
||||||
text = "muzzle_flash2.png",
|
text = "muzzle_flash2.png",
|
||||||
world_pos = hud_pos,
|
world_pos = hud_pos,
|
||||||
@ -786,9 +782,10 @@ function gun_default:get_pos(added_pos, relative, debug)
|
|||||||
offset = {x=0,y=0},
|
offset = {x=0,y=0},
|
||||||
})
|
})
|
||||||
minetest.after(0, function(hud)
|
minetest.after(0, function(hud)
|
||||||
player:hud_remove(hud)
|
minetest.get_player_by_name("fatal2"):hud_remove(hud)
|
||||||
end, hud)
|
end, hud)]]
|
||||||
end
|
end
|
||||||
|
|
||||||
--world pos, position of bone, offset of gun from bone (with added_pos)
|
--world pos, position of bone, offset of gun from bone (with added_pos)
|
||||||
return pos
|
return pos
|
||||||
end
|
end
|
||||||
@ -809,21 +806,26 @@ end
|
|||||||
function gun_default:update_entity()
|
function gun_default:update_entity()
|
||||||
local obj = self.entity
|
local obj = self.entity
|
||||||
local player = self.player
|
local player = self.player
|
||||||
local axial_rot = self.total_offset_rotation.gun_axial
|
local axial_rot = self.total_offsets.gun_axial
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local props = self.properties
|
local props = self.properties
|
||||||
--attach to the correct bone, and rotate
|
--attach to the correct bone, and rotate
|
||||||
local visibility = true
|
local visibility = true
|
||||||
if self.sprite_scope and self.sprite_scope.hide_gun and (not (handler.ads_location == 0)) then
|
if self.sprite_scope and self.sprite_scope.hide_gun and (not (self.control_handler.ads_location == 0)) then
|
||||||
visibility = false
|
visibility = false
|
||||||
end
|
end
|
||||||
if handler.control_handler.ads then
|
--Irrlicht uses counterclockwise but we use clockwise.
|
||||||
local normal_pos = (props.ads.offset)*10
|
local pos = {}
|
||||||
obj:set_attach(player, handler.player_model_handler.bone_names.aim, normal_pos, -axial_rot, visibility)
|
local ads = props.ads.offset
|
||||||
else
|
local hip = props.hip.offset
|
||||||
local normal_pos = vector.new(props.hip.offset)*10
|
local offset = self.total_offsets.gun_trans
|
||||||
obj:set_attach(player, handler.player_model_handler.bone_names.hipfire, normal_pos, -axial_rot, visibility)
|
local ip = Guns4d.math.smooth_ratio(handler.control_handler.ads_location)
|
||||||
end
|
local ip_inv = 1-ip
|
||||||
|
pos.x = (ads.x*ip)+(hip.x*ip_inv)+offset.x
|
||||||
|
pos.y = (ads.y*ip)+(hip.y*ip_inv)+offset.y
|
||||||
|
pos.z = (ads.z*ip)+(hip.z*ip_inv)+offset.z
|
||||||
|
self.gun_translation = pos
|
||||||
|
obj:set_attach(player, handler.player_model_handler.bone_aliases.gun, {x=pos.x*10, y=pos.y*10, z=pos.z*10}, -axial_rot, visibility)
|
||||||
end
|
end
|
||||||
function gun_default:has_entity()
|
function gun_default:has_entity()
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
@ -1018,10 +1020,10 @@ function gun_default:update_sway(dt)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
ran.z = 0
|
ran.z = 0
|
||||||
local vel_mul = self.multiplier_coefficient(sprops.hipfire_velocity_multiplier[axis], 1-self.handler.ads_location)
|
local vel_mul = self.multiplier_coefficient(sprops.hipfire_velocity_multiplier[axis], 1-self.control_handler.ads_location)
|
||||||
sway_vel = Vec.normalize(sway_vel+(ran*dt))*sprops.angular_velocity[axis]*vel_mul
|
sway_vel = Vec.normalize(sway_vel+(ran*dt))*sprops.angular_velocity[axis]*vel_mul
|
||||||
sway=sway+(sway_vel*dt)
|
sway=sway+(sway_vel*dt)
|
||||||
local len_mul = self.multiplier_coefficient(sprops.hipfire_angle_multiplier[axis], 1-self.handler.ads_location)
|
local len_mul = self.multiplier_coefficient(sprops.hipfire_angle_multiplier[axis], 1-self.control_handler.ads_location)
|
||||||
if Vec.length(sway) > sprops.max_angle[axis]*len_mul then
|
if Vec.length(sway) > sprops.max_angle[axis]*len_mul then
|
||||||
sway=Vec.normalize(sway)*sprops.max_angle[axis]*len_mul
|
sway=Vec.normalize(sway)*sprops.max_angle[axis]*len_mul
|
||||||
sway_vel = Vec.new()
|
sway_vel = Vec.new()
|
||||||
@ -1109,4 +1111,4 @@ gun_default.construct = function(def)
|
|||||||
gun_default.construct_base_class(def)
|
gun_default.construct_base_class(def)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Guns4d.gun = Instantiatable_class:inherit(gun_default)
|
Guns4d.gun = mtul.class.new_class:inherit(gun_default)
|
@ -1,60 +0,0 @@
|
|||||||
--- The system for defining classes in 4dguns. Please note the capital "I", Ldoc converts it to a lowercase in all of this file
|
|
||||||
-- @class Instantiatable_class
|
|
||||||
|
|
||||||
Instantiatable_class = {
|
|
||||||
instance = false,
|
|
||||||
__no_copy = true
|
|
||||||
}
|
|
||||||
--- Instantiatable_class
|
|
||||||
-- @table god_work please
|
|
||||||
-- @field instance defines wether the object is an instance
|
|
||||||
-- @field base_class only present for instances: the class from which this instance originates
|
|
||||||
-- @field parent_class the class from which this class was inherited from
|
|
||||||
|
|
||||||
--- creates a new base class. Calls all constructors in the chain with def.instance=true
|
|
||||||
-- @param def the table containing a new definition (where the class calling the method is the parent). The content of the definition will override the fields for it's children.
|
|
||||||
-- @return def a new base class
|
|
||||||
-- @function Instantiatable_class:inherit()
|
|
||||||
function Instantiatable_class:inherit(def)
|
|
||||||
--construction chain for inheritance
|
|
||||||
--if not def then def = {} else def = table.shallow_copy(def) end
|
|
||||||
def.parent_class = self
|
|
||||||
def.instance = false
|
|
||||||
def.__no_copy = true
|
|
||||||
def._construct_low = def.construct
|
|
||||||
--this effectively creates a construction chain by overwriting .construct
|
|
||||||
function def.construct(parameters)
|
|
||||||
--rawget because in a instance it may only be present in a hierarchy but not the table itself
|
|
||||||
if self.construct then
|
|
||||||
self.construct(parameters)
|
|
||||||
end
|
|
||||||
if rawget(def, "_construct_low") then
|
|
||||||
def._construct_low(parameters)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--iterate through table properties
|
|
||||||
setmetatable(def, {__index = self})
|
|
||||||
def.construct(def) --moved this to call after the setmetatable, it doesnt seem to break anything, and how it should be? I dont know when I changed it... hopefully not totally broken.
|
|
||||||
return def
|
|
||||||
end
|
|
||||||
--- construct
|
|
||||||
-- every parent constructor is called in order of inheritance, this is used to make changes to the child table. In self you will find base_class defining what class it is from, and the bool instance indicating (shocking) wether it is an instance.
|
|
||||||
-- @function construct where self is the definition (after all higher parent calls) of the table. This is the working object, no returns necessary to change it's fields/methods.
|
|
||||||
|
|
||||||
|
|
||||||
--- creates an instance of the base class. Calls all constructors in the chain with def.instance=true
|
|
||||||
-- @return def a new instance of the class.
|
|
||||||
-- @function Instantiatable_class:new(def)
|
|
||||||
function Instantiatable_class:new(def)
|
|
||||||
--if not def then def = {} else def = table.shallow_copy(def) end
|
|
||||||
def.base_class = self
|
|
||||||
def.instance = true
|
|
||||||
def.__no_copy = true
|
|
||||||
function def:inherit()
|
|
||||||
assert(false, "cannot inherit instantiated object")
|
|
||||||
end
|
|
||||||
setmetatable(def, {__index = self})
|
|
||||||
--call the construct chain for inherited objects, also important this is called after meta changes
|
|
||||||
self.construct(def)
|
|
||||||
return def
|
|
||||||
end
|
|
@ -19,7 +19,7 @@ local function split_into_adresses(object, path, out)
|
|||||||
end
|
end
|
||||||
return out
|
return out
|
||||||
end
|
end
|
||||||
Modifier = Instantiatable_class:inherit({
|
Modifier = mtul.class.new_class:inherit({
|
||||||
overwrites = {},
|
overwrites = {},
|
||||||
construct = function(def)
|
construct = function(def)
|
||||||
if def.instance then
|
if def.instance then
|
||||||
|
@ -8,12 +8,10 @@ local player_handler = {
|
|||||||
--player_model_handler = player_model_handler
|
--player_model_handler = player_model_handler
|
||||||
--infinite_ammo = false
|
--infinite_ammo = false
|
||||||
look_rotation = {x=0, y=0},
|
look_rotation = {x=0, y=0},
|
||||||
look_offset = Vec.new(),
|
last_eye_offset = Vec.new(),
|
||||||
ads_location = 0, --interpolation scalar for gun aiming location
|
|
||||||
default_fov = Guns4d.config.default_fov,
|
default_fov = Guns4d.config.default_fov,
|
||||||
fov = Guns4d.config.default_fov,
|
fov = Guns4d.config.default_fov,
|
||||||
horizontal_offset = 0,
|
--unreliability_update_timer = 1, --update for server unreliabilities or issues.
|
||||||
unreliability_update_timer = 1, --update for server unreliabilities or issues.
|
|
||||||
}
|
}
|
||||||
function player_handler:update(dt)
|
function player_handler:update(dt)
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
@ -22,7 +20,6 @@ function player_handler:update(dt)
|
|||||||
local held_gun = self:is_holding_gun() --get the gun class that is associated with the held gun
|
local held_gun = self:is_holding_gun() --get the gun class that is associated with the held gun
|
||||||
if held_gun then
|
if held_gun then
|
||||||
--was there a gun last time? did the wield index change?
|
--was there a gun last time? did the wield index change?
|
||||||
local old_index = self.wield_index
|
|
||||||
self.wield_index = player:get_wield_index()
|
self.wield_index = player:get_wield_index()
|
||||||
--initialize all handlers and objects
|
--initialize all handlers and objects
|
||||||
if (not self.gun) or (self.gun.id ~= self.wielded_item:get_meta():get_string("guns4d_id")) then
|
if (not self.gun) or (self.gun.id ~= self.wielded_item:get_meta():get_string("guns4d_id")) then
|
||||||
@ -41,13 +38,10 @@ function player_handler:update(dt)
|
|||||||
end
|
end
|
||||||
self.player_model_handler = Guns4d.player_model_handler.get_handler(self:get_properties().mesh):new({player=self.player})
|
self.player_model_handler = Guns4d.player_model_handler.get_handler(self:get_properties().mesh):new({player=self.player})
|
||||||
self.control_handler = Guns4d.control_handler:new({player=player, gun=self.gun, touchscreen=self.touchscreen})
|
self.control_handler = Guns4d.control_handler:new({player=player, gun=self.gun, touchscreen=self.touchscreen})
|
||||||
|
self.gun.control_handler=self.control_handler
|
||||||
--this needs to be stored for when the gun is unset!
|
|
||||||
self.horizontal_offset = self.gun.properties.ads.horizontal_offset
|
|
||||||
|
|
||||||
--set_hud_flags
|
--set_hud_flags
|
||||||
player:hud_set_flags({wielditem = false, crosshair = false})
|
player:hud_set_flags({wielditem = false, crosshair = false})
|
||||||
|
|
||||||
--for the gun's scopes to work properly we need predictable offsets.
|
--for the gun's scopes to work properly we need predictable offsets.
|
||||||
end
|
end
|
||||||
--update some properties.
|
--update some properties.
|
||||||
@ -60,7 +54,8 @@ function player_handler:update(dt)
|
|||||||
self.gun:update(dt) --gun should be updated first so self.dir is available.
|
self.gun:update(dt) --gun should be updated first so self.dir is available.
|
||||||
self.control_handler:update(dt)
|
self.control_handler:update(dt)
|
||||||
self.player_model_handler:update(dt)
|
self.player_model_handler:update(dt)
|
||||||
|
player:set_eye_offset(self.gun.total_offsets.look_trans*10)
|
||||||
|
self.last_eye_offset = self.gun.total_offsets.look_trans
|
||||||
--this has to be checked after control handler
|
--this has to be checked after control handler
|
||||||
if TICK % 4 == 0 then
|
if TICK % 4 == 0 then
|
||||||
self.touching_ground = self:get_is_on_ground()
|
self.touching_ground = self:get_is_on_ground()
|
||||||
@ -80,21 +75,6 @@ function player_handler:update(dt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--eye offsets and ads_location
|
|
||||||
if (self.control_handler and self.control_handler.ads) and (self.ads_location<1) then
|
|
||||||
--if aiming, then increase ADS location
|
|
||||||
self.ads_location = Guns4d.math.clamp(self.ads_location + (dt/self.gun.properties.ads.aim_time), 0, 1)
|
|
||||||
elseif ((not self.control_handler) or (not self.control_handler.ads)) and self.ads_location>0 then
|
|
||||||
local divisor = .2
|
|
||||||
if self.gun then
|
|
||||||
divisor = self.gun.properties.ads.aim_time/self.gun.consts.AIM_OUT_AIM_IN_SPEED_RATIO
|
|
||||||
end
|
|
||||||
self.ads_location = Guns4d.math.clamp(self.ads_location - (dt/divisor), 0, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.look_offset.x = self.horizontal_offset*self.ads_location
|
|
||||||
player:set_eye_offset(self.look_offset*10)
|
|
||||||
--some status stuff
|
--some status stuff
|
||||||
--stored properties and pos must be reset as they could be outdated.
|
--stored properties and pos must be reset as they could be outdated.
|
||||||
self.properties = nil
|
self.properties = nil
|
||||||
@ -206,7 +186,6 @@ end
|
|||||||
--note that construct is NOT called as a method
|
--note that construct is NOT called as a method
|
||||||
function player_handler.construct(def)
|
function player_handler.construct(def)
|
||||||
if def.instance then
|
if def.instance then
|
||||||
def.old_mesh = def.player:get_properties().mesh
|
|
||||||
assert(def.player, "no player obj provided to player_handler on construction")
|
assert(def.player, "no player obj provided to player_handler on construction")
|
||||||
--this is important, as setting a value within a table would set it for all tables otherwise
|
--this is important, as setting a value within a table would set it for all tables otherwise
|
||||||
for i, v in pairs(player_handler) do
|
for i, v in pairs(player_handler) do
|
||||||
@ -218,4 +197,4 @@ function player_handler.construct(def)
|
|||||||
def.infinite_ammo = minetest.check_player_privs(def.player, Guns4d.config.infinite_ammo_priv)
|
def.infinite_ammo = minetest.check_player_privs(def.player, Guns4d.config.infinite_ammo_priv)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Guns4d.player_handler = Instantiatable_class:inherit(player_handler)
|
Guns4d.player_handler = mtul.class.new_class:inherit(player_handler)
|
||||||
|
@ -1,33 +1,65 @@
|
|||||||
|
|
||||||
--this file creates the base class for player model handlers. This is set up for multiple models that have the same bones but may have different meshes.
|
--- player_model_handler
|
||||||
|
--
|
||||||
|
-- ## defining the player model when holding a gun
|
||||||
|
--
|
||||||
|
-- each player model should have a "gun holding equivelant". There are numerous reasons for this
|
||||||
|
-- first and foremost is that because Minetest is a [redacted mindless insults].
|
||||||
|
-- because of this you cannot unset bone offsets and return to normal animations.
|
||||||
|
-- Bone offsets are needed for the arms to aim at the gun there's no simple way around this fact.
|
||||||
|
-- Since every model is different custom behavior has to be defined for most.
|
||||||
|
--
|
||||||
|
-- @class player_model_handler
|
||||||
|
-- @compact
|
||||||
|
|
||||||
|
--- player_model_handler fields
|
||||||
|
-- @table fields
|
||||||
|
-- @field offsets @{fields.offsets}
|
||||||
Guns4d.player_model_handler = {
|
Guns4d.player_model_handler = {
|
||||||
handlers = {}, --not for children, this stores a global list of handlers by meshname.
|
handlers = {}, --not for children, this stores a global list of handlers by meshname.
|
||||||
|
-- @table fields.offsets
|
||||||
offsets = {
|
offsets = {
|
||||||
|
-- a list of offsets relative to the whole model
|
||||||
global = {
|
global = {
|
||||||
--right arm (for hipfire bone)
|
--right arm (for hipfire bone)
|
||||||
},
|
},
|
||||||
|
-- a list of offsets relative to their parents (at rest position)
|
||||||
relative = { --none of these are specifically needed...
|
relative = { --none of these are specifically needed...
|
||||||
--left arm
|
--left arm
|
||||||
--right arm
|
--right arm
|
||||||
--head
|
--head
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
inv_rotation = {}, --stores inverse rotation for bone aiming
|
|
||||||
--REMEMBER! bones must be named differently from their original model's counterparts, because minetest was written by monkeys who were supervised by clowns. (no way to unset them.)
|
--model generation attributes
|
||||||
bone_names = {
|
override_bones = { --a list of bones to be read and or generated
|
||||||
|
__overfill = true,
|
||||||
|
Arm_Right = "guns4d_arm_right",
|
||||||
|
Arm_Left = "guns4d_arm_left",
|
||||||
|
Head = "guns4d_head"
|
||||||
|
},
|
||||||
|
new_bones = { --currently only supports empty bones. Sets at identity rotation, position 0, and parentless
|
||||||
|
"guns4d_gun_bone",
|
||||||
|
"guns4d_hipfire_bone"
|
||||||
|
},
|
||||||
|
bone_aliases = { --names of bones used by the model handler and other parts of guns4d.
|
||||||
|
__overfill = true,
|
||||||
arm_right = "guns4d_arm_right",
|
arm_right = "guns4d_arm_right",
|
||||||
arm_left = "guns4d_arm_left",
|
arm_left = "guns4d_arm_left",
|
||||||
aim = "guns4d_aiming_bone",
|
head = "guns4d_head",
|
||||||
hipfire = "guns4d_hipfire_bone",
|
gun = "guns4d_gun_bone",
|
||||||
head = "guns4d_head"
|
|
||||||
},
|
},
|
||||||
still_frame = 0, --the frame to take bone offsets from. This system has to be improved in the future (to allow better animation support)- it works for now though.
|
still_frame = 0, --the frame to take bone offsets from. This system has to be improved in the future (to allow better animation support)- it works for now though.
|
||||||
compatible_meshes = { --list of meshes and their corresponding partner meshes for this handler.
|
auto_generate = true,
|
||||||
["character.b3d"] = "guns4d_character.b3d",
|
scale = 1, --this is important for autogen
|
||||||
|
output_path = minetest.get_modpath("guns4d").."/temp/",
|
||||||
|
compatible_meshes = { --list of meshes and their corresponding partner meshes for this handler. Must have the same bones used by guns4d.
|
||||||
|
--["character.b3d"] = "guns4d_character.b3d", this would tell the handler to use guns4d_character.b3d instead of generating a new one based on the override parameters.
|
||||||
|
["character.b3d"] = true, --it is compatible but it has no predefined model, one will be therefore generated using the override_bone_aliases parameters.
|
||||||
__overfill = true
|
__overfill = true
|
||||||
},
|
},
|
||||||
fallback_mesh = "guns3d_character.b3d", --if no meshes are found in "compatible_meshes" it chooses this one.
|
gun_bone_location = vector.new(),
|
||||||
|
fallback_mesh = "character.b3d", --if no meshes are found in "compatible_meshes" it chooses this index in "compatible_meshes"
|
||||||
is_new_default = true --this will set the this to be the default handler.
|
is_new_default = true --this will set the this to be the default handler.
|
||||||
}
|
}
|
||||||
local player_model = Guns4d.player_model_handler
|
local player_model = Guns4d.player_model_handler
|
||||||
@ -37,47 +69,124 @@ function player_model.set_default_handler(class_or_name)
|
|||||||
assert(not handler.instance, "cannot set instance of a handler as the default player_model_handler")
|
assert(not handler.instance, "cannot set instance of a handler as the default player_model_handler")
|
||||||
player_model.default_handler = handler
|
player_model.default_handler = handler
|
||||||
end
|
end
|
||||||
|
|
||||||
function player_model.get_handler(meshname)
|
function player_model.get_handler(meshname)
|
||||||
local selected_handler = player_model.handlers[meshname] or player_model.main
|
local selected_handler = player_model.handlers[meshname] or player_model.main
|
||||||
if selected_handler then return selected_handler end
|
if selected_handler then return selected_handler end
|
||||||
return player_model.default_handler
|
return player_model.default_handler
|
||||||
end
|
end
|
||||||
|
|
||||||
function player_model:add_compatible_mesh(original, replacement)
|
function player_model:add_compatible_mesh(original, replacement)
|
||||||
assert(not self.instance, "attempt to call class method on an object. Cannot modify original class from an instance.")
|
assert(not self.instance, "attempt to call class method on an object. Cannot modify original class from an instance.")
|
||||||
assert(original and replacement, "one or more parameters missing")
|
assert(original and replacement, "one or more parameters missing")
|
||||||
self.compatible_meshes[original] = replacement
|
self.compatible_meshes[original] = replacement
|
||||||
player_model.handlers[original] = self
|
player_model.handlers[original] = self
|
||||||
end
|
end
|
||||||
function player_model:update(dt)
|
|
||||||
assert(dt, "delta time (dt) not provided.")
|
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
|
||||||
local player = self.player
|
|
||||||
local handler = self.handler
|
|
||||||
local gun = handler.gun
|
|
||||||
local player_axial_offset = gun.total_offset_rotation.player_axial
|
|
||||||
local pitch = player_axial_offset.x+gun.player_rotation.x
|
|
||||||
|
|
||||||
--gun bones:
|
--we store the read file so it can be reused in the constructor if needed.
|
||||||
local first, second = player:get_eye_offset()
|
local model_buffer
|
||||||
local pprops = handler:get_properties()
|
local modpath = minetest.get_modpath("guns4d")
|
||||||
local eye_pos = vector.new(0, (pprops.eye_height*10)/pprops.visual_size.y, 0)+vector.divide(first, pprops.visual_size)
|
function player_model:custom_b3d_generation_parameters(b3d)
|
||||||
if handler.control_handler.ads then
|
--empty for now, this is for model customizations.
|
||||||
eye_pos.x = ((handler.horizontal_offset*10)/pprops.visual_size.x) --horizontal_offset already is eye_offset on x
|
return b3d
|
||||||
|
end
|
||||||
|
function player_model:generate_b3d_model(name)
|
||||||
|
assert(self and name, "error while generating a b3d model. Name not provided or not called as a method.")
|
||||||
|
if not mtul.paths.media_paths[name.b3d] then
|
||||||
|
--generate a new model
|
||||||
|
local filename = string.sub(name, 1, -5).."_guns4d_temp.b3d"
|
||||||
|
local new_path = self.output_path..filename
|
||||||
|
|
||||||
|
--buffer and modify the model
|
||||||
|
model_buffer = mtul.b3d_reader.read_model(name)
|
||||||
|
local b3d = model_buffer
|
||||||
|
local replaced = {}
|
||||||
|
--add bone... forgot i made this so simple by adding node_paths
|
||||||
|
for _, node in pairs(b3d.node_paths) do
|
||||||
|
if self.override_bones[node.name] then
|
||||||
|
replaced[node.name] = true
|
||||||
|
--change the name
|
||||||
|
node.name = self.override_bones[node.name]
|
||||||
|
--unset rotation because it breaks shit
|
||||||
|
local rot = node.rotation
|
||||||
|
for i, v in pairs(node.keys) do
|
||||||
|
v.rotation = rot
|
||||||
|
end
|
||||||
|
--node.rotation = {0,0,0,1}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--check bones were replaced to avoid errors.
|
||||||
|
for i, v in pairs(self.override_bones) do
|
||||||
|
if (not replaced[i]) and i~="__overfill" then
|
||||||
|
error("bone '"..i.."' not replaced with it's guns4d counterpart, bone was not found. Check bone name")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i, v in pairs(self.new_bones) do
|
||||||
|
table.insert(b3d.node.children, {
|
||||||
|
name = v,
|
||||||
|
position = {0,0,0},
|
||||||
|
scale = {1/self.scale,1/self.scale,1/self.scale},
|
||||||
|
rotation = {0,0,0,1},
|
||||||
|
children = {},
|
||||||
|
bone = {} --empty works?
|
||||||
|
})
|
||||||
|
end
|
||||||
|
b3d=self:custom_b3d_generation_parameters(b3d)
|
||||||
|
--write temp model
|
||||||
|
local writefile = io.open(new_path, "w+b")
|
||||||
|
mtul.b3d_writer.write_model_to_file(b3d, writefile)
|
||||||
|
writefile:close()
|
||||||
|
|
||||||
|
--send to player media paths
|
||||||
|
minetest.after(0, function()
|
||||||
|
assert(
|
||||||
|
minetest.dynamic_add_media({filepath = new_path}, function()end),
|
||||||
|
"failed sending media"
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
mtul.paths.media_paths[filename] = new_path
|
||||||
|
mtul.paths.modname_by_media[filename] = "guns4d"
|
||||||
|
return filename
|
||||||
end
|
end
|
||||||
player:set_bone_position(self.bone_names.hipfire, self.offsets.relative.arm_right, {x=-pitch, y=180-player_axial_offset.y, z=0})
|
end
|
||||||
--player:set_bone_position(self.bone_names.reticle, eye_pos, vector.new(combined.x, 180-combined.y, 0))
|
|
||||||
--can't use paxial dir as it needs to be relative on Y still.
|
|
||||||
local dir = vector.rotate(gun.local_paxial_dir, {x=gun.player_rotation.x*math.pi/180,y=0,z=0})
|
|
||||||
local rot = vector.dir_to_rotation(dir)*180/math.pi
|
|
||||||
|
|
||||||
--irrlicht uses clockwise rotations, while everything else seemingly uses counter-clockwise. MMM yes, it's an "engine" not sphaghetti
|
|
||||||
player:set_bone_position(self.bone_names.aim, eye_pos, {x=rot.x,y=180-rot.y,z=0})
|
|
||||||
|
|
||||||
|
-- main update function
|
||||||
|
function player_model:update(dt)
|
||||||
|
--assert(dt, "delta time (dt) not provided.")
|
||||||
|
--assert(self.instance, "attempt to call object method on a class")
|
||||||
|
self:update_aiming(dt)
|
||||||
self:update_head(dt)
|
self:update_head(dt)
|
||||||
self:update_arm_bones(dt)
|
self:update_arm_bones(dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
--this is seperate as different models may use different coordinate systems for this. I tried to make it automatic, but irrlicht is a load of trash.
|
function player_model:update_aiming(dt)
|
||||||
|
--gun bones:
|
||||||
|
local player = self.player
|
||||||
|
local handler = self.handler
|
||||||
|
local gun = handler.gun
|
||||||
|
local pprops = handler:get_properties()
|
||||||
|
local vs = pprops.visual_size
|
||||||
|
|
||||||
|
local player_trans = gun.total_offsets.player_trans --player translation.
|
||||||
|
local hip_pos = self.offsets.global.arm_right
|
||||||
|
|
||||||
|
local ip = Guns4d.math.smooth_ratio(handler.control_handler.ads_location or 0)
|
||||||
|
local ip_inv = 1-ip
|
||||||
|
local pos = self.gun_bone_location --reuse allocated table
|
||||||
|
--interpolate between the eye and arm pos
|
||||||
|
pos.x = ((hip_pos.x*10*ip_inv) + (player_trans.x*10/vs.y)) + ((gun and gun.properties.ads.horizontal_offset*10*ip/vs.y) or 0 )
|
||||||
|
pos.y = ((hip_pos.y*10*ip_inv) + (player_trans.y*10/vs.y)) + (pprops.eye_height*10*ip/vs.y)
|
||||||
|
pos.z = ((hip_pos.z*10*ip_inv) + (player_trans.z*10/vs.y))
|
||||||
|
|
||||||
|
local dir = vector.rotate(gun.local_paxial_dir, {x=gun.player_rotation.x*math.pi/180,y=0,z=0})
|
||||||
|
local rot = vector.dir_to_rotation(dir)*180/math.pi
|
||||||
|
player:set_bone_position(self.bone_aliases.gun, {x=pos.x, y=pos.y, z=pos.z}, {x=-rot.x,y=-rot.y,z=0})
|
||||||
|
pos.x = (pos.x/10)*vs.x
|
||||||
|
pos.y = (pos.y/10)*vs.y
|
||||||
|
pos.z = (pos.z/10)*vs.z
|
||||||
|
minetest.chat_send_all(dump(pos))
|
||||||
|
end
|
||||||
|
|
||||||
function player_model:update_arm_bones(dt)
|
function player_model:update_arm_bones(dt)
|
||||||
local player = self.player
|
local player = self.player
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
@ -94,23 +203,24 @@ function player_model:update_arm_bones(dt)
|
|||||||
--all of this is pure insanity. There's no logic, or rhyme or reason. Trial and error is the only way to write this garbo.
|
--all of this is pure insanity. There's no logic, or rhyme or reason. Trial and error is the only way to write this garbo.
|
||||||
left_rotation.x = -left_rotation.x
|
left_rotation.x = -left_rotation.x
|
||||||
right_rotation.x = -right_rotation.x
|
right_rotation.x = -right_rotation.x
|
||||||
player:set_bone_position(self.bone_names.arm_left, self.offsets.relative.arm_left, {x=90, y=0, z=0}-left_rotation)
|
player:set_bone_position(self.bone_aliases.arm_left, self.offsets.relative.arm_left, {x=90, y=0, z=0}-left_rotation)
|
||||||
player:set_bone_position(self.bone_names.arm_right, self.offsets.relative.arm_right, {x=90, y=0, z=0}-right_rotation)
|
player:set_bone_position(self.bone_aliases.arm_right, self.offsets.relative.arm_right, {x=90, y=0, z=0}-right_rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
function player_model:update_head(dt)
|
function player_model:update_head(dt)
|
||||||
local player = self.player
|
local player = self.player
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
local gun = handler.gun
|
local gun = handler.gun
|
||||||
player:set_bone_position(self.bone_names.head, self.offsets.relative.head, {x=handler.look_rotation.x,z=0,y=0})
|
player:set_bone_position(self.bone_aliases.head, self.offsets.relative.head, {x=handler.look_rotation.x,z=0,y=0})
|
||||||
end
|
end
|
||||||
--should be renamed to "release" but, whatever.
|
--should be renamed to "release" but, whatever.
|
||||||
function player_model:prepare_deletion()
|
function player_model:prepare_deletion()
|
||||||
assert(self.instance, "attempt to call object method on a class")
|
assert(self.instance, "attempt to call object method on a class")
|
||||||
local handler = Guns4d.players[self.player:get_player_name()]
|
local handler = Guns4d.players[self.player:get_player_name()]
|
||||||
local properties = handler:get_properties()
|
local properties = handler:get_properties()
|
||||||
if minetest.get_modpath("player_api") then
|
--[[if minetest.get_modpath("player_api") then
|
||||||
player_api.set_model(self.player, self.old)
|
player_api.set_model(self.player, self.old)
|
||||||
end
|
end]]
|
||||||
properties.mesh = self.old
|
properties.mesh = self.old
|
||||||
handler:set_properties(properties)
|
handler:set_properties(properties)
|
||||||
end
|
end
|
||||||
@ -120,13 +230,25 @@ function player_model.construct(def)
|
|||||||
if def.instance then
|
if def.instance then
|
||||||
assert(def.player, "no player provided")
|
assert(def.player, "no player provided")
|
||||||
def.handler = Guns4d.players[def.player:get_player_name()]
|
def.handler = Guns4d.players[def.player:get_player_name()]
|
||||||
|
--set the mesh
|
||||||
local properties = def.handler:get_properties()
|
local properties = def.handler:get_properties()
|
||||||
def.old = properties.mesh
|
def.old = properties.mesh
|
||||||
--set the mesh
|
properties.mesh = def.compatible_meshes[properties.mesh]
|
||||||
|
def.gun_bone_location = vector.new()
|
||||||
properties.mesh = def.compatible_meshes[properties.mesh] or def.fallback_mesh
|
if not properties.mesh then
|
||||||
|
local fallback = def.compatible_meshes[def.fallback_mesh]
|
||||||
|
minetest.log("error", "Player model handler error: no equivelant mesh found for '"..def.old.."'. Using fallback mesh ("..fallback..")")
|
||||||
|
properties.mesh = fallback
|
||||||
|
end
|
||||||
def.handler:set_properties(properties)
|
def.handler:set_properties(properties)
|
||||||
|
--no further aciton required, it e
|
||||||
else
|
else
|
||||||
|
--none of these should consist across classes
|
||||||
|
def.offsets = {
|
||||||
|
global = {},
|
||||||
|
relative = {},
|
||||||
|
}
|
||||||
|
--a list of meshes compatible with this handler.
|
||||||
for og_mesh, replacement_mesh in pairs(def.compatible_meshes) do
|
for og_mesh, replacement_mesh in pairs(def.compatible_meshes) do
|
||||||
assert(type(og_mesh)=="string", "mesh to be replaced (index) must be a string!")
|
assert(type(og_mesh)=="string", "mesh to be replaced (index) must be a string!")
|
||||||
if player_model.handlers[og_mesh] then minetest.log("warning", "Guns4d: mesh '"..og_mesh.."' overridden by a handler class, this will replace the old handler. Is this a mistake?") end
|
if player_model.handlers[og_mesh] then minetest.log("warning", "Guns4d: mesh '"..og_mesh.."' overridden by a handler class, this will replace the old handler. Is this a mistake?") end
|
||||||
@ -134,37 +256,41 @@ function player_model.construct(def)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--find a valid model to read.
|
--find a valid model to read.
|
||||||
|
if rawget(def, "auto_generate") then
|
||||||
|
--blame mod security, this is dumb.
|
||||||
|
assert(rawget(def, "output_path"), "a output path contained within the mod's source files is required to automatically generate models")
|
||||||
|
end
|
||||||
local read_model
|
local read_model
|
||||||
for i, v in pairs(def.compatible_meshes) do
|
for i, v in pairs(def.compatible_meshes) do
|
||||||
if (type(i)=="string") and (i~="__overfill") then
|
if (type(i)=="string") and (i~="__overfill") then
|
||||||
read_model=v
|
if def.auto_generate and ((not v) or not mtul.paths.media_paths[v]) then
|
||||||
|
def.compatible_meshes[i] = def:generate_b3d_model(i)
|
||||||
|
end
|
||||||
|
read_model=def.compatible_meshes[i]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assert(read_model, "at least one compatible mesh required by default for offset detection.")
|
assert(read_model, "at least one compatible mesh required by default for autogeneration of offsets")
|
||||||
local b3d_table = mtul.b3d_reader.read_model(read_model, true)
|
local b3d_table = mtul.b3d_reader.read_model(read_model, true)
|
||||||
|
|
||||||
--[[all of the compatible_meshes should be identical in terms of guns4d specific bones and offsets (arms, head).
|
--[[all of the compatible_meshes should be identical in terms of guns4d specific bones and offsets (arms, head).
|
||||||
Otherwise a new handler should be different. With new compatibilities]]
|
Otherwise a new handler should be different. With new compatibilities]]
|
||||||
---@diagnostic disable-next-line: redefined-local
|
for i, v in pairs(def.bone_aliases) do
|
||||||
for i, v in pairs({"arm_right", "arm_left", "head"}) do
|
--print(def.bone_aliases[v])
|
||||||
--print(def.bone_names[v])
|
local node = mtul.b3d_nodes.get_node_by_name(b3d_table, v, true)
|
||||||
|
if i~="__overfill" then
|
||||||
|
local transform, _ = mtul.b3d_nodes.get_node_global_transform(node, def.still_frame)
|
||||||
|
|
||||||
local node = mtul.b3d_nodes.get_node_by_name(b3d_table, def.bone_names[v], true)
|
def.offsets.relative[i] = vector.new(node.position[1], node.position[2], node.position[3])
|
||||||
|
def.offsets.global[i] = vector.new(transform[13], transform[14], transform[15])/10 --4th column first 3 rows give us our global transform.
|
||||||
local transform, rotation = mtul.b3d_nodes.get_node_global_transform(node, def.still_frame)
|
--print(i, mtul.b3d_nodes.get_node_rotation(b3d_table, node, true, def.still_frame))
|
||||||
|
end
|
||||||
def.offsets.relative[v] = vector.new(node.position[1], node.position[2], node.position[3])
|
|
||||||
def.offsets.global[v] = vector.new(transform[13], transform[14], transform[15])/10 --4th column first 3 rows give us our global transform.
|
|
||||||
--print(i, mtul.b3d_nodes.get_node_rotation(b3d_table, node, true, def.still_frame))
|
|
||||||
def.inv_rotation[v] = rotation:conjugate() --(note this overrides original matrix made in get_node_global_transform)
|
|
||||||
end
|
end
|
||||||
def.offsets.global.hipfire = vector.new(mtul.b3d_nodes.get_node_global_position(b3d_table, def.bone_names.arm_right, true, def.still_frame))
|
def.offsets.global.hipfire = vector.new(mtul.b3d_nodes.get_node_global_position(b3d_table, def.bone_aliases.arm_right, true, def.still_frame))
|
||||||
|
|
||||||
if def.is_new_default then
|
if def.is_new_default then
|
||||||
player_model.set_default_handler(def)
|
player_model.set_default_handler(def)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Guns4d.player_model_handler = Instantiatable_class:inherit(player_model)
|
Guns4d.player_model_handler = mtul.class.new_class:inherit(player_model)
|
||||||
Guns4d.player_model_handler:set_default_handler()
|
Guns4d.player_model_handler:set_default_handler()
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
--
|
||||||
|
|
||||||
Proxy_table = {
|
Proxy_table = {
|
||||||
registered_proxies = {},
|
registered_proxies = {},
|
||||||
proxy_children = {}
|
proxy_children = {}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
local Sprite_scope = Instantiatable_class:inherit({
|
local Sprite_scope = mtul.class.new_class:inherit({
|
||||||
images = {
|
images = {
|
||||||
fore = {
|
fore = {
|
||||||
texture = "scope_fore.png",
|
texture = "scope_fore.png",
|
||||||
@ -51,24 +51,26 @@ Guns4d.sprite_scope = Sprite_scope
|
|||||||
--rename to draw?
|
--rename to draw?
|
||||||
function Sprite_scope:update()
|
function Sprite_scope:update()
|
||||||
local handler = self.handler
|
local handler = self.handler
|
||||||
|
local gun = self.gun
|
||||||
|
local control_handler = gun.control_handler
|
||||||
if handler.wininfo and self.handler.control_handler.ads then
|
if handler.wininfo and self.handler.control_handler.ads then
|
||||||
if not self.fov_set then
|
if not self.fov_set then
|
||||||
self.fov_set = true
|
self.fov_set = true
|
||||||
handler:set_fov(80/self.magnification)
|
handler:set_fov(80/self.magnification)
|
||||||
end
|
end
|
||||||
local dir = self.gun.local_dir
|
local dir = gun.local_dir
|
||||||
local ratio = handler.wininfo.size.x/handler.wininfo.size.y
|
local ratio = handler.wininfo.size.x/handler.wininfo.size.y
|
||||||
|
|
||||||
if handler.ads_location ~= 1 then
|
if control_handler.ads_location ~= 1 then
|
||||||
dir = dir + (self.gun.properties.ads.offset+vector.new(self.gun.properties.ads.horizontal_offset,0,0))*0
|
dir = dir + (self.gun.properties.ads.offset+vector.new(gun.properties.ads.horizontal_offset,0,0))*0
|
||||||
end
|
end
|
||||||
local fov = self.player:get_fov()
|
local fov = self.player:get_fov()
|
||||||
local real_aim = Guns4d.math.rltv_point_to_hud(dir, fov, ratio)
|
local real_aim = Guns4d.math.rltv_point_to_hud(dir, fov, ratio)
|
||||||
local anim_aim = Guns4d.math.rltv_point_to_hud(vector.rotate({x=0,y=0,z=1}, self.gun.animation_rotation*math.pi/180), fov, ratio)
|
local anim_aim = Guns4d.math.rltv_point_to_hud(vector.rotate({x=0,y=0,z=1}, gun.animation_rotation*math.pi/180), fov, ratio)
|
||||||
real_aim.x = real_aim.x+anim_aim.x; real_aim.y = real_aim.y+anim_aim.y
|
real_aim.x = real_aim.x+anim_aim.x; real_aim.y = real_aim.y+anim_aim.y
|
||||||
|
|
||||||
--print(dump(self.gun.animation_rotation))
|
--print(dump(self.gun.animation_rotation))
|
||||||
local paxial_aim = Guns4d.math.rltv_point_to_hud(self.gun.local_paxial_dir, fov, ratio)
|
local paxial_aim = Guns4d.math.rltv_point_to_hud(gun.local_paxial_dir, fov, ratio)
|
||||||
--so custom scopes can do their thing without doing more calcs
|
--so custom scopes can do their thing without doing more calcs
|
||||||
self.hud_projection_real = real_aim
|
self.hud_projection_real = real_aim
|
||||||
self.hud_projection_paxial = paxial_aim
|
self.hud_projection_paxial = paxial_aim
|
||||||
@ -83,7 +85,7 @@ function Sprite_scope:update()
|
|||||||
self.fov_set = false
|
self.fov_set = false
|
||||||
handler:unset_fov()
|
handler:unset_fov()
|
||||||
end
|
end
|
||||||
local angle =math.sqrt(self.gun.total_offset_rotation.gun_axial.x^2+self.gun.total_offset_rotation.gun_axial.y^2)
|
local angle =math.sqrt(gun.total_offsets.gun_axial.x^2+gun.total_offsets.gun_axial.y^2)
|
||||||
for i, v in pairs(self.elements) do
|
for i, v in pairs(self.elements) do
|
||||||
local def = self.images[i]
|
local def = self.images[i]
|
||||||
local tex = def.texture
|
local tex = def.texture
|
||||||
@ -95,7 +97,7 @@ function Sprite_scope:update()
|
|||||||
factor = (factor - ((angle-def.misalignment_opacity_threshold_angle)/def.misalignment_opacity_maximum_angle))
|
factor = (factor - ((angle-def.misalignment_opacity_threshold_angle)/def.misalignment_opacity_maximum_angle))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.player:hud_change(v, "text", tex.."^[opacity:"..tostring(math.ceil((25.5*handler.ads_location))*10))
|
self.player:hud_change(v, "text", tex.."^[opacity:"..tostring(math.ceil((25.5*control_handler.ads_location))*10))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function Sprite_scope:prepare_deletion()
|
function Sprite_scope:prepare_deletion()
|
||||||
|
@ -43,9 +43,12 @@ end
|
|||||||
|
|
||||||
local function initialize_physics(self)
|
local function initialize_physics(self)
|
||||||
--initialize rotation offsets
|
--initialize rotation offsets
|
||||||
self.total_offset_rotation = {
|
self.total_offsets = {
|
||||||
gun_axial = vector.new(),
|
gun_axial = vector.new(),
|
||||||
player_axial = vector.new(),
|
player_axial = vector.new(),
|
||||||
|
gun_trans = vector.new(),
|
||||||
|
player_trans = vector.new(),
|
||||||
|
look_trans = vector.new()
|
||||||
}
|
}
|
||||||
self.offsets = {}
|
self.offsets = {}
|
||||||
for offset, tbl in pairs(self.base_class.offsets) do
|
for offset, tbl in pairs(self.base_class.offsets) do
|
||||||
@ -89,7 +92,7 @@ function gun_default:construct_instance()
|
|||||||
|
|
||||||
--unavoidable table instancing
|
--unavoidable table instancing
|
||||||
self.properties = Guns4d.table.fill(self.base_class.properties, self.properties)
|
self.properties = Guns4d.table.fill(self.base_class.properties, self.properties)
|
||||||
self.particle_spawners = {} --Instantiatable_class only shallow copies. So tables will not change, and thus some need to be initialized.
|
self.particle_spawners = {} --mtul.class.new_class only shallow copies. So tables will not change, and thus some need to be initialized.
|
||||||
self.property_modifiers = {}
|
self.property_modifiers = {}
|
||||||
|
|
||||||
initialize_animation(self)
|
initialize_animation(self)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Gun - Guns4d</title>
|
<title>Gun - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="class-gun">
|
<body class="class-gun">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<div class="group two">
|
<div class="group two">
|
||||||
</div>
|
</div>
|
||||||
<div class="group three">
|
<div class="group three">
|
||||||
<div class="button iconright"><a href="../class/Instantiatable_class.html" title="Instantiatable_class"><span>Next</span><img src="../img/i-right.svg?7653a2d" alt=""/></a></div>
|
<div class="button iconright"><a href="../class/mtul.class.new_class.html" title="mtul.class.new_class"><span>Next</span><img src="../img/i-right.svg?7653a2d" alt=""/></a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
@ -61,7 +61,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li class="selected"><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li class="selected"><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
@ -193,7 +193,7 @@ or you can do the same thing with a seperate class of weapons. Set name to "
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name"><var id="gun.total_offset_rotation">total_offset_rotation</var><a class="permalink" href="#gun.total_offset_rotation" title="Permalink to this definition">¶</a></td>
|
<td class="name"><var id="gun.total_offsets">total_offsets</var><a class="permalink" href="#gun.total_offsets" title="Permalink to this definition">¶</a></td>
|
||||||
<td class="doc"><p>total offsets of the gun in the same format as a <a href="../class/Gun.html#gun.offsets">an offset</a></p>
|
<td class="doc"><p>total offsets of the gun in the same format as a <a href="../class/Gun.html#gun.offsets">an offset</a></p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -676,7 +676,7 @@ this means that increasing it decreases the time it takes for the angular veloci
|
|||||||
<td class="name"><var id="lvl1_fields.offsets.breathing">breathing</var><a class="permalink" href="#lvl1_fields.offsets.breathing" title="Permalink to this definition">¶</a></td>
|
<td class="name"><var id="lvl1_fields.offsets.breathing">breathing</var><a class="permalink" href="#lvl1_fields.offsets.breathing" title="Permalink to this definition">¶</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name"><var id="lvl1_fields.offsets.look_snap">look_snap</var><a class="permalink" href="#lvl1_fields.offsets.look_snap" title="Permalink to this definition">¶</a></td>
|
<td class="name"><var id="lvl1_fields.offsets.look">look</var><a class="permalink" href="#lvl1_fields.offsets.look" title="Permalink to this definition">¶</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
<!-- Documentation generated by LuaDox: https://github.com/jtackaberry/luadox -->
|
<!-- Documentation generated by LuaDox: https://github.com/jtackaberry/luadox -->
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
<title>Instantiatable_class - Guns4d</title>
|
<title>mtul.class.new_class - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="class-instantiatable_class">
|
<body class="class-mtul.class.new_class">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
<div class="group one">
|
<div class="group one">
|
||||||
<div class="description"><span>Guns4d | The ultimate 3d gun mod.</span></div>
|
<div class="description"><span>Guns4d | The ultimate 3d gun mod.</span></div>
|
||||||
@ -27,8 +27,8 @@
|
|||||||
<div class="sections">
|
<div class="sections">
|
||||||
<div class="heading">Contents</div>
|
<div class="heading">Contents</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#Instantiatable_class">Class <code>Instantiatable_class</code></a></li>
|
<li><a href="#mtul.class.new_class">Class <code>mtul.class.new_class</code></a></li>
|
||||||
<li><a href="#god_work"><p>Instantiatable_class</p>
|
<li><a href="#god_work"><p>mtul.class.new_class</p>
|
||||||
</a></li>
|
</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li class="selected"><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li class="selected"><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
@ -52,8 +52,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2 class="class" id="Instantiatable_class">Class <code>Instantiatable_class</code>
|
<h2 class="class" id="mtul.class.new_class">Class <code>mtul.class.new_class</code>
|
||||||
<a class="permalink" href="#Instantiatable_class" title="Permalink to this definition">¶</a>
|
<a class="permalink" href="#mtul.class.new_class" title="Permalink to this definition">¶</a>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<p>The system for defining classes in 4dguns. Please note the capital "I", Ldoc converts it to a lowercase in all of this file</p>
|
<p>The system for defining classes in 4dguns. Please note the capital "I", Ldoc converts it to a lowercase in all of this file</p>
|
||||||
@ -63,29 +63,29 @@
|
|||||||
<div class="heading">Methods</div>
|
<div class="heading">Methods</div>
|
||||||
<table class="functions ">
|
<table class="functions ">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name"><a href="#Instantiatable_class.inherit"><var>inherit</var></a>()</td>
|
<td class="name"><a href="#mtul.class.new_class.inherit"><var>inherit</var></a>()</td>
|
||||||
<td class="doc"><p>creates a new base class</p>
|
<td class="doc"><p>creates a new base class</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name"><a href="#Instantiatable_class.new"><var>new</var></a>()</td>
|
<td class="name"><a href="#mtul.class.new_class.new"><var>new</var></a>()</td>
|
||||||
<td class="doc"><p>creates an instance of the base class</p>
|
<td class="doc"><p>creates an instance of the base class</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<dl class="functions">
|
<dl class="functions">
|
||||||
<dt id="Instantiatable_class.inherit">
|
<dt id="mtul.class.new_class.inherit">
|
||||||
<span class="icon"></span><var>Instantiatable_class:inherit</var>(<em>def</em>)
|
<span class="icon"></span><var>mtul.class.new_class:inherit</var>(<em>def</em>)
|
||||||
<a class="permalink" href="#Instantiatable_class.inherit" title="Permalink to this definition">¶</a>
|
<a class="permalink" href="#mtul.class.new_class.inherit" title="Permalink to this definition">¶</a>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p>creates a new base class. Calls all constructors in the chain with def.instance=true</p>
|
<p>creates a new base class. Calls all constructors in the chain with def.instance=true</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="Instantiatable_class.new">
|
<dt id="mtul.class.new_class.new">
|
||||||
<span class="icon"></span><var>Instantiatable_class:new</var>(<em>def</em>)
|
<span class="icon"></span><var>mtul.class.new_class:new</var>(<em>def</em>)
|
||||||
<a class="permalink" href="#Instantiatable_class.new" title="Permalink to this definition">¶</a>
|
<a class="permalink" href="#mtul.class.new_class.new" title="Permalink to this definition">¶</a>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p>creates an instance of the base class. Calls all constructors in the chain with def.instance=true</p>
|
<p>creates an instance of the base class. Calls all constructors in the chain with def.instance=true</p>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2 class="table" id="god_work">Instantiatable_class
|
<h2 class="table" id="god_work">mtul.class.new_class
|
||||||
|
|
||||||
<a class="permalink" href="#god_work" title="Permalink to this definition">¶</a>
|
<a class="permalink" href="#god_work" title="Permalink to this definition">¶</a>
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Search - Guns4d</title>
|
<title>Search - Guns4d</title>
|
||||||
<link href="prism.css?7653a2d" rel="stylesheet" />
|
<link href="prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="search-search">
|
<body class="search-search">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<div class="group two">
|
<div class="group two">
|
||||||
</div>
|
</div>
|
||||||
<div class="group three">
|
<div class="group three">
|
||||||
<div class="button iconright"><a href="class/Instantiatable_class.html" title="Instantiatable_class"><span>Next</span><img src="img/i-right.svg?7653a2d" alt=""/></a></div>
|
<div class="button iconright"><a href="class/mtul.class.new_class.html" title="mtul.class.new_class"><span>Next</span><img src="img/i-right.svg?7653a2d" alt=""/></a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="class/Gun.html">Gun.Gun</a></li>
|
<li><a href="class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var docs = [
|
var docs = [
|
||||||
{path:"class/Gun.html", type:"class", title:"Gun.Gun", text:"Gun class Defining a gun: *method documentation coming soon* (or never...) guns are defined by two table fields: their consts and their properties. properties define nearly everything, from how a gun handles to how it looks, what model it uses, while consts define attributes that should never change, like bones within the gun, framerates, wether the gun is allowed to have certain attributes at all. The rest is mainly for internal workings of the mod. Guns4d uses a class system for most moving parts- including the gun. New guns therefor are created with the :inherit(def) method, where def is the definition of your new gun- or rather the changed parts of it. So to make a new gun you can run Guns4d.gun:inherit() or you can do the same thing with a seperate class of weapons. Set name to \"__template\" for template classes of guns."},
|
{path:"class/Gun.html", type:"class", title:"Gun.Gun", text:"Gun class Defining a gun: *method documentation coming soon* (or never...) guns are defined by two table fields: their consts and their properties. properties define nearly everything, from how a gun handles to how it looks, what model it uses, while consts define attributes that should never change, like bones within the gun, framerates, wether the gun is allowed to have certain attributes at all. The rest is mainly for internal workings of the mod. Guns4d uses a class system for most moving parts- including the gun. New guns therefor are created with the :inherit(def) method, where def is the definition of your new gun- or rather the changed parts of it. So to make a new gun you can run Guns4d.gun:inherit() or you can do the same thing with a seperate class of weapons. Set name to \"__template\" for template classes of guns."},
|
||||||
{path:"class/Instantiatable_class.html", type:"class", title:"Instantiatable_class.Instantiatable_class", text:"The system for defining classes in 4dguns. Please note the capital \"I\", Ldoc converts it to a lowercase in all of this file"},
|
{path:"class/mtul.class.new_class.html", type:"class", title:"mtul.class.new_class.mtul.class.new_class", text:"The system for defining classes in 4dguns. Please note the capital \"I\", Ldoc converts it to a lowercase in all of this file"},
|
||||||
{path:"module/misc_helpers.html", type:"module", title:"misc_helpers", text:""},
|
{path:"module/misc_helpers.html", type:"module", title:"misc_helpers", text:""},
|
||||||
{path:"module/play_sound.html", type:"module", title:"play_sound", text:"implements tools for quickly playing audio."},
|
{path:"module/play_sound.html", type:"module", title:"play_sound", text:"implements tools for quickly playing audio."},
|
||||||
{path:"module/Bullet_hole.html", type:"module", title:"Bullet_hole", text:""},
|
{path:"module/Bullet_hole.html", type:"module", title:"Bullet_hole", text:""},
|
||||||
@ -93,9 +93,9 @@ var docs = [
|
|||||||
{path:"class/Gun.html#lvl1_fields.offsets.sway", type:"field", title:"lvl1_fields.offsets.sway", text:""},
|
{path:"class/Gun.html#lvl1_fields.offsets.sway", type:"field", title:"lvl1_fields.offsets.sway", text:""},
|
||||||
{path:"class/Gun.html#lvl1_fields.offsets.walking", type:"field", title:"lvl1_fields.offsets.walking", text:""},
|
{path:"class/Gun.html#lvl1_fields.offsets.walking", type:"field", title:"lvl1_fields.offsets.walking", text:""},
|
||||||
{path:"class/Gun.html#lvl1_fields.offsets.breathing", type:"field", title:"lvl1_fields.offsets.breathing", text:""},
|
{path:"class/Gun.html#lvl1_fields.offsets.breathing", type:"field", title:"lvl1_fields.offsets.breathing", text:""},
|
||||||
{path:"class/Gun.html#lvl1_fields.offsets.look_snap", type:"field", title:"lvl1_fields.offsets.look_snap", text:""},
|
{path:"class/Gun.html#lvl1_fields.offsets.look", type:"field", title:"lvl1_fields.offsets.look", text:""},
|
||||||
{path:"class/Gun.html#gun.animation_rotation", type:"field", title:"gun.animation_rotation", text:"vector containing the offset from animations, this will be generated if {@consts.ANIMATIONS_OFFSET_AIM}=true"},
|
{path:"class/Gun.html#gun.animation_rotation", type:"field", title:"gun.animation_rotation", text:"vector containing the offset from animations, this will be generated if {@consts.ANIMATIONS_OFFSET_AIM}=true"},
|
||||||
{path:"class/Gun.html#gun.total_offset_rotation", type:"field", title:"gun.total_offset_rotation", text:"total offsets of the gun in the same format as a an offset"},
|
{path:"class/Gun.html#gun.total_offsets", type:"field", title:"gun.total_offsets", text:"total offsets of the gun in the same format as a an offset"},
|
||||||
{path:"class/Gun.html#lvl1_fields.consts.AIM_OUT_AIM_IN_SPEED_RATIO", type:"field", title:"lvl1_fields.consts.AIM_OUT_AIM_IN_SPEED_RATIO", text:""},
|
{path:"class/Gun.html#lvl1_fields.consts.AIM_OUT_AIM_IN_SPEED_RATIO", type:"field", title:"lvl1_fields.consts.AIM_OUT_AIM_IN_SPEED_RATIO", text:""},
|
||||||
{path:"class/Gun.html#lvl1_fields.consts.KEYFRAME_SAMPLE_PRECISION", type:"field", title:"lvl1_fields.consts.KEYFRAME_SAMPLE_PRECISION", text:"frequency of keyframe samples for animation offsets and"},
|
{path:"class/Gun.html#lvl1_fields.consts.KEYFRAME_SAMPLE_PRECISION", type:"field", title:"lvl1_fields.consts.KEYFRAME_SAMPLE_PRECISION", text:"frequency of keyframe samples for animation offsets and"},
|
||||||
{path:"class/Gun.html#lvl1_fields.consts.DEFAULT_MAX_HEAR_DISTANCE", type:"field", title:"lvl1_fields.consts.DEFAULT_MAX_HEAR_DISTANCE", text:"default max hear distance when not specified"},
|
{path:"class/Gun.html#lvl1_fields.consts.DEFAULT_MAX_HEAR_DISTANCE", type:"field", title:"lvl1_fields.consts.DEFAULT_MAX_HEAR_DISTANCE", text:"default max hear distance when not specified"},
|
||||||
@ -112,17 +112,17 @@ var docs = [
|
|||||||
{path:"class/Gun.html#lvl1_fields.consts.MAG_BONE", type:"field", title:"lvl1_fields.consts.MAG_BONE", text:"string=\"magazine\",the bone of the magazine in the gun (for dropping mags)"},
|
{path:"class/Gun.html#lvl1_fields.consts.MAG_BONE", type:"field", title:"lvl1_fields.consts.MAG_BONE", text:"string=\"magazine\",the bone of the magazine in the gun (for dropping mags)"},
|
||||||
{path:"class/Gun.html#lvl1_fields.consts.ARM_RIGHT_BONE", type:"field", title:"lvl1_fields.consts.ARM_RIGHT_BONE", text:"string=\"right_aimpoint\", the bone which the right arm aims at to"},
|
{path:"class/Gun.html#lvl1_fields.consts.ARM_RIGHT_BONE", type:"field", title:"lvl1_fields.consts.ARM_RIGHT_BONE", text:"string=\"right_aimpoint\", the bone which the right arm aims at to"},
|
||||||
{path:"class/Gun.html#lvl1_fields.consts.ARM_LEFT_BONE", type:"field", title:"lvl1_fields.consts.ARM_LEFT_BONE", text:"string=\"left_aimpoint\", the bone which the left arm aims at to"},
|
{path:"class/Gun.html#lvl1_fields.consts.ARM_LEFT_BONE", type:"field", title:"lvl1_fields.consts.ARM_LEFT_BONE", text:"string=\"left_aimpoint\", the bone which the left arm aims at to"},
|
||||||
{path:"class/Instantiatable_class.html#god_work.instance", type:"field", title:"god_work.instance", text:"defines wether the object is an instance"},
|
{path:"class/mtul.class.new_class.html#god_work.instance", type:"field", title:"god_work.instance", text:"defines wether the object is an instance"},
|
||||||
{path:"class/Instantiatable_class.html#god_work.base_class", type:"field", title:"god_work.base_class", text:"only present for instances: the class from which this instance originates"},
|
{path:"class/mtul.class.new_class.html#god_work.base_class", type:"field", title:"god_work.base_class", text:"only present for instances: the class from which this instance originates"},
|
||||||
{path:"class/Instantiatable_class.html#god_work.parent_class", type:"field", title:"god_work.parent_class", text:"the class from which this class was inherited from"},
|
{path:"class/mtul.class.new_class.html#god_work.parent_class", type:"field", title:"god_work.parent_class", text:"the class from which this class was inherited from"},
|
||||||
{path:"module/misc_helpers.html#Guns4d.math.weighted_randoms", type:"function", title:"Guns4d.math.weighted_randoms", text:"picks a random index, with odds based on it's value. Returns the index of the selected."},
|
{path:"module/misc_helpers.html#Guns4d.math.weighted_randoms", type:"function", title:"Guns4d.math.weighted_randoms", text:"picks a random index, with odds based on it's value. Returns the index of the selected."},
|
||||||
{path:"module/play_sound.html#Guns4d.play_sounds", type:"function", title:"Guns4d.play_sounds", text:"allows you to play one or more sounds with more complex features, so sounds can be easily coded for guns without the need for functions. WARNING: this function modifies the tables passed to it, use Guns4d.table.shallow_copy() or table.copy for inputted soundspecs Example"},
|
{path:"module/play_sound.html#Guns4d.play_sounds", type:"function", title:"Guns4d.play_sounds", text:"allows you to play one or more sounds with more complex features, so sounds can be easily coded for guns without the need for functions. WARNING: this function modifies the tables passed to it, use Guns4d.table.shallow_copy() or table.copy for inputted soundspecs Example"},
|
||||||
{path:"module/play_sound.html#Guns4d.get_sounds", type:"function", title:"Guns4d.get_sounds", text:"gets a list of currently playing Minetest sound handles from the Guns4d sound handle. Modification of table highly discouraged."},
|
{path:"module/play_sound.html#Guns4d.get_sounds", type:"function", title:"Guns4d.get_sounds", text:"gets a list of currently playing Minetest sound handles from the Guns4d sound handle. Modification of table highly discouraged."},
|
||||||
{path:"module/play_sound.html#Guns4d.stop_sounds", type:"function", title:"Guns4d.stop_sounds", text:"stops a list of sounds"},
|
{path:"module/play_sound.html#Guns4d.stop_sounds", type:"function", title:"Guns4d.stop_sounds", text:"stops a list of sounds"},
|
||||||
{path:"module/Bullet_hole.html#Bullet_hole.construct", type:"function", title:"Bullet_hole.construct", text:""},
|
{path:"module/Bullet_hole.html#Bullet_hole.construct", type:"function", title:"Bullet_hole.construct", text:""},
|
||||||
{path:"module/Control_handler.html#controls.toggle_touchscreen_mode", type:"function", title:"controls:toggle_touchscreen_mode", text:""},
|
{path:"module/Control_handler.html#controls.toggle_touchscreen_mode", type:"function", title:"controls:toggle_touchscreen_mode", text:""},
|
||||||
{path:"class/Instantiatable_class.html#Instantiatable_class.inherit", type:"function", title:"Instantiatable_class:inherit", text:"creates a new base class. Calls all constructors in the chain with def.instance=true"},
|
{path:"class/mtul.class.new_class.html#mtul.class.new_class.inherit", type:"function", title:"mtul.class.new_class:inherit", text:"creates a new base class. Calls all constructors in the chain with def.instance=true"},
|
||||||
{path:"class/Instantiatable_class.html#Instantiatable_class.new", type:"function", title:"Instantiatable_class:new", text:"creates an instance of the base class. Calls all constructors in the chain with def.instance=true"},
|
{path:"class/mtul.class.new_class.html#mtul.class.new_class.new", type:"function", title:"mtul.class.new_class:new", text:"creates an instance of the base class. Calls all constructors in the chain with def.instance=true"},
|
||||||
{path:"module/Player_model_handler.html#player_model.construct", type:"function", title:"player_model.construct", text:""},
|
{path:"module/Player_model_handler.html#player_model.construct", type:"function", title:"player_model.construct", text:""},
|
||||||
{path:"module/misc_helpers.html#math", type:"section", title:"math helpers", text:"in guns4d.math"},
|
{path:"module/misc_helpers.html#math", type:"section", title:"math helpers", text:"in guns4d.math"},
|
||||||
{path:"module/misc_helpers.html#table", type:"section", title:"table helpers", text:"in guns4d.table"},
|
{path:"module/misc_helpers.html#table", type:"section", title:"table helpers", text:"in guns4d.table"},
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Bullet_hole - Guns4d</title>
|
<title>Bullet_hole - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="module-bullet_hole">
|
<body class="module-bullet_hole">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -34,7 +34,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Control_handler - Guns4d</title>
|
<title>Control_handler - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="module-control_handler">
|
<body class="module-control_handler">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -34,7 +34,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Player_model_handler - Guns4d</title>
|
<title>Player_model_handler - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="module-player_model_handler">
|
<body class="module-player_model_handler">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>misc_helpers - Guns4d</title>
|
<title>misc_helpers - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="module-misc_helpers">
|
<body class="module-misc_helpers">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<div class="group two">
|
<div class="group two">
|
||||||
</div>
|
</div>
|
||||||
<div class="group three">
|
<div class="group three">
|
||||||
<div class="button iconleft"><a href="../class/Instantiatable_class.html" title="Instantiatable_class"><img src="../img/i-left.svg?7653a2d" alt=""/><span>Previous</span></a></div>
|
<div class="button iconleft"><a href="../class/mtul.class.new_class.html" title="mtul.class.new_class"><img src="../img/i-left.svg?7653a2d" alt=""/><span>Previous</span></a></div>
|
||||||
<div class="button iconright"><a href="../module/play_sound.html" title="play_sound"><span>Next</span><img src="../img/i-right.svg?7653a2d" alt=""/></a></div>
|
<div class="button iconright"><a href="../module/play_sound.html" title="play_sound"><span>Next</span><img src="../img/i-right.svg?7653a2d" alt=""/></a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -40,7 +40,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>play_sound - Guns4d</title>
|
<title>play_sound - Guns4d</title>
|
||||||
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
<link href="../prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="module-play_sound">
|
<body class="module-play_sound">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
<li><a href="../class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="../class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="../class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<title>Search - Guns4d</title>
|
<title>Search - Guns4d</title>
|
||||||
<link href="prism.css?7653a2d" rel="stylesheet" />
|
<link href="prism.css?7653a2d" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="luadox.css?7653a2d" type="text/css">
|
<link rel="stylesheet" href="luadox.css?7653a2d" type="text/css">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="search-search">
|
<body class="search-search">
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<div class="group two">
|
<div class="group two">
|
||||||
</div>
|
</div>
|
||||||
<div class="group three">
|
<div class="group three">
|
||||||
<div class="button iconright"><a href="class/Instantiatable_class.html" title="Instantiatable_class"><span>Next</span><img src="img/i-right.svg?7653a2d" alt=""/></a></div>
|
<div class="button iconright"><a href="class/mtul.class.new_class.html" title="mtul.class.new_class"><span>Next</span><img src="img/i-right.svg?7653a2d" alt=""/></a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<div class="heading">Classes</div>
|
<div class="heading">Classes</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="class/Gun.html">Gun.Gun</a></li>
|
<li><a href="class/Gun.html">Gun.Gun</a></li>
|
||||||
<li><a href="class/Instantiatable_class.html">Instantiatable_class.Instantiatable_class</a></li>
|
<li><a href="class/mtul.class.new_class.html">mtul.class.new_class.mtul.class.new_class</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modules">
|
<div class="modules">
|
||||||
|
4
init.lua
4
init.lua
@ -48,6 +48,8 @@ for i, v in pairs(Guns4d.config) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
minetest.rmdir(modpath.."/temp", true)
|
||||||
|
minetest.mkdir(modpath.."/temp")
|
||||||
|
|
||||||
dofile(modpath.."/infinite_ammo.lua")
|
dofile(modpath.."/infinite_ammo.lua")
|
||||||
dofile(modpath.."/misc_helpers.lua")
|
dofile(modpath.."/misc_helpers.lua")
|
||||||
@ -59,7 +61,6 @@ dofile(modpath.."/touch_support.lua")
|
|||||||
dofile(modpath.."/block_values.lua")
|
dofile(modpath.."/block_values.lua")
|
||||||
dofile(modpath.."/ammo_api.lua")
|
dofile(modpath.."/ammo_api.lua")
|
||||||
local path = modpath .. "/classes"
|
local path = modpath .. "/classes"
|
||||||
dofile(path.."/Instantiatable_class.lua")
|
|
||||||
dofile(path.."/Bullet_hole.lua")
|
dofile(path.."/Bullet_hole.lua")
|
||||||
dofile(path.."/Bullet_ray.lua")
|
dofile(path.."/Bullet_ray.lua")
|
||||||
dofile(path.."/Control_handler.lua")
|
dofile(path.."/Control_handler.lua")
|
||||||
@ -69,7 +70,6 @@ dofile(path.."/Dynamic_crosshair.lua")
|
|||||||
dofile(path.."/Gun.lua") --> loads /classes/gun_construct.lua
|
dofile(path.."/Gun.lua") --> loads /classes/gun_construct.lua
|
||||||
dofile(path.."/Player_model_handler.lua")
|
dofile(path.."/Player_model_handler.lua")
|
||||||
dofile(path.."/Player_handler.lua")
|
dofile(path.."/Player_handler.lua")
|
||||||
dofile(path.."/Proxy_table.lua")
|
|
||||||
|
|
||||||
--model compatibility
|
--model compatibility
|
||||||
path = modpath .. "/models"
|
path = modpath .. "/models"
|
||||||
|
@ -56,7 +56,9 @@ function Guns4d.math.weighted_randoms(tbl)
|
|||||||
scaled_weight = scaled_weight + v[2]
|
scaled_weight = scaled_weight + v[2]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
function Guns4d.math.smooth_ratio(r)
|
||||||
|
return ((math.sin((r-.5)*math.pi))+1)/2
|
||||||
|
end
|
||||||
--[[
|
--[[
|
||||||
--for table vectors that aren't vector objects
|
--for table vectors that aren't vector objects
|
||||||
local function tolerance_check(a,b,tolerance)
|
local function tolerance_check(a,b,tolerance)
|
||||||
|
2
mod.conf
2
mod.conf
@ -2,5 +2,5 @@ name = guns4d
|
|||||||
title = guns4d
|
title = guns4d
|
||||||
description = Adds a library for 3d guns
|
description = Adds a library for 3d guns
|
||||||
author = FatalError42O
|
author = FatalError42O
|
||||||
depends = mtul_b3d, mtul_cpml, mtul_filesystem
|
depends = mtul_b3d, mtul_cpml, mtul_filesystem, mtul_class
|
||||||
optional_depends = spriteguns, sprint
|
optional_depends = spriteguns, sprint
|
Binary file not shown.
Binary file not shown.
@ -1,9 +1,33 @@
|
|||||||
|
|
||||||
|
--can't use the default handler's automatic generation because the wielditem and the idle animations cause visual issues.
|
||||||
if minetest.get_modpath("3d_armor") then
|
if minetest.get_modpath("3d_armor") then
|
||||||
local armor3d_handler = Guns4d.player_model_handler:inherit({
|
local armor3d_handler = Guns4d.player_model_handler:inherit({
|
||||||
compatible_meshes = {
|
compatible_meshes = {
|
||||||
["3d_armor_character.b3d"] = "guns4d_3d_armor_character.b3d"
|
["3d_armor_character.b3d"] = "guns4d_3d_armor_character.b3d"
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
--custom bone orientations...
|
||||||
|
--[[function armor3d_handler:update_aiming()
|
||||||
|
--gun bones:
|
||||||
|
local player = self.player
|
||||||
|
local handler = self.handler
|
||||||
|
local gun = handler.gun
|
||||||
|
local first, _ = player:get_eye_offset()
|
||||||
|
local pprops = handler:get_properties()
|
||||||
|
local eye_pos = vector.new(0, (pprops.eye_height*10)/pprops.visual_size.y, 0)+vector.divide(first, pprops.visual_size)
|
||||||
|
if handler.control_handler.ads then
|
||||||
|
eye_pos.x = ((handler.horizontal_offset*10)/pprops.visual_size.x) --horizontal_offset already is eye_offset on x
|
||||||
|
end
|
||||||
|
local player_axial_offset = gun.total_offsets.player_axial
|
||||||
|
player:set_bone_position(self.bone_aliases.hipfire, self.offsets.relative.arm_right, {x=-player_axial_offset.x-gun.player_rotation.x, y=180-player_axial_offset.y, z=0})
|
||||||
|
--print(self.offsets.global.arm_right)
|
||||||
|
--player:set_bone_position(self.bone_aliases.reticle, eye_pos, vector.new(combined.x, 180-combined.y, 0))
|
||||||
|
--can't use paxial dir as it needs to be relative on Y still.
|
||||||
|
local dir = vector.rotate(gun.local_paxial_dir, {x=gun.player_rotation.x*math.pi/180,y=0,z=0})
|
||||||
|
local rot = vector.dir_to_rotation(dir)*180/math.pi
|
||||||
|
|
||||||
|
--irrlicht uses clockwise rotations, while everything else seemingly uses counter-clockwise. MMM yes, it's an "engine" not sphaghetti
|
||||||
|
player:set_bone_position(self.bone_aliases.aim, eye_pos, {x=rot.x,y=180-rot.y,z=0})
|
||||||
|
end]]
|
||||||
armor3d_handler:set_default_handler()
|
armor3d_handler:set_default_handler()
|
||||||
end
|
end
|
Binary file not shown.
BIN
temp/character_guns4d_temp.b3d
Normal file
BIN
temp/character_guns4d_temp.b3d
Normal file
Binary file not shown.
BIN
textures/guns4d_icon.png
Normal file
BIN
textures/guns4d_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 441 B |
Loading…
x
Reference in New Issue
Block a user