Some gmod stuff showcase made by me. :::spoiler Contacts - Discord: chelog#8888 - Steam: https://steamcommunity.com/id/chelog - Forum: https://forum.facepunch.com/u/chelog ::: # Game :::spoiler Unity-like 3d editor with gizmos {%youtube q9p_IBcpmCg %} {%youtube A6YlGB0_4Ak %} ::: :::spoiler Menus and interaction with some entities {%youtube QrF0Bn5Mkvs %} ::: :::spoiler First person camera and animation features {%youtube yiiSDE0qLMQ %} ::: :::spoiler Some roleplaying tools {%youtube z4GYJcvTzCw %} ::: # CI and such stuff My little master-lib for gmod development: octolib. It's powered by node (TypeScript and sockets) as well as Lua part (GMod addon with utility functions and some systems) integrated as git submodule. We have Docker containerized servers which pull from master branch on startup so I made this kind of framework It's pretty robust, so there's some little features which are easy to show: :::spoiler Lua runner > Simple system to run and test lua code without launching the game. Love to use it for backend development on my laptop to save battery ![](https://i.imgur.com/zp4ROKq.png) {%youtube QxGkUgMT8Fw %} ::: :::spoiler Test framework > Automated tests to check new changes didn't break anything existing. It's mainly used in GitLab CI after committing to dev branch. Catches runtime errors and of course has timeouts ```lua local ent local entityTests = { { name = 'Create entity', run = function(finish) ent = ents.Create('prop_physics') ent:SetModel('models/chairs/armchair.mdl') ent:SetPos(Vector(0,0,30)) ent:Spawn() if not IsValid(ent) then return finish('Entity is not valid') end finish() end, }, { name = 'Import inventory', run = function(finish) ent:ImportInventory({ cont = { name = 'Container', volume = 50 }}) finish() end, }, { name = 'Add items', run = function(finish) ent:AddItem('money', 1000) ent:AddItem('souvenir', { name = 'OctoRP', volume = 40 }) finish() end, }, { name = 'Check given items', run = function(finish) if ent:HasItem('money') ~= 1000 then return finish('Money amount mismatch') end if ent:FindItem({ class = 'souvenir' }):GetData('volume') ~= 40 then return finish('Item volume mismatch') end if ent:FindItem({ class = 'souvenir' }):GetData('name') ~= 'OctoRP' then return finish('Item name mismatch') end finish() end, }, { name = 'Remove entity', run = function(finish) ent:GetInventory():Remove() if ent:GetInventory() ~= nil then return finish('Inventory not removed') end ent:Remove() finish() end, }, } octolib.registerTests({ name = 'octoinv', children = { { name = 'Entities', children = entityTests, }, }, }) ``` ![](https://i.imgur.com/n2TLoIN.png) ![](https://i.imgur.com/A4G4qCR.png) ![](https://i.imgur.com/TbpKb1v.png) :::