mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
253 lines
5.9 KiB
Lua
253 lines
5.9 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
|
|
include( "duplicator/transport.lua" )
|
|
include( "duplicator/arming.lua" )
|
|
|
|
if ( CLIENT ) then
|
|
|
|
include( "duplicator/icon.lua" )
|
|
|
|
else
|
|
|
|
AddCSLuaFile( "duplicator/arming.lua" )
|
|
AddCSLuaFile( "duplicator/transport.lua" )
|
|
AddCSLuaFile( "duplicator/icon.lua" )
|
|
util.AddNetworkString( "CopiedDupe" )
|
|
|
|
end
|
|
|
|
TOOL.Category = "Construction"
|
|
TOOL.Name = "#tool.duplicator.name"
|
|
|
|
TOOL.Information = {
|
|
{ name = "left" },
|
|
{ name = "right" }
|
|
}
|
|
|
|
cleanup.Register( "duplicates" )
|
|
|
|
--
|
|
-- PASTE
|
|
--
|
|
function TOOL:LeftClick( trace )
|
|
|
|
if ( CLIENT ) then return true end
|
|
|
|
--
|
|
-- Get the copied dupe. We store it on the player so it will still exist if they die and respawn.
|
|
--
|
|
local dupe = self:GetOwner().CurrentDupe
|
|
if ( !dupe ) then return false end
|
|
|
|
--
|
|
-- We want to spawn it flush on thr ground. So get the point that we hit
|
|
-- and take away the mins.z of the bounding box of the dupe.
|
|
--
|
|
local SpawnCenter = trace.HitPos
|
|
SpawnCenter.z = SpawnCenter.z - dupe.Mins.z
|
|
|
|
--
|
|
-- Spawn it rotated with the player - but not pitch.
|
|
--
|
|
local SpawnAngle = self:GetOwner():EyeAngles()
|
|
SpawnAngle.pitch = 0
|
|
SpawnAngle.roll = 0
|
|
|
|
--
|
|
-- Spawn them all at our chosen positions
|
|
--
|
|
duplicator.SetLocalPos( SpawnCenter )
|
|
duplicator.SetLocalAng( SpawnAngle )
|
|
|
|
DisablePropCreateEffect = true
|
|
|
|
local Ents = duplicator.Paste( self:GetOwner(), dupe.Entities, dupe.Constraints )
|
|
|
|
DisablePropCreateEffect = nil
|
|
|
|
duplicator.SetLocalPos( vector_origin )
|
|
duplicator.SetLocalAng( angle_zero )
|
|
|
|
--
|
|
-- Create one undo for the whole creation
|
|
--
|
|
undo.Create( "Duplicator" )
|
|
|
|
for k, ent in pairs( Ents ) do
|
|
undo.AddEntity( ent )
|
|
end
|
|
|
|
for k, ent in pairs( Ents ) do
|
|
self:GetOwner():AddCleanup( "duplicates", ent )
|
|
end
|
|
|
|
undo.SetPlayer( self:GetOwner() )
|
|
|
|
undo.Finish()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
--
|
|
-- Copy
|
|
--
|
|
function TOOL:RightClick( trace )
|
|
|
|
if ( !IsValid( trace.Entity ) ) then return false end
|
|
if ( CLIENT ) then return true end
|
|
|
|
--
|
|
-- Set the position to our local position (so we can paste relative to our `hold`)
|
|
--
|
|
duplicator.SetLocalPos( trace.HitPos )
|
|
duplicator.SetLocalAng( Angle( 0, self:GetOwner():EyeAngles().yaw, 0 ) )
|
|
|
|
local Dupe = duplicator.Copy( trace.Entity )
|
|
|
|
duplicator.SetLocalPos( vector_origin )
|
|
duplicator.SetLocalAng( angle_zero )
|
|
|
|
if ( !Dupe ) then return false end
|
|
|
|
--
|
|
-- Tell the clientside that they're holding something new
|
|
--
|
|
net.Start( "CopiedDupe" )
|
|
net.WriteUInt( 1, 1 )
|
|
net.WriteVector( Dupe.Mins )
|
|
net.WriteVector( Dupe.Maxs )
|
|
net.WriteString( "Unsaved dupe" )
|
|
net.WriteUInt( table.Count( Dupe.Entities ), 24 )
|
|
net.WriteUInt( 0, 16 )
|
|
net.Send( self:GetOwner() )
|
|
|
|
--
|
|
-- Store the dupe on the player
|
|
--
|
|
self:GetOwner().CurrentDupeArmed = false
|
|
self:GetOwner().CurrentDupe = Dupe
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
if ( CLIENT ) then
|
|
|
|
--
|
|
-- Builds the context menu
|
|
--
|
|
function TOOL.BuildCPanel( CPanel, tool )
|
|
|
|
CPanel:ClearControls()
|
|
|
|
CPanel:AddControl( "Header", { Description = "#tool.duplicator.desc" } )
|
|
|
|
CPanel:AddControl( "Button", { Text = "#tool.duplicator.showsaves", Command = "dupe_show" } )
|
|
|
|
if ( !tool && IsValid( LocalPlayer() ) ) then tool = LocalPlayer():GetTool( "duplicator" ) end
|
|
if ( !tool || !tool.CurrentDupeName ) then return end
|
|
|
|
local info = "Name: " .. tool.CurrentDupeName
|
|
info = info .. "\nEntities: " .. tool.CurrentDupeEntCount
|
|
|
|
CPanel:AddControl( "Label", { Text = info } )
|
|
|
|
if ( tool.CurrentDupeWSIDs && #tool.CurrentDupeWSIDs > 0 ) then
|
|
CPanel:AddControl( "Label", { Text = "Required workshop content:" } )
|
|
for _, wsid in pairs( tool.CurrentDupeWSIDs ) do
|
|
local subbed = ""
|
|
if ( steamworks.IsSubscribed( wsid ) ) then subbed = " (Subscribed)" end
|
|
local b = CPanel:AddControl( "Button", { Text = wsid .. subbed } )
|
|
b.DoClick = function( s, ... ) steamworks.ViewFile( wsid ) end
|
|
steamworks.FileInfo( wsid, function( result )
|
|
if ( !IsValid( b ) ) then return end
|
|
b:SetText( result.title .. subbed )
|
|
end )
|
|
end
|
|
end
|
|
|
|
if ( tool.CurrentDupeCanSave ) then
|
|
local b = CPanel:AddControl( "Button", { Text = "#dupes.savedupe", Command = "dupe_save" } )
|
|
hook.Add( "DupeSaveUnavailable", b, function() b:Remove() end )
|
|
end
|
|
|
|
end
|
|
|
|
function TOOL:RefreshCPanel()
|
|
local CPanel = controlpanel.Get( "duplicator" )
|
|
if ( !CPanel ) then return end
|
|
|
|
self.BuildCPanel( CPanel, self )
|
|
end
|
|
|
|
--
|
|
-- Received by the client to alert us that we have something copied
|
|
-- This allows us to enable the save button in the spawn menu
|
|
--
|
|
net.Receive( "CopiedDupe", function( len, client )
|
|
|
|
local canSave = net.ReadUInt( 1 )
|
|
if ( canSave == 1 ) then
|
|
hook.Run( "DupeSaveAvailable" )
|
|
else
|
|
hook.Run( "DupeSaveUnavailable" )
|
|
end
|
|
|
|
local ply = LocalPlayer()
|
|
if ( !IsValid( ply ) || !ply.GetTool ) then return end
|
|
|
|
local tool = ply:GetTool( "duplicator" )
|
|
if ( !tool ) then return end
|
|
|
|
tool.CurrentDupeCanSave = canSave == 1
|
|
tool.CurrentDupeMins = net.ReadVector()
|
|
tool.CurrentDupeMaxs = net.ReadVector()
|
|
|
|
tool.CurrentDupeName = net.ReadString()
|
|
tool.CurrentDupeEntCount = net.ReadUInt( 24 )
|
|
|
|
local workshopCount = net.ReadUInt( 16 )
|
|
local addons = {}
|
|
for i = 1, workshopCount do
|
|
table.insert( addons, net.ReadString() )
|
|
end
|
|
tool.CurrentDupeWSIDs = addons
|
|
|
|
tool:RefreshCPanel()
|
|
|
|
end )
|
|
|
|
-- This is not perfect, but let the player see roughly the outline of what they are about to paste
|
|
function TOOL:DrawHUD()
|
|
|
|
local ply = LocalPlayer()
|
|
if ( !IsValid( ply ) || !self.CurrentDupeMins || !self.CurrentDupeMaxs ) then return end
|
|
|
|
local tr = LocalPlayer():GetEyeTrace()
|
|
|
|
local pos = tr.HitPos
|
|
pos.z = pos.z - self.CurrentDupeMins.z
|
|
|
|
local ang = LocalPlayer():GetAngles()
|
|
ang.p = 0
|
|
ang.r = 0
|
|
|
|
cam.Start3D()
|
|
render.DrawWireframeBox( pos, ang, self.CurrentDupeMins, self.CurrentDupeMaxs )
|
|
cam.End3D()
|
|
|
|
end
|
|
|
|
end
|