Hi, it works very well. Is there a way to save the changes? I tried to save it and when I reload, the npc reverts to original outfit. Not sure if this is the place to ask, but is there a mod that can replace all npc cars on the road to custom car models?
For all those waiting for this mod to be fixed for the current update, it's quite easy.
Open the following file in a text editor, notepad should work fine, but Visual Studio Code is definitely a better option for this sort of stuff. plugins\cyber_engine_tweaks\mods\NPCTool\init.lua
Copy and paste the code in the spoiler below and you should be able to set all of the actions mentioned in this mod to whatever key binding you want under the Hotkeys menu in cyber engine tweaks. Note that you must set these key bindings before anything will start working. Also, since the key bindings were originally hard-coded into the GUI, and because I have not yet found a way to figure out what keys a user has bound to what action, the GUI will still show the original hard-coded key bindings for the "Options" and "Quickhacks" sections, even if you set the actions to a different key. I will update this if and when I find a way to correlate key bindings to actions.
Spoiler:
Show
local root = "plugins\\cyber_engine_tweaks\\mods\\NPCTool\\" local npcTool local player local npcObj local npcRef local npcName local npcFName local npcApp local scanNPC = false local chgApp = false local scanned = {} local npcApl = {} local count = 0 local imShow local isChild local listApp = {} local listVeh = {} local cleanTab = {} local npcFam = {} local function dbclean(v) local t = cleanTab for _, x in ipairs(t) do v = v:gsub(x, '') end return v end local function cleanUp(n, v) if listApp then v = dbclean(v) end v = v:gsub(n, ''):gsub('__', '_') v = v:gsub('_q[%d][%d][%d]_', ''):gsub('_', ' ') return v end local function familiar(tab, val) for _, v in ipairs(tab) do if v == val then return true end end return false end local function getAppearance(o) o = o:GetCurrentAppearanceName() local t = {} for a in string.gmatch(tostring(o), '[^%s]+') do table.insert(t, a) end return t[9] end local function setAppearance() local d = npcApl[count] npcObj:ScheduleAppearanceChange(d) end local function listAppearance(ref) for _, v in ipairs(npcApl) do if v == npcApp then ImGui.Text(' >' ..cleanUp(ref, v)) else ImGui.Text(' ' ..cleanUp(ref, v)) end end end local function friendlyName(i) local t = {} for a in string.gmatch(i, '(%w+)_(%w+)') do table.insert(t, a) end return tostring(t[1]) end local function friendlyVehName(i) local t = {} for a in string.gmatch(i, '(%w+)_') do table.insert(t, a) end if string.find(i, '__') then return tostring(t[1] ..'_' ..t[2] ..'__' ..t[3] ..'_') else return tostring(t[1] ..'_' ..t[2] ..'_' ..t[3] ..'_') end end local function tableCount(v) table.insert(npcApl, v) local c = #npcApl if v == npcApp then count = c end end local function npcHack(e) if not npcObj:IsCharacterChildren() then Game.ApplyEffectOnNPC('BaseStatusEffect.' ..e) end end local function buildDatabase(i, t) local ini = io.open(root ..'data\\' ..i ..'.ini', 'r') if not ini then ini = io.open('NPCTool\\data\\' ..i ..'.ini', 'r') end for l in ini:lines() do table.insert(t, l) end table.sort(t) ini:close() end local function initDB() buildDatabase('outfits', listApp) buildDatabase('vehicles', listVeh) buildDatabase('cleantab', cleanTab) buildDatabase('npcfam', npcFam) if #npcFam > 1 then return true end end
registerHotkey("scanNPC_Down", "Down", function() if scanNPC then count = count + 1 chgApp = true end end)
registerHotkey("scanNPC_Up", "Up", function() if scanNPC then count = count - 1 chgApp = true end end)
registerHotkey("scanNPC_Kill_NPC", "Kill NPC", function() if scanNPC then if scanNPC and npcObj:IsNPC() and not npcObj:IsCharacterChildren() then npcObj:Kill() end end end)
registerHotkey("scanNPC_Close_Window", "Close Window", function() if scanNPC then scanNPC = false end end)
registerHotkey("scanNPC_Set_NPC_On_Fire", "Set NPC On Fire", function() if scanNPC then npcHack('Burning') end end)
registerHotkey("scanNPC_Stun_NPC", "Stun NPC", function() if scanNPC then if scanNPC and not npcObj:IsVehicle() then npcHack('Stun') elseif npcObj:IsVehicle() then npcObj:DetachAllParts() end end end)
registerHotkey("scanNPC_Overload_NPC", "Overload NPC", function() if scanNPC then if scanNPC and not npcObj:IsVehicle() then npcHack('Overload') end end end)
registerHotkey("scanNPC_Cyberware_Malfunction", "Cyberware Malfunction", function() if scanNPC then if scanNPC and not npcObj:IsVehicle() then npcHack('CyberwareMalfunctionLvl3') end end end)
registerHotkey("scanNPC_NPC_Suicide", "NPC Suicide", function() if scanNPC then if scanNPC and not npcObj:IsVehicle() then npcHack('SuicideWithWeapon') end end end)
-- registerHotkey("scanNPC_", "", function() -- if scanNPC then
-- end -- end)
registerForEvent("onUpdate", function() player = Game.GetPlayer() imShow = false -- if ImGui.IsKeyPressed(0x2D, false) then -- scanNPC = not scanNPC -- end -- if scanNPC then -- if ImGui.IsKeyPressed(0x22, false) then -- count = count + 1 -- chgApp = true -- end -- if ImGui.IsKeyPressed(0x21, false) then -- count = count - 1 -- chgApp = true -- end -- if ImGui.IsKeyPressed(0x23, false) then -- if scanNPC and npcObj:IsNPC() -- and not npcObj:IsCharacterChildren() then -- npcObj:Kill() -- end -- end -- if ImGui.IsKeyPressed(0x1B, false) then -- scanNPC = false -- end -- if ImGui.IsKeyPressed(0x2E, false) then -- npcHack('Burning') -- end -- if ImGui.IsKeyPressed(0x70, false) then -- if scanNPC and not npcObj:IsVehicle() then -- npcHack('Stun') -- elseif npcObj:IsVehicle() then -- npcObj:DetachAllParts() -- end -- end -- if ImGui.IsKeyPressed(0x71, false) then -- if scanNPC and not npcObj:IsVehicle() then -- npcHack('Overload') -- end -- end -- if ImGui.IsKeyPressed(0x72, false) then -- if scanNPC and not npcObj:IsVehicle() then -- npcHack('CyberwareMalfunctionLvl3') -- end -- end -- if ImGui.IsKeyPressed(0x73, false) then -- if scanNPC and not npcObj:IsVehicle() then -- npcHack('SuicideWithWeapon') -- end -- end -- end if scanNPC then player = Game.GetPlayer() if player then --npcObj = npcTool:GetLookAtObject(player,false,false) npcObj = Game.GetTargetingSystem():GetLookAtObject(player, false, false) end if npcObj then if npcObj:IsNPC() then npcName = npcObj:GetTweakDBDisplayName(true) npcFName = npcObj:GetTweakDBFullDisplayName(true) isChild = npcObj:IsCharacterChildren() npcApp = getAppearance(npcObj) imShow = true if npcName ~= 'NC Resident' then npcRef = string.lower(tostring(npcName) ..'_') npcRef = npcRef:gsub('johnny_', 'silverhand_') if not familiar(scanned, npcRef) then npcApl = {} scanned = {} count = 0 for _, v in ipairs(listApp) do if string.find(v, npcRef) then tableCount(v) end end table.insert(scanned, npcRef) end end if chgApp then if familiar(npcFam, npcName) then if count > #npcApl then count = 1 elseif count < 1 then count = #npcApl end setAppearance() else npcObj:ScheduleAppearanceChange('random') end end if npcObj:IsDead() then npcFName = 'Dead ' ..npcFName end end if npcObj:IsVehicle() then npcApp = getAppearance(npcObj) npcRef = friendlyVehName(npcApp) npcFName = npcObj:GetDisplayName() npcName = 'vehicle' imShow = true if not familiar(scanned, npcRef and npcApp) and not string.find(npcFName, 'NCPD') then npcApl = {} scanned = {} count = 0 for _, v in ipairs(listVeh) do if string.find(v, npcRef) then if not string.find(v, 'nomad') and not string.find(npcApp, 'nomad') then tableCount(v) elseif string.find(npcApp, 'nomad') and string.find(v, 'nomad') then tableCount(v) end end end table.insert(scanned, npcRef) table.insert(scanned, npcApp) end if chgApp then if count > #npcApl then count = 1 elseif count < 1 then count = #npcApl end setAppearance() end end end end chgApp = false end) registerForEvent("onDraw", function() if scanNPC then ImGui.SetNextWindowPos(10, 300) ImGui.SetNextWindowSize(0, 0) ImGui.Begin("NPCTool") if imShow then ImGui.SetWindowFontScale(1.8) ImGui.Text(npcFName) ImGui.SetWindowFontScale(1.4) if npcName == 'NC Resident' then ImGui.Text(friendlyName(npcApp)) end if npcObj and npcName == 'vehicle' then if not string.find(npcFName, 'NCPD') then ImGui.Spacing() ImGui.Text('Interact:') ImGui.Text(' [F1] Detach all parts') ImGui.Spacing() ImGui.Spacing() ImGui.Text('Skins:') listAppearance(npcRef) end elseif npcObj then if familiar(npcFam, npcName) then ImGui.Spacing() ImGui.Text('Outfits:') listAppearance(npcRef) end if not isChild then ImGui.Spacing() ImGui.Text('Options:') ImGui.Text(' [END] Kill NPC') ImGui.Text(' [DEL] Set on fire') ImGui.Spacing() ImGui.Text('QuickHacks:') ImGui.Text(' [F1] Stun') ImGui.Text(' [F2] Overload') ImGui.Text(' [F3] Malfunction') ImGui.Text(' [F4] Suicide') end end else ImGui.Text('Scanning...') end ImGui.Spacing() ImGui.End() end end) registerForEvent("onInit", function() npcTool = Game.GetTargetingSystem() if initDB() then print('[NPCTool]: Database OK - (' ..#listApp ..' outfit loaded)') print('[NPCTool]: Database OK - (' ..#listVeh ..' vehicles loaded)') print('[NPCTool] Loaded NPCTool v0.1.2a by Raymnd') end end)
does the new code replace the whole earlier code, do I add it to the end of the written sheet of codes, or is it supposed to replace parts of the written code automatically or by some selected control? I've tried the first two and not been able to activate the scanner at all. I'm up to date on the game and I've got cybertweak engine working.
@darksamurai24 You replace all of the code in the original init.lua file with the code I provided, you then open up the Cyber Engine Tweaks console, click on "Hotkeys" and set the hotkeys for each action.
93 comments
Is there a way to save the changes? I tried to save it and when I reload, the npc reverts to original outfit.
Not sure if this is the place to ask, but is there a mod that can replace all npc cars on the road to custom car models?
Open the following file in a text editor, notepad should work fine, but Visual Studio Code is definitely a better option for this sort of stuff.
plugins\cyber_engine_tweaks\mods\NPCTool\init.lua
Copy and paste the code in the spoiler below and you should be able to set all of the actions mentioned in this mod to whatever key binding you want under the Hotkeys menu in cyber engine tweaks. Note that you must set these key bindings before anything will start working. Also, since the key bindings were originally hard-coded into the GUI, and because I have not yet found a way to figure out what keys a user has bound to what action, the GUI will still show the original hard-coded key bindings for the "Options" and "Quickhacks" sections, even if you set the actions to a different key. I will update this if and when I find a way to correlate key bindings to actions.
local root = "plugins\\cyber_engine_tweaks\\mods\\NPCTool\\"
local npcTool
local player
local npcObj
local npcRef
local npcName
local npcFName
local npcApp
local scanNPC = false
local chgApp = false
local scanned = {}
local npcApl = {}
local count = 0
local imShow
local isChild
local listApp = {}
local listVeh = {}
local cleanTab = {}
local npcFam = {}
local function dbclean(v)
local t = cleanTab
for _, x in ipairs(t) do
v = v:gsub(x, '')
end
return v
end
local function cleanUp(n, v)
if listApp then
v = dbclean(v)
end
v = v:gsub(n, ''):gsub('__', '_')
v = v:gsub('_q[%d][%d][%d]_', ''):gsub('_', ' ')
return v
end
local function familiar(tab, val)
for _, v in ipairs(tab) do
if v == val then
return true
end
end
return false
end
local function getAppearance(o)
o = o:GetCurrentAppearanceName()
local t = {}
for a in string.gmatch(tostring(o), '[^%s]+') do
table.insert(t, a)
end
return t[9]
end
local function setAppearance()
local d = npcApl[count]
npcObj:ScheduleAppearanceChange(d)
end
local function listAppearance(ref)
for _, v in ipairs(npcApl) do
if v == npcApp then
ImGui.Text(' >' ..cleanUp(ref, v))
else
ImGui.Text(' ' ..cleanUp(ref, v))
end
end
end
local function friendlyName(i)
local t = {}
for a in string.gmatch(i, '(%w+)_(%w+)') do
table.insert(t, a)
end
return tostring(t[1])
end
local function friendlyVehName(i)
local t = {}
for a in string.gmatch(i, '(%w+)_') do
table.insert(t, a)
end
if string.find(i, '__') then
return tostring(t[1] ..'_' ..t[2] ..'__' ..t[3] ..'_')
else
return tostring(t[1] ..'_' ..t[2] ..'_' ..t[3] ..'_')
end
end
local function tableCount(v)
table.insert(npcApl, v)
local c = #npcApl
if v == npcApp then
count = c
end
end
local function npcHack(e)
if not npcObj:IsCharacterChildren() then
Game.ApplyEffectOnNPC('BaseStatusEffect.' ..e)
end
end
local function buildDatabase(i, t)
local ini = io.open(root ..'data\\' ..i ..'.ini', 'r')
if not ini then
ini = io.open('NPCTool\\data\\' ..i ..'.ini', 'r')
end
for l in ini:lines() do
table.insert(t, l)
end
table.sort(t)
ini:close()
end
local function initDB()
buildDatabase('outfits', listApp)
buildDatabase('vehicles', listVeh)
buildDatabase('cleantab', cleanTab)
buildDatabase('npcfam', npcFam)
if #npcFam > 1 then
return true
end
end
-- Update hotkey registration
registerHotkey("scanNPC_Menu", "Toggle Window", function()
scanNPC = not scanNPC
end)
registerHotkey("scanNPC_Down", "Down", function()
if scanNPC then
count = count + 1
chgApp = true
end
end)
registerHotkey("scanNPC_Up", "Up", function()
if scanNPC then
count = count - 1
chgApp = true
end
end)
registerHotkey("scanNPC_Kill_NPC", "Kill NPC", function()
if scanNPC then
if scanNPC and npcObj:IsNPC()
and not npcObj:IsCharacterChildren() then
npcObj:Kill()
end
end
end)
registerHotkey("scanNPC_Close_Window", "Close Window", function()
if scanNPC then
scanNPC = false
end
end)
registerHotkey("scanNPC_Set_NPC_On_Fire", "Set NPC On Fire", function()
if scanNPC then
npcHack('Burning')
end
end)
registerHotkey("scanNPC_Stun_NPC", "Stun NPC", function()
if scanNPC then
if scanNPC and not npcObj:IsVehicle() then
npcHack('Stun')
elseif npcObj:IsVehicle() then
npcObj:DetachAllParts()
end
end
end)
registerHotkey("scanNPC_Overload_NPC", "Overload NPC", function()
if scanNPC then
if scanNPC and not npcObj:IsVehicle() then
npcHack('Overload')
end
end
end)
registerHotkey("scanNPC_Cyberware_Malfunction", "Cyberware Malfunction", function()
if scanNPC then
if scanNPC and not npcObj:IsVehicle() then
npcHack('CyberwareMalfunctionLvl3')
end
end
end)
registerHotkey("scanNPC_NPC_Suicide", "NPC Suicide", function()
if scanNPC then
if scanNPC and not npcObj:IsVehicle() then
npcHack('SuicideWithWeapon')
end
end
end)
-- registerHotkey("scanNPC_", "", function()
-- if scanNPC then
-- end
-- end)
registerForEvent("onUpdate", function()
player = Game.GetPlayer()
imShow = false
-- if ImGui.IsKeyPressed(0x2D, false) then
-- scanNPC = not scanNPC
-- end
-- if scanNPC then
-- if ImGui.IsKeyPressed(0x22, false) then
-- count = count + 1
-- chgApp = true
-- end
-- if ImGui.IsKeyPressed(0x21, false) then
-- count = count - 1
-- chgApp = true
-- end
-- if ImGui.IsKeyPressed(0x23, false) then
-- if scanNPC and npcObj:IsNPC()
-- and not npcObj:IsCharacterChildren() then
-- npcObj:Kill()
-- end
-- end
-- if ImGui.IsKeyPressed(0x1B, false) then
-- scanNPC = false
-- end
-- if ImGui.IsKeyPressed(0x2E, false) then
-- npcHack('Burning')
-- end
-- if ImGui.IsKeyPressed(0x70, false) then
-- if scanNPC and not npcObj:IsVehicle() then
-- npcHack('Stun')
-- elseif npcObj:IsVehicle() then
-- npcObj:DetachAllParts()
-- end
-- end
-- if ImGui.IsKeyPressed(0x71, false) then
-- if scanNPC and not npcObj:IsVehicle() then
-- npcHack('Overload')
-- end
-- end
-- if ImGui.IsKeyPressed(0x72, false) then
-- if scanNPC and not npcObj:IsVehicle() then
-- npcHack('CyberwareMalfunctionLvl3')
-- end
-- end
-- if ImGui.IsKeyPressed(0x73, false) then
-- if scanNPC and not npcObj:IsVehicle() then
-- npcHack('SuicideWithWeapon')
-- end
-- end
-- end
if scanNPC then
player = Game.GetPlayer()
if player then
--npcObj = npcTool:GetLookAtObject(player,false,false)
npcObj = Game.GetTargetingSystem():GetLookAtObject(player, false, false)
end
if npcObj then
if npcObj:IsNPC() then
npcName = npcObj:GetTweakDBDisplayName(true)
npcFName = npcObj:GetTweakDBFullDisplayName(true)
isChild = npcObj:IsCharacterChildren()
npcApp = getAppearance(npcObj)
imShow = true
if npcName ~= 'NC Resident' then
npcRef = string.lower(tostring(npcName) ..'_')
npcRef = npcRef:gsub('johnny_', 'silverhand_')
if not familiar(scanned, npcRef) then
npcApl = {}
scanned = {}
count = 0
for _, v in ipairs(listApp) do
if string.find(v, npcRef) then
tableCount(v)
end
end
table.insert(scanned, npcRef)
end
end
if chgApp then
if familiar(npcFam, npcName) then
if count > #npcApl then
count = 1
elseif count < 1 then
count = #npcApl
end
setAppearance()
else
npcObj:ScheduleAppearanceChange('random')
end
end
if npcObj:IsDead() then
npcFName = 'Dead ' ..npcFName
end
end
if npcObj:IsVehicle() then
npcApp = getAppearance(npcObj)
npcRef = friendlyVehName(npcApp)
npcFName = npcObj:GetDisplayName()
npcName = 'vehicle'
imShow = true
if not familiar(scanned, npcRef and npcApp) and
not string.find(npcFName, 'NCPD') then
npcApl = {}
scanned = {}
count = 0
for _, v in ipairs(listVeh) do
if string.find(v, npcRef) then
if not string.find(v, 'nomad')
and not string.find(npcApp, 'nomad') then
tableCount(v)
elseif string.find(npcApp, 'nomad')
and string.find(v, 'nomad') then
tableCount(v)
end
end
end
table.insert(scanned, npcRef)
table.insert(scanned, npcApp)
end
if chgApp then
if count > #npcApl then
count = 1
elseif count < 1 then
count = #npcApl
end
setAppearance()
end
end
end
end
chgApp = false
end)
registerForEvent("onDraw", function()
if scanNPC then
ImGui.SetNextWindowPos(10, 300)
ImGui.SetNextWindowSize(0, 0)
ImGui.Begin("NPCTool")
if imShow then
ImGui.SetWindowFontScale(1.8)
ImGui.Text(npcFName)
ImGui.SetWindowFontScale(1.4)
if npcName == 'NC Resident' then
ImGui.Text(friendlyName(npcApp))
end
if npcObj and npcName == 'vehicle' then
if not string.find(npcFName, 'NCPD') then
ImGui.Spacing()
ImGui.Text('Interact:')
ImGui.Text(' [F1] Detach all parts')
ImGui.Spacing()
ImGui.Spacing()
ImGui.Text('Skins:')
listAppearance(npcRef)
end
elseif npcObj then
if familiar(npcFam, npcName) then
ImGui.Spacing()
ImGui.Text('Outfits:')
listAppearance(npcRef)
end
if not isChild then
ImGui.Spacing()
ImGui.Text('Options:')
ImGui.Text(' [END] Kill NPC')
ImGui.Text(' [DEL] Set on fire')
ImGui.Spacing()
ImGui.Text('QuickHacks:')
ImGui.Text(' [F1] Stun')
ImGui.Text(' [F2] Overload')
ImGui.Text(' [F3] Malfunction')
ImGui.Text(' [F4] Suicide')
end
end
else
ImGui.Text('Scanning...')
end
ImGui.Spacing()
ImGui.End()
end
end)
registerForEvent("onInit", function()
npcTool = Game.GetTargetingSystem()
if initDB() then
print('[NPCTool]: Database OK - (' ..#listApp ..' outfit loaded)')
print('[NPCTool]: Database OK - (' ..#listVeh ..' vehicles loaded)')
print('[NPCTool] Loaded NPCTool v0.1.2a by Raymnd')
end
end)