Jump to content

Adding new professions in 2.9.9.17


Banjo

Recommended Posts

I'm trying to figure out of my noobish coding skills (aka "guesswork") are what's causing PZ to crash on loading a save, or if there's something hinky in 2.9.9.17 regarding adding professions that's causing said crash (after the title sequence) when my mod is loaded.

 

I assume that it's my fault, because I can get the 'Action Hero' profession mod to load just fine.

 

So... what's wrong with my code?

function DoProfessions()    local model = ProfessionFactory.addProfession("model", "Model", "Prof_ParkRanger");    model:addFreeTrait("LightEater");    model:addFreeTrait("Graceful");endEvents.OnGameBoot.Add(DoProfessions);

Something obvious, I'm sure... but what have I screwed up?

 

Note that I can create new traits just fine and have the game use them/not crash. It's adding professions that causes the game to crash for me.

Link to comment
Share on other sites

You should check out RegularX's Xmod which adds a ton of new professions:

 

http://theindiestone.com/forums/index.php/topic/912-wip-xmod/

 

 

Can't see anything wrong with it (besides being a global function :P) on the first look. Do you get any errors?

Thanks for the reply, mate.

 

When the mod is loaded, my profession appears in the list on making a new character. So I choose it, start the game (with no other traits), the titles play up until "This is how you died"... aaaand then it freezes on a black screen. Console window says:

Exception in thread "Thread-6" java.lang.NullPointerException        at zombie.iso.IsoLot.<init>(IsoLot.java:173)        at zombie.iso.CellLoader.LoadCellBinaryChunkForLater(CellLoader.java:394)        at zombie.iso.IsoChunk.LoadForLater(IsoChunk.java:259)        at zombie.iso.IsoChunkMap.LoadChunkForLater(IsoChunkMap.java:114)        at zombie.iso.CellLoader.LoadCellBinaryChunk(CellLoader.java:438)        at zombie.iso.IsoWorld.init(IsoWorld.java:914)        at zombie.gameStates.GameLoadingState$1.run(GameLoadingState.java:138)        at java.lang.Thread.run(Unknown Source)

... which means nothing to me, I'm afraid. :(

 

I even tried copying the Action Hero profession line for line and just changing the free traits and names... same crash, yet the original version loads fine... which is confusing as hell to me! :)

 

(XMod looks very cool, by the way... thanks for the link!)

Link to comment
Share on other sites

That was the problem! I'd not messed with those before (I don't believe it was needed in older builds) but that made total sense the moment I read it (why the code seemed 'right' yet crashed, but only crashed on game/map load).

 

Now I need to learn how spawn points for professions work (is there a link anywhere to a discussion on this?)

 

Anyway, thanks HEAPS for the help, folks! Not only has this let me fix/continue my mod, but has taught me two new things about modding PZ: spawnpoints and avoiding global functions (something else that didn't matter it seemed in old mods, but makes sense to not do).

 

But now i can make this work, it's time to start making icons/graphics... :)

Link to comment
Share on other sites

Oh I mistyped ... I meant that the function isn't stored in a "global table" like:

 

MyMod = {} function MyMod.doProfessions()    local model = ProfessionFactory.addProfession("model", "Model", "Prof_ParkRanger");    model:addFreeTrait("LightEater");    model:addFreeTrait("Graceful");endEvents.OnGameBoot.Add(MyMod.doProfessions);

 

Well I just started using local functions myself yesterday ... they are a bit confusing because they don't quite work like private functions in java:

 

local function doProfessions()    local model = ProfessionFactory.addProfession("model", "Model", "Prof_ParkRanger");    model:addFreeTrait("LightEater");    model:addFreeTrait("Graceful");endEvents.OnGameBoot.Add(doProfessions);
Link to comment
Share on other sites

No discussion on spawnpoints outside of that thread, that I know of - you'll want to look at MainCreationMethods and CharacterCreationProfession, I think.

 

The problem I ran into customizing them is that I'm not entirely sure how the coordinates listed in the spawnpoint are being translated to the map itself - or to be more accurate, the opposite of that.  CharacterCreationProfession has:

if spawn then				local randSpawnPoint = spawn[(ZombRand(#spawn) + 1)];				getWorld():setLuaSpawnCellX(randSpawnPoint.worldX);				getWorld():setLuaSpawnCellY(randSpawnPoint.worldY);				getWorld():setLuaPosX(randSpawnPoint.posX);				getWorld():setLuaPosY(randSpawnPoint.posY);			end

So it's determining the right cell, and the right coordinates in that cell ... but I haven't seen methods off of Square which reports back the same LuaSpawnCellX/LuaPosX figures.  I wanted to add a Farmer profession to Xmod which just lets players start at one of the farms, but I'm not sure how to run to one of those farms and console back the right coordinates.  But I'm quite probably missing something.  That's also way right now all the XProfessions just dupe the unemployed spawn point.

Link to comment
Share on other sites

 

Oh I mistyped ... I meant that the function isn't stored in a "global table"...

That's okay, mate... I actually understood what you meant as soon as I looked at Xmod's scripts for an example.

 

Your own example above of my original code (thanks for going the extra mile!) resembles the ways I changed my code by hand as below...

BanjoProfessions = {}BanjoProfessions.DoProfessions = function()    local model = ProfessionFactory.addProfession("model", "Model", "media/ui/professions/prof_model.png");    model:addFreeTrait("LightEater");    model:addFreeTrait("Graceful");endEvents.OnGameBoot.Add(BanjoProfessions.DoProfessions);

... which is encouraging, to say the least! :)

 

But how do I express...

function GiveProfessionItemsBanjo(player,square)

... as a local value? It's the only one from my mod I got stuck on converting!

 

As to why this is better done this way... as a non-programmer, I'm assuming tidiness and compatibility?

 

No discussion on spawnpoints outside of that thread, that I know of - you'll want to look at MainCreationMethods and CharacterCreationProfession, I think.

 

The problem I ran into customizing them is that I'm not entirely sure how the coordinates listed in the spawnpoint are being translated to the map itself - or to be more accurate, the opposite of that.  CharacterCreationProfession has:

if spawn then

                local randSpawnPoint = spawn[(ZombRand(#spawn) + 1)];

                getWorld():setLuaSpawnCellX(randSpawnPoint.worldX);

                getWorld():setLuaSpawnCellY(randSpawnPoint.worldY);

                getWorld():setLuaPosX(randSpawnPoint.posX);

                getWorld():setLuaPosY(randSpawnPoint.posY);

            end

So it's determining the right cell, and the right coordinates in that cell ... but I haven't seen methods off of Square which reports back the same LuaSpawnCellX/LuaPosX figures.  I wanted to add a Farmer profession to Xmod which just lets players start at one of the farms, but I'm not sure how to run to one of those farms and console back the right coordinates.  But I'm quite probably missing something.  That's also way right now all the XProfessions just dupe the unemployed spawn point.

Interesting info.

 

Looking though your code (I can't wait to play your mod now, mate!), it took me a moment to realize that Xmod DID use the same spawnpoints when i copied them to my script to test your suggestion.

 

Definitely a worthwhile topic, I'd say, as part of the fun of adding custom professions is new spawn points, I think (logger at the lumber yard, tourist at the train station, etc.).

Link to comment
Share on other sites

function GiveProfessionItemsBanjo(player,square)

I'm not sure how the body of this function looks like but if it's just custom items you want then try the following:

CustomProfessions.startItems = function()          if    getPlayer():getDescriptor():getProfession() == "CustomProfession" then                getPlayer():getInventory():AddItem("Module.Item");          endendEvents.OnNewGame.Add(CustomProfession.startItems);

A little maths comes in handy to determine a spawn point:

{worldX=11, worldY=8, posX=116, posY=232} -- little house2

dumbs you at the coordinates x = 3416, y = 2632.

{worldX=1, worldY=1, posX=1, posY=1}

gets you to x = 301, y = 301. In other words worldX/Y is multplier of 300 for x/y.

 

You can use a simple getX/getY and then divide by 300 with the remainder going into posX/posY. That's how i did it, although i'm guessing that there is a more elegant way for this.

 

And btw, don't try to find the edge of the map. Chances are you freeze before you reach x/y = 49.

Link to comment
Share on other sites

But how do I express...

function GiveProfessionItemsBanjo(player,square)

... as a local value? It's the only one from my mod I got stuck on converting!

 

If you want to store your function into a global table, then you should do what The_Real_AI suggested. As to why you should do it: If you only name it GiveProfessionitemsBanjo it will conflict whenever there is another function of the same name because lua doesn't care if it is defined in a different script, so it is better to give it a unique position (similar to what packages do for java) and store it in a global table.

 

I started using local functions a few days ago. They are only available to the functions in the same script and can't be called from the outside. I'm not sure if it makes a difference when it comes to performance or memory allocation, but it doesn't pollute the global environment. If your function is only needed in one place you could make it a local function.

 

The problem is, that then you have to move away from using this

yourFunction = function(foo, bar)end

because the only way to declare it as a local varaible would be this (IIRC):

local yourFunction;yourFunction = function(foo, bar)end

Lua offers syntactic sugar for this, namely:

local function yourFunction(foo, bar)end

Which not only looks tidier, but also has some special meaning when it comes to recursive local functions. That's at least how far I understood it, but I suggest that you read this. This is an example of how I use global functions in my new mod:

 

local function forceOverwrite(_player)    if not _player:isAsleep() then        _player:getStats():setFatigue(SleepSchedule.currentFatigue);    endend----- Calculate what fatigue modifier should be applied based-- on the sleeping schedule.local function calculateFatigue()    local time = getGameTime(); -- get instance of Game Time    -- we have 0 to 24end----- Loads the saved data needed for the schedule calculation.--local function loadData()    local player = getSpecificPlayer(0);    local modData = player:getModData();    -- Stored fatigue    modData.storedFatigue = modData.storedFatigue or 0;    SleepSchedule.currentFatigue = modData.storedFatigue;    -- Sleep schedule times    -- TODO save as table - Currently saving tables in modData isn't possible     --    modData.sleepTimes = modData.sleepTimes or { 22, 22, 22, 22, 22, 22, 22 };    --    SleepSchedule.sleepTimes = modData.sleepTimes;    modData.sleepTime1 = modData.sleepTime1 or 22;    modData.sleepTime2 = modData.sleepTime2 or 22;    modData.sleepTime3 = modData.sleepTime3 or 22;    modData.sleepTime4 = modData.sleepTime4 or 22;    modData.sleepTime5 = modData.sleepTime5 or 22;    modData.sleepTime6 = modData.sleepTime6 or 22;    modData.sleepTime7 = modData.sleepTime7 or 22;    table.insert(SleepSchedule.sleepTimes, modData.sleepTime1);    table.insert(SleepSchedule.sleepTimes, modData.sleepTime2);    table.insert(SleepSchedule.sleepTimes, modData.sleepTime3);    table.insert(SleepSchedule.sleepTimes, modData.sleepTime4);    table.insert(SleepSchedule.sleepTimes, modData.sleepTime5);    table.insert(SleepSchedule.sleepTimes, modData.sleepTime6);    table.insert(SleepSchedule.sleepTimes, modData.sleepTime7);    Utility.tPrint(SleepSchedule.sleepTimes);end----- Saves the mod data.--local function saveData()    local player = getSpecificPlayer(0);    local modData = player:getModData();    modData.storedFatigue = SleepSchedule.currentFatigue;    modData.sleepTime1 = SleepSchedule.sleepTimes[1]    modData.sleepTime2 = SleepSchedule.sleepTimes[2]    modData.sleepTime3 = SleepSchedule.sleepTimes[3]    modData.sleepTime4 = SleepSchedule.sleepTimes[4]    modData.sleepTime5 = SleepSchedule.sleepTimes[5]    modData.sleepTime6 = SleepSchedule.sleepTimes[6]    modData.sleepTime7 = SleepSchedule.sleepTimes[7]end-- -------------------------------------------------- Game Hooks-- ------------------------------------------------Events.EveryTenMinutes.Add(calculateFatigue);Events.OnPlayerUpdate.Add(forceOverwrite);Events.OnGameStart.Add(loadData);Events.OnSave.Add(saveData); 

 

You can use a simple getX/getY and then divide by 300 with the remainder going into posX/posY. That's how i did it, although i'm guessing that there is a more elegant way for this.

 

 

getX / getY get you the absolute Position on the map, whereas after a division by 300 you get the correct chunk IIRC - afaik that's how the devs to their thingy too :)

Link to comment
Share on other sites

 

function GiveProfessionItemsBanjo(player,square)

A little maths comes in handy to determine a spawn point:

{worldX=11, worldY=8, posX=116, posY=232} -- little house2

dumbs you at the coordinates x = 3416, y = 2632.

{worldX=1, worldY=1, posX=1, posY=1}

gets you to x = 301, y = 301. In other words worldX/Y is multplier of 300 for x/y.

 

You can use a simple getX/getY and then divide by 300 with the remainder going into posX/posY. That's how i did it, although i'm guessing that there is a more elegant way for this.

 

And btw, don't try to find the edge of the map. Chances are you freeze before you reach x/y = 49.

 

 

 

Ah, thanks again Al - now The Farmer might make it into Xmod after all.

Link to comment
Share on other sites

I've been attempting a 'Farmer' profession myself, too, with a higher starting farming skill, and it got me wondering if there is way to make a character start out at a certain "level" in a certain skill... or can they only be given free XP points that the player must then assign themselves in the skill panel?

 

For example:

BanjoTraits = {}BanjoTraits.GiveEIEIOStuff = function()    local player = getSpecificPlayer(0);    local playerData = player:getModData();    playerData.TraitStuffEIEIO = playerData.TraitStuffEIEIO or "false";    if(playerData.TraitStuffEIEIO == "false") then        if player:HasTrait("EIEIO") then            getPlayer():getXp():AddXP(Perks.Farming, 1890);            playerData.TraitStuffEIEIO = "true";        end    endendBanjoTraits.DoTraits = function()    TraitFactory.addTrait("EIEIO", "E-I-E-I-O", 0, "Increased farming skill.", true);endEvents.OnGameBoot.Add(BanjoTraits.DoTraits);Events.OnGameStart.Add(BanjoTraits.GiveEIEIOStuff);

... will give the player enough free XP points in the farming skill to reach Level 3... but the player still needs to open the skill panel and click each level ("+") to finalize this.

 

Is there a way to have a trait set a starting skill level automatically (with no need for player input), or is this an engine limitation?

Link to comment
Share on other sites

I haven't found a way to do it without the player having to use the points.  Which I honestly find an odd system - what else the user going to do with them?

Agreed! Since you gain XP for a certain skill only, why doesn't it then auto-level-up?

 

Thanks for the input. I've been going over the code trying to figure it out, to no avail. You're way ahead of me in modding skills, so if you didn't find it either, I suspect it might not be possible. it would be neat if such a script function could be added at some point, though.

Link to comment
Share on other sites

I haven't found a way to do it without the player having to use the points.  Which I honestly find an odd system - what else the user going to do with them?

Agreed! Since you gain XP for a certain skill only, why doesn't it then auto-level-up?

 

Thanks for the input. I've been going over the code trying to figure it out, to no avail. You're way ahead of me in modding skills, so if you didn't find it either, I suspect it might not be possible. it would be neat if such a script function could be added at some point, though.

A dangerous assumption :). one of the things I love about this forum is that I'm constantly finding out new stuff. Though unless poking at the code for the UI which cashes in on those points, this one might be a blocker. Could be worth a post on the suggestion forum, the XP system feels like something with a strong backbone but low priority for tweaking.

Link to comment
Share on other sites

In regards to the discussion here about adding spawn points, I just spent a day going around the game map and generating a whole bunch of co-ordinates for places of interest (farms, stores, cabins, etc.) for use with my own WIP "alternate start" mod (which I'll be posting tonight or tomorrow, after a few final tests).

 

I owe a ton of gratitude to other modders here for their tools/help for being able to do this (The_Real_Al, RegularX, RoboMat and Blindcoder, in particular), so I wanted to ask... would my info be useful to anyone else? I haven't seen any starting position changing mods, but the data I gathered could be helpful to those who want to make such a thing.

 

It's currently in the form of an Excel spreadsheet I created to calculate the correct spawn values off in-game co-ordinates (thanks, Co-Ordinate Viewer mod!) based on The_Real_Al's formula posted in this thread (major thanks, mate... none of this would be possible without knowing that info!), and contains spawn points for almost every non-residential building in Muldraugh town, some of the outskirts, and a few faraway places like Dixie Mobile Park and the distant farm (near Pony Roam-o Ranch). basically, if it's on the Project Zomboid Map Project map, I travelled there and grabbed some co-ordinates! I just hope someone hasn't already done this and I wasted my time... ;)

 

(nah, regardless, it was fun to take a grand tour of the PZ world, something I've not had the chance to do when playing "properly"!).

 

I find it really refreshing to be able to start a new game somewhere totally new, like at the TIS Construction yard, the second farm that's normally miles away, or in my new favourite hangout: Dixie Mobile Park. It's also rather atmospheric to start off, as I just did on a random test run, in a dark jail cell at Muldraugh PD!

Link to comment
Share on other sites

Hey guys,

 

I now use the "unemployed" spawn point if you don't have set specific spawn point for your new profession, that should avoid that kind of problem :)

 

Cheers !

Thanks! Great idea, and helpful for those who either don't know how/they need to set it... or for those of us who forget! :)

 

 

contains spawn points for almost every non-residential building in Muldraugh town

 

Ah, i get all foamy around the corners of my mouth. Post it!

 

Heh! Sure thing! I was going to post it right now, but decided to add a few more locations to it first. Will get it posted ASAP (in the "resources" section) for ya. Thanks again for the help!

Link to comment
Share on other sites

In regards to the discussion here about adding spawn points, I just spent a day going around the game map and generating a whole bunch of co-ordinates for places of interest (farms, stores, cabins, etc.) for use with my own WIP "alternate start" mod (which I'll be posting tonight or tomorrow, after a few final tests).

Hey Banjo, did you post this spreadsheet already? I would love to see it - would probably help a ton of people :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...