34 Commits

Author SHA1 Message Date
86dc0d9b5f copium 3
All checks were successful
CI Test / fix-permission (push) Successful in 39s
CI Test / gettools (push) Successful in 2m57s
2026-02-09 12:01:30 +07:00
a8185d22d1 copium 2
Some checks failed
CI Test / gettools (push) Failing after 48s
2026-02-09 11:57:27 +07:00
a6cd066c20 copium 1
Some checks failed
CI Test / gettools (push) Failing after 1m6s
2026-02-09 11:48:04 +07:00
2132f61c25 hopium 5
Some checks failed
CI Test / gettools (push) Failing after 1m23s
2026-02-09 11:38:12 +07:00
b231f89a01 test new 12
Some checks failed
CI Test / gettools (push) Failing after 48s
2026-02-09 11:27:16 +07:00
315ae23928 hopium 4
Some checks failed
CI Test / gettools (push) Failing after 1m14s
2026-02-09 11:13:54 +07:00
178b98cbc4 hopium 3
Some checks failed
CI Test / gettools (push) Failing after 1m16s
2026-02-09 11:09:50 +07:00
a967329768 hopium 2
Some checks failed
CI Test / gettools (push) Failing after 50s
2026-02-09 11:03:42 +07:00
044d52e839 test new 11
All checks were successful
CI Test / gettools (push) Successful in 1m7s
2026-02-09 10:52:16 +07:00
50865478f1 hopium
All checks were successful
CI Test / gettools (push) Successful in 1m14s
2026-02-09 10:50:16 +07:00
68068326f7 test new 10
Some checks failed
CI Test / gettools (push) Failing after 39s
2026-02-09 10:44:44 +07:00
dfccfce10b resr new 9
Some checks failed
CI Test / gettools (push) Failing after 38s
2026-02-09 10:41:23 +07:00
09ce9906cd test new 8
Some checks failed
CI Test / gettools (push) Has been cancelled
2026-02-09 10:15:39 +07:00
24edabf74f test new 7
Some checks failed
CI Test / gettools (push) Failing after 1m54s
2026-02-09 10:11:58 +07:00
9a9abd309f test new 6
Some checks failed
CI Test / gettools (push) Failing after 1m9s
2026-02-09 10:07:50 +07:00
073eb0d52e test new 5
Some checks failed
CI Test / gettools (push) Failing after 38s
2026-02-09 09:50:07 +07:00
d835f54a5f test new 4
Some checks failed
CI Test / gettools (push) Failing after 38s
2026-02-09 09:46:23 +07:00
3d7b2e97eb test new 3
Some checks failed
CI Test / gettools (push) Failing after 39s
2026-02-09 09:44:08 +07:00
3f59b18b9d test new 2
Some checks failed
CI Test / gettools (push) Failing after 39s
2026-02-09 09:42:32 +07:00
440acf6a8b test new 1
Some checks failed
CI Test / gettools (push) Failing after 1m7s
2026-02-09 09:39:37 +07:00
ce0819540e test 10
All checks were successful
CI Test / test (push) Successful in 37s
2026-02-08 23:09:39 +07:00
f94a53e75f test 9
All checks were successful
CI Test / test (push) Successful in 37s
2026-02-08 23:02:31 +07:00
0c64b094ff test 8
All checks were successful
CI Test / test (push) Successful in 37s
2026-02-08 22:57:32 +07:00
8c48517285 test 7
All checks were successful
CI Test / test (push) Successful in 38s
2026-02-08 22:57:10 +07:00
b00d612842 test 6
All checks were successful
CI Test / test (push) Successful in 38s
2026-02-08 22:55:22 +07:00
2c9e507afa test 5
All checks were successful
CI Test / test (push) Successful in 38s
2026-02-08 22:54:08 +07:00
ee74e3d886 test 4
Some checks failed
CI Test / test (push) Successful in 38s
CI Test / test2 (push) Failing after 37s
2026-02-08 22:45:49 +07:00
072cab5526 test 3
Some checks failed
CI Test / test (push) Successful in 38s
CI Test / test2 (push) Failing after 38s
2026-02-08 22:43:49 +07:00
c9ebdbe065 test 2
Some checks failed
CI Test / test (push) Successful in 45s
CI Test / test2 (push) Failing after 43s
2026-02-08 22:41:28 +07:00
032f7d2e4b test 1
All checks were successful
CI Test / test (push) Successful in 44s
CI Test / test2 (push) Successful in 2m3s
2026-02-08 22:35:57 +07:00
2ef029297f test pipeline
All checks were successful
CI Test / build (push) Successful in 1m48s
2026-02-08 22:24:16 +07:00
61c8823555 update desc and pics 2025-08-10 22:27:34 +07:00
154ffe2fed working blacklist system and apply list command 2025-08-10 21:03:20 +07:00
dd0d995f3f add blacklist settings 2025-08-10 15:16:20 +07:00
4 changed files with 138 additions and 61 deletions

43
.gitea/workflows/test.yml Normal file
View File

@@ -0,0 +1,43 @@
name: CI Test
on:
push:
branches:
- pipeline/test
pull_request:
jobs:
fix-permission:
runs-on: ubuntu-latest
container:
image: cm2network/steamcmd
volumes:
- /srv/act_runner/data/steamapps:/home/steam/Steam/steamapps
env:
STEAM_DIR: /home/steam/Steam
options: --user root
steps:
- name: Change steamapps permission
run: |
chown -R steam:steam $STEAM_DIR/steamapps
gettools:
runs-on: ubuntu-latest
needs: fix-permission
container:
image: cm2network/steamcmd
volumes:
- runner_data_steamcmd_login:/home/steam/Steam/config
- /srv/act_runner/data/steamapps:/home/steam/Steam/steamapps
env:
STEAMCMD_DIR: /home/steam/steamcmd
STEAM_DIR: /home/steam/Steam
steps:
- name: Login steam cmd
run: |
if ! grep -q "${{ secrets.STEAM_USERNAME }}" "$STEAM_DIR/config/config.vdf" 2>/dev/null; then
$STEAMCMD_DIR/steamcmd.sh +login ${{ secrets.STEAM_USERNAME }} ${{ secrets.STEAM_PASSWORD }} +quit
fi
$STEAMCMD_DIR/steamcmd.sh +login ${{ secrets.STEAM_USERNAME }} +app_update 4000 validate +quit

View File

@@ -1,27 +1,32 @@
Title: Custom Hostile NPCs to Citizen!
Title: Custom Hostile NPCs to Citizen
This is my first mod ever!
# About this Addon
[h2]About this Addon[/h2]
Tired of hearing your favorite character's enemy NPC sound like a combine? or buggy if using weapons rather than citizen NPCs?
This mod makes custom hostile NPC models change their behavior from Combine to Citizen.
This simple mod changes custom hostile NPC models change their behavior from combine to citizen by [b]overwriting the spawnmenu data[/b]. making hostile more human.
If you spawn NPCs from custom model addons as enemies or hostiles you realize that their behavior and their voices are combine soldiers. That's because most hostile NPCs from custom model addons use Combine as their base NPC.
If you spawn NPCs from custom model addons as enemies or hostiles you realize that their behavior and their voices are combine soldiers. That's because most hostile NPCs from custom model addons use combine as their base NPC.
Since the March 2025 update, gmod has added a new NPC called Enemy Rebel, which makes citizens hostile. This can be changed to custom NPCs that use Combine as their enemy.
If you want your enemies to be more human, this mod will change all hostile NPC custom models to behave like citizens.
[h2]Features[/h2]
[list]
[*] Change the behavior of custom models NPCs from combine to citizen
[*] Blacklist of NPCs who don't want to become citizens.
[/list]
# Features
- Change the behavior of custom models NPCs from combine to citizen
- Allows hostile to attack with melee weapons
To blacklist an NPC, right-click and copy the NPC in the spawn menu, go to Options > Replace Hostile Settings, paste the NPC class into the blacklist. to add multiple NPC, separate them with commas, example: npc_myhostile,npc_lenna,gfl2_lenna_enemy
I'll make VJ version if i can
You can reload blacklisted and non-blacklisted hostile NPCs with [b]replacehostile_reload[/b] or “Reload NPCs” button in settings
---
I'll make VJ version if i can. i'm still learning...
-----------
models used:
- Lenna https://steamcommunity.com/sharedfiles/filedetails/?id=3167885628
- Tomoko https://steamcommunity.com/sharedfiles/filedetails/?id=3133369749
- [url=https://steamcommunity.com/sharedfiles/filedetails/?id=3167885628]Lenna[/url]
- [url=https://steamcommunity.com/sharedfiles/filedetails/?id=3133369749]Tomoko[/url]
Note: i couldn't find a mod similar to the one i made, so i don't know who made it first.

View File

@@ -1,61 +1,90 @@
local npcs = list.Get("NPC")
local citizenEnemy = npcs["npc_citizen_rebel_enemy"]
local originalListSet = list.Set
function list.Set(listType, class, npc)
if listType == "NPC" then
if npc["Class"] == "npc_combine_s" and npc["Category"] ~= "#spawnmenu.category.combine" then
if !npc["KeyValues"] then
npc["KeyValues"] = {}
end
npc["KeyValues"]["SquadName"] = "m_EnemyRebel"
end
end
originalListSet(listType, class, npc)
local function loadBlacklistFile()
local json = file.Read("npc_blacklist.json", "DATA")
if not json or json == "" then return {} end
local data = util.JSONToTable(json)
return istable(data) and data or {}
end
hook.Add("OnEntityCreated", "ForceReplaceCombine", function(ent)
timer.Simple(0, function()
if !SERVER then return end
if not IsValid(ent) then return end
if ent:GetClass() == "npc_citizen" then
local function resetHostile()
local npcs = list.Get("NPC")
for class, npc in pairs(npcs) do
if npc["m_OldData"] then
local oldData = util.JSONToTable(npc["m_OldData"])
if oldData then
list.Set("NPC", class, oldData)
end
end
end
end
if ent:GetKeyValues()["squadname"] == "m_EnemyRebel" then
local pos = ent:GetPos()
local ang = ent:GetAngles()
local mdl = ent:GetModel()
local weps = ent:GetWeapons()
local health = ent:GetMaxHealth()
local keyValues = ent:GetKeyValues()
local function replaceHostile()
local blacklist = loadBlacklistFile()
local npcs = list.Get("NPC")
local citizenEnemy = npcs["npc_citizen_rebel_enemy"]
ent:Remove()
for class, npc in pairs(npcs) do
if table.HasValue(blacklist, class) then continue end
if npc["Class"] == "npc_combine_s" and npc["Category"] ~= "#spawnmenu.category.combine" then
npc["m_OldData"] = npc["m_OldData"] or util.TableToJSON(npc, false)
npc["Class"] = citizenEnemy["Class"]
npc["KeyValues"] = {
Hostile = 1,
SquadName = "overwatch",
citizentype = 4
}
list.Set("NPC", class, npc)
end
end
end
local npc = ents.Create("npc_citizen")
if not IsValid(npc) then return end
CreateClientConVar("replacehostile_blacklist", "", false, false, "Blacklist NPC Classes")
for key, value in pairs(keyValues) do
npc:SetKeyValue(key, tostring(value))
-- if value ~= "" then
-- end
concommand.Add("replacehostile_reload", function()
resetHostile()
replaceHostile()
print("NPC Hostile Reloaded")
end)
hook.Add("PopulateToolMenu", "ReplaceHostileMenu", function()
local blacklist = loadBlacklistFile()
local defaultBlacklistStr = table.concat(blacklist, ",")
RunConsoleCommand("replacehostile_blacklist", defaultBlacklistStr)
spawnmenu.AddToolMenuOption("Options", "Replace Hostile", "ReplaceHostileConfig", "Settings", "", "", function(panel)
panel:ClearControls()
local blacklistEntry = panel:TextEntry("Blacklist Classes", "replacehostile_blacklist")
panel:ControlHelp("Separate classes with commas.\nExample: npc_my_custom_hostile,npc_my_hostile,npc_hostile_test")
panel:Button("Reload NPCs", "replacehostile_reload")
blacklistEntry.OnChange = function(self)
local val = self:GetValue() or ""
local newBlacklist = {}
for e in string.gmatch(val, '([^,]+)') do
local trimmed = string.Trim(e)
if trimmed ~= "" then
table.insert(newBlacklist, trimmed)
end
end
npc:SetHealth(health)
npc:SetMaxHealth(health)
npc:SetKeyValue("hostile", 1)
npc:SetKeyValue("squadname", "overwatch")
npc:SetKeyValue("citizentype", 4)
for _, wep in ipairs(weps) do
npc:Give(wep:GetClass())
local valid = true
for _, v in ipairs(newBlacklist) do
if type(v) ~= "string" or v == "" then
valid = false
break
end
end
npc:SetPos(pos)
npc:SetAngles(ang)
npc:SetModel(mdl)
npc:Spawn()
if valid then
file.Write("npc_blacklist.json", util.TableToJSON(newBlacklist, false))
end
end
end)
end)
timer.Simple(0, function()
replaceHostile()
end)

BIN
pics/pic_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB