#Mod Resources

1 messages · Page 1 of 1 (latest)

charred ridge
#

.
breakdance If one of the posted links helped you in any ways please react to that post. breakdance
glytch1 Thank you glytch2

.

#

Mod Learning Materials

``
PzWiki:
https://pzwiki.net/wiki/Modding

Lua events:
https://pzwiki.net/wiki/Modding:Lua_Events

Mod permissions:
https://theindiestone.com/forums/index.php?/topic/2530-mod-permissions/

Fenris guide:
https://github.com/FWolfe/Zomboid-Modding-Guide

Dislaiks guide:
https://steamcommunity.com/id/Dislaik/myworkshopfiles/?section=guides

https://projectzomboid.com/modding/index-files/index-1.html

Konijimas guide:
https://gist.github.com/Konijima/7e6bd1adb6f69444e7b620965a611b74

Konijima library guide:
https://github.com/Konijima/PZ-Libraries

Mr bounty guide:
https://github.com/MrBounty/PZ-Mod---Doc

Recipe and item variables:
https://theindiestone.com/forums/index.php?/topic/15188-item-and-recipe-script-variables-brief-description/

Lua:
https://www.lua.org/pil/contents.html

Server client commands:
https:// github.com/RangerSimple/ProjZomb-Guides

Mapping and tiles:
https://youtube.com/@daddydirkiedirk119

Loot distrib:
#mapping message

Clothing masks:
#modeling message

DoParam:
#mod_development message

Item full type:
#mod_development message

Mod Testing:
#mod_development message

Startup Param:
https://pzwiki.net/wiki/Startup_parameters

Clothing mod:
https://steamlists.com/project-zomboid-how-create-a-clothing-mod-41-60/

Authentic peach guide:
https://theindiestone.com/forums/index.php?/topic/49385-do-not-delete-luascript-files-from-your-mod-some-modding-guidelines/#comment-342943

tag system:
https://theindiestone.com/forums/index.php?/topic/53019-details-on-the-improved-modding-tag-system-in-4169/

GitHub

Guide to modding various aspects of Project Zomboid - GitHub - FWolfe/Zomboid-Modding-Guide: Guide to modding various aspects of Project Zomboid

#

.
azakaela's wordzed guide:
[#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1067081088519905280/#msg-1067082836852605028)

Javadocs:
https://rentry.co/BluesModClues

MusicMan's SandBox Guide:
[#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1067244156130439168/#msg-1067734593597354034)

Vanilla Sandbox
https://theindiestone.com/forums/index.php?/topic/20771-sandboxvarslua-file-explanation/

Albion: OnPlayerGetDamage event
[#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1032713369507086366/#msg-1032850385737617439)

Albion: Hook Guide:
https://github.com/demiurgeQuantified/PZ-events-guide/blob/main/Hooks.md

#

.
Vehicle modding:
https://theindiestone.com/forums/index.php?/topic/24408-how-to-create-new-vehicle-mods/

Vehicle modding:
https://theindiestone.com/forums/index.php?/topic/28633-complete-vehicle-modding-tutorial/

Vehicle skins modding:
https://theindiestone.com/forums/index.php?/topic/24278-how-to-edit-vehicle-skins/

Mod install:
https://pzwiki.net/wiki/Modding#How_to_install/play_mods

Tile properties https://pzwiki.net/wiki/Tile_Properties

Chucks guide:( object types and flags)
[#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1040438127673737267/#msg-1040597993658781696)

Check serverclient game mode:
[#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1037180129186676857/#msg-1037519465866338384)

#
#

Disabling contextmenu reference: [#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1068331968284086303/#msg-1068898626996289626)

#

.
Vishnya's Benchmark code: [#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1070081956307538001/#msg-1070332054581035058)

#

.
Pao's tile modification during world seed:
https://github.com/ZioPao/Destroyable-World-Fences

charred ridge
#

TIS pz translation https://github.com/TheIndieStone/ProjectZomboidTranslations

charred ridge
#

Tilezed mapping shop:
https://theindiestone.com/forums/index.php?/topic/21951-the-one-stop-tilezed-mapping-shop/

Lua:
https://devhints.io/lua

charred ridge
#

Blackbeard:
https://youtu.be/2M2fWLBLaX8

charred ridge
#

Aiteron's Guide:
https://pzwiki.net/wiki/User:Aiteron

charred ridge
#

tiledef used by mods: https://pzwiki.net/wiki/List_of_Tiledefs_in_use_by_mods
.

#

Zomcast feat. Authentic Peach: https://youtu.be/aJfnawoIwsc

charred ridge
#

Map system:
https://theindiestone.com/forums/index.php?/topic/43627-how-to-update-your-map-mod-to-work-with-the-new-in-game-map-system/

trynaeat modelling:
https://trynaeat.github.io/zomboid-modeling-docs/

#

Authentic Peach's model resources:
https://theindiestone.com/forums/index.php?/topic/37647-the-one-stop-shop-for-3d-modeling-from-blender-to-zomboid/

charred ridge
#

Glytch3r's PZ Mod Sheet:
(you may edit this and improve on it add on it)
https://docs.google.com/spreadsheets/d/1Wf08bl7Cq2jRyKDJPsWI_Tm8Iiq4LgxvIyL4e2xSDmU/edit?usp=sharing

#

.
Ckyb's Events:
https://paste.sr.ht/~ckyb/99d2d134360d355f33ceecf255b971f6b1d03624

Events:
https://pzwiki.net/wiki/Modding:Lua_Events

charred ridge
#

Mod Resources

charred ridge
charred ridge
#

Pao's attach to body code: [#mod_development message](/guild/136501320340209664/channel/232196827577974784/p/1072396290656321536/#msg-1072436365444264016)

charred ridge
#

Using discord Codeblock for lua codes:
`` ```lua
--codehere

``
charred ridge
#

suicide using debug:

getPlayer():Kill(getPlayer())
charred ridge
charred ridge
#

Burryaga Decoration Example:

Example = {}

Example.ISReadABook = {}

Example.ISReadABook.new = ISReadABook.new

-- Example of a decoration in which I dgaf about params
function ISReadABook:new(...)

    local o = Example.ISReadABook.new(self, ...)

    o.stopOnWalk = false;

    return o

end
charred ridge
charred ridge
charred ridge
gritty skiff
charred ridge
tranquil ocean
#

Quicker suicide using debug:

Define (in one of your mods that you always use):
function oof() getPlayer():Kill(ImaDeliciousBanana) end
Usage:
oof()
😉 Because I have to kill myself in -debug often (input to Kill can be any variable name with a nil value and still work fine).

(PS: For those running Wookiee Gamepad Support, oof() is already available through WookieeUtilities.lua.)

charred ridge
#

Mine is killme

#

Hmmm

local me = getPlayer()

#

That could be nice

gritty skiff
#

get current FPS in SP or client side: getAverageFPS()

in mp maybe this works

local statisticsData = getMPStatistics()
--statisticsData.clientFPS
--statisticsData.serverFPS

useful to do more optimized mods, if are dealing with intense processing
#mod_development message

gritty skiff
charred ridge
charred ridge
charred ridge
gritty skiff
gritty skiff
gritty skiff
gritty skiff
thick ice
charred ridge
gritty skiff
#

Zomboid mods -
Hollywood Page of Fame #40 to #1 most popular from all time 03/2023 - Reifel
extracted and categorized data

modId modName creatorsWorkshopUrl collectionsListed visitorsTotal subscribers favorites ratings lastDateUpdated changes awardsCount comments creators tagString

#mod_development message

charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
#

when reloading lua you might not have noticed that this is a searchbox

charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
thick ice
#

Project Zomboid, Build 41.78.16 is using Java JDK 17.0.1 according to the game files, in case anyone is tinkering in that.

thick ice
charred ridge
charred ridge
charred ridge
rocky ore
#

dont understand how to download the pzstudio one?

charred ridge
viral sundial
rocky ore
#

i see this and idk

#

i dont get how im suppose to do this

viral sundial
#

You need to open a terminal and enter the commands.
Its a CLI tool for now.

#

hold-shift and right click in a directory to open the powershell on windows

rocky ore
#

ok i use VSCode for all my scripting does that matter

viral sundial
#

@rocky ore vscode is perfect

rocky ore
#

so do i just downlod node and git on there or does it need to be on the pc

#

or is the setup different through VS

viral sundial
#

node and git is just requirement for pzstudio to work properly. You can use it inside vscode, i use it in vscode

rocky ore
#

ok

#

ty

viral sundial
#

np

viral sundial
# rocky ore ty

once your project is generated (using pzstudio new), then open it in vscode and you'll have the npm script available

#

i created a directory in my documents named Workspace and i create all my project there. The build/watch command will transfer everything into C:\Users\Konijima\Zomboid\Workshop for me

rocky ore
#

thats a good idea

charred ridge
#

Bruh dont chat on this thread tho

rocky ore
#

sorry

teal quartz
charred ridge
vestal bolt
#

@charred ridge Do you know where all of the exported model resources have gone to?

#

Clothes, Weapons etc

charred ridge
#

? Exported?

vestal bolt
#

To open up in Blender etc

charred ridge
soft horizon
#

So, I'll share this snippet of code for people who don't want to write multiple if-else (and please avoid doing so when you can for sanity) in lua.

This is what I consider the equivalent of switch-case in other languages.

You create a table with all the key-value pairs (and it will be easier to read than if-else).

This is an example with keyboard keys

local keyPressed = "k" .. tostring(keyNum);
    local keyMap = {
        k55 = PZNSTest_Wipe,                -- numpad *
        k71 = doNothing,                    -- numpad 7
        k72 = PZNS_GetPlayerCellGridSquare, -- numpad 8
        k73 = doNothing,                    -- numpad 9
        k74 = doNothing,                    -- numpad -
        k75 = doNothing,                    -- numpad 4
        k76 = doNothing,                    -- numpad 5
        k77 = doNothing,                    -- numpad 6
        k78 = doNothing,                    -- numpad +
        k79 = PZNSTest_logTemplateNPCsInfo, -- numpad 1 -- WIP - Cows: For now, this only prints the npc info.
        k80 = doNothing,                    -- numpad 2
        k81 = doNothing,                    -- numpad 3
        -- k82 = doNothing,                    -- numpad 0 -- WIP - Cows: Seems to be used by another mod. Do not use for now.
        k83 = PZNSTest_deleteTemplateNPCs,  -- numpad .
        k156 = PZNSTest_spawnTemplateNPCs,  -- numpad enter
    };

And now, you can do what I consider to be a silly thing and call the k-v mapped function directly from the table.

    if (keyMap[keyPressed] ~= nil) then
        if (keyNum ~= 72) then
            return keyMap[keyPressed](); -- Cows: I'm amazed this even works... but it does.
        else
            return keyMap[keyPressed](0);
        end
    end

Unless the mapped function requires input parameter(s), you can call the mapped function by appending the parenthesis at the end ()

empty pivot
charred ridge
tranquil ocean
#

@autumn steeple

autumn steeple
tranquil ocean
#

This whole thread has tons of resources for learning about modding.

#

I recommend you start from the top and try to find what you need, one idea at a time.

tranquil ocean
#

@pine gulch

jade cypress
tranquil ocean
#

@surreal flame

surreal flame
#

It’s not related to PZ I guess

tranquil ocean
#

You're in a thread for modding resources. It's just one of many.

#

Yes, it is. All these resources are for PZ

surreal flame
#

Oh it will help me to learn modding in general?

tranquil ocean
#

Party Animal is a mod on the Workshop; that is a repo showing the code required to upload it.

#

Showing what folder structure you need and where key files like mod.info and workshop.txt need to go

#

There is also at least one video tutorial in this thread, among other stuff.

surreal flame
#

I will check it out thanks (:

tranquil ocean
#

Good luck!

tranquil ocean
#

@fierce lily This and the pz wiki is as close as it gets. A lot of us learn by reading vanilla code or the code of other mods.

tranquil ocean
#

@fast raft

#

(Anyone who wants to refactor any of my mods is welcome to do so provided they change mod ids, file names, and global object names. I have many on the Workshop that you can try to use to learn.)

fast raft
#

So I’m looking through all these guides. Unless I missed it, is there a tutorial on how to create traits/occupations and how to get rid of the original ones?

#

I would eventually like to have all mods on my server created by myself but I am NOWHERE close to that and in the learning stage at the moment.

tranquil ocean
tranquil ocean
fierce lily
shy charm
#

Media Folder Github Repo

I've taken the liberty to throw (most of) the media folder files into a github repository for easy access for modders.
https://github.com/Niteghxst/Project-Zomboid-Media-Files

Note:

I had to leave 3 folders out due too Github's upload limit. These are in the repo's readme at the bottom.

And just in case:

GitHub

This repository holds all files that are contained within the "media" folder within Project Zomboid's folder structure, to allow all-time access from anywhere and everywhe...

tranquil ocean
#

@lament sun

#

Browse this for resources and tips

lament sun
#

Ok

tranquil ocean
#

@fringe axle

fringe axle
#

Thanks!

fierce lily
# tranquil ocean <@310487823205793794>

Dude, thank you for shepherding me into the community. Just realized how frequently you're helping out in the manner, and there's never a lot of recognition after the fact. I hope you realize this lays the blame for witnessing Disco Crab solely on your shoulders.

tranquil ocean
fringe axle
tranquil ocean
#

@tidal obsidian

tranquil ocean
charred ridge
#

ever wonder how large a loaded chunk is? i mean visually
everything outside of the space technically doesn't exist for your local player

https://imgur.com/5mXf6fV

charred ridge
charred ridge
#

salute global moddata key delete button
i had to do this while working on a squad mod, as i needed to do tests, might help others too, idk...
https://imgur.com/8Tv0IHU

Events.OnGameStart.Add(function()

    local hook = GlobalModDataDebug.createChildren
    function GlobalModDataDebug:createChildren()
        hook(self)

        local y, obj = ISDebugUtils.addButton(self,"close",self.width-200,self.height-40,180,20,getText("IGUI_CraftUI_Close"),GlobalModDataDebug.onClickClose);
        y, obj = ISDebugUtils.addButton(self,"refresh",self.width-400,self.height-40,180,20,"Refresh",GlobalModDataDebug.onClickRefresh);
        y, obj = ISDebugUtils.addButton(self,"delete",self.width-600,self.height-40,180,20,"Delete",GlobalModDataDebug.onClickDelete);

        self:populateList();
    end


    function GlobalModDataDebug:onClickDelete()
        local selectedItem = self.tableNamesList.items[self.tableNamesList.selected];
        if selectedItem then
            local tableName = selectedItem.text;
            ModData.remove(tableName);
            ModData.transmit(tableName)
            self:populateList();
        end
    end

end)
tranquil ocean
#

@solemn pawn

#

A lot of this is good.

tranquil ocean
#

@bitter ether I think you should start here.

bitter ether
#

ok

charred ridge
charred ridge
#

sandbox option table

from string to table
sample:


function parseStatements(str)
    local outfits = {}    
    local parts = {}
    for part in string.gmatch(str, "[^;]+") do
        table.insert(parts, part)
    end    
    for _, part in ipairs(parts) do
        local outfit_name, statements_str = string.match(part, "([^=]+)=(.+)")
        if outfit_name and statements_str then
            local statements = {}            
            for statement in string.gmatch(statements_str, "[^:;]+") do
                if statement ~= "" then
                    table.insert(statements, statement)
                end
            end            
            outfits[outfit_name] = statements
        end
    end    
    return outfits
end
sample :

key: Outfit_Ranger
values: Howdy?, Yeehaw!


this is what you actually input on the option

option NPC_Zed.InteractStatements  {
    type = string, default = Outfit_Ranger=Howdy?:Yeehaw!;Outfit_Survivalist=...:Blend with the shadows;Outfit_Bandit=Hey buddy:How Can I help You?:What?,
    page = NPC_Zed, translation = NPC_Zed_InteractStatements,
}
--test print
local string = SandboxVars.NPC_Zed.InteractStatements

local parsed_outfits = parseStatements(string)

for outfit, statements in pairs(parsed_outfits) do
    print(outfit)
    for _, statement in ipairs(statements) do
       print(statement)
    end
  
end

using this servers and players can add infinite number of entry to a single sandboxoption
instead of providing them fixed number of options
letsay youre trying to make a teleporter
then you could do this for the option

"School:3124:4563:0;Camp:5124:1423:0;"
School 3124 4563 0
school is the key and the numbers are xyz coordinates

= after each key
: delimiter for the values
; delimiter for keys

keys1=keys1_value1:keys1_value2:keys1_value3;

im not sure if anyone will actually use this
if incase you do please let me know
thanks

tranquil ocean
#

@fading lodge

tranquil ocean
#

But what you need to do depends quite a bit on what mod you want to make

fading lodge
#

alright thank you man means alot to me

tranquil ocean
#

Hence my cheeky list of things to do

#

Deciding what to make really is step 1

tranquil ocean
#

Compare your workshop directory structure / workshop.txt / mod.info etc. to this

wicked sparrow
#

Thanks man I got it figured out

charred ridge
tranquil ocean
#

@vale shale

#

You have been looped.

vale shale
#

Tysm

tranquil ocean
wicked sparrow
#

?

#

Did I get pinged

tranquil ocean
#

@wicked sparrow You may not have realized when I first pinged you here

#

But this is a place for learning Lua

wicked sparrow
#

It just appeared 😭

#

Ok sounds good

tranquil ocean
#

I realized in retrospect I've pigned you here before

wicked sparrow
#

Lmao

tranquil ocean
#

But you may have thought we were in mod_development

wicked sparrow
#

I'll check it out.

tranquil ocean
#

Because I got you after you had solved a problem already

#

:p

#

But this is a resource thread

foggy crest
#

Does anyone here know how to make mods?

foggy crest
#

It is possible to change the skills in relation to the job, like putting the % lower?

tranquil ocean
tranquil ocean
#

@fast raft

charred ridge
#

wrong channel

charred ridge
charred ridge
#

close context menu

have you experienced there are times that the context menu gets stuck after clicking it?
idk if its a bug but if that happens to you then heres a solution
on the function thats triggered by that option
do this

force close context menu after clicking

context:hideAndChildren()

sample of when i used it

                local optTip = apSub:addOption(tostring(invItem:getDisplayName()), invItem, function()
                    ClassRankMod.doAppraiseTimed(pl, invItem)
                    context:hideAndChildren()
                end)
                optTip.iconTexture = getTexture("media/ui/ClassRank_Appraise.png")
                local tip = ISInventoryPaneContextMenu.addToolTip()
                tip.description = tostring(invItem:getFullType()) .. "\nAppraise this item."
                tip:setName("Appraise: ")
                optTip.toolTip = tip
charred ridge
#

custom zombie outfit file checklist:

note: not all of the files here are strict when it comes to folder structure

construct the outfit

declare what clothing items it will spawn with
this is how you add custom outfit
clothing/clothing.xml

construct the actual clothing

so that the model and the texture are linked, you then add this to your outfit
clothing/clothingItems/yourMod.xml

fileGuidTable entry

so that the game recognize your clothing item
fileGuidTable.xml

to turn the clothing into an item

scripts/yourMod.txt

the actual model

the actual model files
models_X/Skinned/yourMod.fbx or models_X/Skinned/yourMod.x

texture file must the thing you declare on your clothingItem xml

without this you wont see the model
textures/Body/yourMod.png

add the outfit to the ZombiesZoneDefinition table via lua file

this file is optional
so that they will naturally spawn in the game
lua/shared/yourMod.lua

charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
#

Vanilla Hit Reactions:

Players:

  • BiteDefended
  • CrawlerBite
  • EndDeath
  • Bite
  • Shot
  • BiteLEFT
  • BiteRIGHT
  • CrawlerBiteLEFT
  • CrawlerBiteRIGHT

Zombies:

  • HeadLeft
  • HeadRight
  • HeadTop
  • BiteDefended
  • Eating
  • FenceWindow
  • GettingUpFront
  • ShotBelly
  • Uppercut
  • Chainsaw
  • HitSpearDeath1
  • HitSpearDeath2
  • KnifeDeath
  • ShotBellyStep
  • ShotChestR
  • ShotChestL
  • ShotShoulderL
  • ShotShoulderR
  • Floor
  • ShotLegR
  • ShotLegL
  • ShotChestStepL
  • ShotChestStepR
  • ShotHeadBwd
  • ShotHeadFwd
  • ShotHeadFwd02
  • ShotShoulderStepL
  • ShotShoulderStepR
  • OnKnees

Usage

Zombie hit react

    <m_Events>
        <m_EventName>SetVariable</m_EventName>
        <m_Time>Start</m_Time>
        <m_ParameterValue>ZombieHitReaction=HeadLeft</m_ParameterValue>
    </m_Events>

Player hit react


    <m_Events>
        <m_EventName>SetVariable</m_EventName>
        <m_Time>Start</m_Time>
        <m_ParameterValue>PlayerHitReaction=Bite</m_ParameterValue>
    </m_Events>

this will set the reaction to the character that gets hit
this is done via animsets xml files

charred ridge
charred ridge
charred ridge
charred ridge
crystal ruin
#

Bit of a nitpick but putting the if not vehicle above the if not vehicleIsCountach() makes it so that you don't check if not vehicle twice.

Optimization ✨

crystal ruin
# crystal ruin Bit of a nitpick but putting the `if not vehicle` above the `if not vehicleIsCou...

Bug fix:

---@param character IsoGameCharacter
local function unregisterVehicle(character)
    VehiclePartConditions["CountachFrontTrunk"] = nil
    VehiclePartConditions["Engine"] = nil
    VehiclePartConditions["EngineDoor"] = nil
    VehiclePartConditions["TruckBed"] = nil
end
````VehiclePartConditions` wasn't getting properly unregistered so if your parts got damaged from outside the vehicle from uninstalling/installing, setting the condition via cheats, etc. It was still executing the `vehiclePartDamageCheck`.
charred ridge
charred ridge
#

Traits related

Setting mutual exclusive traits easier

--modify the table to suit your need
local toSetMutualExclusive = {
    {'ShortSighted', 'EagleEyed', 'EagleEyed2'},
    {'FearoftheDark', 'NightVision1', 'NightVision2', 'Desensitized', 'Desensitized2', 'Brave', 'Brave2'},
    {'Dextrous', 'Dextrous2', 'AllThumbs'},
}

Events.OnPostDistributionMerge.Add(function()
    local result = ''; local toPair = nil
    for _, v in pairs(toSetMutualExclusive) do
        for _, k in pairs(v) do
            for _, j in pairs(v) do
                if k ~= j then
                    if isDebugEnabled() then
                        toPair = tostring(k..' | '.. j)
                        result = result .. toPair .. '\n';
                    end
                    TraitFactory.setMutualExclusive(k, j);
                end
            end
        end
        if isDebugEnabled() then  Clipboard.setClipboard(result); print(result) end
    end
end)

use debug console to use the codes below

check mutual traits of a specified trait

local traitToCheck = 'ShortSighted' -- change this to the trait you want to test
local function getMutualTraits(traitStr)
    for i=0,TraitFactory.getTraits():size()-1 do
        local tCheck = TraitFactory.getTraits():get(i);
        if tCheck:getMutuallyExclusiveTraits():contains(traitStr) then
            local tr = tostring(tCheck:getType())
            print("Trait: "..tostring(tr)..  " HasTrait: ".. tostring(pl:HasTrait(tr))) 
        end
    end
    return false
end
getMutualTraits(traitToCheck) 

store all the installed traits onto your clipboard

local result = '';
for i=0,TraitFactory.getTraits():size()-1 do
    local tCheck = TraitFactory.getTraits():get(i);
    result = result .. tostring(tCheck:getType()).. '\n';
end
Clipboard.setClipboard(result);
print(result)
getPlayer():setHaloNote(tostring("open a notepad and press ctrl v to paste the copied trait list"),150,250,150,900) 
    

gain all positive traits



local pl = getPlayer() 
local tr = TraitFactory.getTraits()
for i=0, tr:size()-1 do
    local trait = tr:get(i);
    if trait:getCost() > 0 then
        if not pl:HasTrait(trait:getType()) then pl:getTraits():add(trait:getType()) end
    else
        if pl:HasTrait(trait:getType()) then  pl:getTraits():remove(trait:getType()) end
    end
end

clear all characters traits

local pl = getPlayer() 
local tr = TraitFactory.getTraits()
for i=0, tr:size()-1 do
    local trait = tr:get(i);
    if pl:HasTrait(trait:getType()) then pl:getTraits():remove(trait:getType()) end
end

#

Recipe

stores all recipe names and info onto clipboard



    local pl = getPlayer() 
    local count = RecipeManager.getKnownRecipesNumber(pl)
    local result = ''
    for i=1, getAllRecipes():size() do
        local recipe = getAllRecipes():get(i-1)
        local rName = recipe:getOriginalname()
        local line = tostring(rName).."  ["..tostring(pl:isRecipeKnown(recipe)).."]"
        result = result .. tostring(line).. '\n';
    end    

    result = "Learned Count: ".. tostring(count).. '\n\n'.. result     
    result = "Player Knows All Recipe [CHEAT]: ".. tostring(getDebugOptions():getBoolean("Cheat.Recipe.KnowAll")).."\n".. result 
    result = "Known Recipe Details:\n"..result
    Clipboard.setClipboard(result);
    print(result)
    pl:setHaloNote(tostring("open a notepad and press ctrl v to paste the copied list"),150,250,150,900) 
    


charred ridge
charred ridge
#

Store the global mod data to clipboard


local function GlobalModDataUtil(t, indent)
    indent = indent or ""
    local result = ""
    for k, v in pairs(t) do
        local key = tostring(k)
        if type(v) == "table" then
            result = result .. indent .. key .. ":\n" .. GlobalModDataUtil(v, indent .. "  ")
        else
            result = result .. indent .. key .. ": " .. tostring(v) .. "\n"
        end
    end
    return result
end

local tableNames = ModData.getTableNames()
if tableNames:size() == 0 then
    Clipboard.setClipboard("Err")
    return
end

local str = "Global ModData:\n\n"
for i = 0, tableNames:size() - 1 do
    local tableName = tableNames:get(i)
    local modData = ModData.get(tableName)
    if modData then
        str = str .. tableName .. ":\n" .. GlobalModDataUtil(modData, "  ") .. "\n"
    else
        str = str .. tableName .. ": Table not found.\n"
    end
end

Clipboard.setClipboard(str)
local text = "Glytch3r:\n To store the global mod data\nPress Ctrl + V on a Notepad\n"
getPlayer():setHaloNote(tostring(text),150,250,150,900) 
print(text)


charred ridge
#

Firearms to Clipboard


-- use to check all installed guns, use it to check if your gun mod is installed


local result = ""
local items = getScriptManager():getAllItems()
for i=0, items:size()-1 do
    local item = items:get(i)
    if item then
        if tostring(item:getType()) == "Weapon" and item:isRanged()  then
            local item = InventoryItemFactory.CreateItem(item:getName())
            if item then    result = result .. tostring(item:getFullType()) .. "\n"; end
        end
    end
end
Clipboard.setClipboard(result);
print(result)
getPlayer():setHaloNote(tostring("Glytch3r:\n open notepad and press ctrl + v"),150,250,150,900)



charred ridge
#

Glytch3r's MountOn function (reference)

--adds your mod weapon to a bunch of weapon parts MountOn property via lua scriptmanager instead of overwriting the weaponparts scripts
#modeling message

charred ridge
charred ridge
hearty creek
charred ridge
hearty creek
#

@charred ridge Sup dude, remember me? I was doing Node Manager? Life stuff happened and had to stop what I was doing for good awhile. I'm back with Modix. Changed the name

charred ridge
charred ridge
#

isPistol (boolean function)

--input type or fulltype as string or an inventoryitem instance

local function isPistol(item)
    local wpn = nil
    if type(item) == 'string' then
        wpn = instanceItem(item)
    else
        wpn = item
    end
    if wpn and instanceof(wpn, 'HandWeapon') then
        return (wpn:getSwingAnim() and wpn:getSwingAnim() == "Handgun")
    end
    return false
end

    

Sample Usage:

    isPistol("Revolver") -- type 
    isPistol("Base.Revolver") -- fulltype
    isPistol(getPlayer():getPrimaryHandItem()) --inventoryitem 
charred ridge
charred ridge
charred ridge
charred ridge
#

FitnessExercises.exercisesType



squats 
    type : squats
    name : Squats
    tooltip : Improves fitness when performed regularly.
    stiffness : legs
    metabolics : Fitness
    xpMod : 1
pushups 
    type : pushups
    name : Push-ups
    tooltip : Improves strength when performed regularly.
    stiffness : arms,chest
    metabolics : Fitness
    xpMod : 1
situp 
    type : situp
    name : Sit-ups
    tooltip : Improves fitness when performed regularly.
    stiffness : abs
    metabolics : Fitness
    xpMod : 1
burpees 
    type : burpees
    name : Burpees
    tooltip : Improves strength and fitness when performed regularly. Will drain endurance a lot.
    stiffness : legs,arms,chest
    metabolics : FitnessHeavy
    xpMod : 0.8
barbellcurl 
    type : barbellcurl
    name : Barbell Curls
    tooltip : Improves strength when performed regularly.
    item : Base.BarBell
    prop : twohands
    stiffness : arms,chest
    metabolics : FitnessHeavy
    xpMod : 1.2
dumbbellpress 
    type : dumbbellpress
    name : Dumbbell Presses
    tooltip : Improves strength when performed regularly.
    item : Base.DumbBell
    prop : switch
    stiffness : arms
    metabolics : FitnessHeavy
    xpMod : 1.8
bicepscurl 
    type : bicepscurl
    name : Bicep Curls
    tooltip : Improves strength when performed regularly.
    item : Base.DumbBell
    prop : switch
    stiffness : arms
    metabolics : FitnessHeavy
    xpMod : 1.8```
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
tough pivot
#

Object Highlighter

-- highlight arg "object" only when mouse is over it.
-- returns the object object when clicked

---@param playerObj IsoPlayer  player object
---@param object String        IE "Base.Log" or "Log"
local function objectHighlighter(playerObj, object)
    local CancelActions, GetMouseCoords, OnMouseClick, OnTick
    local lastHighlighted
    local x, y, z

    CancelActions = function()
        if instanceof(playerObj, "IsoPlayer") then
            if playerObj:pressedCancelAction() or playerObj:isAttacking() then
                return true
            end
        end
    end

    GetMouseCoords = function(playerObj)
        local x, y = ISCoordConversion.ToWorld(getMouseXScaled(), getMouseYScaled(), playerObj:getZ())
        x, y, z = math.floor(x), math.floor(y), playerObj:getZ()
        return x, y, z
    end

    OnMouseClick = function()
        Events.OnTick.Remove(OnTick)
        Events.OnMouseDown.Remove(OnMouseClick)
        if lastHighlighted then
            if lastHighlighted:isHighlighted() then
                lastHighlighted:setHighlighted(false)
            end
            return lastHighlighted
        end
    end

    OnTick = function()
        if CancelActions(playerObj) then
            Events.OnTick.Remove(OnTick)
            Events.OnMouseDown.Remove(OnMouseClick)
            return nil
        end
        x, y, z = GetMouseCoords(playerObj)
        local square = getSquare(x, y, z)

        local wobs = square:getWorldObjects()
        for i = 0, wobs:size() - 1 do
            local wob = wobs:get(i)
            if instanceof(wob, object) or wob:getItem():getFullType() == object then
                lastHighlighted = wob
                wob:setHighlighted(true)
                wob:setOutlineHighlight(true)
                return
            else
                if lastHighlighted and lastHighlighted:isHighlighted() then
                    lastHighlighted:setHighlighted(false)
                    return
                end
            end
        end

        local objs = square:getObjects()
        for i = 0, objs:size() - 1 do
            local obj = objs:get(i)
            if instanceof(obj, object) or obj:getType() == object then
                lastHighlighted = obj
                obj:setHighlighted(true)
                return
            else
                if lastHighlighted and lastHighlighted:isHighlighted() then
                    lastHighlighted:setHighlighted(false)
                    return
                end
            end
        end
    end

    Events.OnTick.Add(OnTick)
    Events.OnMouseDown.Add(OnMouseClick)
end
#

Get All Windows In A Room
since room:getWindows() is non-functional

-- returns a table of window objects

---@param playerObj IsoPlayer    player object
local function getWindowsInRoom(playerObj)
    local windows = {}
    local roomSquares = playerObj:getSquare():getRoom():getSquares()
    for i = 1, roomSquares:size() -1 do
        local square = roomSquares:get(i)
        local south = square:getS()
        local east = square:getE()
        if square:getWindow() then
            table.insert(windows, square:getWindow())
        elseif square:isWindowTo(south) then
            table.insert(windows, south:getWindow())
        elseif square:isWindowTo(east) then
            table.insert(windows, east:getWindow())
        end
    end
    return windows
end
vagrant basalt
#

Should that be an API ?

#

Bcs I'd rather we don't spread the usage of the same Lua file like Item Tweaker....

#

Good job anyway but yes please make that an API !

tough pivot
charred ridge
vagrant basalt
charred ridge
subtle furnace
vagrant basalt
waxen wyvern
#

sorry

tough pivot
#

Tiny Timer. Call it with tinyTimer(5) to wait 5 seconds

local function tinyTimer(seconds)
    local OnTick
    local start = os.time()
    local stop = start + seconds
    OnTick = function()
        if os.time() < stop then
            return
        end
        -- do you thing here
        Events.OnTick.Remove(OnTick)
    end
    Events.OnTick.Add(OnTick)
end```
charred ridge
charred ridge
tough pivot
wicked thistle
#

Yo chat,The "better fps" mod It doesn't work anymore for this update, and I really need it, can someone make a patch?

charred ridge
charred ridge
# charred ridge ever wonder how large a loaded chunk is? i mean visually everything outside of t...

more ingfo about this
so i learned that
you dont have access to the entire 300x300 cekk


local function countLoadedSquares(isForce)
    local pl = getPlayer()
    local cell = getCell()

    local cellX = math.floor(pl:getX() / 300)
    local cellY = math.floor(pl:getY() / 300)
    local startX = cellX * cell:getHeight()
    local startY = cellY * cell:getWidth()
    local z = 0
    local count = 0
    if not cell then return end

    for y = startY, startY + 299 do
        for x = startX, startX + 299 do
            local sq = cell:getGridSquare(x, y, z)
            if not sq and isForce then
                sq = cell:getOrCreateGridSquare(x, y, z)
            end
            if sq then
                count = count + 1
            end
        end
    end
    return count
end
print(countLoadedSquares(false)) -- 36100
print(countLoadedSquares(true)) -- 90000


local function getCellCentersForce(isForce)
    local pl = getPlayer()


    local cellX = math.floor(pl:getX() / 300)
    local cellY = math.floor(pl:getY() / 300)
    local startX = cellX * 300
    local startY = cellY * 300
    local z = 0

    local centerX = startX + 149
    local centerY = startY + 149

    local cell = getCell()
    local centerSquare = cell:getGridSquare(centerX, centerY, z)
    if isForce then
        centerSquare = cell:getOrCreateGridSquare(centerX, centerY, z)
    end
    print("\n")
    if centerSquare then
        print("Center Sq Coords: "..centerX..' '..    centerY)
        print(tostring(centerSquare))
        local dist = pl:DistTo(centerX, centerY)
        print("Ditance: ".. tostring(round(dist)))
        return centerSquare
    else
        print("not loaded")
        return nil
    end


end
getCellCentersForce(true)

vagrant basalt
#

getOrCreateGridSquare ?

vagrant basalt
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
charred ridge
tough pivot
#

Change craftRecipe outputs on the fly

local originalRecipe = getScriptManager():getCraftRecipe("Base.SawLogs")
local newRecipe = getScriptManager():getCraftRecipe("JBLogging.JBSawLogs")

originalRecipe:getOutputs():clear()

for i = 0, newRecipe:getOutputs():size() - 1 do
    local newOutput = newRecipe:getOutputs():get(i)
    originalRecipe:getOutputs():add(i, newOutput)
end

It would probably work with inputs but I never tried it. The newRecipe is set as NeedTobeLearn = true so it's hidden from the player. There might be a better way to hide the recipe that I haven't found yet.

charred ridge
charred ridge
#

checking game versions


local function isB42()
    local version = getCore():getGameVersion()
    return version and version:getMajor() >= 42 
end


local function isB41()
    local version = getCore():getGameVersion()
    return version and version:getMajor() == 41 
end

alternative method

local function isB42()
    return luautils.stringStarts(getCore():getVersion(), "42")
end


local function isB41()
    return luautils.stringStarts(getCore():getVersion(), "41")
end



output examples:

print(getCore():getGameVersion())
--returns 42.11
print(getCore():getVersion()) 
--returns 42.11.0  rev:30715 2025-08-04 18:15:07 (ZB)