How to define what gender a new race is?

Users who are viewing this thread

Hello, I'm trying to set a different gender/race for lords of a specific faction in a new mod I'm making but I can't figure out how I do that, I never did this before but I thought it would be simple. Anyone knows what am I missing? Thanks in advance.

Edit: To explain it better, the real question is where I define that a race is male or female because I can give the flag for the race right before the "hero" flag however not being defined as male all races are seen as female, so what I really need to know is how to define what gender a new race is.

Edit 2: I already fixed the dialog part using TLD fix, but in notes/character the race still seems to be considered as female when it should be male.
I found this:

"Slawomir of Aaarrghh:
There is a little trick to do that, though you must have your entries in module_skins sorted. They should be like this: male, female, male, female, male, female... etc.

So 0,2,4,6,8...  will be males.
And 1,3,5,7,9... will be females."

I've already done this but it doesn't seem to change it.
 
That's because Native identifies male as the default gender value of 0 and female as every other value of 1 or above. You need to modify every place where it calls troop_get_type, see how Diplomacy uses a script call as replacement.
 
Somebody said:
That's because Native identifies male as the default gender value of 0 and female as every other value of 1 or above. You need to modify every place where it calls troop_get_type, see how Diplomacy uses a script call as replacement.

I did modified the troop_get_type in dialogs.py using the bit of code from TLD and in dialogs the race is identified as male as it should but it doesn't change the fact that the race is still technically female. I guess I need to change something in scripts.py too maybe?

Edit: To clarify what I did in dialogs was to add this bit of code right after troop_get_type lines:

                    (try_begin),
                      (neq, reg65, 1), #not female
                      (assign, reg65, 0), #make it male for strings
                    (try_end),
 
That's only one place where you change the register. If you've been doing the first method correctly and splitting up races into both genders, you should be using the modulus and not just assigning everything to male. Again,
Code:
troop_get_type
is called in hundreds of different places, you need to replace those.
 
Somebody said:
That's only one place where you change the register. If you've been doing the first method correctly and splitting up races into both genders, you should be using the modulus and not just assigning everything to male. Again,
Code:
troop_get_type
is called in hundreds of different places, you need to replace those.

Well assigning a gender to a race is what I'm trying and failing to do apparently :\
 
jacobhinds said:
There's no single value for gender. Whenever a script needs to know whether a troop is male or female it uses "troop_get_type". This merely returns the ID of the race tuple, i.e  male=0, female=1, undead=2 etc. because of their positions in module_skins.

Yeah but I actually have put the races in an order so that male races are 0,2,4, etc in the skins order but it doesn't seem to affect anything. Anyway Michadr is already helping me with this so hopefully I'll manage to fix it ^^
 
modulus is definitely the easy way to go, but you could do it any way that works for you.  Here was an early way I did it, since you mention Perisno
in module_scripts.py
Code:
################
              # race/gender fix (call before dialogs)
              # concept by Keedo420 - http://forums.taleworlds.com/index.php/topic,59300.msg1534679.html#msg1534679
              
              ("gender_fix",
                [
                  (store_script_param, ":troop_no", 1),
                  (troop_get_type,":character_race",":troop_no"),
                    (assign, ":gender",-1),    # GS gender    curious if any cases outside this tree pop up
                  (try_begin), #male species
                    (this_or_next|eq,":character_race",tf_male),
                    (this_or_next|eq,":character_race",tf_elven_male),
                    (this_or_next|eq,":character_race",tf_dwarf_male),
                    (this_or_next|eq,":character_race",tf_giant_male),
                    (this_or_next|eq,":character_race",tf_undead),
                    (             eq,":character_race",tf_drow_male),
                    (assign, ":gender",0),
                  
                  (else_try), #female species
                    (this_or_next|eq,":character_race",tf_female),
		    (this_or_next|eq,":character_race",tf_elven_female),
                    (this_or_next|eq,":character_race",tf_dwarf_female),
                    (this_or_next|eq,":character_race",tf_giant_female),
                    (this_or_next|eq,":character_race",tf_skeleton),
                    (             eq,":character_race",tf_drow_female),
                    (assign, ":gender",1),
                  (try_end),
                  
                  (try_begin),
                    (eq, ":gender", -1),
                     (assign, reg33, ":character_race"),    # GS gender TODO?   want a trap here for now
                    (display_message, "@{!} ERROR: called script gender_fix with bad argument {reg33}"),
                  (try_end),
                  
                  (assign, reg33, ":gender"), #we return the choice as 1 or 0, Female =1  male=0 -1=big problem
                                              #in dialogs 1 is used for the first option of the conditional and 0 for the second one
                                              #{reg33?her:him}
              ]),
  mainly this is inferior to modulus but allows you to skip having female used as often to free up skins, as is done in other mods with many races.  The above actually just did a modulus type implementation but I had the luxury of 7 races instead of 15 to implement.

  But that isnt really the magic part of gender dialogs.  Next you need to have a test that returns gender; it may as well be the one diplomacy users, and then have it call the above..
Code:
  ("dplmc_store_troop_is_female_reg",
  [
	(store_script_param_1, ":troop_no"),
	(store_script_param_2, ":reg_no"),

        (try_begin),
           (call_script, "script_cf_dplmc_troop_is_female", "trp_player"),  # GS gender refresh reg33 for strings lordlady,sirmadam
        (try_end),
        (assign, ":return_reg33",reg33),  # GS gender to attempt to save reg33 as player gender, implicitly

        (try_begin),
          (call_script, "script_gender_fix", ":troop_no"),      # GS gender fix ??
        (try_end),                               # returns reg33 as sex  0 male 1 female
              #The following will make it so, for example, tf_undead does not appear to be female.
	#Mods where this is relevant will likely want to tweak it, but this will work in at
	#least one that I know of that has non-human lords.
	#(try_begin),
	#	(neq, ":is_female", 0),
	#	(neq, ":is_female", 1),
	#	(assign, ":is_female", 0),
	#(try_end),
        ##Can asign to registers 0,1,2,3, 65, or 4
	(try_begin),
          (eq, ":reg_no", 4),
          (assign, reg4, reg33),    # GS gender
           (else_try),
	  (eq, ":reg_no", 3),
	  (assign, reg3, reg33),
	(else_try),
	  (eq, ":reg_no", 2),
	  (assign, reg2, reg33),
	(else_try),
	  (eq, ":reg_no", 1),
	  (assign, reg1, reg33),
	(else_try),
	  (eq, ":reg_no", 0),
	  (assign, reg0, reg33),
	(else_try),
	  (eq, ":reg_no", 65),
	  (assign, reg65, reg33),
        (else_try),
          ##default to reg4
          (assign, reg4, ":reg_no"),
          (display_message, "@{!} ERROR: called script dplmc-store-troop-is-female-reg with bad argument {reg4}"),
          (assign, reg4, reg33),
        (try_end),
        
       (assign, reg33,":return_reg33"),    # GS gender  "about the player"  sets reg33 = player gender cleanup
  ]),

  ##script_cf_dplmc_troop_is_female
  #
  #This exists to make it easy to modify this to work with mods that redefine the troop types.
  #See script_dplmc_store_troop_is_female
  #
  #INPUT: arg1: troop_no
  #OUTPUT: reg33    0=male  1=female  (global written from script_gender_fix)   #GS gender updated
  ("cf_dplmc_troop_is_female",
  [
    (store_script_param_1, ":troop_no"),
      #(ge, ":troop_no", 0),#Undefined behavior when the arguments are invalid.

   (try_begin),
      (eq, ":troop_no", active_npcs_including_player_begin),
      (assign, ":troop_no", "trp_player"),
   (try_end),

   # (assign, reg33, 0),   # GS force male  redundant
    (try_begin),
      (call_script, "script_gender_fix", ":troop_no"),   # GS gender change 10 Nov 2014
    (try_end),
   #The following will make it so, for example, tf_undead does not appear to be female.
   #Mods where this is relevant will likely want to tweak it, but this will work in at
   #least one that I know of that has non-human lords.
   #(eq, ":is_female", tf_female),
  ]),


  #
  #This exists to make it easy to modify this to work with mods that redefine the troop types.
  #
  #If you change this, remember to also change script_cf_dplmc_troop_is_female and
  #script_dplmc_store_is_female_troop_1_troop_2
  #
  #INPUT: arg1: troop_no
  #
  #OUTPUT:
  #       reg0: 1 is F, 0 is M for gender of troop_no   [and -1 is error trap from gender_fix]
  #
  ("dplmc_store_troop_is_female",
  [
	(store_script_param_1, ":troop_no"),

        (try_begin),
           (call_script, "script_cf_dplmc_troop_is_female", "trp_player"),  # GS gender refresh reg33 for strings lordlady,sirmadam
        (try_end),
        (assign, ":return_reg33",reg33),  # GS gender to attempt to save reg33 as player gender, implicitly
        
	(try_begin),
	   (eq, ":troop_no", active_npcs_including_player_begin),
	   (assign, ":troop_no", "trp_player"),  
	(try_end),

        (assign, reg0, 0),          # GS gender   default male
        (try_begin),
           (call_script, "script_gender_fix", ":troop_no"), # GS gender fix attempt ??  
        (try_end),                                          # GS currently gender_fix overwrites reg33, which I'd like to stay player's gender
        (assign, reg0, reg33),                              # 
        (assign, reg33, ":return_reg33"),                   # GS trying to save reg33 as implicit player gender
	#(try_begin),
	#	(neq, reg0, 0),
	#	(neq, reg0, 1),
	#	(assign, reg0, 0),#e.g. this would apply to tf_undead
	#(try_end),
  ]),

  Oh, you'd think you're done but now its time to go over to module_dialogs.py and actually put it to use...
up top you may as well put trp_player 's gender in a place that isn't walked on often; diplomacy uses  reg33 for this

dialogs = [
[anyone ,"start", [(store_conversation_troop, "$g_talk_troop"),
              (store_conversation_agent, "$g_talk_agent"),
              (store_troop_faction, "$g_talk_troop_faction", "$g_talk_troop"),
#                    (troop_get_slot, "$g_talk_troop_relation", "$g_talk_troop", slot_troop_player_relation),
              (call_script, "script_troop_get_player_relation", "$g_talk_troop"),
              (assign, "$g_talk_troop_relation", reg0),

            (try_begin),
                (call_script, "script_cf_dplmc_troop_is_female", "trp_player"),  # GS gender seed reg33
            (try_end),


    next you get to browse EVERY SINGLE LINE OF DIALOG looking for  {he said/she said} pairs embedded in the dialog.  All of these are wrong if you are lazy and let native handle it for you.  But you want to be clever and have a mod when men are men and ladies arent the set of all elves, dwarves, and undead, eh?  Then you have to suck up and edit a few thousand lines, like I did in Perisno:

for example:
  [trp_nurse_for_lady, "start", [
#  (eq, "$talk_context", tc_garden),
##diplomacy start+ just in case make gender-correct
], "I humbly request that your {reg33?lady:lord}ship keeps {reg33?her:his} hands where I can see them.", "close_window",[]],
##diplomacy end+

  notice after the test, since female is TRUE (1) it comes FIRST not last, so reverse the order of all the female phrases.

  But doing this against every line in dialogs doesnt mean you're done.  Oh no.  Now a true modder opens module_strings.py
and probably by now notices that its considerably FASTER to just search on    {    the open brace, which you could have done in dialogs if I wasnt so cruel as to make you understand WHY you have to do this a certain way.  But I suppose I should be nice on a peer.

  So in module_strings.py  the lines will end up like this:
# Companion Dialogues 
  ("npc1_intro", "Psst! You want to know something?"),
  ("npc2_intro", "You! {reg33?Girl:Boy}! You hire mercenary!?"),
  ("npc3_intro", "Hello there. Do you happen to be a mercenary captain?"),
  ("npc4_intro", "Greetings. I am Tylen, and I come from the noble family Tylenia of Tolrania."),
  ("npc5_intro", "Greetings."),
  ("npc6_intro", "The Old Gods talk to me. I am their preacher, their messenger..."),
  ("npc7_intro", "Keep your distance! I don't want some rogue near me!"),
  ("npc8_intro", "What do you want?"),
  ("npc9_intro", "You there, good {reg33?woman:man}, be so kind as to fetch me another drink, eh?"),
  ("npc10_intro", "Greetings. I am Fazl, a merchant from the deserts of Drahara."),
  ("npc11_intro", "Hey you, how are you? Care to chat for a little while?"),
  ("npc12_intro", "Hello, my friend. Care to join me for a drink?"),
  ("npc13_intro", "Greetings. I am Dohosan, hailing from Aroulo."),
  ("npc14_intro", "Yes? What is it?"),
  ("npc15_intro", "You there, I've heard of you. They call you a leader of men. Is that true?"),
  ("npc16_intro", "Hello. From your look, I can tell you are a leader. A mercenary, perhaps? What is it you want?"),
  ("npc17_intro", "Don't fear me, {reg33?gentle Lady:noble Sir}.  I am but half drow.  I escaped the matriarchy and now seek a leader who would protect the common people.  Are YOU such a person?"),

    look familiar?  It should...  But theres hundreds of such lines to change.  Maybe thousands, counting dialogs and strings combined.  You'll be pretty tired of the exercise by the time you're done.  I did it for you in Rigale v12.4 so you could see it working, but I only put 4 skins so its not very exciting.  I'll guess you want at least 8 or so skins to have 4 races or more.  This is a function of just making sure your gender test ultimately calls something that actually returns a 1 (female) or 0 (male) response, but since I was using diplomacy embedded in the mod I needed to be sure diplomacy was altered to call the correct test.

  Anyway that's a 2 minute (well, probably took 15 minutes) walk through as done in Perisno.  If I did it again I'd either do a simple modulus test for speed or like above a discrete test so as to have some races skip a gender to allow more races, as was done for Warsword Conquest.  Either way the result is a variation of the above, and some clod has to go edit a few thousand lines so as to make the mod respect genders as you envision them.  If it was easy, you wouldn't have asked :smile:  but 2-3 days from now you'll have it working and that is a lot better than the 2 weeks or so I needed to discover this by myself...  (I work faster now, a year and some months later).

  - GS

 
 
I've done everything you said, gsanders, but it just hasn't worked for me so far. I haven't changed all the dialog lines, only the one I can check as soon as I start a new game everytime.

header_troops:
Code:
#Troop flags
tf_male           = 0
tf_female         = 1
tf_undead         = 2
tf_pretty_female  = 3

module_scripts:
Code:
################
              # race/gender fix (call before dialogs)
              # concept by Keedo420 - http://forums.taleworlds.com/index.php/topic,59300.msg1534679.html#msg1534679
              # GS   this could also be just a simple mod(2) test of race: with 0 or 1 resulting
              ("gender_fix",
                [
                  (store_script_param, ":troop_no", 1),
                  (troop_get_type,":character_race",":troop_no"),
                    (assign, ":gender",-1),    # GS gender    curious if any cases outside this tree pop up
                  (try_begin), #male species
                    (this_or_next|eq,":character_race",tf_male),
                    (eq,":character_race",tf_undead),
                    (assign, ":gender",0),
                  
                  (else_try), #female species
                    (this_or_next|eq,":character_race",tf_female),
                    (eq,":character_race",tf_pretty_female),
                    (assign, ":gender",1),
                  (try_end),
                  
                  (try_begin),
                    (eq, ":gender", -1),
                     (assign, reg33, ":character_race"),  #   want a trap here for now
                    (display_message, "@{!} ERROR: called script gender_fix with bad argument {reg33}"),
                  (try_end),
                  
                  (assign, reg33, ":gender"), #we return the choice as 1 or 0, Female =1  male=0 -1=big problem
                                              #in dialogs 1 is used for the first option of the conditional and 0 for the second one
                                              #{reg33?her:him}
              ]),
	
  ##script_cf_dplmc_troop_is_female
  #
  #This exists to make it easy to modify this to work with mods that redefine the troop types.
  #See script_dplmc_store_troop_is_female
  #
  #INPUT: arg1: troop_no
  #OUTPUT: reg33    0=male  1=female  (global written from script_gender_fix)   #GS gender updated
  ("cf_dplmc_troop_is_female",
  [
    (store_script_param_1, ":troop_no"),
      #(ge, ":troop_no", 0),#Undefined behavior when the arguments are invalid.

   (try_begin),
      (eq, ":troop_no", active_npcs_including_player_begin),
      (assign, ":troop_no", "trp_player"),
   (try_end),

   # (assign, reg33, 0),   # GS force male  redundant
    (try_begin),
      (call_script, "script_gender_fix", ":troop_no"),   # GS gender change 10 Nov 2014
    (try_end),
   #The following will make it so, for example, tf_undead does not appear to be female.
   #Mods where this is relevant will likely want to tweak it, but this will work in at
   #least one that I know of that has non-human lords.
   #(eq, ":is_female", tf_female),
  ]),



  ##script_dplmc_store_is_female_troop_1_troop_2
  #
  #This exists to make it easy to modify this to work with mods that redefine the troop types.
  #See script_dplmc_store_troop_is_female
  #
  #INPUT:
  #      arg1: troop_1
  #      arg2: troop_2
  #OUTPUT:
  #       reg0: 0 for not female, 1 for female
  #       reg1: 0 for not female, 1 for female
  #       reg33: set back to player gender
  ("dplmc_store_is_female_troop_1_troop_2",
  [
	(store_script_param_1, ":troop_1"),
	(store_script_param_2, ":troop_2"),
         
        (try_begin),
          (call_script, "script_gender_fix", ":troop_1"),
        (try_end),
        (assign, ":is_female_1", reg33),
        
        (try_begin),  # GS gender  Michadr had a function that assigned a status to "gender_fix" so need to strip that or get stack creep
          (call_script, "script_gender_fix", ":troop_2"), 
        (try_end),
        (assign, ":is_female_2", reg33),

        (try_begin),
            (call_script, "script_gender_fix", "trp_player"),
        (try_end),
        
	#The following will make it so, for example, tf_undead does not appear to be female.
	#Mods where this is relevant will likely want to tweak it, but this will work in at
	#least one that I know of that has non-human lords.
	#(try_begin),
	#	(neq, ":is_female_1", 0),
	#	(neq, ":is_female_1", 1),
	#	(assign, ":is_female_1", 0),
	#(try_end),
	#(try_begin),
	#	(neq, ":is_female_2", 0),
	#	(neq, ":is_female_2", 1),
	#	(assign, ":is_female_2", 0),
	#(try_end),
	(assign, reg0, ":is_female_1"),
	(assign, reg1, ":is_female_2"),
  ]),


  ##script_dplmc_store_troop_is_female
  #
  #This exists to make it easy to modify this to work with mods that redefine the troop types.
  #
  #If you change this, remember to also change script_cf_dplmc_troop_is_female and
  #script_dplmc_store_is_female_troop_1_troop_2
  #
  #INPUT: arg1: troop_no
  #
  #OUTPUT:
  #       reg0: 1 is F, 0 is M for gender of troop_no   [and -1 is error trap from gender_fix]
  #
  ("dplmc_store_troop_is_female",
  [
	(store_script_param_1, ":troop_no"),

        (try_begin),
           (call_script, "script_cf_dplmc_troop_is_female", "trp_player"),  # GS gender refresh reg33 for strings lordlady,sirmadam
        (try_end),
        (assign, ":return_reg33",reg33),  # GS gender to attempt to save reg33 as player gender, implicitly
        
	(try_begin),
	   (eq, ":troop_no", active_npcs_including_player_begin),
	   (assign, ":troop_no", "trp_player"),  
	(try_end),

        (assign, reg0, 0),          # GS gender   default male
        (try_begin),
           (call_script, "script_gender_fix", ":troop_no"), # GS gender fix attempt ??  
        (try_end),                                          # GS currently gender_fix overwrites reg33, which I'd like to stay player's gender
        (assign, reg0, reg33),                              # 
        (assign, reg33, ":return_reg33"),                   # GS trying to save reg33 as implicit player gender
	#(try_begin),
	#	(neq, reg0, 0),
	#	(neq, reg0, 1),
	#	(assign, reg0, 0),#e.g. this would apply to tf_undead
	#(try_end),
  ]),


  ("dplmc_store_troop_is_female_reg",
  [
	(store_script_param_1, ":troop_no"),
	(store_script_param_2, ":reg_no"),

        (try_begin),
           (call_script, "script_cf_dplmc_troop_is_female", "trp_player"),  # GS gender refresh reg33 for strings lordlady,sirmadam
        (try_end),
        (assign, ":return_reg33",reg33),  # GS gender to attempt to save reg33 as player gender, implicitly

        (try_begin),
          (call_script, "script_gender_fix", ":troop_no"),      # GS gender fix ??
        (try_end),                               # returns reg33 as sex  0 male 1 female
              #The following will make it so, for example, tf_undead does not appear to be female.
	#Mods where this is relevant will likely want to tweak it, but this will work in at
	#least one that I know of that has non-human lords.
	#(try_begin),
	#	(neq, ":is_female", 0),
	#	(neq, ":is_female", 1),
	#	(assign, ":is_female", 0),
	#(try_end),
        ##Can asign to registers 0,1,2,3, 65, or 4
	(try_begin),
          (eq, ":reg_no", 4),
          (assign, reg4, reg33),    # GS gender
           (else_try),
	  (eq, ":reg_no", 3),
	  (assign, reg3, reg33),
	(else_try),
	  (eq, ":reg_no", 2),
	  (assign, reg2, reg33),
	(else_try),
	  (eq, ":reg_no", 1),
	  (assign, reg1, reg33),
	(else_try),
	  (eq, ":reg_no", 0),
	  (assign, reg0, reg33),
	(else_try),
	  (eq, ":reg_no", 65),
	  (assign, reg65, reg33),
        (else_try),
          ##default to reg4
          (assign, reg4, ":reg_no"),
          (display_message, "@{!} ERROR: called script dplmc-store-troop-is-female-reg with bad argument {reg4}"),
          (assign, reg4, reg33),
        (try_end),
        
       (assign, reg33,":return_reg33"),    # GS gender  "about the player"  sets reg33 = player gender cleanup
  ]),

dialog I changed in module_dialogs:
Code:
##diplomacy start+ Add bizarro-world version
], "My {reg33?lady:lord}, you seem to have the makings of a good war leader. For a {reg33?woman:man} to show such skill is an uncommon thing in Calradia, but not completely without precedent. Noble{reg33?women:men} have often taken command of armies after their {reg33?husbands:wives} or {reg33?fathers:mothers} were slain or captured, for example.", "lord_ask_enter_service_female_2",[
(assign, "$bypass_female_vassal_explanation", 1),
##diplomacy end+

Now, the pretty_female appears to be female in game, but the King will identify himself as a "queen" and will refer to the pretty_female as "my Lord" and a "man". This also happens if the player is a man. What am I missing?
 
Back
Top Bottom