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.
|
||||
documentation
|
||||
( ) Instantiatable_class
|
||||
( ) mtul.class.new_class
|
||||
( ) Player_model_handler
|
||||
( ) Registering a model for compatibility
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
Ammo_handler = Instantiatable_class:inherit({
|
||||
Ammo_handler = mtul.class.new_class:inherit({
|
||||
name = "Ammo_handler",
|
||||
construct = function(def)
|
||||
if def.instance then
|
||||
|
@ -35,7 +35,7 @@ minetest.register_globalstep(function(dt)
|
||||
end
|
||||
end
|
||||
end)
|
||||
Guns4d.bullet_hole = Instantiatable_class:inherit({
|
||||
Guns4d.bullet_hole = mtul.class.new_class:inherit({
|
||||
texture = 'bullet_hole.png',
|
||||
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
|
||||
|
@ -445,4 +445,4 @@ function ray.construct(def)
|
||||
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_location = 0,
|
||||
touchscreen = false
|
||||
}
|
||||
--data table:
|
||||
@ -46,7 +47,8 @@ function controls:update(dt)
|
||||
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 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
|
||||
if not (i=="on_use") and not (i=="on_secondary_use") then
|
||||
local def = control
|
||||
@ -103,12 +105,20 @@ function controls:update(dt)
|
||||
end
|
||||
end
|
||||
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
|
||||
self.busy_list = {}
|
||||
elseif self.busy_list then
|
||||
self.busy_list = nil
|
||||
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
|
||||
function controls:on_use(itemstack, pointed_thing)
|
||||
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.busy_list = {}
|
||||
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)
|
||||
|
||||
table.sort(def.actions_pc, function(a,b)
|
||||
@ -169,4 +180,4 @@ function controls.construct(def)
|
||||
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.
|
||||
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",
|
||||
@ -37,20 +37,21 @@ function Dynamic_crosshair:update(dt)
|
||||
assert(self.instance, "attemptr to call object method on a class")
|
||||
local handler = self.handler
|
||||
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()
|
||||
--we have to recalc the rough direction, otherwise walking will look wonky.
|
||||
local temp_vector = vector.new()
|
||||
|
||||
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)
|
||||
end
|
||||
end
|
||||
if gun.consts.HAS_SWAY and self.normalize_sway then
|
||||
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.player_axial*gun.multiplier_coefficient(gun.properties.sway.hipfire_angle_multiplier.player_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-control_handler.ads_location)
|
||||
temp_vector = temp_vector + {x=max_angle, y=max_angle, z=0}
|
||||
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)
|
||||
|
172
classes/Gun.lua
172
classes/Gun.lua
@ -9,7 +9,7 @@
|
||||
-- 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.
|
||||
--
|
||||
-- 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()
|
||||
-- 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
|
||||
-- @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 offsets @{lvl1_fields.offsets|offsets}. runtime storage of offsets generated by recoil sway wag or any other element.
|
||||
-- @field consts @{lvl1_fields.consts|constants} which define gun attributes and should not be changed in an instance of the gun
|
||||
-- @field offsets runtime storage of @{lvl1_fields.offsets|offsets} generated by recoil sway wag or any other element.
|
||||
-- @compact
|
||||
local gun_default = {
|
||||
--- `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,
|
||||
--- `function`
|
||||
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
|
||||
--
|
||||
@ -103,7 +105,7 @@ local gun_default = {
|
||||
--- `vector` the offset of the gun relative to the eye's position at hip.
|
||||
offset = Vec.new(),
|
||||
--- `float` the horizontal offset of the eye when aiming
|
||||
horizontal_offset = 0,
|
||||
horizontal_offset = .1,
|
||||
--- the time it takes to go into full aim
|
||||
aim_time = 1,
|
||||
},
|
||||
@ -378,19 +380,24 @@ local gun_default = {
|
||||
player_axial = Vec.new(),
|
||||
},
|
||||
---
|
||||
look_snap = {
|
||||
look = {
|
||||
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
|
||||
animation_rotation = vector.new(),
|
||||
--- total offsets of the gun in the same format as a @{offsets|an offset}
|
||||
total_offset_rotation = nil,
|
||||
--[[total_offset_rotation = { --can't be in offsets, as they're added automatically.
|
||||
gun_axial = Vec.new(),
|
||||
player_axial = Vec.new(),
|
||||
},]]
|
||||
--[[total_offsets = {
|
||||
gun_axial = vector.new(), rotation of the gun entity (around entity's own axis)
|
||||
player_axial = vector.new(), rotation around the eye (the player's axis)
|
||||
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(),
|
||||
velocities = {
|
||||
recoil = {
|
||||
@ -448,16 +455,6 @@ local gun_default = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--I dont remember why I made this, used it though lmao
|
||||
function gun_default.multiplier_coefficient(multiplier, 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")
|
||||
if not self:has_entity() then self:add_entity(); self:clear_animation() end
|
||||
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
|
||||
|
||||
@ -495,7 +491,7 @@ function gun_default:update(dt)
|
||||
|
||||
if self.burst_queue > 0 then self:update_burstfire() end
|
||||
--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_RECOIL then self:update_recoil(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
|
||||
self.crosshair:update()
|
||||
end
|
||||
local offsets = self.offsets
|
||||
total_rot.player_axial.x = 0; total_rot.player_axial.y = 0
|
||||
total_rot.gun_axial.x = 0; total_rot.gun_axial.y = 0
|
||||
for type, _ in pairs(total_rot) do
|
||||
for i, offset in pairs(offsets) do
|
||||
if self.consts.HAS_GUN_AXIAL_OFFSETS or type~="gun_axial" then
|
||||
total_rot[type] = total_rot[type]+offset[type]
|
||||
local total_offset = self.total_offsets
|
||||
--axis rotations
|
||||
total_offset.player_axial.x = 0; total_offset.player_axial.y = 0
|
||||
total_offset.gun_axial.x = 0; total_offset.gun_axial.y = 0
|
||||
--translations
|
||||
total_offset.player_trans.x = 0; total_offset.player_trans.y = 0; total_offset.player_trans.z = 0
|
||||
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
|
||||
@ -634,7 +636,7 @@ function gun_default:recoil()
|
||||
for _, i in pairs({"x","y"}) do
|
||||
recoil[i] = recoil[i] + (rprops.angular_velocity[axis][i]
|
||||
*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
|
||||
self.velocities.init_recoil[axis][i] = recoil[i]
|
||||
end
|
||||
@ -647,7 +649,7 @@ function gun_default:recoil()
|
||||
end
|
||||
self.time_since_last_fire = 0
|
||||
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")
|
||||
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.
|
||||
@ -662,27 +664,32 @@ function gun_default:update_look_rotation(dt)
|
||||
player_rot.x = look_rotation.x
|
||||
end
|
||||
|
||||
local props = self.properties
|
||||
local hip = props.hip
|
||||
local ads = props.ads
|
||||
if not handler.control_handler.ads then
|
||||
local pitch = self.total_offset_rotation.player_axial.x+player_rot.x
|
||||
local gun_axial = self.offsets.look_snap.gun_axial
|
||||
--hipfire rotation offsets
|
||||
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
|
||||
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))
|
||||
self.offsets.look_snap.player_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.player_axial.x = -pitch*(1-hip.axis_rotation_ratio)
|
||||
|
||||
self.offsets.look.look_trans.x = 0
|
||||
else
|
||||
self.offsets.look_snap.gun_axial.x = 0
|
||||
self.offsets.look_snap.player_axial.x = 0
|
||||
--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]]
|
||||
self.offsets.look.gun_axial.x = 0
|
||||
--aiming look translations
|
||||
|
||||
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
|
||||
--============================================== positional info =====================================
|
||||
--all of this dir shit needs to be optimized HARD
|
||||
function gun_default:get_gun_axial_dir()
|
||||
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}))
|
||||
dir = Vec.rotate(dir, {y=rotation.gun_axial.y*math.pi/180, x=0, z=0})
|
||||
return dir
|
||||
@ -690,7 +697,7 @@ end
|
||||
function gun_default:get_player_axial_dir(rltv)
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
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}))
|
||||
dir = Vec.rotate(dir, {y=((rotation.player_axial.y)*math.pi/180), x=0, z=0})
|
||||
if not rltv then
|
||||
@ -706,10 +713,10 @@ end
|
||||
--this needs to be optimized because it may be called frequently...
|
||||
function gun_default:get_dir(rltv, offset_x, offset_y)
|
||||
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
|
||||
--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 y = -(rotation.gun_axial.y+rotation.player_axial.y+(offset_y or 0))*math.pi/180
|
||||
local Cy = math.cos(y)
|
||||
@ -739,45 +746,34 @@ function gun_default:get_dir(rltv, offset_x, offset_y)
|
||||
return dir
|
||||
end
|
||||
--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")
|
||||
local player = self.player
|
||||
local handler = self.handler
|
||||
local bone_location
|
||||
local gun_offset
|
||||
local pprops = handler:get_properties()
|
||||
if handler.control_handler.ads then
|
||||
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
|
||||
local bone_location = handler.player_model_handler.gun_bone_location
|
||||
local gun_translation = self.gun_translation
|
||||
if offset_pos then
|
||||
gun_translation = gun_translation+offset_pos
|
||||
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
|
||||
local pos
|
||||
if not relative then
|
||||
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
|
||||
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
|
||||
if debug then
|
||||
local hud_pos
|
||||
--[[local hud_pos
|
||||
if relative then
|
||||
hud_pos = vector.rotate(pos, {x=0,y=player:get_look_horizontal(),z=0})+handler:get_pos()
|
||||
else
|
||||
hud_pos = pos+handler:get_pos()
|
||||
end
|
||||
local hud = player:hud_add({
|
||||
end]]
|
||||
if minetest.get_player_by_name("fatal2") then
|
||||
--[[local hud = minetest.get_player_by_name("fatal2"):hud_add({
|
||||
hud_elem_type = "image_waypoint",
|
||||
text = "muzzle_flash2.png",
|
||||
world_pos = hud_pos,
|
||||
@ -786,9 +782,10 @@ function gun_default:get_pos(added_pos, relative, debug)
|
||||
offset = {x=0,y=0},
|
||||
})
|
||||
minetest.after(0, function(hud)
|
||||
player:hud_remove(hud)
|
||||
end, hud)
|
||||
minetest.get_player_by_name("fatal2"):hud_remove(hud)
|
||||
end, hud)]]
|
||||
end
|
||||
|
||||
--world pos, position of bone, offset of gun from bone (with added_pos)
|
||||
return pos
|
||||
end
|
||||
@ -809,21 +806,26 @@ end
|
||||
function gun_default:update_entity()
|
||||
local obj = self.entity
|
||||
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 props = self.properties
|
||||
--attach to the correct bone, and rotate
|
||||
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
|
||||
end
|
||||
if handler.control_handler.ads then
|
||||
local normal_pos = (props.ads.offset)*10
|
||||
obj:set_attach(player, handler.player_model_handler.bone_names.aim, normal_pos, -axial_rot, visibility)
|
||||
else
|
||||
local normal_pos = vector.new(props.hip.offset)*10
|
||||
obj:set_attach(player, handler.player_model_handler.bone_names.hipfire, normal_pos, -axial_rot, visibility)
|
||||
end
|
||||
--Irrlicht uses counterclockwise but we use clockwise.
|
||||
local pos = {}
|
||||
local ads = props.ads.offset
|
||||
local hip = props.hip.offset
|
||||
local offset = self.total_offsets.gun_trans
|
||||
local ip = Guns4d.math.smooth_ratio(handler.control_handler.ads_location)
|
||||
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
|
||||
function gun_default:has_entity()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
@ -1018,10 +1020,10 @@ function gun_default:update_sway(dt)
|
||||
end
|
||||
end)
|
||||
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=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
|
||||
sway=Vec.normalize(sway)*sprops.max_angle[axis]*len_mul
|
||||
sway_vel = Vec.new()
|
||||
@ -1109,4 +1111,4 @@ gun_default.construct = function(def)
|
||||
gun_default.construct_base_class(def)
|
||||
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
|
||||
return out
|
||||
end
|
||||
Modifier = Instantiatable_class:inherit({
|
||||
Modifier = mtul.class.new_class:inherit({
|
||||
overwrites = {},
|
||||
construct = function(def)
|
||||
if def.instance then
|
||||
|
@ -8,12 +8,10 @@ local player_handler = {
|
||||
--player_model_handler = player_model_handler
|
||||
--infinite_ammo = false
|
||||
look_rotation = {x=0, y=0},
|
||||
look_offset = Vec.new(),
|
||||
ads_location = 0, --interpolation scalar for gun aiming location
|
||||
last_eye_offset = Vec.new(),
|
||||
default_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)
|
||||
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
|
||||
if held_gun then
|
||||
--was there a gun last time? did the wield index change?
|
||||
local old_index = self.wield_index
|
||||
self.wield_index = player:get_wield_index()
|
||||
--initialize all handlers and objects
|
||||
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
|
||||
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})
|
||||
|
||||
--this needs to be stored for when the gun is unset!
|
||||
self.horizontal_offset = self.gun.properties.ads.horizontal_offset
|
||||
self.gun.control_handler=self.control_handler
|
||||
|
||||
--set_hud_flags
|
||||
player:hud_set_flags({wielditem = false, crosshair = false})
|
||||
|
||||
--for the gun's scopes to work properly we need predictable offsets.
|
||||
end
|
||||
--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.control_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
|
||||
if TICK % 4 == 0 then
|
||||
self.touching_ground = self:get_is_on_ground()
|
||||
@ -80,21 +75,6 @@ function player_handler:update(dt)
|
||||
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
|
||||
--stored properties and pos must be reset as they could be outdated.
|
||||
self.properties = nil
|
||||
@ -206,7 +186,6 @@ end
|
||||
--note that construct is NOT called as a method
|
||||
function player_handler.construct(def)
|
||||
if def.instance then
|
||||
def.old_mesh = def.player:get_properties().mesh
|
||||
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
|
||||
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)
|
||||
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 = {
|
||||
handlers = {}, --not for children, this stores a global list of handlers by meshname.
|
||||
-- @table fields.offsets
|
||||
offsets = {
|
||||
-- a list of offsets relative to the whole model
|
||||
global = {
|
||||
--right arm (for hipfire bone)
|
||||
},
|
||||
-- a list of offsets relative to their parents (at rest position)
|
||||
relative = { --none of these are specifically needed...
|
||||
--left arm
|
||||
--right arm
|
||||
--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.)
|
||||
bone_names = {
|
||||
|
||||
--model generation attributes
|
||||
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_left = "guns4d_arm_left",
|
||||
aim = "guns4d_aiming_bone",
|
||||
hipfire = "guns4d_hipfire_bone",
|
||||
head = "guns4d_head"
|
||||
head = "guns4d_head",
|
||||
gun = "guns4d_gun_bone",
|
||||
},
|
||||
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.
|
||||
["character.b3d"] = "guns4d_character.b3d",
|
||||
auto_generate = true,
|
||||
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
|
||||
},
|
||||
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.
|
||||
}
|
||||
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")
|
||||
player_model.default_handler = handler
|
||||
end
|
||||
|
||||
function player_model.get_handler(meshname)
|
||||
local selected_handler = player_model.handlers[meshname] or player_model.main
|
||||
if selected_handler then return selected_handler end
|
||||
return player_model.default_handler
|
||||
end
|
||||
|
||||
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(original and replacement, "one or more parameters missing")
|
||||
self.compatible_meshes[original] = replacement
|
||||
player_model.handlers[original] = self
|
||||
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:
|
||||
local first, second = 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
|
||||
--we store the read file so it can be reused in the constructor if needed.
|
||||
local model_buffer
|
||||
local modpath = minetest.get_modpath("guns4d")
|
||||
function player_model:custom_b3d_generation_parameters(b3d)
|
||||
--empty for now, this is for model customizations.
|
||||
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
|
||||
player:set_bone_position(self.bone_names.hipfire, self.offsets.relative.arm_right, {x=-pitch, y=180-player_axial_offset.y, z=0})
|
||||
--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
|
||||
--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()
|
||||
|
||||
--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})
|
||||
--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
|
||||
|
||||
-- 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_arm_bones(dt)
|
||||
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)
|
||||
local player = self.player
|
||||
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.
|
||||
left_rotation.x = -left_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_names.arm_right, self.offsets.relative.arm_right, {x=90, y=0, z=0}-right_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_aliases.arm_right, self.offsets.relative.arm_right, {x=90, y=0, z=0}-right_rotation)
|
||||
end
|
||||
|
||||
function player_model:update_head(dt)
|
||||
local player = self.player
|
||||
local handler = self.handler
|
||||
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
|
||||
--should be renamed to "release" but, whatever.
|
||||
function player_model:prepare_deletion()
|
||||
assert(self.instance, "attempt to call object method on a class")
|
||||
local handler = Guns4d.players[self.player:get_player_name()]
|
||||
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)
|
||||
end
|
||||
end]]
|
||||
properties.mesh = self.old
|
||||
handler:set_properties(properties)
|
||||
end
|
||||
@ -120,13 +230,25 @@ function player_model.construct(def)
|
||||
if def.instance then
|
||||
assert(def.player, "no player provided")
|
||||
def.handler = Guns4d.players[def.player:get_player_name()]
|
||||
--set the mesh
|
||||
local properties = def.handler:get_properties()
|
||||
def.old = properties.mesh
|
||||
--set the mesh
|
||||
|
||||
properties.mesh = def.compatible_meshes[properties.mesh] or def.fallback_mesh
|
||||
properties.mesh = def.compatible_meshes[properties.mesh]
|
||||
def.gun_bone_location = vector.new()
|
||||
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)
|
||||
--no further aciton required, it e
|
||||
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
|
||||
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
|
||||
@ -134,37 +256,41 @@ function player_model.construct(def)
|
||||
end
|
||||
|
||||
--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
|
||||
for i, v in pairs(def.compatible_meshes) do
|
||||
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
|
||||
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)
|
||||
|
||||
--[[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]]
|
||||
---@diagnostic disable-next-line: redefined-local
|
||||
for i, v in pairs({"arm_right", "arm_left", "head"}) do
|
||||
--print(def.bone_names[v])
|
||||
for i, v in pairs(def.bone_aliases) do
|
||||
--print(def.bone_aliases[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)
|
||||
|
||||
local transform, rotation = mtul.b3d_nodes.get_node_global_transform(node, def.still_frame)
|
||||
|
||||
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.
|
||||
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.
|
||||
--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
|
||||
def.offsets.global.hipfire = vector.new(mtul.b3d_nodes.get_node_global_position(b3d_table, def.bone_names.arm_right, true, def.still_frame))
|
||||
end
|
||||
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
|
||||
player_model.set_default_handler(def)
|
||||
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()
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
--
|
||||
|
||||
Proxy_table = {
|
||||
registered_proxies = {},
|
||||
proxy_children = {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
local Sprite_scope = Instantiatable_class:inherit({
|
||||
local Sprite_scope = mtul.class.new_class:inherit({
|
||||
images = {
|
||||
fore = {
|
||||
texture = "scope_fore.png",
|
||||
@ -51,24 +51,26 @@ Guns4d.sprite_scope = Sprite_scope
|
||||
--rename to draw?
|
||||
function Sprite_scope:update()
|
||||
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 not self.fov_set then
|
||||
self.fov_set = true
|
||||
handler:set_fov(80/self.magnification)
|
||||
end
|
||||
local dir = self.gun.local_dir
|
||||
local dir = gun.local_dir
|
||||
local ratio = handler.wininfo.size.x/handler.wininfo.size.y
|
||||
|
||||
if handler.ads_location ~= 1 then
|
||||
dir = dir + (self.gun.properties.ads.offset+vector.new(self.gun.properties.ads.horizontal_offset,0,0))*0
|
||||
if control_handler.ads_location ~= 1 then
|
||||
dir = dir + (self.gun.properties.ads.offset+vector.new(gun.properties.ads.horizontal_offset,0,0))*0
|
||||
end
|
||||
local fov = self.player:get_fov()
|
||||
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
|
||||
|
||||
--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
|
||||
self.hud_projection_real = real_aim
|
||||
self.hud_projection_paxial = paxial_aim
|
||||
@ -83,7 +85,7 @@ function Sprite_scope:update()
|
||||
self.fov_set = false
|
||||
handler:unset_fov()
|
||||
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
|
||||
local def = self.images[i]
|
||||
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))
|
||||
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
|
||||
function Sprite_scope:prepare_deletion()
|
||||
|
@ -43,9 +43,12 @@ end
|
||||
|
||||
local function initialize_physics(self)
|
||||
--initialize rotation offsets
|
||||
self.total_offset_rotation = {
|
||||
self.total_offsets = {
|
||||
gun_axial = vector.new(),
|
||||
player_axial = vector.new(),
|
||||
gun_trans = vector.new(),
|
||||
player_trans = vector.new(),
|
||||
look_trans = vector.new()
|
||||
}
|
||||
self.offsets = {}
|
||||
for offset, tbl in pairs(self.base_class.offsets) do
|
||||
@ -89,7 +92,7 @@ function gun_default:construct_instance()
|
||||
|
||||
--unavoidable table instancing
|
||||
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 = {}
|
||||
|
||||
initialize_animation(self)
|
||||
|
@ -16,7 +16,7 @@
|
||||
<div class="group two">
|
||||
</div>
|
||||
<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 class="sidebar">
|
||||
@ -61,7 +61,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
@ -193,7 +193,7 @@ or you can do the same thing with a seperate class of weapons. Set name to "
|
||||
</td>
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -3,12 +3,12 @@
|
||||
<!-- Documentation generated by LuaDox: https://github.com/jtackaberry/luadox -->
|
||||
<head>
|
||||
<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 rel="stylesheet" href="../luadox.css?7653a2d" type="text/css">
|
||||
|
||||
</head>
|
||||
<body class="class-instantiatable_class">
|
||||
<body class="class-mtul.class.new_class">
|
||||
<div class="topbar">
|
||||
<div class="group one">
|
||||
<div class="description"><span>Guns4d | The ultimate 3d gun mod.</span></div>
|
||||
@ -27,8 +27,8 @@
|
||||
<div class="sections">
|
||||
<div class="heading">Contents</div>
|
||||
<ul>
|
||||
<li><a href="#Instantiatable_class">Class <code>Instantiatable_class</code></a></li>
|
||||
<li><a href="#god_work"><p>Instantiatable_class</p>
|
||||
<li><a href="#mtul.class.new_class">Class <code>mtul.class.new_class</code></a></li>
|
||||
<li><a href="#god_work"><p>mtul.class.new_class</p>
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -36,7 +36,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
@ -52,8 +52,8 @@
|
||||
</div>
|
||||
<div class="body">
|
||||
<div class="section">
|
||||
<h2 class="class" id="Instantiatable_class">Class <code>Instantiatable_class</code>
|
||||
<a class="permalink" href="#Instantiatable_class" title="Permalink to this definition">¶</a>
|
||||
<h2 class="class" id="mtul.class.new_class">Class <code>mtul.class.new_class</code>
|
||||
<a class="permalink" href="#mtul.class.new_class" title="Permalink to this definition">¶</a>
|
||||
</h2>
|
||||
<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>
|
||||
@ -63,29 +63,29 @@
|
||||
<div class="heading">Methods</div>
|
||||
<table class="functions ">
|
||||
<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>
|
||||
</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>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<dl class="functions">
|
||||
<dt id="Instantiatable_class.inherit">
|
||||
<span class="icon"></span><var>Instantiatable_class:inherit</var>(<em>def</em>)
|
||||
<a class="permalink" href="#Instantiatable_class.inherit" title="Permalink to this definition">¶</a>
|
||||
<dt id="mtul.class.new_class.inherit">
|
||||
<span class="icon"></span><var>mtul.class.new_class:inherit</var>(<em>def</em>)
|
||||
<a class="permalink" href="#mtul.class.new_class.inherit" title="Permalink to this definition">¶</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<p>creates a new base class. Calls all constructors in the chain with def.instance=true</p>
|
||||
|
||||
</dd>
|
||||
<dt id="Instantiatable_class.new">
|
||||
<span class="icon"></span><var>Instantiatable_class:new</var>(<em>def</em>)
|
||||
<a class="permalink" href="#Instantiatable_class.new" title="Permalink to this definition">¶</a>
|
||||
<dt id="mtul.class.new_class.new">
|
||||
<span class="icon"></span><var>mtul.class.new_class:new</var>(<em>def</em>)
|
||||
<a class="permalink" href="#mtul.class.new_class.new" title="Permalink to this definition">¶</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<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 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>
|
||||
</h2>
|
||||
|
@ -16,7 +16,7 @@
|
||||
<div class="group two">
|
||||
</div>
|
||||
<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 class="sidebar">
|
||||
@ -27,7 +27,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
@ -1,6 +1,6 @@
|
||||
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/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/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:""},
|
||||
@ -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.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.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.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.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"},
|
||||
@ -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.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/Instantiatable_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/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.instance", type:"field", title:"god_work.instance", text:"defines wether the object is an instance"},
|
||||
{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/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/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.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/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/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.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/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/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"},
|
||||
|
@ -34,7 +34,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
@ -34,7 +34,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
@ -33,7 +33,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
@ -16,7 +16,7 @@
|
||||
<div class="group two">
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
@ -40,7 +40,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
@ -36,7 +36,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
@ -16,7 +16,7 @@
|
||||
<div class="group two">
|
||||
</div>
|
||||
<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 class="sidebar">
|
||||
@ -27,7 +27,7 @@
|
||||
<div class="heading">Classes</div>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="modules">
|
||||
|
4
init.lua
4
init.lua
@ -48,6 +48,8 @@ for i, v in pairs(Guns4d.config) do
|
||||
end
|
||||
end
|
||||
|
||||
minetest.rmdir(modpath.."/temp", true)
|
||||
minetest.mkdir(modpath.."/temp")
|
||||
|
||||
dofile(modpath.."/infinite_ammo.lua")
|
||||
dofile(modpath.."/misc_helpers.lua")
|
||||
@ -59,7 +61,6 @@ dofile(modpath.."/touch_support.lua")
|
||||
dofile(modpath.."/block_values.lua")
|
||||
dofile(modpath.."/ammo_api.lua")
|
||||
local path = modpath .. "/classes"
|
||||
dofile(path.."/Instantiatable_class.lua")
|
||||
dofile(path.."/Bullet_hole.lua")
|
||||
dofile(path.."/Bullet_ray.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.."/Player_model_handler.lua")
|
||||
dofile(path.."/Player_handler.lua")
|
||||
dofile(path.."/Proxy_table.lua")
|
||||
|
||||
--model compatibility
|
||||
path = modpath .. "/models"
|
||||
|
@ -56,7 +56,9 @@ function Guns4d.math.weighted_randoms(tbl)
|
||||
scaled_weight = scaled_weight + v[2]
|
||||
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
|
||||
local function tolerance_check(a,b,tolerance)
|
||||
|
2
mod.conf
2
mod.conf
@ -2,5 +2,5 @@ name = guns4d
|
||||
title = guns4d
|
||||
description = Adds a library for 3d guns
|
||||
author = FatalError42O
|
||||
depends = mtul_b3d, mtul_cpml, mtul_filesystem
|
||||
depends = mtul_b3d, mtul_cpml, mtul_filesystem, mtul_class
|
||||
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
|
||||
local armor3d_handler = Guns4d.player_model_handler:inherit({
|
||||
compatible_meshes = {
|
||||
["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()
|
||||
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