Creating Mods

I don't know what this article looked like on the original wiki, but it didn't survive the transfer very well. The XML file was an absolute mess. I've cleaned it up as well as I can, but it's still a very difficult page to read - hopefully someone that actually understands modding can improve it further. -Pocket


This explanation written by julzor.


First of all, I suggest getting a copy of Girl Life from GitHub, since that gets the files and utilities that you will need to use. https://git.catrenelle.com/Kevin_Smarts/glife


You can open another mod (or any .qsp file) with QGen 5. QGen 5 is in the main repository of Girl Life. For instance, I cloned the Girl life repository in the folder "~/GitHub/glife". QGen 5 is "~/GitHub/glife/QSP/QGen5/QGen.exe".


Since I'm using MacOS, I start it with wine, which works just fine.

wine "~/GitHub/glife/QSP/QGen5/QGen.exe"


(Junjulaug75 note: I couldn't check this line because I don't have wine. Please check this KeyMAsterOfGozer)


To understand how a mod is set up: Open up an existing mod and look at the locations. Illume made two examples mods easy to install and understand, they should be in the forum, in the mod thread; they add a couple of basic actions to the game, but it''s better to not rush things.


Open the mod you prefer and look for the three locations (assuming the modder didn't change the locations order, they will work anyway...)

Every mod should have these:

mod_modname_setup

mod_modname_readme

mod_modname


Remember that the "modname" part in these is substituted with the actual mod's name. So in the case of the iwhore mod, these locations are:

mod_iwhore_setup

mod_iwhore_readme

mod_iwhore


1) mod_modname_setup

This location sets up basic info to be displayed in the mods admin page in the main app. Should look something like this:

!input basic mod information here.

!this location must be the first one


$mod_info[0] = 'pornster'

!0=mod name, saved to $mod_name[i] array

$mod_info[1] = '00100'

!1=mod version

!this will be displayed as version 1.2, fix3.

!if you input 40500, will be showen as version 4.5

$mod_info[2] = 'KeyMasterOfGozer'

!2=mod author

$mod_info[3] = 'Micro-manage porn schedule.'

!3=mod description, input a short brief here.


Illume worked his magic here: $mod_info[0] will be the name of your mod, but not the location that will be checked for. Pay attention to what's added before and after

mod_info[0]

In that case "mod_" and "_setup". So the location that it will be checked is "mod_modname_setup"

if curloc = 'mod_<<$mod_info[0]

usehtml = 1

!this will be only showed if you exec mod file. This location should be only called by gs, so this line will not trigger on normal mod playing

'<center><h1><font color=red>ACCESS DENIED</font></h1></center>

$mod_info[0] is a mod for Girl Life - English Community Version and can not be played individually.'

'You can find the main game in Tfgames site (external link)

'Our forum: Tfgames site (external link)'



2) mod_modname_readme

This location is just to give a detailed description for the main app's modpage. Should look something like this:

if curloc = 'mod_<<$mod_info[0]>>_readme':

'Mod <center><b>< font color=red> Pornster </font></b></center>'

'Mod is to allow fine-grained tweaking of the porn schedule. This is mostly just for me to get my feet wet making a mod.'

end

And the "core" of your mod will be checked it the same way. It's not displayed here but in the main game mod location... Anyway, once in game you read the detailed description written by the mod author you just installed the mod...


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

3) mod_modname


This location gets run in every location in the game. So for this reason, it's probably best practice to make whatever you put here be a light as possible. It should probably only be a set of if statement checks that see if the current location that is actualy running is one that your mod is interested in. For instance, if you mod does something in your appartment in the city, you should check to see if the current location is the appartment in the city, and then do stuff. Probably a good idea to do a "gs" or "gt".

Example:

if curloc = 'mod_<<mod_info[0]>>_readme':

!input mod entry point here. this will be checked on every location, please keep it clean and brief to avoid game lag

!pornstudio

if $curloc = 'pornstudio': act "Hack the Schedule": gs 'mod_pornster_hack'

end


Notice, all this example does is add an additional action if the player is currently in the Porn Studio location.

The action then points them off to a safer location that acts more normally and is not run for all locations.


!!!!!PAY ATTENTION!!!!!!!


4) ALL INCLUDED LOCATIONS MUST BE NAMED IN THE FORMAT "mod_modname_locationname"

The "core" location of the mod not only will be checked by Illume's magic everytime... . The check that allow the mod to be used do not accept locations that have not the prefix "mod_" and the name of the mod itself. EVERY LOCATIONS.

So if you are used to create a location to store names variable code part number values and what do you want, and you are used to call it for example "notes"... doing that you will make a great mess. Instead call the storing location "mod_modname_notes" and everything will be fine.

A single location that have not the format "mod_modname_xxxxxx" will break the mod and it won''t load or will give error; be sure to double check the location format and the "_" break line symbol (put the correct name here)


Here is another sample from @julzor:

location: mod_testmod

if $loc = 'korrPar' and hour > 0 and hour < 6: gt 'mod_testmod_korrParAddition', 'night_event'

location mod_testmod_korrParAddition

if $ARGS[0] = 'night_event':

> add event

end

or if we also want to add a new action to korrPar, that is always there,

for example to go to the new balcony (we use a gs and not a gt):

location: mod_testmod

if $loc = 'korrPar' and hour &gt; 0 and hour &lt; 6: gt 'mod_testmod_korrParAddition', 'night_event'

if $loc = 'korrPar': gs 'mod_testmod_korrParAddition', 'new_action'

location mod_testmod_korrParAddition

if $ARGS[0] = 'night_event':

> add event

end

if $ARGS[0] = 'new_action':

act 'Go to the balcony: gt 'mod_testmod_balcony'

end



Some other words and examples from Junjulaug75...(absolutely in a terrible english)

$loc is a named stored variable (remember that "$" allow to store variable as name...) that Girl Life use sometimes to adress locations as long as $metka; they probably comes from the russian authors...

If the location you want to check is addressed that way, when you enter there you will have no problems; also Girl Life use in most of its location this address so you should go smooth most of the times...

IF NOT USE INSTEAD:

"$curloc"

"$curloc" is something that is part of the qgen/qsp: it stores the locations you visit independantly by the action you made: it will be always been checked...


Let summarize for the moment... .

Mod name conventions:

"mod_" will be the prefix for every location so if your mod will be called "wonderwoman", your core location will be "mod_wonderwoman".

The first two location have to be called "mod_wonderwoman_setup" "mod_wonderwoman_readme".

Then if you want to create a new location called "planet" it cannot be called simply "planet" but "mod_wonderwoman_planet".


Do not make a mess with names:

"notes" location: will make a mess

"mod_wonderwoman_notes" location: you can go smooth


What happen when you wrote "if $loc = 'school': act'stuff': gt 'school', 'lesson'" in your "core" mod location (mod_modname)?

If the location "school" address itself in that way $loc = 'school'

location: school

$loc = 'school'

$metka = 'something'

if $args[0]='lesson':

act 'study': stuff.................

end

...then when you will go to school you will go straight to the location "school" $args[0] = 'lesson'...

If not

location: school

$loc = 'something_blue'

$metka = 'something_green'

if $args[0]='lesson':

act 'study': stuff.................

end

that's because the check failed due to the lack of "$loc = 'school'" in the location school; in that case you should use "if $curloc" because it will be stored always.

We'll return to that later

Couple of examples:

If you want to add an action when you spray milk from your boobs at school...then you should do something like that in your mod:

First you should start, so you should create the three location in the right way. Copy/past the three locations Illume created. Rename them with the right format, adjust them according to your mod description and names or the setup will go wrong; you could use search/replace with qgen, but my advice is to have a look in them and do that manually; it will help you in a better coding understanding...

You should have the right named locations and setted

"mod_wonderwoman_setup"

"mod_wonderwoman_readme"

"mod_wonderwoman".


Now create a new location and name it

"mod_wonderwoman_milk"


Write in "mod_wonderwoman_milk" these lines

if $args[0] = 'wave':

msg 'why having boobs if i cannot shoot with them?...'

act 'SHOOT!': gt 'mod_wonderwoman_milk','no_wave'

end

if $args[0] = 'drink':

hydra += 20

act 'I think i have no more...': gt 'school_ground', 'start'

end

if $args[0] = 'no_wave':

msg 'Crap...i did not wrote how to wave...'

act 'return': gt 'school_ground', 'start'

end


Write in your "core" location ("mod_wonderwoman") these lines

#Location:"mod_wonderwoman"

if $curloc = 'school_ground' and $args[0] = 'start':

act 'spray milk': gt 'mod_wonderwoman_milk','wave'

act 'nahhh....i''m thirsty': gt 'mod_wonderwoman_milk','drink'

end&lt;/nowiki&gt;&lt;/code&gt;


TIPS

From the new location you created you return back with gt 'school_ground', 'start' (...assuming the school_ground is a location i may be wrong and it could be gschool_ground....just look for it in the main game...)That will happen if the location has inside an $args[0] = 'start'.

Location can be entered even if they have no $args[0]; in that case you will go there simply with gt 'school_ground'. That is valid even when searching locations: if the location school_ground (or gschool_ground) has inside an $arg[0]='start' that is probably the entry point:

'school_ground'

and you will look for it that way.


if $curloc = 'school_ground' and $args[0] = 'start':

otherwise the entry point it's simply


'school_ground', 'start'

and you will look for it that way


if $curloc = 'school_ground':

The entry point is usually what have the main pic of the location of course; that is not valid if the location you are looking for is not a "physical" one.


DELETING ACTIONS

If you want to delete an action that is in game you should use "delact" and rewrite the act you just deleted as you wish (i'm not a master about it...) but it will be in the form:

#Location:"mod_wonderwoman"

if $curloc = 'school_ground' and $args[0] = 'start':

delact 'Go school'

act 'Go school': gt 'mod_wonderwoman_milk','milk_school'

end&lt;/code&gt;

Of course the location 'school_ground' have to have the action "go school" (...i don't remember actually....) Do not commit mispell: if you are deleting the action "go school" you are deleting the action "go school" and not "go school naked"

...to delete "go school naked" use

delact "go school naked"

(...this for sure is not in the game....)

AVOID TO USE DYNAMICS

From what i know dynamics stores something that can be used easily by the game...anyway Illume said to not use them, you should recreate what the dynamics do and use what you created...that's a pain....

Let made it simple: shower is one of the things that is called with "dynamic" in that way:

dynamic $showerdin

So if you want to call the use of shower in your mod you should recreate what dynamic does inside your mod and call them in another way: i do that with

gs 'mod_modname_alocationthatstoresallthedynamicsiused'

(not called that way obviously)


This is the dynamic form for the shower:

$showerdin = {

menu_off = 1

if hypnoAddict = 0:

cumspclnt = 1

else

cumspclnt = 18

end

gs 'cum_cleanup'

pcs_hairbsh = 0

pcs_makeup = 1

if pcs_sweat &gt; 10: pcs_sweat = 10 + rand(0,4)

if false_lashes &gt;= 1:

if rand(0,4) &lt;= 2:

'You''re careful enough that your false lashes make it through relatively unscathed.'

else

'Unfortunately, your false lashes don''t make it through the shower.'

false_lashes = 0

pcs_lashes = pcs_naturallashes

gs 'body_shape', 'basebeautycalc', 1

end

end

}


That's what i do:

I create 'mod_modname_alocationthatstoresallthedynamicsiused' location ...then i put in there

if $args[0] = 'showerdin':

menu_off = 1

if hypnoAddict = 0:

cumspclnt = 1

else

cumspclnt = 18

end

gs 'cum_cleanup'

pcs_hairbsh = 0

pcs_makeup = 1

if pcs_sweat &gt; 10: pcs_sweat = 10 + rand(0,4)

if false_lashes &gt;= 1:

if rand(0,4) &lt;= 2:

'You''re careful enough that your false lashes make it through relatively unscathed.'

else

'Unfortunately, your false lashes don''t make it through the shower.'

false_lashes = 0

pcs_lashes = pcs_naturallashes

gs 'body_shape', 'basebeautycalc', 1

end

end

end

and i call that dynamic as a state:


'mod_modname_alocationthatstoresallthedynamicsiused', 'showerdin'


AGAIN: DYNAMICS CAN CALL FOR OTHER DYNAMICS INSIDE THEMSELF(...and the pain rise...and rise ...and rise...)


Another hint: pay attention to the main game changes.

Sometimes authors change the entry to a location; the entry in the park of pavlovsk, for example, time ago was simply gt 'gskver', because the entry were outside an $args[0].

It can happen that you wrote that correctly at the beginning but then things changed... .