Creating New Content - TankNut/gmod-voxel GitHub Wiki

Workshop support

Because of a recent change to the whitelist, we can upload models straight to the workshop!

The game will automatically load any models it finds in data_static/voxel/ and data/voxel/ with the latter overriding the former. This means that players can potentially save their models to the server and have it replace built-in ones, write your addons with the assumption that things like attachments aren't guaranteed. You've been warned.

Entities

For entities the creation process is fairly straightforward, simply basing your entity off of either voxel_base_static for models that won't ever change or voxel_base_dynamic for models that might change after creation.

Any physics changes should be applied in ENT:SetupPhysics() as such:

DEFINE_BASECLASS("voxel_base_xxx")

function ENT:SetupPhysics()
    BaseClass.SetupPhysics(self)

    -- Your code here
end

voxel_base_static

ENT.Voxel = {
	Model = "builtin/directions",
	Scale = 1,

	Offset = Vector()
}

voxel_base_dynamic

local ent = ents.Create("your_class_here")

-- ...

ent:SetVoxelModel("builtin/directions")
ent:SetVoxelScale(1)

Weapons

For weapons there are two bases, voxel_swep_base for the most barebones base available and spades_base for a fully fledged weapon base with a number of bells and whistles.

voxel_swep_base

Edit SWEP.Voxel with your model and view/world offsets, otherwise you can use it as normal.

spades_base

Look at any of the existing weapons as well as weapons/spades_base/shared.lua for in-depth documentation on the various fields available

effects

Because we don't use traditional models, most muzzle and tracer effects won't work out of the box. For general use there are replacements included which are recreations of Half Life 2's standard muzzle flashes and tracers designed to work with the voxel models.

To create your own compatible effects, simply configure your effect with the following code:

function EFFECT:IsDrawingVM()
	return self.Ent:IsCarriedByLocalPlayer() and not LocalPlayer():ShouldDrawLocalPlayer()
end

function EFFECT:GetStartPos(ent)
	if not ent.VoxelModel then
		return
	end

	local pos, ang = ent.VoxelModel:GetAttachment("attachment")

	if self:IsDrawingVM() then
		pos, ang = LocalToWorld(pos * ent.Voxel.Scale, ang, ent:GetViewPos(true))

		return translatefov(ent, pos), ang
	else
		return LocalToWorld(pos * ent.Voxel.Scale, ang, ent:GetWorldPos())
	end
end