Commit 86d3f39d authored by Connor Price's avatar Connor Price 🤣

Some fixes, sight gadget overhaul, and some weird stuff.

parent 5e9d2004
function FPCameraPlayerBase:play_sound(unit, event)
if alive(self._parent_unit) then
local weapon = self._parent_unit:inventory():equipped_unit()
if weapon then
local weapon_tweak_data = weapon:base():weapon_tweak_data()
if weapon_tweak_data.sounds and ( weapon_tweak_data.sounds.replacements or weapon_tweak_data.sounds.reload ) then
local sound_replacements = weapon_tweak_data.sounds.replacements or weapon_tweak_data.sounds.reload
event = sound_replacements[event] or event
end
end
self._parent_unit:sound():play(event)
end
end
local function needs_shit( part_data )
if part_data.stats and ( part_data.stats.extra_ammo_new or part_data.stats.total_ammo_mod_new ) then
return true
end
if part_data.custom_stats and ( part_data.custom_stats.rof_mult ) then
return true
end
if part_data.weapon_reload_override or part_data.weapon_hold_override or part_data.weapon_stance_override or part_data.timer_multiplier or part_data.timer_adder then
return true
end
return false
end
local name_id_to_factory_id = {}
local function super_fun_conversion( part_id_for_warning, part_data )
if not needs_shit( part_data ) then return end
log("[WeaponLib] [Backwards Compatibility] WARNING: '" .. part_id_for_warning .. "' is using outdated/deprecated tweak data!")
part_data.stats = part_data.stats or {}
part_data.custom_stats = part_data.custom_stats or {}
part_data.override_weapon = part_data.override_weapon or {}
part_data.override_weapon_add = part_data.override_weapon_add or {}
part_data.override_weapon_multiply = part_data.override_weapon_multiply or {}
part_data.override_weapon_add["CLIP_AMMO_MAX"] = part_data.stats.extra_ammo_new
part_data.override_weapon_add["AMMO_MAX"] = part_data.stats.total_ammo_mod_new
if part_data.weapon_reload_override then
for name_id, value in pairs(part_data.weapon_reload_override) do
part_data.override_weapon["animations"] = part_data.override_weapon["animations"] or {}
part_data.override_weapon["animations"]["reload_name_id"] = value
end
end
if part_data.weapon_hold_override then
for name_id, value in pairs(part_data.weapon_hold_override) do
part_data.override_weapon["weapon_hold"] = value
end
end
if part_data.weapon_stance_override then
for name_id, value in pairs(part_data.weapon_stance_override) do
part_data.override_weapon["use_stance"] = value
end
end
if part_data.timer_multiplier then
part_data.override_weapon_multiply["timers"] = part_data.override_weapon_multiply["timers"] or {}
for timer_name, value in pairs(part_data.timer_multiplier) do
part_data.override_weapon_multiply["timers"][timer_name] = value
end
end
if part_data.timer_adder then
part_data.override_weapon_add["timers"] = part_data.override_weapon_add["timers"] or {}
for timer_name, value in pairs(part_data.timer_adder) do
part_data.override_weapon_add["timers"][timer_name] = value
end
end
if part_data.custom_stats.rof_mult then
part_data.override_weapon_multiply["fire_mode_data"] = part_data.override_weapon_multiply["fire_mode_data"] or {}
part_data.override_weapon_multiply["fire_mode_data"]["fire_rate"] = 1/part_data.custom_stats.rof_mult
end
-- Recursive Fun!
if part_data.override then
for part_id, part_data in pairs(part_data.override) do
super_fun_conversion( part_id_for_warning .. ".override." .. part_id, part_data )
end
end
end
Hooks:PostHook( WeaponTweakData, "_init_data_player_weapons", "BackPatConversion", function(self)
local parts = self.factory.parts
for part_id, part_data in pairs(parts) do
super_fun_conversion( part_id, part_data )
end
end)
\ No newline at end of file
Hooks:PostHook( NewNPCRaycastWeaponBase, "init", "CustomAttachmentPoints_NPCThirdPersonAttachments", function( self, unit )
local weapon_tweak_data = tweak_data.weapon[self._name_id]
if weapon_tweak_data and weapon_tweak_data.attachment_points then
self.cap_objects = self.cap_objects or {}
local attachment_points = weapon_tweak_data.attachment_points
for _, attachment_point_data in pairs(attachment_points) do
local ids_name = tostring(Idstring(attachment_point_data.name))
self.cap_objects[ids_name] = self.cap_objects[ids_name] or {
offset = {
position = attachment_point_data.position,
rotation = attachment_point_data.rotation
},
part_attach_data = attachment_point_data.part_attach_data
}
if attachment_point_data.base_a_obj then
local base_id = Idstring(attachment_point_data.base_a_obj)
if base_id then
self.cap_objects[ids_name].base_obj = self.cap_objects[ids_name].base_a_obj or base_id
end
end
end
end
end)
\ No newline at end of file
This diff is collapsed.
function NewRaycastWeaponBase:PartAttachmentStuff()
local parts_tweak = tweak_data.weapon.factory.parts
-- We need these to do anything no point in continuing if we don't have either of them.
if ( not parts_tweak ) then return end
if ( not self.part_attach_data ) then return end
for part_id, part in pairs(self.part_attach_data) do
end
for part_id, part in pairs(self._parts) do
-- Unlikely to not exist but better to be safe!
if ( not part.unit ) then goto continue end
-- Get our parts attachment object and check if it exists. We need this as well so we stop if we don't have it.
local part_a_obj = parts_tweak[part_id] and managers.weapon_factory:get_part_data_by_part_id_from_weapon(part_id, self._factory_id, self._blueprint).a_obj
if ( not part_a_obj ) then goto continue end
-- Get attachment data relevant to that attachment point. If it doesn't exist we don't bother continuing.
local part_attachment_data = self.part_attach_data[part_a_obj]
if ( not part_attachment_data ) then goto continue end
local attach_parts = part_attachment_data[1] -- First part of data is a list of weapon parts which we attach to.
local attach_obj = part_attachment_data[2] -- Second is a string of the object on the weapon_part we want to attach to.
-- Find the first part from attach_parts. If it's not on here don't bother!
local attach_part = nil
local attach_part_id = nil
for index, part_id in ipairs(attach_parts) do
if ( self._parts[part_id] and self._parts[part_id].unit ) then
attach_part = self._parts[part_id].unit
attach_part_id = part_id
break
end
end
if ( not attach_part ) then goto continue end
local a_obj = Idstring( attach_obj )
local attachment_object = attach_part:get_object( a_obj )
local base_attachment_position = Vector3(0,0,0)
local base_attachment_rotation = Rotation(0,0,0)
--Not gonna lie I don't really know why this works.
local base_a_obj = part_attachment_data.base_a_obj
if base_a_obj then
local base_a_obj_idstring = Idstring( base_a_obj )
local base_a_obj_object = self._unit:get_object( base_a_obj_idstring )
if base_a_obj_object then
local cap_offset_check = self:CheckCAPOffset( attach_part_id )
local base_a_obj_position = base_a_obj_object:local_position() or Vector3(0,0,0)
base_attachment_position = base_a_obj_position - cap_offset_check.position
local base_a_obj_rotation = base_a_obj_object:local_rotation() or Vector3(0,0,0)
base_attachment_rotation = Rotation(
base_a_obj_rotation:yaw() - cap_offset_check.rotation:yaw(),
base_a_obj_rotation:pitch() - cap_offset_check.rotation:pitch(),
base_a_obj_rotation:roll() - cap_offset_check.rotation:roll()
)
else
log( "[WeaponLib] [Custom Attachment Points Legacy] Base '" .. base_a_obj .. "' Not Found on '" .. self._name_id .. "'" )
end
end
local offset_position = part_attachment_data.position
local offset_rotation = part_attachment_data.rotation
-- Link the object to the part!
local res = attach_part:link(a_obj, part.unit, part.unit:orientation_object():name())
-- Calculate the new position and rotation! ( With some defaults just in case. )
local new_position = ( base_attachment_position + offset_position ) or Vector3(0,0,0)
local new_rotation = Rotation(
base_attachment_rotation:yaw() + offset_rotation:yaw(),
base_attachment_rotation:pitch() + offset_rotation:pitch(),
base_attachment_rotation:roll() + offset_rotation:roll()
) or Rotation(0,0,0)
-- Set the new position and rotation!
part.unit:set_position( new_position )
part.unit:set_rotation( new_rotation )
::continue::
end
end
-- Cancer shit to sort of fix when the part your attaching to has been CAP edited aswell.
function NewRaycastWeaponBase:CheckCAPOffset( part_id )
local position_offset = Vector3(0,0,0)
local rotation_offset = RotationCAP(0,0,0)
local parts_tweak = tweak_data.weapon.factory.parts
if parts_tweak then
local part_a_obj_name = parts_tweak[part_id] and managers.weapon_factory:get_part_data_by_part_id_from_weapon(part_id, self._factory_id, self._blueprint).a_obj
if part_a_obj_name then
local part_a_obj = self._unit:get_object( Idstring(part_a_obj_name) )
if part_a_obj then
position_offset = position_offset + part_a_obj:local_position()
rotation_offset = RotationCAP(
rotation_offset:yaw() + part_a_obj:local_rotation():yaw(),
rotation_offset:pitch() + part_a_obj:local_rotation():pitch(),
rotation_offset:roll() + part_a_obj:local_rotation():roll()
)
end
local weapons_tweak = tweak_data.weapon
if weapons_tweak then
local weapon_tweak_data = weapons_tweak[self._name_id]
if weapon_tweak_data then
local attachment_points = weapon_tweak_data.attachment_points
if attachment_points then
for index, value in ipairs( attachment_points ) do
if (value.name) and ( value.name == part_a_obj_name ) then
position_offset = position_offset + ( value.position or Vector3(0,0,0) )
rotation_offset = RotationCAP(
rotation_offset:yaw() + ( value.rotation:yaw() or Vector3(0,0,0) ),
rotation_offset:pitch() + ( value.rotation:pitch() or Vector3(0,0,0) ),
rotation_offset:roll() + ( value.rotation:roll() or Vector3(0,0,0) )
)
end
end
end
end
end
end
end
return {
position = position_offset,
rotation = rotation_offset
}
end
Hooks:PostHook( NewRaycastWeaponBase, "_assemble_completed", "MenuRayCastWeaponBasePartAttachments", function( self )
self:PartAttachmentStuff()
end)
\ No newline at end of file
require("lib/units/weapons/RaycastWeaponBase")
NewRaycastWeaponBase = NewRaycastWeaponBase or class(RaycastWeaponBase)
\ No newline at end of file
function NewRaycastWeaponBase:PartAttachmentStuff()
local parts_tweak = tweak_data.weapon.factory.parts
-- We need these to do anything no point in continuing if we don't have either of them.
if ( not parts_tweak ) then return end
if ( not self.part_attach_data ) then return end
for part_id, part in pairs(self.part_attach_data) do
end
for part_id, part in pairs(self._parts) do
-- Unlikely to not exist but better to be safe!
if ( not part.unit ) then goto continue end
-- Get our parts attachment object and check if it exists. We need this as well so we stop if we don't have it.
local part_a_obj = parts_tweak[part_id] and managers.weapon_factory:get_part_data_by_part_id_from_weapon(part_id, self._factory_id, self._blueprint).a_obj
if ( not part_a_obj ) then goto continue end
-- Get attachment data relevant to that attachment point. If it doesn't exist we don't bother continuing.
local part_attachment_data = self.part_attach_data[part_a_obj]
if ( not part_attachment_data ) then goto continue end
local attach_parts = part_attachment_data[1] -- First part of data is a list of weapon parts which we attach to.
local attach_obj = part_attachment_data[2] -- Second is a string of the object on the weapon_part we want to attach to.
-- Find the first part from attach_parts. If it's not on here don't bother!
local attach_part = nil
local attach_part_id = nil
for index, part_id in ipairs(attach_parts) do
if ( self._parts[part_id] and self._parts[part_id].unit ) then
attach_part = self._parts[part_id].unit
attach_part_id = part_id
break
end
end
if ( not attach_part ) then goto continue end
local a_obj = Idstring( attach_obj )
local attachment_object = attach_part:get_object( a_obj )
local base_attachment_position = Vector3(0,0,0)
local base_attachment_rotation = Rotation(0,0,0)
--Not gonna lie I don't really know why this works.
local base_a_obj = part_attachment_data.base_a_obj
if base_a_obj then
local base_a_obj_idstring = Idstring( base_a_obj )
local base_a_obj_object = self._unit:get_object( base_a_obj_idstring )
if base_a_obj_object then
local cap_offset_check = self:CheckCAPOffset( attach_part_id )
local base_a_obj_position = base_a_obj_object:local_position() or Vector3(0,0,0)
base_attachment_position = base_a_obj_position - cap_offset_check.position
local base_a_obj_rotation = base_a_obj_object:local_rotation() or Vector3(0,0,0)
base_attachment_rotation = Rotation(
base_a_obj_rotation:yaw() - cap_offset_check.rotation:yaw(),
base_a_obj_rotation:pitch() - cap_offset_check.rotation:pitch(),
base_a_obj_rotation:roll() - cap_offset_check.rotation:roll()
)
else
log( "Custom Attachment Points Error: Base Not Found on Weapon" )
end
end
local offset_position = part_attachment_data.position
local offset_rotation = part_attachment_data.rotation
-- Link the object to the part!
local res = attach_part:link(a_obj, part.unit, part.unit:orientation_object():name())
-- Calculate the new position and rotation! ( With some defaults just in case. )
local new_position = ( base_attachment_position + offset_position ) or Vector3(0,0,0)
local new_rotation = Rotation(
base_attachment_rotation:yaw() + offset_rotation:yaw(),
base_attachment_rotation:pitch() + offset_rotation:pitch(),
base_attachment_rotation:roll() + offset_rotation:roll()
) or Rotation(0,0,0)
-- Set the new position and rotation!
part.unit:set_position( new_position )
part.unit:set_rotation( new_rotation )
::continue::
end
end
-- Cancer shit to sort of fix when the part your attaching to has been CAP edited aswell.
function NewRaycastWeaponBase:CheckCAPOffset( part_id )
local position_offset = Vector3(0,0,0)
local rotation_offset = RotationCAP(0,0,0)
local parts_tweak = tweak_data.weapon.factory.parts
if parts_tweak then
local part_a_obj_name = parts_tweak[part_id] and managers.weapon_factory:get_part_data_by_part_id_from_weapon(part_id, self._factory_id, self._blueprint).a_obj
if part_a_obj_name then
local part_a_obj = self._unit:get_object( Idstring(part_a_obj_name) )
if part_a_obj then
position_offset = position_offset + part_a_obj:local_position()
rotation_offset = RotationCAP(
rotation_offset:yaw() + part_a_obj:local_rotation():yaw(),
rotation_offset:pitch() + part_a_obj:local_rotation():pitch(),
rotation_offset:roll() + part_a_obj:local_rotation():roll()
)
end
local weapons_tweak = tweak_data.weapon
if weapons_tweak then
local weapon_tweak_data = weapons_tweak[self._name_id]
if weapon_tweak_data then
local attachment_points = weapon_tweak_data.attachment_points
if attachment_points then
for index, value in ipairs( attachment_points ) do
if (value.name) and ( value.name == part_a_obj_name ) then
position_offset = position_offset + ( value.position or Vector3(0,0,0) )
rotation_offset = RotationCAP(
rotation_offset:yaw() + ( value.rotation:yaw() or Vector3(0,0,0) ),
rotation_offset:pitch() + ( value.rotation:pitch() or Vector3(0,0,0) ),
rotation_offset:roll() + ( value.rotation:roll() or Vector3(0,0,0) )
)
end
end
end
end
end
end
end
return {
position = position_offset,
rotation = rotation_offset
}
end
Hooks:PostHook( NewRaycastWeaponBase, "clbk_assembly_complete", "NewRayCastWeaponBasePartAttachments", function( self )
self:PartAttachmentStuff()
end)
\ No newline at end of file
-- Save the original function as a backup.
WeaponFactoryManager._spawn_and_link_unit_weaponlib_original = WeaponFactoryManager._spawn_and_link_unit
-- Storage for stuff!
local last_name_id = ""
local temp_custom_attachment_points = {}
function WeaponFactoryManager:_spawn_and_link_unit( u_name, a_obj, third_person, link_to_unit )
if ( link_to_unit and link_to_unit:base() and link_to_unit:base().weapon_tweak_data and link_to_unit:base()._name_id ) then
local name_id = link_to_unit:base()._name_id
local weapon_tweakdata = link_to_unit:base():weapon_tweak_data()
-- Save the attachment point stuff and remember the last name id because for some reason the tweakdata or name_id doesn't always show up.
if ( name_id ) then
last_name_id = name_id
end
if ( weapon_tweakdata and weapon_tweakdata.attachment_points ) then
temp_custom_attachment_points[name_id] = weapon_tweakdata.attachment_points
end
end
if ( last_name_id and temp_custom_attachment_points[last_name_id] ) then
for index, attach_point in ipairs( temp_custom_attachment_points[last_name_id] ) do
-- Store values in shorter variables. ( I'm lazy. ) Also, sorts out the defaults.
local a_name = attach_point.name or nil
local a_base_a_obj = attach_point.base_a_obj or nil
local a_position = attach_point.position or Vector3( 0, 0, 0 )
local a_rotation = attach_point.rotation or Rotation( 0, 0, 0 )
local a_part_attach_data = attach_point.part_attach_data or nil
-- Check if the current 'attach_point' matches the one we are trying to attach to.
if (a_name) then
if ( Idstring( a_name ) == a_obj ) then
-- Yes, this is the point we are looking for so spawn the unit!
local unit = World:spawn_unit( u_name, Vector3(), Rotation() )
-- If we are attaching to a part don't bother. We will deal with this later!
if a_part_attach_data then
-- Store any attachment data on the weapon for later use!
link_to_unit:base().part_attach_data = link_to_unit:base().part_attach_data or {}
link_to_unit:base().part_attach_data[a_name] = a_part_attach_data
link_to_unit:base().part_attach_data[a_name].position = a_position
link_to_unit:base().part_attach_data[a_name].rotation = a_rotation
link_to_unit:base().part_attach_data[a_name].base_a_obj = a_base_a_obj
-- Some occlusion code which exists in the original so probably a good idea to include it again!
if managers.occlusion and not third_person then
managers.occlusion:remove_occlusion(unit)
end
return unit
end
if (a_base_a_obj) then
-- Get the attachment_object for the position and rotation.
local base_a_obj = Idstring( a_base_a_obj )
local attachment_object = link_to_unit:get_object( base_a_obj )
if attachment_object then
-- Get the original position and rotation!
local base_attachment_position = attachment_object:position() or Vector3(0,0,0)
local base_attachment_rotation = attachment_object:rotation() or Rotation(0,0,0)
-- Link the object to the gun!
local res = link_to_unit:link(base_a_obj, unit, unit:orientation_object():name())
-- Calculate the new position and rotation! ( With some defaults just in case. )
local new_position = ( base_attachment_position + a_position ) or Vector3(0,0,0)
local new_rotation = Rotation(
(base_attachment_rotation:yaw() + a_rotation:yaw() ) % 360,
(base_attachment_rotation:pitch() + a_rotation:pitch() ) % 360,
(base_attachment_rotation:roll() + a_rotation:roll() ) % 360
) or Rotation(0,0,0)
-- Set the new position and rotation!
unit:set_position( new_position )
unit:set_rotation( new_rotation )
-- Some occlusion code which exists in the original so probably a good idea to include it again!
if managers.occlusion and not third_person then
managers.occlusion:remove_occlusion(unit)
end
return unit
else
log( "[WeaponLib] [Custom Attachment Points Legacy] WARNING: Base Not Found on Weapon - " .. last_name_id .. " - " .. a_name )
end
else
log( "[WeaponLib] [Custom Attachment Points Legacy] WARNING: Missing Base - " .. last_name_id .. " - " .. a_name )
end
end
else
log( "[WeaponLib] [Custom Attachment Points Legacy] WARNING: Missing Name - " .. last_name_id )
end
end
end
-- If all else fails do the original function!
return self:_spawn_and_link_unit_weaponlib_original( u_name, a_obj, third_person, link_to_unit )
end
\ No newline at end of file
function WeaponTweakData:SetupAttachmentPoint( id, attachment_table )
if not ( self[id] ) then return end
if not ( self[id].attachment_points ) then
self[id].attachment_points = {}
end
table.insert( self[id].attachment_points, attachment_table )
if self[id .. "_crew"] and ( not self[id .. "_crew"].attachment_points ) then
self[id .. "_crew"].attachment_points = self[id].attachment_points
end
end
\ No newline at end of file
function RotationCAP( yaw, pitch, roll )
local rotation_object = {
values = {
yaw = yaw,
pitch = pitch,
roll = roll
},
yaw = function(self) return self.values.yaw end,
pitch = function(self) return self.values.pitch end,
roll = function(self) return self.values.roll end
}
return rotation_object
end
\ No newline at end of file
Hooks:PostHook( PlayerStandard, "enter", "CustomScopeEffect_StateEnter", function(self)
self:_update_steelsight_color_grading()
end)
Hooks:PostHook( PlayerStandard, "_start_action_equip_weapon", "CustomScopeEffect_WeaponSwitch", function(self)
self:_update_steelsight_color_grading()
end)
Hooks:PostHook( PlayerStandard, "_steelsight_on_end", "CustomScopeEffect_SteelsightOn", function(self)
local weap_base = self._ext_inventory:equipped_unit():base()
if weap_base and weap_base:is_second_sight_on() then
self:_set_colour_grading( self._state_data._second_sight_colour_grading )
else
self:_set_colour_grading( self._state_data._sight_colour_grading )
end
end)
Hooks:PostHook( PlayerStandard, "_steelsight_off_start", "CustomScopeEffect_SteelsightOff", function(self)
self:_set_colour_grading( false )
end)
Hooks:PostHook( PlayerStandard, "_toggle_second_sight", "CustomScopeEffect_ToggleSecondSight", function(self, second_sight_on)
if self:in_steelsight() then
if second_sight_on then
self:_set_colour_grading( self._state_data._second_sight_colour_grading )
else
self:_set_colour_grading( self._state_data._sight_colour_grading )
end
end
end)
function PlayerStandard:_update_steelsight_color_grading()
local weapon = self._equipped_unit:base()
for index, part_id in ipairs(weapon._blueprint) do
local part_data = managers.weapon_factory:get_part_data_by_part_id_from_weapon(part_id, weapon._factory_id, weapon._blueprint)
if part_data.scope_effect then
if ( part_data.type and ( part_data.type == "sight" ) ) then
self._state_data._sight_colour_grading = part_data.scope_effect
elseif ( part_data.sub_type and ( part_data.sub_type == "second_sight" ) ) then
self._state_data._second_sight_colour_grading = part_data.scope_effect
end
end
end
end
function PlayerStandard:_set_colour_grading( colour_grading_value )
if not managers.environment_controller then return end
local ignore_user_setting = not not colour_grading_value
if ( colour_grading_value == false ) then
colour_grading_value = managers.environment_controller:game_default_color_grading()
end
managers.environment_controller:set_default_color_grading(colour_grading_value, ignore_user_setting)
managers.environment_controller:refresh_render_settings()
end
\ No newline at end of file
function AkimboWeaponBase:_create_second_gun(unit_name)
local factory_weapon = tweak_data.weapon.factory[self._factory_id]
local ids_unit_name = Idstring(factory_weapon.second_unit or factory_weapon.unit)
if not managers.dyn_resource:is_resource_ready(Idstring("unit"), ids_unit_name, DynamicResourceManager.DYN_RESOURCES_PACKAGE) then
managers.dyn_resource:load(Idstring("unit"), ids_unit_name, DynamicResourceManager.DYN_RESOURCES_PACKAGE, false)
end
local new_unit = World:spawn_unit(ids_unit_name, Vector3(), Rotation())
new_unit:base():set_factory_data(self._factory_id)
if self._cosmetics_id then
new_unit:base():set_cosmetics_data({
id = self._cosmetics_id,
quality = self._cosmetics_quality,
bonus = self._cosmetics_bonus
})
end
if self._blueprint then
new_unit:base():assemble_from_blueprint(self._factory_id, self._blueprint, nil, true)
elseif not unit_name then
new_unit:base():assemble(self._factory_id)
end
self._second_gun = new_unit
self._second_gun:base().SKIP_AMMO = true
self._second_gun:base().parent_weapon = self._unit
if self:fire_mode() == "auto" then