dobrograd-13-06-2022/garrysmod/addons/feature-wire/lua/entities/gmod_wire_eyepod.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

359 lines
9.5 KiB
Lua

AddCSLuaFile()
DEFINE_BASECLASS( "base_wire_entity" )
ENT.PrintName = "Wire Eye Pod"
ENT.Purpose = "To control the player's view in a pod and output their mouse movements"
ENT.WireDebugName = "Eye Pod"
if CLIENT then
local enabled = false
local rotate90 = false
local freezePitch = true
local freezeYaw = true
local previousEnabled = false
usermessage.Hook("UpdateEyePodState", function(um)
if not um then return end
local eyeAng = um:ReadAngle()
enabled = um:ReadBool()
rotate90 = um:ReadBool()
freezePitch = um:ReadBool() and eyeAng.p
freezeYaw = um:ReadBool() and eyeAng.y
end)
hook.Add("CreateMove", "WireEyePodEyeControl", function(ucmd)
if enabled then
currentAng = ucmd:GetViewAngles()
if freezePitch then
currentAng.p = freezePitch
end
if freezeYaw then
currentAng.y = freezeYaw
end
currentAng.r = 0
ucmd:SetViewAngles(currentAng)
previousEnabled = true
elseif previousEnabled then
if rotate90 then
ucmd:SetViewAngles(Angle(0,90,0))
else
ucmd:SetViewAngles(Angle(0,0,0))
end
previousEnabled = false
end
end)
return -- No more client
end
-- Server
function ENT:Initialize()
self:PhysicsInit(SOLID_VPHYSICS)
self:SetMoveType(MOVETYPE_VPHYSICS)
self:SetSolid(SOLID_VPHYSICS)
self:SetCollisionGroup(COLLISION_GROUP_WORLD)
self:DrawShadow(false)
-- Set wire I/O
self.Inputs = WireLib.CreateSpecialInputs(self, { "Enable", "SetPitch", "SetYaw", "SetViewAngle", "UnfreezePitch", "UnfreezeYaw" }, { "NORMAL", "NORMAL", "NORMAL", "ANGLE", "NORMAL", "NORMAL" })
self.Outputs = WireLib.CreateSpecialOutputs(self, { "X", "Y", "XY" }, { "NORMAL", "NORMAL", "VECTOR2" })
-- Initialize values
self.driver = nil
self.X = 0
self.Y = 0
self.enabled = false
self.pod = nil
self.eyeAng = Angle(0, 0, 0)
self.rotate90 = false
self.DefaultToZero = 1
self.ShowRateOfChange = 0
self.LastUpdateTime = CurTime()
-- clamps
self.ClampXMin = 0
self.ClampXMax = 0
self.ClampYMin = 0
self.ClampYMax = 0
self.ClampX = 0
self.ClampY = 0
self.freezePitch = true
self.freezeYaw = true
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
self:ColorByLinkStatus(self.LINK_STATUS_UNLINKED)
end
function ENT:UpdateOverlay()
self:SetOverlayText(
string.format( "Default to Zero: %s\nCumulative: %s\nMin: %s,%s\nMax: %s,%s\n%s\n\nActivated: %s%s",
(self.DefaultToZero == 1) and "Yes" or "No",
(self.ShowRateOfChange == 0) and "Yes" or "No",
self.ClampXMin, self.ClampYMin,
self.ClampXMax, self.ClampYMax,
IsValid( self.pod ) and "Linked to: " .. self.pod:GetModel() or "Not linked",
self.enabled and "Yes" or "No",
(self.enabled == true and IsValid( self.driver )) and "\nIn use by: " .. self.driver:Nick() or ""
)
)
end
function ENT:Setup(DefaultToZero, RateOfChange, ClampXMin, ClampXMax, ClampYMin, ClampYMax, ClampX, ClampY)
self.DefaultToZero = DefaultToZero
self.ShowRateOfChange = RateOfChange
self.ClampXMin = ClampXMin
self.ClampXMax = ClampXMax
self.ClampYMin = ClampYMin
self.ClampYMax = ClampYMax
self.ClampX = ClampX
self.ClampY = ClampY
self:UpdateOverlay()
end
local Rotate90ModelList = {
["models/props_c17/furniturechair001a.mdl"] = true,
["models/airboat.mdl"] = true,
["models/props_c17/chair_office01a.mdl"] = true,
["models/nova/chair_office02.mdl"] = true,
["models/nova/chair_office01.mdl"] = true,
["models/props_combine/breenchair.mdl"] = true,
["models/nova/chair_wood01.mdl"] = true,
["models/nova/airboat_seat.mdl"] = true,
["models/nova/chair_plastic01.mdl"] = true,
["models/nova/jeep_seat.mdl"] = true,
["models/props_phx/carseat.mdl"] = true,
["models/props_phx/carseat2.mdl"] = true,
["models/props_phx/carseat3.mdl"] = true,
["models/buggy.mdl"] = true,
["models/vehicle.mdl"] = true
}
-- Old function alias
function ENT:PodLink(vehicle) return self:LinkEnt(vehicle) end
function ENT:LinkEnt(vehicle)
vehicle = WireLib.GetClosestRealVehicle(vehicle,self:GetPos(),self:GetPlayer())
if not IsValid(vehicle) or not vehicle:IsVehicle() then
if IsValid(self.pod) then
self.pod.AttachedWireEyePod = nil
end
self.pod = nil
self:UpdateOverlay()
return false, "Must link to a vehicle"
end
self.pod = vehicle
vehicle:CallOnRemove("wire_eyepod_remove",function()
self:UnlinkEnt(vehicle)
end)
self.rotate90 = false
self.eyeAng = Angle(0, 0, 0)
if IsValid(vehicle) and vehicle:IsVehicle() then
if Rotate90ModelList[string.lower(vehicle:GetModel())] then
self.rotate90 = true
self.eyeAng = Angle(0, 90, 0)
end
end
vehicle.AttachedWireEyePod = self
self:UpdateOverlay()
WireLib.SendMarks(self,{vehicle})
self:ColorByLinkStatus(IsValid(vehicle) and self.LINK_STATUS_LINKED or self.LINK_STATUS_UNLINKED)
return true
end
function ENT:UnlinkEnt()
if IsValid(self.pod) then
self.pod.AttachedWireEyePod = nil
self.pod:RemoveCallOnRemove("wire_eyepod_remove")
end
self.pod = nil
if IsValid(self.driver) then
self:updateEyePodState(false)
self.driver = nil
end
WireLib.SendMarks(self,{})
self:UpdateOverlay()
self:ColorByLinkStatus(self.LINK_STATUS_UNLINKED)
return true
end
function ENT:updateEyePodState(enabled)
self:ColorByLinkStatus(enabled and self.LINK_STATUS_ACTIVE or self.LINK_STATUS_LINKED)
umsg.Start("UpdateEyePodState", self.driver)
umsg.Angle(self.eyeAng)
umsg.Bool(enabled)
umsg.Bool(self.rotate90)
umsg.Bool(self.freezePitch)
umsg.Bool(self.freezeYaw)
umsg.End()
end
hook.Add("PlayerEnteredVehicle","gmod_wire_eyepod_entervehicle",function(ply,vehicle)
local eyepod = vehicle.AttachedWireEyePod
if eyepod ~= nil then
if IsValid(eyepod) then
eyepod.driver = vehicle:GetDriver()
eyepod:updateEyePodState(eyepod.enabled)
eyepod:UpdateOverlay()
else
vehicle.AttachedWireEyePod = nil
end
end
end)
hook.Add("PlayerLeaveVehicle","gmod_wire_eyepod_leavevehicle",function(ply,vehicle)
local eyepod = vehicle.AttachedWireEyePod
if eyepod ~= nil then
if IsValid(eyepod) then
eyepod:updateEyePodState(false)
eyepod.driver = nil
if (eyepod.X ~= 0 or eyepod.Y ~= 0) and eyepod.DefaultToZero == 1 then
eyepod.X = 0
eyepod.Y = 0
WireLib.TriggerOutput( eyepod, "X", 0 )
WireLib.TriggerOutput( eyepod, "Y", 0 )
WireLib.TriggerOutput( eyepod, "XY", {0,0} )
end
eyepod:UpdateOverlay()
else
vehicle.AttachedWireEyePod = nil
end
end
end)
function ENT:OnRemove()
self:UnlinkEnt()
end
local function AngNorm(Ang)
return (Ang + 180) % 360 - 180
end
local function AngNorm90(Ang)
return (Ang + 90) % 180 - 90
end
function ENT:TriggerInput(iname, value)
-- Change variables to reflect input
if iname == "Enable" then
self.enabled = value ~= 0
if self.enabled == false and self.DefaultToZero == 1 and (self.X ~= 0 or self.Y ~= 0) then
self.X = 0
self.Y = 0
WireLib.TriggerOutput( self, "X", 0 )
WireLib.TriggerOutput( self, "Y", 0 )
WireLib.TriggerOutput( self, "XY", {0,0} )
end
self:UpdateOverlay()
elseif iname == "SetPitch" then
self.eyeAng = Angle(AngNorm90(value), self.eyeAng.y, self.eyeAng.r)
elseif iname == "SetYaw" then
if self.rotate90 == true then
self.eyeAng = Angle(AngNorm90(self.eyeAng.p), AngNorm(value+90), self.eyeAng.r)
else
self.eyeAng = Angle(AngNorm90(self.eyeAng.p), AngNorm(value), self.eyeAng.r)
end
elseif iname == "SetViewAngle" then
if self.rotate90 == true then
self.eyeAng = Angle(AngNorm90(value.p), AngNorm(value.y+90), 0)
else
self.eyeAng = Angle(AngNorm90(value.p), AngNorm(value.y), 0)
end
elseif iname == "UnfreezePitch" then
self.freezePitch = value == 0
elseif iname == "UnfreezeYaw" then
self.freezeYaw = value == 0
end
if IsValid(self.pod) and IsValid(self.driver) then
self:updateEyePodState(self.enabled)
end
end
hook.Add("SetupMove", "WireEyePodMouseControl", function(ply, movedata)
--is the player in a vehicle?
if not ply then return end
if not ply:InVehicle() then return end
local vehicle = ply:GetVehicle()
if not IsValid(vehicle) then return end
--get the EyePod
local eyePod = vehicle.AttachedWireEyePod
--is the vehicle linked to an EyePod?
if not IsValid(eyePod) then return end
if eyePod.enabled then
local cmd = ply:GetCurrentCommand()
local oldX = eyePod.X
local oldY = eyePod.Y
--reset the output so it is not cumualative if you want the rate of change
if eyePod.ShowRateOfChange == 1 then
eyePod.X = 0
eyePod.Y = 0
end
--update the cumualative output
eyePod.X = cmd:GetMouseX()/10 + eyePod.X
eyePod.Y = -cmd:GetMouseY()/10 + eyePod.Y
--clamp the output
if eyePod.ClampX == 1 then
eyePod.X = math.Clamp(eyePod.X, eyePod.ClampXMin, eyePod.ClampXMax)
end
if eyePod.ClampY == 1 then
eyePod.Y = math.Clamp(eyePod.Y, eyePod.ClampYMin, eyePod.ClampYMax)
end
if oldX ~= eyePod.X or oldY ~= eyePod.Y then
-- Update outputs
WireLib.TriggerOutput(eyePod, "X", eyePod.X)
WireLib.TriggerOutput(eyePod, "Y", eyePod.Y)
local XY_Vec = {eyePod.X, eyePod.Y}
WireLib.TriggerOutput(eyePod, "XY", XY_Vec)
end
--reset the mouse
cmd:SetMouseX(0)
cmd:SetMouseY(0)
end
end)
-- Advanced Duplicator Support
function ENT:BuildDupeInfo()
local info = BaseClass.BuildDupeInfo(self) or {}
if IsValid(self.pod) then
info.pod = self.pod:EntIndex()
end
return info
end
function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID)
BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID)
self:PodLink(GetEntByID(info.pod))
end
duplicator.RegisterEntityClass("gmod_wire_eyepod", WireLib.MakeWireEnt, "Data", "DefaultToZero", "ShowRateOfChange" , "ClampXMin" , "ClampXMax" , "ClampYMin" , "ClampYMax" , "ClampX", "ClampY")