News:

Please request registration email again and then check your "Spam" folder

Former www.henthighschool.com

[Resources] Writing events for BK

Started by Goldo, May 19, 2022, 09:17 AM

Previous topic - Next topic

AlolanNinetales

I don't know if anyone has already tried doing this, but I was wondering if it were possible for a girl to "transform" and use a different set of girlpack images once she transforms into her new form. For example, she would transform after reaching a certain threshhold in Love or other stats, and then she would stop using her previous girlpack pictures and use new ones. This would hopefully work like the the angel from monster girl club bifrost. After she got enough libido, she would turn into her dark angel form and would only see pictures of her in that form. Obviously this would mean in her "girlpack" there would be another folder with all of her new transormation's pics.

Jman

As far as I can tell, you can just change her 'path' to another girlpack's and that's it. Doesn't even need to include the mix name if she's in a mix directory.

E.g.
MC.girls[0].path = 'Batgirl'
MC.girls[0].refresh_pictures() # for portraits and profiles to change immediately

I'm not sure you can use a girlpack subdirectory for this. But you can make the 'Dark Angel' pack 'generate_as = "story"' so it never generates any girls on its own.
And with strange aeons even death may die...

Necrilem

(I hope this is the right place to ask for help with this)

So, I am working on a girl pack I want to give 2 custom traits to.
I have given a custom trait to a girl before but am not sure how exactly I would add a second one.
Might be a dumb question with an easy and obvious solution, but could someone help me with this?

Here an example of how I added a custom trait until now:

init -2 python:

    def void_hunter(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

    # This code is executed when your girl is being created (for her first appearance in the slavemarket or in the city)
    # The trait is added to whatever other traits she already spawns with

        global gold_traits, pos_traits, neg_traits
        global trait_dict

        # Start by defining your trait
        # If you just want to add a Trait King trait, you can copy it from /game/Mods/Trait King.rpy

        my_custom_trait = Trait("Void Hunter", verb="be a", effects=[Effect("boost", "body", 0.25), Effect("change", "all sex skills", 5, scales_with="rank"), Effect("boost", "constitution", 0.25), Effect("change", "all skill max", 10, scales_with = "rank"), Effect("change", "defense", 5), Effect("boost", "max energy", 0.3), Effect("boost", "prestige", 3)], archetype="The Model", base_description = "She is a Void Hunter and immensely powerful. The last line of defense against the strongest of Ethereals.")

        try: # Plan A: If Trait King (or any other mod) is active and you're asking for a trait that's already in the dictionary

            girl.add_trait(trait_dict[my_custom_trait.name], _pos=1) # pos determines where in the girl's trait list the trait appears

        except: # This is Plan B if the above fails. It adds the trait to a category and dictionary before adding it to the girl

            # You can remove or comment out the line below if you want to add a unique trait that will not randomly appear on new generated girls
            gold_traits += [my_custom_trait] # change to gold_traits, pos_traits or neg_traits as desired

            trait_dict[my_custom_trait.name] = my_custom_trait

            girl.add_trait(trait_dict[my_custom_trait.name], _pos=1) #

        return

Jman

#243
I think these days it's done via the 'register_trait()' function. Like this:
voidhunter_trait = Trait("Void Hunter", verb="be a", effects=[Effect("boost", "body", 0.25), Effect("change", "all sex skills", 5, scales_with="rank"), Effect("boost", "constitution", 0.25), Effect("change", "all skill max", 10, scales_with = "rank"), Effect("change", "defense", 5), Effect("boost", "max energy", 0.3), Effect("boost", "prestige", 3)], archetype="The Model", base_description = "She is a Void Hunter and immensely powerful. The last line of defense against the strongest of Ethereals.")

register_trait(voidhunter_trait, type="gold")

girl.add_trait(trait_dict[voidhunter_trait.name], _pos=1)

failed_hunter_trait = Trait("Failed Hunter", verb="be a", effects=[Effect("boost", "body", -0.25), Effect("change", "all sex skills", -5, scales_with="rank"), Effect("boost", "constitution", -0.25), Effect("change", "all skill max", -10, scales_with = "rank"), Effect("change", "defense", -5), Effect("boost", "max energy", -0.3)], base_description = "She was a Void Hunter but is now cursed by the gods.")

register_trait(failed_hunter_trait, type="neg")

girl.add_trait(trait_dict[failed_hunter_trait.name], _pos=len(girl.traits))

This is all still within your 'def void_hunter(girl)' function.



Do note that increasing 'max energy' without a corresponding 'energy' increase is not particularly useful.



The 'register_trait()' function is not as robust as neronero's case-by-case handling and will override anyone else's 'Void Hunter' traits. So there might be some strangeness if two custom girls use different traits with the same names.
And with strange aeons even death may die...

Necrilem

#244
Quote from: Jman on Nov 01, 2025, 09:19 PMI think these days it's done via the 'register_trait()' function. Like this:
voidhunter_trait = Trait("Void Hunter", verb="be a", effects=[Effect("boost", "body", 0.25), Effect("change", "all sex skills", 5, scales_with="rank"), Effect("boost", "constitution", 0.25), Effect("change", "all skill max", 10, scales_with = "rank"), Effect("change", "defense", 5), Effect("boost", "max energy", 0.3), Effect("boost", "prestige", 3)], archetype="The Model", base_description = "She is a Void Hunter and immensely powerful. The last line of defense against the strongest of Ethereals.")

register_trait(voidhunter_trait, type="gold")

girl.add_trait(trait_dict[voidhunter_trait.name], _pos=1)

failed_hunter_trait = Trait("Failed Hunter", verb="be a", effects=[Effect("boost", "body", -0.25), Effect("change", "all sex skills", -5, scales_with="rank"), Effect("boost", "constitution", -0.25), Effect("change", "all skill max", -10, scales_with = "rank"), Effect("change", "defense", -5), Effect("boost", "max energy", -0.3)], base_description = "She was a Void Hunter but is now cursed by the gods.")

register_trait(failed_hunter_trait, type="neg")

girl.add_trait(trait_dict[failed_hunter_trait.name], _pos=len(girl.traits))

This is all still within your 'def void_hunter(girl)' function.



Do note that increasing 'max energy' without a corresponding 'energy' increase is not particularly useful.



The 'register_trait()' function is not as robust as neronero's case-by-case handling and will override anyone else's 'Void Hunter' traits. So there might be some strangeness if two custom girls use different traits with the same names.

Thanks, I'll try it out after dinner.

Not sure I understand what you mean with the energy. Doesn't Effect("boost", "max energy", 0.3) just increase the max energy by 30%? Do I need to use Effect("boost", "energy", 0.3) as well?

So, if I add another custom girl who is also supposed to have the same void hunter trait, it could cause issues?

Jman

'Max energy' just extends the bar, it doesn't make energy regenerate faster. 'Energy' does. So having only the first means you can make your girl work longer shifts, but she won't be working more hours overall. Because the longer shifts also require longer rest periods.

So, yeah, you need ("boost", "energy"), too, unless you're trying to accomplish something specific (an insomniac girl, maybe?).



If the trait is the exact same, there probably won't be issues. Maybe. IDK. I think nothing really checks the trait dict for any kind of functionality. Personally, I'd still do:
        try:
            girl.add_trait(trait_dict["Void Hunter"], _pos=1)
        except:
            voidhunter_trait = Trait("Void Hunter", verb="be a", effects=[Effect("boost", "body", 0.25), Effect("change", "all sex skills", 5, scales_with="rank"), Effect("boost", "constitution", 0.25), Effect("change", "all skill max", 10, scales_with = "rank"), Effect("change", "defense", 5), Effect("boost", "max energy", 0.3), Effect("boost", "prestige", 3)], archetype="The Model", base_description = "She is a Void Hunter and immensely powerful. The last line of defense against the strongest of Ethereals.")

            register_trait(voidhunter_trait, type="gold")

            girl.add_trait(trait_dict[voidhunter_trait.name], _pos=1)
And with strange aeons even death may die...

Necrilem

#246
Quote from: Jman on Nov 01, 2025, 09:38 PM'Max energy' just extends the bar, it doesn't make energy regenerate faster. 'Energy' does. So having only the first means you can make your girl work longer shifts, but she won't be working more hours overall. Because the longer shifts also require longer rest periods.

So, yeah, you need ("boost", "energy"), too, unless you're trying to accomplish something specific (an insomniac girl, maybe?).



If the trait is the exact same, there probably won't be issues. Maybe. IDK. I think nothing really checks the trait dict for any kind of functionality. Personally, I'd still do:
        try:
            girl.add_trait(trait_dict["Void Hunter"], _pos=1)
        except:
            voidhunter_trait = Trait("Void Hunter", verb="be a", effects=[Effect("boost", "body", 0.25), Effect("change", "all sex skills", 5, scales_with="rank"), Effect("boost", "constitution", 0.25), Effect("change", "all skill max", 10, scales_with = "rank"), Effect("change", "defense", 5), Effect("boost", "max energy", 0.3), Effect("boost", "prestige", 3)], archetype="The Model", base_description = "She is a Void Hunter and immensely powerful. The last line of defense against the strongest of Ethereals.")

            register_trait(voidhunter_trait, type="gold")

            girl.add_trait(trait_dict[voidhunter_trait.name], _pos=1)


Tried setting up 2 custom traits, but whenever I try to launch the picture tagging tool, I get a "Parsing the script failed."

This is the _events.rpy I'm trying:

init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

    # This code is executed when your girl is being created (for her first appearance in the slavemarket or in the city)
    # The trait is added to whatever other traits she already spawns with

        global gold_traits, pos_traits, neg_traits
        global trait_dict

        # Start by defining your trait
        # If you just want to add a Trait King trait, you can copy it from /game/Mods/Trait King.rpy

       
elite_bodyguard_trait = Trait("Elite Bodyguard", verb="be an", effects=[Effect("change", "defense", 5), Effect("change", "body", 10, scales_with = "rank"), Effect("boost", "constitution", 0.2), Effect("boost", "xp gains", 0.1), Effect("boost", "energy", 0.2)], archetype="The Model", base_description = "She is the bodyguard of Astra Yao, New Eridu's most iconic songstress.")

register_trait(elite_bodyguard_trait, type="gold")

girl.add_trait(trait_dict[elite_bodyguard_trait.name], _pos=1)

star_manager_hunter_trait = Trait("Star Manager", verb="be a", effects=[Effect("boost", "tip", 0.1), Effect("change", "job customer capacity", 2), archetype="The Courtesan"), Effect("change", "whore customer capacity", 1), Effect("gain", "reputation", 5), Effect("boost", "upkeep", -0.2)], base_description = "She is the manager of Astra Yao, New Eridu's most iconic songstress.")

register_trait(star_manager_trait, type="gold")

girl.add_trait(trait_dict[star_manager_trait.name], _pos=2)

        try: # Plan A: If Trait King (or any other mod) is active and you're asking for a trait that's already in the dictionary

            girl.add_trait(trait_dict[my_custom_trait.name], _pos=1) # pos determines where in the girl's trait list the trait appears

        except: # This is Plan B if the above fails. It adds the trait to a category and dictionary before adding it to the girl

            # You can remove or comment out the line below if you want to add a unique trait that will not randomly appear on new generated girls

            trait_dict[my_custom_trait.name] = my_custom_trait

            girl.add_trait(trait_dict[my_custom_trait.name], _pos=1) #

        return


This is the error:

I'm sorry, but errors were detected in your script. Please correct the
errors listed below, and try again.


File "game/images/Evelyn Chevalier/_events.rpy", line 15: expected statement.
    elite_bodyguard_trait = Trait("Elite Bodyguard", verb="be an", effects=[Effect("change", "defense", 5), Effect("change", "body", 10, scales_with = "rank"), Effect("boost", "constitution", 0.2), Effect("boost", "xp gains", 0.1), Effect("boost", "energy", 0.2)], archetype="The Model", base_description = "She is the bodyguard of Astra Yao, New Eridu's most iconic songstress.")
                          ^

File "game/images/Evelyn Chevalier/_events.rpy", line 17: expected statement.
    register_trait(elite_bodyguard_trait, type="gold")
                                                      ^

File "game/images/Evelyn Chevalier/_events.rpy", line 19: expected statement.
    girl.add_trait(trait_dict[elite_bodyguard_trait.name], _pos=1)
                                                                  ^

File "game/images/Evelyn Chevalier/_events.rpy", line 21: expected statement.
    star_manager_hunter_trait = Trait("Star Manager", verb="be a", effects=[Effect("boost", "tip", 0.1), Effect("change", "job customer capacity", 2), archetype="The Courtesan"), Effect("change", "whore customer capacity", 1), Effect("gain", "reputation", 5), Effect("boost", "upkeep", -0.2)], base_description = "She is the manager of Astra Yao, New Eridu's most iconic songstress.")
                              ^

File "game/images/Evelyn Chevalier/_events.rpy", line 23: expected statement.
    register_trait(star_manager_trait, type="gold")
                                                  ^

File "game/images/Evelyn Chevalier/_events.rpy", line 25: expected statement.
    girl.add_trait(trait_dict[star_manager_trait.name], _pos=2)
                                                              ^

Ren'Py Version: Ren'Py 8.3.4.24120703
Sat Nov  1 22:58:10 2025

Jman

#247
There are quite a few issues here. Try something like this:
init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

        try:
            girl.add_trait(trait_dict["Elite Bodyguard"], _pos=1)
        except:
            elite_bodyguard_trait = Trait("Elite Bodyguard", verb="be an", effects=[Effect("change", "defense", 5), Effect("change", "body", 10, scales_with = "rank"), Effect("boost", "constitution", 0.2), Effect("boost", "xp gains", 0.1), Effect("boost", "energy", 0.2)], archetype="The Model", base_description = "She is the bodyguard of Astra Yao, New Eridu's most iconic songstress.")

            register_trait(elite_bodyguard_trait, type="gold")

            girl.add_trait(trait_dict[elite_bodyguard_trait.name], _pos=1)

        try:
            girl.add_trait(trait_dict["Star Manager"], _pos=1)
        except:
            star_manager_trait = Trait("Star Manager", verb="be a", effects=[Effect("boost", "tip", 0.1), Effect("change", "job customer capacity", 2), Effect("change", "whore customer capacity", 1), Effect("gain", "reputation", 5), Effect("boost", "upkeep", -0.2)], archetype="The Courtesan", base_description = "She is the manager of Astra Yao, New Eridu's most iconic songstress.")

            register_trait(star_manager_trait, type="gold")

            girl.add_trait(trait_dict[star_manager_trait.name], _pos=2)

        return
And with strange aeons even death may die...

Necrilem

Quote from: Jman on Nov 01, 2025, 10:18 PMThere are quite a few issues here. Try something like this:
init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

        try:
            girl.add_trait(trait_dict["Elite Bodyguard"], _pos=1)
        except:
            elite_bodyguard_trait = Trait("Elite Bodyguard", verb="be an", effects=[Effect("change", "defense", 5), Effect("change", "body", 10, scales_with = "rank"), Effect("boost", "constitution", 0.2), Effect("boost", "xp gains", 0.1), Effect("boost", "energy", 0.2)], archetype="The Model", base_description = "She is the bodyguard of Astra Yao, New Eridu's most iconic songstress.")

            register_trait(elite_bodyguard_trait, type="gold")

            girl.add_trait(trait_dict[elite_bodyguard_trait.name], _pos=1)

        try:
            girl.add_trait(trait_dict["Star Manager"], _pos=1)
        except:
            star_manager_trait = Trait("Star Manager", verb="be a", effects=[Effect("boost", "tip", 0.1), Effect("change", "job customer capacity", 2), Effect("change", "whore customer capacity", 1), Effect("gain", "reputation", 5), Effect("boost", "upkeep", -0.2)], archetype="The Courtesan", base_description = "She is the manager of Astra Yao, New Eridu's most iconic songstress.")

            register_trait(star_manager_trait, type="gold")

            girl.add_trait(trait_dict[star_manager_trait.name], _pos=2)

        return

Looks like it works now, thank you so much!

Necrilem

Actually, now I noticed a new issue.

So, I give 2 custom gold traits. I don't want her to have any other gold traits, maybe 1 or 2 green traits. I know I can list all base game gold traits for her to never have, but among the I don't know how many dozen girl packs I have, there seem to be a lot that drip their custom traits to other girls, meaning in addition to my 2 custom gold traits, she gets at least 1 (from what i've seen) more gold trait from some other girl pack.

Is there a way to specify for this girl pack to not receive any of those?

Jman

#250
How do they 'drip' these gold traits? By just expanding the gold trait pool and adding the regular gold trait all originals get? Or if they specifically override your girl's traits with custom ones, then that's a problem and these girl packs' event scripts need fixing.

I don't think there's any specific _BK.ini setting for barring any and all unwanted traits, but you can extend your init function like this:
init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

        girl.traits = [tr for tr in girl.traits if not tr in gold_traits]

        try:
            girl.add_trait(trait_dict["Elite Bodyguard"], _pos=1)
        except:
            ...

Won't work against non-registered traits, though.
And with strange aeons even death may die...

Necrilem

#251
Quote from: Jman on Nov 01, 2025, 10:46 PMHow do they 'drip' these gold traits? By just expanding the gold trait pool and adding the regular gold trait all originals get? Or if they specifically override your girl's traits with custom ones, then that's a problem and these girl packs' event scripts need fixing.

I don't think there's any specific _BK.ini setting for barring any and all unwanted traits, but you can extend your init function like this:
init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

        girl.traits = [tr for tr in girl.traits if not tr in gold_traits]

        try:
            girl.add_trait(trait_dict["Elite Bodyguard"], _pos=1)
        except:
            ...

Won't work against non-registered traits, though.

Well tbh, I assume that is what is happening. Using Headhunter mod to cycle through versions of my girl pack and it keeps getting third gold traits that aren't in BKtraits.rpy like "Ambitious" for example. Would be great if there was a way to exclude any and all gold traits except ones specified/defined.

Jman

"Ambitious" is a Trait King trait, though?

The code snippet from my last post can do what you want. E.g. like this:
init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

        girl.traits = [tr for tr in girl.traits if not tr in gold_traits or tr.name in ["Princess", "Royal concubine", "Idol"]]

        try:
            girl.add_trait(trait_dict["Elite Bodyguard"], _pos=1)
        except:
            ...
And with strange aeons even death may die...

Necrilem

Quote from: Jman on Nov 02, 2025, 12:40 AM"Ambitious" is a Trait King trait, though?

The code snippet from my last post can do what you want. E.g. like this:
init -2 python:

    def chevalier(girl): # Remember to change "my_custom_init_function" to something unique, identical to what's mentioned in your _BK.ini

        girl.traits = [tr for tr in girl.traits if not tr in gold_traits or tr.name in ["Princess", "Royal concubine", "Idol"]]

        try:
            girl.add_trait(trait_dict["Elite Bodyguard"], _pos=1)
        except:
            ...

I think this helped? Still getting weird trait combos and especially orders, given my custom traits should be 1st and 2nd.

Few examples from generating via headhunter (in that order):

- Dedicated (Green), Elite Bodyguard (Gold), Star Manager (Gold), Fake orgasms (Green), Strong (Green)
- Brisk (Green), Elite Bodyguard (Gold), Star Manager (Gold), Square (Red)
- Idol (Gold), Elite Bodyguard (Gold), Star Manager (Gold), Rebellious (Red), Paranoid (Red)

Jman

#254
There's a bit of a bug with 'add_trait()'. It can't put traits into the first position due to considering position 0 (the actual first position) to be 'False'. Hope Goldo will come around and change that sometime soon.

Headhunter should be fixing the order issue if you're using the latest version, though. Unless you are overriding trait objects somewhere during girl creation, which shouldn't happen. Even Trait King only does the replacing once.

You can also do this yourself via the console or within the girl's init function (somewhere after traits have been added):
girl.traits = [x for x in girl.traits if not trait_dict[x.name] in gold_traits + pos_traits + neg_traits] + [x for x in girl.traits if trait_dict[x.name] in gold_traits] + [x for x in girl.traits if trait_dict[x.name] in pos_traits] + [x for x in girl.traits if trait_dict[x.name] in neg_traits]


"Idol" being the third gold trait is working as intended, since the example code explicitly allows "Idol". You did say you wanted to keep 'ones specified/defined'.


Two gold and three green traits should still be allowed by Trait King.
And with strange aeons even death may die...