Skip to content

Commit 73f0c45

Browse files
Autoregister Improvements and Persist Lua Seats
Restructure and Refactor the Autoregister Library Wiremod pod/cam/egp controllers and ACF AIO controllers can now be linked to baseplates or crew for their lua generated seats to be used.
1 parent d18a252 commit 73f0c45

File tree

6 files changed

+185
-116
lines changed

6 files changed

+185
-116
lines changed

lua/acf/core/classes/entities/registration.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ Entities.AddUserArgumentType("String", function(Value, Specs)
102102
return Value
103103
end)
104104

105+
Entities.AddUserArgumentType("Boolean", function(Value, Specs)
106+
if not isbool(Value) then
107+
Value = Specs.Default or false
108+
end
109+
110+
return Value
111+
end)
112+
105113
Entities.AddUserArgumentType("SimpleClass", function(Value, Specs)
106114
if not isstring(Value) then
107115
Value = Specs.Default or "N/A"

lua/acf/core/utilities/util_sh.lua

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,4 +1083,42 @@ do -- Reload related
10831083
local BaseTime = ACF.BaseReload + (BulletData.CartMass * ACF.MassToTime) * MagSize + ((BulletData.PropLength + BulletData.ProjLength) * ACF.LengthToTime)
10841084
return BaseTime * ReloadMod, true
10851085
end
1086+
1087+
--- Generates a lua seat for a given entity
1088+
--- @param Entity any The entity to attach the seat to
1089+
--- @param Player any The owner of the entity
1090+
--- @param Pos any The position of the seat
1091+
--- @param Angle any The angle of the seat
1092+
--- @param Model any The model of the seat
1093+
--- @param Invisible boolean Whether the seat should be invisible to traces and
1094+
--- @return unknown Pod The generated seat
1095+
function ACF.GenerateLuaSeat(Entity, Player, Pos, Angle, Model, Invisible)
1096+
local Pod = ents.Create("prop_vehicle_prisoner_pod")
1097+
if IsValid(Pod) and IsValid(Player) then
1098+
Pod:SetAngles(Angle)
1099+
Pod:SetModel(Model)
1100+
Pod:SetPos(Pos)
1101+
Pod:Spawn()
1102+
Pod:SetParent(Entity)
1103+
1104+
Pod.Owner = Player
1105+
Pod:CPPISetOwner(Player)
1106+
1107+
Pod:SetKeyValue("vehiclescript", "scripts/vehicles/prisoner_pod.txt") -- I don't know what this does, but for good measure...
1108+
Pod:SetKeyValue("limitview", 0) -- Let the player look around
1109+
1110+
Pod.Vehicle = Entity
1111+
Pod.ACF = Pod.ACF or {}
1112+
1113+
if Invisible then
1114+
Pod:SetNoDraw(true) -- Don't render the seat
1115+
Pod:SetMoveType(MOVETYPE_NONE)
1116+
Pod:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE)
1117+
Pod.ACF.LegalChecks = false
1118+
end
1119+
return Pod
1120+
else
1121+
return nil
1122+
end
1123+
end
10861124
end

lua/acf/menu/items_cl/controllers.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ local function CreateMenu(Menu)
1717
Instructions:AddLabel("Gun -> To shoot guns")
1818
Instructions:AddLabel("Racks -> To shoot racks")
1919
Instructions:AddLabel("Baseplates -> To use baseplate seats or to read speed from the controller.")
20+
Instructions:AddLabel("Crew -> To use crew seats if you're doing multicrew stuff.")
2021
Instructions:AddLabel("Only these entities need to be linked. The rest will be automatically detected.")
2122
Instructions:AddLabel("If you don't want the AIO controller to control something, just don't link it.")
2223

lua/entities/acf_baseplate/init.lua

Lines changed: 66 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,68 @@ do -- Random timer crew stuff
4141
end
4242
end
4343

44+
--- Configures a lua seat generated by the crew entity
45+
--- Called when first creating the seat, or when reusing it from a dupe
46+
local function ConfigureLuaSeat(Entity, Pod)
47+
Entity.AlreadyHasSeat = true
48+
49+
Entity:SetUseType(SIMPLE_USE)
50+
Entity.Pod = Pod
51+
52+
local Found = constraint.Find( Entity, Pod, "NoCollide", 0, 0)
53+
if not Found then print("Creating NoCollide", constraint.NoCollide(Entity, Pod, 0, 0), Entity, Pod) else print("Found NoCollide", Found) end
54+
55+
hook.Add("PlayerEnteredVehicle", "ACFBaseplateSeatEnter" .. Entity:EntIndex(), function(Ply, Veh)
56+
if Veh == Pod then
57+
-- Ply:GodEnable() -- Remove this if aliases are removed?
58+
Ply:SetNoDraw(true)
59+
end
60+
end)
61+
62+
-- Make the player visible and vulnerable when they leave the seat
63+
hook.Add("PlayerLeaveVehicle", "ACFBaseplateSeatExit" .. Entity:EntIndex(), function(Ply, Veh)
64+
if Veh == Pod then
65+
-- Ply:GodDisable() -- Remove this if aliases are removed?
66+
Ply:SetNoDraw(false)
67+
end
68+
end)
69+
70+
-- Allow players to enter the seat externally by pressing use on a prop on the same contraption as the baseplate
71+
hook.Add("PlayerUse", "ACFBaseplateSeatEnterExternal" .. Entity:EntIndex(), function(Ply, Ent)
72+
if not Ply:KeyDown(IN_SPEED) then return end
73+
if IsValid(Ent) then
74+
local Contraption = Ent:GetContraption()
75+
if Contraption then
76+
local Base = Contraption.Base
77+
if Base == Entity and Pod:GetDriver() ~= Ply then
78+
Ply:EnterVehicle(Pod)
79+
end
80+
end
81+
end
82+
end)
83+
84+
-- Cleanup hooks and stuff when the baseplate is removed
85+
Entity:CallOnRemove("ACF_RemoveVehiclePod", function(Ent)
86+
hook.Remove("PlayerEnteredVehicle", "ACFBaseplateSeatEnter" .. Entity:EntIndex())
87+
hook.Remove("PlayerLeaveVehicle", "ACFBaseplateSeatExit" .. Entity:EntIndex())
88+
hook.Remove( "PlayerUse", "ACFBaseplateSeatEnterExternal" .. Entity:EntIndex())
89+
90+
local Owner = Entity:CPPIGetOwner()
91+
if IsValid(Owner) then Owner:GodDisable() end
92+
93+
SafeRemoveEntity(Ent.Pod)
94+
95+
if Entity.Crews and next(Entity.Crews) then
96+
for Crew in pairs(Entity.Crews) do
97+
if IsValid(Crew) then Entity:Unlink(Crew) end
98+
end
99+
end
100+
end)
101+
102+
WireLib.TriggerOutput(Entity, "Vehicles", {Pod})
103+
end
104+
105+
44106
-- Might be a good idea to put this somewhere else later
45107
ACF.ActiveBaseplatesTable = ACF.ActiveBaseplatesTable or {}
46108

@@ -71,77 +133,10 @@ function ENT:ACF_PostSpawn(_, _, _, ClientData)
71133
WireLib.TriggerOutput(self, "Entity", self)
72134

73135
-- Add seat support for baseplates
74-
local Pod = ents.Create("prop_vehicle_prisoner_pod")
75136
local Owner = self:CPPIGetOwner()
76-
if IsValid(Pod) and IsValid(Owner) then
77-
self:SetUseType(SIMPLE_USE) -- Avoid running activator function constantly...
78-
self.Pod = Pod
79-
Pod:SetAngles(self:GetAngles())
80-
Pod:SetModel("models/vehicles/pilot_seat.mdl")
81-
Pod:SetPos(self:GetPos())
82-
Pod:Spawn()
83-
Pod:SetParent(self)
84-
Pod.Owner = Owner
85-
Pod:SetKeyValue("vehiclescript", "scripts/vehicles/prisoner_pod.txt") -- I don't know what this does, but for good measure...
86-
Pod:SetKeyValue("limitview", 0) -- Let the player look around
87-
Pod:SetNoDraw(true) -- Don't render the seat
88-
Pod:SetMoveType(MOVETYPE_NONE)
89-
Pod:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE)
90-
Pod.Vehicle = self
91-
Pod.ACF = Pod.ACF or {}
92-
Pod.ACF.LegalSeat = true
93-
Pod.DoNotDuplicate = true -- Don't duplicate cause baseplate will generate one on spawn
94-
Pod.ACF_InvisibleToBallistics = true -- Baseplate seat
95-
96-
-- Make the player invisible and invincible while in the seat
97-
hook.Add("PlayerEnteredVehicle", "ACFBaseplateSeatEnter" .. self:EntIndex(), function(Ply, Veh)
98-
if Veh == Pod then
99-
-- Ply:GodEnable() -- Remove this if aliases are removed?
100-
Ply:SetNoDraw(true)
101-
end
102-
end)
103-
104-
-- Make the player visible and vulnerable when they leave the seat
105-
hook.Add("PlayerLeaveVehicle", "ACFBaseplateSeatExit" .. self:EntIndex(), function(Ply, Veh)
106-
if Veh == Pod then
107-
-- Ply:GodDisable() -- Remove this if aliases are removed?
108-
Ply:SetNoDraw(false)
109-
end
110-
end)
111-
112-
-- Allow players to enter the seat externally by pressing use on a prop on the same contraption as the baseplate
113-
hook.Add("PlayerUse", "ACFBaseplateSeatEnterExternal" .. self:EntIndex(), function(Ply, Ent)
114-
if not Ply:KeyDown(IN_SPEED) then return end
115-
if IsValid(Ent) then
116-
local Contraption = Ent:GetContraption()
117-
if Contraption then
118-
local Base = Contraption.Base
119-
if Base == self and Pod:GetDriver() ~= Ply then
120-
Ply:EnterVehicle(Pod)
121-
end
122-
end
123-
end
124-
end)
125-
126-
-- Cleanup hooks and stuff when the baseplate is removed
127-
self:CallOnRemove("ACF_RemoveVehiclePod", function(Ent)
128-
hook.Remove("PlayerEnteredVehicle", "ACFBaseplateSeatEnter" .. self:EntIndex())
129-
hook.Remove("PlayerLeaveVehicle", "ACFBaseplateSeatExit" .. self:EntIndex())
130-
hook.Remove( "PlayerUse", "ACFBaseplateSeatEnterExternal" .. self:EntIndex())
131-
132-
local Owner = self:CPPIGetOwner()
133-
if IsValid(Owner) then Owner:GodDisable() end
134-
135-
SafeRemoveEntity(Ent.Pod)
136-
137-
if self.Crews and next(self.Crews) then
138-
for Crew in pairs(self.Crews) do
139-
if IsValid(Crew) then self:Unlink(Crew) end
140-
end
141-
end
142-
end)
143-
144-
WireLib.TriggerOutput(self, "Vehicles", {Pod})
137+
if not self.AlreadyHasSeat then
138+
local Pod = ACF.GenerateLuaSeat(self, Owner, self:GetPos(), self:GetAngles(), self:GetModel(), true)
139+
if IsValid(Pod) then ConfigureLuaSeat(self, Pod) end
145140
end
146141

147142
ACF.AugmentedTimer(function(cfg) self:UpdateAccuracyMod(cfg) end, function() return IsValid(self) end, nil, {MinTime = 0.5, MaxTime = 1})
@@ -156,7 +151,7 @@ function ENT:Use(Activator)
156151
end
157152

158153
do
159-
-- Maintain a record in the contraption of its current crew
154+
-- Maintain a record in the contraption of its current baseplate
160155
hook.Add("cfw.contraption.entityAdded", "ACF_CFWBaseIndex", function(contraption, ent)
161156
if ent:GetClass() == "acf_baseplate" then
162157
contraption.Base = ent

lua/entities/acf_controller/init.lua

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -669,31 +669,38 @@ local function OnActiveChanged(Controller, Ply, Active)
669669
net.Send(Ply)
670670
end
671671

672+
local function OnLinkedSeat(Controller, Target)
673+
hook.Add("PlayerEnteredVehicle", "ACFControllerSeatEnter" .. Controller:EntIndex(), function(Ply, Veh)
674+
if Veh == Target then OnActiveChanged(Controller, Ply, true) end
675+
end)
676+
677+
hook.Add("PlayerLeaveVehicle", "ACFControllerSeatExit" .. Controller:EntIndex(), function(Ply, Veh)
678+
if Veh == Target then OnActiveChanged(Controller, Ply, false) end
679+
end)
680+
681+
-- Remove the hooks when the controller is removed
682+
Controller:CallOnRemove("ACFRemoveController", function(Ent)
683+
hook.Remove("PlayerEnteredVehicle", "ACFControllerSeatEnter" .. Ent:EntIndex())
684+
hook.Remove("PlayerLeaveVehicle", "ACFControllerSeatExit" .. Ent:EntIndex())
685+
end)
686+
end
687+
688+
local function OnUnlinkedSeat(Controller)
689+
-- Remove the hooks when the seat is unlinked
690+
hook.Remove("PlayerEnteredVehicle", "ACFControllerSeatEnter" .. Controller:EntIndex())
691+
hook.Remove("PlayerLeaveVehicle", "ACFControllerSeatExit" .. Controller:EntIndex())
692+
end
693+
672694
-- Using this to auto generate the link/unlink functions
673695
local LinkConfigs = {
674696
prop_vehicle_prisoner_pod = {
675697
Field = "Seat",
676698
Single = true,
677699
OnLinked = function(Controller, Target)
678-
-- Register hooks when a new seat is linked
679-
hook.Add("PlayerEnteredVehicle", "ACFControllerSeatEnter" .. Controller:EntIndex(), function(Ply, Veh)
680-
if Veh == Target then OnActiveChanged(Controller, Ply, true) end
681-
end)
682-
683-
hook.Add("PlayerLeaveVehicle", "ACFControllerSeatExit" .. Controller:EntIndex(), function(Ply, Veh)
684-
if Veh == Target then OnActiveChanged(Controller, Ply, false) end
685-
end)
686-
687-
-- Remove the hooks when the controller is removed
688-
Controller:CallOnRemove("ACFRemoveController", function(Ent)
689-
hook.Remove("PlayerEnteredVehicle", "ACFControllerSeatEnter" .. Ent:EntIndex())
690-
hook.Remove("PlayerLeaveVehicle", "ACFControllerSeatExit" .. Ent:EntIndex())
691-
end)
700+
OnLinkedSeat(Controller, Target)
692701
end,
693702
OnUnlinked = function(Controller, _)
694-
-- Unregister hooks when the seat is unlinked
695-
hook.Remove("PlayerEnteredVehicle", "ACFControllerSeatEnter" .. Controller:EntIndex())
696-
hook.Remove("PlayerLeaveVehicle", "ACFControllerSeatExit" .. Controller:EntIndex())
703+
OnUnlinkedSeat(Controller)
697704
end,
698705
},
699706
acf_gearbox = {
@@ -716,7 +723,23 @@ local LinkConfigs = {
716723
},
717724
acf_baseplate = {
718725
Field = "Baseplate",
719-
Single = true
726+
Single = true,
727+
OnLinked = function(Controller, Target)
728+
if IsValid(Target.Pod) then Controller:Link(Target.Pod) end
729+
end,
730+
OnUnlinked = function(Controller, Target)
731+
if IsValid(Target.Pod) then Controller:Unlink(Target.Pod) end
732+
end
733+
},
734+
acf_crew = {
735+
Field = "Crew",
736+
Single = true,
737+
OnLinked = function(Controller, Target)
738+
if IsValid(Target.Pod) then Controller:Link(Target.Pod) end
739+
end,
740+
OnUnlinked = function(Controller, Target)
741+
if IsValid(Target.Pod) then Controller:Unlink(Target.Pod) end
742+
end
720743
},
721744
acf_rack = {
722745
Field = "Racks",
@@ -742,6 +765,7 @@ for Class, Data in pairs(LinkConfigs) do
742765
if Single then Controller[Field] = Target
743766
else Controller[Field][Target] = true end
744767

768+
-- Alot of things initialize in the first tick, so wait for them to be available
745769
timer.Simple(0, function()
746770
if OnLinked then OnLinked(Controller, Target) end
747771
end)

0 commit comments

Comments
 (0)