Jump to content


Photo

How to change colours

NPCs creatures items

  • Please log in to reply
15 replies to this topic

#1 Miloch

Miloch

    Barbarian

  • Modder
  • 6579 posts

Posted 29 January 2012 - 08:08 AM

I'm writing this by request to show how to change NPC colours. Actually, it will work for any creatures that have palettable animations (like humans, elves and hobgoblins). It won't affect non-palettable animations (like orcs and lizardmen). Most typically, this shows how to make sure NPC avatars and paperdolls match mods that give them different portraits. It also demonstrates some basic WeiDU modding fundamentals, though there are other tutorials for that (particularly in the WeiDU documentation).

First, some basics. This is a typical header for a mod's .tp2 installer. This text file is called something like setup-mymod.tp2 or just mymod.tp2. It is executed by a copy of WeiDU.exe renamed to the .tp2 name (setup-mymod.exe).
BACKUP ~adjports/backup~ //Where the mod backs up files
AUTHOR ~www.shsforums.net/forum/584-portrait-mods/~ //Where to submit error reports
VERSION ~v1~
README ~adjports/adjports.html~
BACKUP and AUTHOR are mandatory. VERSION is optional but recommended. It prints the version number in the WeiDU.log file that keeps track of all mods installed. README will ask the user whether to view the readme.

There is also a subheader for each component. Some mods will have only one component; others will have many. In simple form, a component for changing an NPC's colours would look something like this:
BEGIN ~My Portrait Mod~
DESIGNATED 100

ACTION_FOR_EACH npc IN ~aerbod01~ ~aerie12~ ~cwsaer~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
    COPY_EXISTING ~%npc%.cre~ ~override~ //Aerie
	  WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
	  WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
	  WRITE_BYTE 0x2e 2 //Major color (dark gold, was 37 dark dirty yellow)
	  WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
	  WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
	  WRITE_BYTE 0x31 30 //Armor color (light iron gray)
	  WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
	BUT_ONLY_IF_IT_CHANGES
  END
END
BEGIN specifies the component name when installing; it is mandatory. DESIGNATED is optional but highly recommended - it hardcodes a component number as appears in the WeiDU.log. It also allows other mods to detect the component and automated programs (such as the BiG World Project) to install the component. If you don't use DESIGNATED, your component numbers will run consecutively from zero. Thus, they will change as you add and remove new components, which isn't a good thing for automation.

The main block is a loop consisting of ACTION_FOR_EACH, ACTION_IF FILE_EXISTS_IN_GAME and COPY_EXISTING. In layman's terms, this feeds a list of filenames to WeiDU (ACTION_FOR_EACH) and says: if each file exists in the game (ACTION_IF ...) then copy it to the override folder (COPY_EXISTING) and make some changes. As for those changes, we are making a series of one-byte changes to the file (WRITE_BYTE). We use an editor (either Near Infinity or DLTCEP) to look up the existing values if we want, the IESDP to find the offsets and the desired colour gradients and their numeric values. Once that is done, we simply plug all that into our patch.

BUT_ONLY_IF_IT_CHANGES (BUT_ONLY for short) says only to copy the file if it is modified by the patches. If, for example, it already has the colour values specified, it will simply be skipped. Two ENDs close out our ACTION loops. That is all you need to do to change an NPC's colours in its simplest form. Like other mods, this will not change any NPC who has already joined the party, as they are stored in the save game.

Here is a slightly more complex example. This component gives two choices for changing Aerie's garb, thus uses SUBCOMPONENT.
BEGIN ~Aerdrie's Garb~
SUBCOMPONENT ~Aerie as Priestess of Aerdrie/Baervan~
DESIGNATED 50
REQUIRE_PREDICATE ((NOT FILE_EXISTS_IN_GAME ~_plat06.itm~) AND ((FILE_EXISTS_IN_GAME ~aerie12.cre~) OR (FILE_EXISTS_IN_GAME ~cwsaer.cre~))) ~Aerie not available~
In this case, SUBCOMPONENT actually indicates the component name, and BEGIN indicates one of several choices the user has. Other choices will follow with their own BEGIN/SUBCOMPONENT sections.

REQUIRE_PREDICATE is a good way to ensure the NPC is present. If the conditions aren't fulfilled, the installer will skip the component and go to the next one. In this case, we want to skip the component if Tutu. Aerie is present but not joinable on Tutu (all BG2 files are). Therefore, we give it a Tutu item _plat06.itm and NOT FILE_EXISTS_IN_GAME for the condition. With the AND we also make sure at least version of Aerie is present (either aerie12 or cwsaer) and pair those with an OR. The whole condition looks like this in simpler terms: (NOT Tutu) AND (aerie12 OR cwsaer). This is followed by a text message (~Aerie not available~) that will display when the installer skips the component.
COPY ~adjports/bmp/t-aeri1l.bmp~ ~override~
	 ~adjports/bmp/t-aeri1m.bmp~ ~override~
	 ~adjports/bmp/t-aeri1s.bmp~ ~override~
The section above copies the portraits for this component. Most people don't do it this way - they overwrite the existing portraits. This demonstrates a way of avoiding that to keep the previous portraits available for other purposes.
ACTION_FOR_EACH tda IN ~aeriend1~ ~aeriend2~ ~aerifnd1~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%tda%.2da~ BEGIN
	COPY_EXISTING ~%tda%.2da~ ~override~ //ToB epilogue tables
	  SET_2DA_ENTRY 1 0 1 ~*T-AERI1L~
	BUT_ONLY
  END
END
That section replaces Aerie's Throne of Bhaal epilogue portrait in the relevant tables. It is only relevant for ToB NPCs, and then only if you don't overwrite the existing portrait.
COPY_EXISTING ~spin745.spl~ ~override~ //Aerie Portrait Spell
  PATCH_IF SOURCE_SIZE > 0x71 BEGIN
	READ_LONG 0x64 hf //Extended header offset
	READ_SHORT 0x68 hc //Extended header count
	READ_LONG 0x6a fb //Feature block offset
	FOR (i1 = 0; i1 < hc; i1 += 1) BEGIN //Cycle through extended headers
	  READ_SHORT (0x28 * i1 + hf + 0x1e) fc //Feature count
	  READ_SHORT (0x28 * i1 + hf + 0x20) fs //Feature offset
	  FOR (i2 = fs; i2 < (fs + fc); i2 += 1) BEGIN //Cycle through ability effects
		READ_SHORT (i2 * 0x30 + fs) opcode
		READ_LONG (i2 * 0x30 + fs + <img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> param2
		PATCH_IF (opcode = 107) AND (param2 = 0) BEGIN //If small portrait
		  WRITE_ASCII (i2 * 0x30 + fs + 0x14) ~t-aeri1s~ #8
		END
		PATCH_IF (opcode = 107) AND (param2 = 1) BEGIN //If large portrait
		  WRITE_ASCII (i2 * 0x30 + fs + 0x14) ~t-aeri1m~ #8
		END
	  END
	END
  END
BUT_ONLY
The above section is relevant only to Aerie, as there is a spell effect that morphs her back into avariel form after being an ogre. It specifies her small and medium portraits. I won't detail the code, but it basically loops through all effects attached to the spell and changes those where it finds portraits.
ACTION_FOR_EACH npc IN ~aerbod01~ ~aerie12~ ~cwsaer~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
	COPY_EXISTING ~%npc%.cre~ ~override~ //Aerie
	  PATCH_IF SOURCE_SIZE > 0x2d3 BEGIN //Ensures valid .cre file size
		WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
		WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
		WRITE_BYTE 0x2e 2 //Major color (dark gold, was 37 dark dirty yellow)
		WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
		WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
		WRITE_BYTE 0x31 30 //Armor color (light iron gray)
		WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
	  END
	BUT_ONLY_IF_IT_CHANGES
  END
END
Finally, the code above changes her colours as in the first example. For the second subcomponent, we'd copy and paste the same code above and just change the BEGIN name (e.g. to ~Baervan's Garb~), increase the DESIGNATED component number (e.g. to 60), change all the portraits we're copying (e.g. from t-aeri1 to t-aeri2) and finally, change the colours in the second set of code to match her second portrait, following the techique above (i.e. look them up in the IESDP).

Here's the full code for a slightly simpler example. It provides two different examples for Branwen (based on portraits with either brown or purple robes).

There's no ToB Branwen nor morphing spell for her, so we just need to copy the relevant portraits and assign them and the appropriate colours on her .cre files. We do, however, have to check via REQUIRE_PREDICATE that Branwen is present, so we look for Tutu (_branwe5.cre), BGT (branwe5.cre) and at least 4 different mod versions. Apparently, Branwen is a popular gal - you could in theory have a party with you and 5 other Branwens! Ah, the joys of redundant mods, er, I mean user choices.
BEGIN ~Brown Robe~
SUBCOMPONENT ~Branwen as Priestess of Tempus~
DESIGNATED 100
REQUIRE_PREDICATE ((FILE_EXISTS_IN_GAME ~_branwe5.cre~) OR (FILE_EXISTS_IN_GAME ~branwe5.cre~) OR (FILE_EXISTS_IN_GAME ~cb3513bw.cre~) OR (FILE_EXISTS_IN_GAME ~dl#bwn.cre~) OR (FILE_EXISTS_IN_GAME ~ttbran.cre~) OR (FILE_EXISTS_IN_GAME ~wlbran0.cre~)) ~Branwen not available~

COPY ~adjports/bmp/t-bran1l.bmp~ ~override~
	 ~adjports/bmp/t-bran1m.bmp~ ~override~
	 ~adjports/bmp/t-bran1s.bmp~ ~override~

ACTION_FOR_EACH npc IN ~_branwe~ ~_branwe5~ ~branwe~ ~branwe5~ ~cb3513bw~ ~dl#bwn~ ~ttbran~ ~wlbran0~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
	COPY_EXISTING ~%npc%.cre~ ~override~ //Branwen
	  PATCH_IF SOURCE_SIZE > 0x2d3 BEGINWeiDU documentation
		WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
		WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
		WRITE_BYTE 0x2e 2 //Major color (dark gold, was 37 dark dirty yellow)
		WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
		WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
		WRITE_BYTE 0x31 30 //Armor color (light iron gray)
		WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
		WRITE_ASCII 0x34 ~t-bran1s~ #8 //Small portrait
		WRITE_ASCII 0x3c ~t-bran1m~ #8 //Large portrait
	  END
	BUT_ONLY_IF_IT_CHANGES
  END
END

BEGIN ~Purple Robe~
SUBCOMPONENT ~Branwen as Priestess of Tempus~
DESIGNATED 105
REQUIRE_PREDICATE ((FILE_EXISTS_IN_GAME ~_plat06.itm~) OR (FILE_EXISTS_IN_GAME ~plat06.itm~)) ~Branwen not found~

COPY ~adjports/bmp/t-bran2l.bmp~ ~override~
	 ~adjports/bmp/t-bran2m.bmp~ ~override~
	 ~adjports/bmp/t-bran2s.bmp~ ~override~

ACTION_FOR_EACH npc IN ~_branwe~ ~_branwe5~ ~branwe~ ~branwe5~ ~cb3513bw~ ~dl#bwn~ ~ttbran~ ~wlbran0~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
	COPY_EXISTING ~%npc%.cre~ ~override~ //Branwen
	  PATCH_IF SOURCE_SIZE > 0x2d3 BEGIN
		WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
		WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
		WRITE_BYTE 0x2e 60 //Major color (dark purple, was 37 dark dirty yellow)
		WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
		WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
		WRITE_BYTE 0x31 104 //Armor color (dark chrome purple)
		WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
		WRITE_ASCII 0x34 ~t-bran2s~ #8 //Small portrait
		WRITE_ASCII 0x3c ~t-bran2m~ #8 //Large portrait
	  END
	BUT_ONLY_IF_IT_CHANGES
  END
END
And that's it for a simple component with two different portrait options.

Folks have also asked me how to change the colours of items. Say you've changed the hue of an NPC's special armour in your portrait and you want the item to follow suit. I won't get into how to change the icons. BAM Batcher and your favourite graphics program can do that easily enough, and there are probably other tutorials for that. This changes the colours on the paperdoll and animation or avatar when equipping the item.
BEGIN ~Ankheg Plate matches its icon~
DESIGNATED 25

ACTION_FOR_EACH ank IN ~_plat06~ ~plat06~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%ank%.itm~ BEGIN
	COPY_EXISTING ~%ank%.itm~ ~override~ //Ankheg Plate
	  PATCH_IF SOURCE_SIZE > 0x71 BEGIN //Ensures valid .itm file size
		READ_LONG 0x6a eq_off //Equipped effects offset
		READ_SHORT 0x70 eq_cnt //Equipped effects count
		FOR (i1 = 0; i1 < eq_cnt; i1 += 1) BEGIN
		  READ_SHORT (i2 * 0x30 + eq_off) opcode
		  READ_LONG (i2 * 0x30 + eq_off + <img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> param2
		  PATCH_IF (opcode = 7) AND (param2 = 5) BEGIN //If armor color
			WRITE_SHORT (i2 * 0x30 + eq_off + 4) 7 //Dark metallic green
		  END
		  PATCH_IF (opcode = 7) AND (param2 = 4) BEGIN //If strap color
			WRITE_SHORT (i2 * 0x30 + eq_off + 4) 1 //Light pure gold
		  END
		  PATCH_IF (opcode = 7) AND (param2 = 0) BEGIN //If belt color
			WRITE_SHORT (i2 * 0x30 + eq_off + 4) 36 //Light dirty yellow
		  END
		END
	  END
	BUT_ONLY
  END
END
Fairly straightforward example for the Ankheg Plate. Following the ACTION... logic described above, the code loops through each version of the item, looks for equipped effects matching certain conditions (opcode 7 for colour effects) and sets them to the relevant colours when it finds the right effects (for armour, strap and belt in this case).

Edited by Miloch, 29 January 2012 - 08:11 AM.

Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle


#2 Enkida

Enkida

    Full Cyborg

  • Member
  • 338 posts

Posted 29 January 2012 - 08:31 AM

Thank you, exactly what I was looking for. :-)


Edit: Am I also actually the first person to be offended by the fact that they named Valygar's skin colour "Dark Poopy Brown" ? WTF!?

Edited by Enkida, 29 January 2012 - 02:51 PM.


#3 Enkida

Enkida

    Full Cyborg

  • Member
  • 338 posts

Posted 29 January 2012 - 04:06 PM

One quick question: if I only want to replace certain components from the default (in this case, only skin and hair colours, or in some cases, only skin colours), do I have to relist the default values for everything else like the major, minor, leather and armour colours in the .cre override I create regardless? I think I do from what I read here, but I want to be doubly sure. :)

#4 Miloch

Miloch

    Barbarian

  • Modder
  • 6579 posts

Posted 29 January 2012 - 09:23 PM

No, you don't have to list values you aren't changing. However, some other mod may have changed them already, so it is safe to list them all, as I have done. Also, if you want to find all NPC filenames, the level1npcs.tp2 is a good place to look. Just scroll down or search for the NPC component names, e.g. those labeled "Branwen Branwen Branwen" etc.

The colour names are from whomever compiled that part of the IESDP, probably igi or Avenger, so blame them :D.

Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle


#5 Enkida

Enkida

    Full Cyborg

  • Member
  • 338 posts

Posted 30 January 2012 - 02:11 AM

Thanks, will do! Amd for the record, it really should be named "hottie ranger brown". ;-)

#6 Eric P.

Eric P.

    Journeyman Modder

  • Member
  • 1178 posts

Donator

Posted 08 February 2012 - 09:02 AM

What is the advantage to handling the setting of colors in this way, rather than by simply assigning them in the .cre (using NI, for example)? I've been advised to do everything related to color schemes and gear via NI, but I've seen some NPC mods that do it in the .tp2, so I'm curious.

Working and playing on a Mac Pro 6,1 running Mac OS X 10.13.6 High Sierra, and a Mac Pro 3,1 running Mac OS X 10.11.6 El Capitan.

~Buion na 'ell! I serve with joy! Your eyes and ears I shall be. Let us hunt together!~
- Erysseril Gwaethorien: a joinable, romanceable NPC mod for BGII - SoA/ToB, in sporadic development.

A female elf warrior of nature and a Bhaalspawn cross paths during their quests, joining forces to share adventure and companionship. Will they find more?


#7 Miloch

Miloch

    Barbarian

  • Modder
  • 6579 posts

Posted 08 February 2012 - 09:54 AM

If it is your own NPC, there is no reason to do it this way rather than set them on the CREs you're copying over. This is for changing colours for CREs that are already installed, e.g. in the context of a portrait mod that is going to apply specific portraits (and colours) to pre-existing NPCs.

Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle


#8 Eric P.

Eric P.

    Journeyman Modder

  • Member
  • 1178 posts

Donator

Posted 14 February 2012 - 07:48 AM

Ah! I might never have imagined a need for that, but then I'm not creating portraits, either (you don't want characters looking like Snoopy, do you?). That said, my mind is already starting to suggest uses for this...

Thanks!

Working and playing on a Mac Pro 6,1 running Mac OS X 10.13.6 High Sierra, and a Mac Pro 3,1 running Mac OS X 10.11.6 El Capitan.

~Buion na 'ell! I serve with joy! Your eyes and ears I shall be. Let us hunt together!~
- Erysseril Gwaethorien: a joinable, romanceable NPC mod for BGII - SoA/ToB, in sporadic development.

A female elf warrior of nature and a Bhaalspawn cross paths during their quests, joining forces to share adventure and companionship. Will they find more?


#9 Eric P.

Eric P.

    Journeyman Modder

  • Member
  • 1178 posts

Donator

Posted 30 March 2012 - 06:51 AM

When Adalon changes the characters in the party to appear as drow, does it handle the color changes sufficiently, or should this method of changing colors still apply? I have a separate drow portrait for my mod NPC, and I've coded for it to be applied under these conditions and for her normal portrait to be restored when the drow guise is removed. I haven't yet dug into the game files to see how exactly the drow change is set up.

Working and playing on a Mac Pro 6,1 running Mac OS X 10.13.6 High Sierra, and a Mac Pro 3,1 running Mac OS X 10.11.6 El Capitan.

~Buion na 'ell! I serve with joy! Your eyes and ears I shall be. Let us hunt together!~
- Erysseril Gwaethorien: a joinable, romanceable NPC mod for BGII - SoA/ToB, in sporadic development.

A female elf warrior of nature and a Bhaalspawn cross paths during their quests, joining forces to share adventure and companionship. Will they find more?


#10 Miloch

Miloch

    Barbarian

  • Modder
  • 6579 posts

Posted 30 March 2012 - 03:21 PM

AFAIK, there is a way of changing portraits but not of reliably changing them back (had this problem in FFT). As for colours, I don't know if there's a reliable way of changing them outside of applied spell effects.

Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle


#11 Eric P.

Eric P.

    Journeyman Modder

  • Member
  • 1178 posts

Donator

Posted 31 March 2012 - 06:34 AM

AFAIK, there is a way of changing portraits but not of reliably changing them back (had this problem in FFT). As for colours, I don't know if there's a reliable way of changing them outside of applied spell effects.


OK. That's how I have the portrait change coded: a spell effect to change to drow portraits under the right conditions, and another spell effect to change back. I followed the method used in the mod "Drows":

COPY ~Meleryn/lib/EP#MELD.SPL~ ~override~
COPY ~Meleryn/lib/EP#MELDD.SPL~ ~override~
COPY_EXISTING ~AR2102.bcs~ ~override~
  DECOMPILE_BCS_TO_BAF
	REPLACE_TEXTUALLY ~ActionOverride(Player6,ApplySpell(Myself,DROW_CHANGE))~ ~ActionOverride(Player6,ApplySpell(Myself,DROW_CHANGE))
																				ActionOverride("EP#Mel",ApplySpellRES("EP#MELDD",Myself))
  COMPILE_BAF_TO_BCS
  BUT_ONLY_IF_IT_CHANGES

COPY_EXISTING ~CUT44C.bcs~ ~override~
  DECOMPILE_BCS_TO_BAF
	REPLACE_TEXTUALLY ~ActionOverride(Player6,ApplySpell(Myself,UNDER_NORM))~ ~ActionOverride(Player6,ApplySpell(Myself,UNDER_NORM))
																			   ActionOverride("EP#Mel",ApplySpellRES("EP#MELD",Myself))
  COMPILE_BAF_TO_BCS
  BUT_ONLY_IF_IT_CHANGES
COPY_EXISTING ~dragsilv.bcs~ ~override~
  DECOMPILE_BCS_TO_BAF
	REPLACE_TEXTUALLY ~ActionOverride(Player6,ApplySpell(Myself,UNDER_NORM))~ ~ActionOverride(Player6,ApplySpell(Myself,UNDER_NORM))
																			   ActionOverride("EP#Mel",ApplySpellRES("EP#MELD",Myself))
  COMPILE_BAF_TO_BCS
  BUT_ONLY_IF_IT_CHANGES

I haven't tested this yet, as the mod is far from ready to install. Looking at the code, I'm unsure how to adapt it to make a new section to handle such things as major, minor, and armor colors. Part of me wants to see if it can be done, and part of me feels it's too much effort for too little reward, so to speak. Thoughts?

Edited by Eric P., 31 March 2012 - 06:36 AM.

Working and playing on a Mac Pro 6,1 running Mac OS X 10.13.6 High Sierra, and a Mac Pro 3,1 running Mac OS X 10.11.6 El Capitan.

~Buion na 'ell! I serve with joy! Your eyes and ears I shall be. Let us hunt together!~
- Erysseril Gwaethorien: a joinable, romanceable NPC mod for BGII - SoA/ToB, in sporadic development.

A female elf warrior of nature and a Bhaalspawn cross paths during their quests, joining forces to share adventure and companionship. Will they find more?


#12 Miloch

Miloch

    Barbarian

  • Modder
  • 6579 posts

Posted 31 March 2012 - 07:29 AM

Look at effect opcode #7 - you can set whatever colours you want (01 is minor colour, 03 skin colour, etc.). If it's a duration, the original colours should be restored when it expires. In theory, at least, I haven't tested that but I know it doesn't work with portraits (opcode #107). If you have two spells, one to change the colours and one to change them back, and it's for a custom NPC, then it probably isn't a problem. The only potential hangup might be if you allow different portraits, but as long as they're getting copied to the same portrait resource (e.g. COPY ~mymod/portr1.bmp~ ~portraits/myportr.bmp~ etc.) then that probably isn't an issue either, since you'll be restoring whatever myportr.bmp is.

Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle


#13 #GothemKnight

#GothemKnight
  • Member
  • 1 posts

Posted 24 June 2013 - 07:07 PM

I'm writing this by request to show how to change NPC colours. Actually, it will work for any creatures that have palettable animations (like humans, elves and hobgoblins). It won't affect non-palettable animations (like orcs and lizardmen). Most typically, this shows how to make sure NPC avatars and paperdolls match mods that give them different portraits. It also demonstrates some basic WeiDU modding fundamentals, though there are other tutorials for that (particularly in the WeiDU documentation).

First, some basics. This is a typical header for a mod's .tp2 installer. This text file is called something like setup-mymod.tp2 or just mymod.tp2. It is executed by a copy of WeiDU.exe renamed to the .tp2 name (setup-mymod.exe).


BACKUP ~adjports/backup~ //Where the mod backs up files
AUTHOR ~www.shsforums.net/forum/584-portrait-mods/~ //Where to submit error reports
VERSION ~v1~
README ~adjports/adjports.html~
BACKUP and AUTHOR are mandatory. VERSION is optional but recommended. It prints the version number in the WeiDU.log file that keeps track of all mods installed. README will ask the user whether to view the readme.

There is also a subheader for each component. Some mods will have only one component; others will have many. In simple form, a component for changing an NPC's colours would look something like this:
BEGIN ~My Portrait Mod~
DESIGNATED 100

ACTION_FOR_EACH npc IN ~aerbod01~ ~aerie12~ ~cwsaer~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
    COPY_EXISTING ~%npc%.cre~ ~override~ //Aerie
	  WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
	  WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
	  WRITE_BYTE 0x2e 2 //Major color (dark gold, was 37 dark dirty yellow)
	  WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
	  WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
	  WRITE_BYTE 0x31 30 //Armor color (light iron gray)
	  WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
	BUT_ONLY_IF_IT_CHANGES
  END
END
BEGIN specifies the component name when installing; it is mandatory. DESIGNATED is optional but highly recommended - it hardcodes a component number as appears in the WeiDU.log. It also allows other mods to detect the component and automated programs (such as the BiG World Project) to install the component. If you don't use DESIGNATED, your component numbers will run consecutively from zero. Thus, they will change as you add and remove new components, which isn't a good thing for automation.

The main block is a loop consisting of ACTION_FOR_EACH, ACTION_IF FILE_EXISTS_IN_GAME and COPY_EXISTING. In layman's terms, this feeds a list of filenames to WeiDU (ACTION_FOR_EACH) and says: if each file exists in the game (ACTION_IF ...) then copy it to the override folder (COPY_EXISTING) and make some changes. As for those changes, we are making a series of one-byte changes to the file (WRITE_BYTE). We use an editor (either Near Infinity or DLTCEP) to look up the existing values if we want, the IESDP to find the offsets and the desired colour gradients and their numeric values. Once that is done, we simply plug all that into our patch.

BUT_ONLY_IF_IT_CHANGES (BUT_ONLY for short) says only to copy the file if it is modified by the patches. If, for example, it already has the colour values specified, it will simply be skipped. Two ENDs close out our ACTION loops. That is all you need to do to change an NPC's colours in its simplest form. Like other mods, this will not change any NPC who has already joined the party, as they are stored in the save game.

Here is a slightly more complex example. This component gives two choices for changing Aerie's garb, thus uses SUBCOMPONENT.
BEGIN ~Aerdrie's Garb~
SUBCOMPONENT ~Aerie as Priestess of Aerdrie/Baervan~
DESIGNATED 50
REQUIRE_PREDICATE ((NOT FILE_EXISTS_IN_GAME ~_plat06.itm~) AND ((FILE_EXISTS_IN_GAME ~aerie12.cre~) OR (FILE_EXISTS_IN_GAME ~cwsaer.cre~))) ~Aerie not available~
In this case, SUBCOMPONENT actually indicates the component name, and BEGIN indicates one of several choices the user has. Other choices will follow with their own BEGIN/SUBCOMPONENT sections.

REQUIRE_PREDICATE is a good way to ensure the NPC is present. If the conditions aren't fulfilled, the installer will skip the component and go to the next one. In this case, we want to skip the component if Tutu. Aerie is present but not joinable on Tutu (all BG2 files are). Therefore, we give it a Tutu item _plat06.itm and NOT FILE_EXISTS_IN_GAME for the condition. With the AND we also make sure at least version of Aerie is present (either aerie12 or cwsaer) and pair those with an OR. The whole condition looks like this in simpler terms: (NOT Tutu) AND (aerie12 OR cwsaer). This is followed by a text message (~Aerie not available~) that will display when the installer skips the component.
COPY ~adjports/bmp/t-aeri1l.bmp~ ~override~
	 ~adjports/bmp/t-aeri1m.bmp~ ~override~
	 ~adjports/bmp/t-aeri1s.bmp~ ~override~
The section above copies the portraits for this component. Most people don't do it this way - they overwrite the existing portraits. This demonstrates a way of avoiding that to keep the previous portraits available for other purposes.
ACTION_FOR_EACH tda IN ~aeriend1~ ~aeriend2~ ~aerifnd1~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%tda%.2da~ BEGIN
	COPY_EXISTING ~%tda%.2da~ ~override~ //ToB epilogue tables
	  SET_2DA_ENTRY 1 0 1 ~*T-AERI1L~
	BUT_ONLY
  END
END
That section replaces Aerie's Throne of Bhaal epilogue portrait in the relevant tables. It is only relevant for ToB NPCs, and then only if you don't overwrite the existing portrait.
COPY_EXISTING ~spin745.spl~ ~override~ //Aerie Portrait Spell
  PATCH_IF SOURCE_SIZE > 0x71 BEGIN
	READ_LONG 0x64 hf //Extended header offset
	READ_SHORT 0x68 hc //Extended header count
	READ_LONG 0x6a fb //Feature block offset
	FOR (i1 = 0; i1 < hc; i1 += 1) BEGIN //Cycle through extended headers
	  READ_SHORT (0x28 * i1 + hf + 0x1e) fc //Feature count
	  READ_SHORT (0x28 * i1 + hf + 0x20) fs //Feature offset
	  FOR (i2 = fs; i2 < (fs + fc); i2 += 1) BEGIN //Cycle through ability effects
		READ_SHORT (i2 * 0x30 + fs) opcode
		READ_LONG (i2 * 0x30 + fs + <img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> param2
		PATCH_IF (opcode = 107) AND (param2 = 0) BEGIN //If small portrait
		  WRITE_ASCII (i2 * 0x30 + fs + 0x14) ~t-aeri1s~ #8
		END
		PATCH_IF (opcode = 107) AND (param2 = 1) BEGIN //If large portrait
		  WRITE_ASCII (i2 * 0x30 + fs + 0x14) ~t-aeri1m~ #8
		END
	  END
	END
  END
BUT_ONLY
The above section is relevant only to Aerie, as there is a spell effect that morphs her back into avariel form after being an ogre. It specifies her small and medium portraits. I won't detail the code, but it basically loops through all effects attached to the spell and changes those where it finds portraits.
ACTION_FOR_EACH npc IN ~aerbod01~ ~aerie12~ ~cwsaer~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
	COPY_EXISTING ~%npc%.cre~ ~override~ //Aerie
	  PATCH_IF SOURCE_SIZE > 0x2d3 BEGIN //Ensures valid .cre file size
		WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
		WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
		WRITE_BYTE 0x2e 2 //Major color (dark gold, was 37 dark dirty yellow)
		WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
		WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
		WRITE_BYTE 0x31 30 //Armor color (light iron gray)
		WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
	  END
	BUT_ONLY_IF_IT_CHANGES
  END
END
Finally, the code above changes her colours as in the first example. For the second subcomponent, we'd copy and paste the same code above and just change the BEGIN name (e.g. to ~Baervan's Garb~), increase the DESIGNATED component number (e.g. to 60), change all the portraits we're copying (e.g. from t-aeri1 to t-aeri2) and finally, change the colours in the second set of code to match her second portrait, following the techique above (i.e. look them up in the IESDP).

Here's the full code for a slightly simpler example. It provides two different examples for Branwen (based on portraits with either brown or purple robes).

There's no ToB Branwen nor morphing spell for her, so we just need to copy the relevant portraits and assign them and the appropriate colours on her .cre files. We do, however, have to check via REQUIRE_PREDICATE that Branwen is present, so we look for Tutu (_branwe5.cre), BGT (branwe5.cre) and at least 4 different mod versions. Apparently, Branwen is a popular gal - you could in theory have a party with you and 5 other Branwens! Ah, the joys of redundant mods, er, I mean user choices.
BEGIN ~Brown Robe~
SUBCOMPONENT ~Branwen as Priestess of Tempus~
DESIGNATED 100
REQUIRE_PREDICATE ((FILE_EXISTS_IN_GAME ~_branwe5.cre~) OR (FILE_EXISTS_IN_GAME ~branwe5.cre~) OR (FILE_EXISTS_IN_GAME ~cb3513bw.cre~) OR (FILE_EXISTS_IN_GAME ~dl#bwn.cre~) OR (FILE_EXISTS_IN_GAME ~ttbran.cre~) OR (FILE_EXISTS_IN_GAME ~wlbran0.cre~)) ~Branwen not available~

COPY ~adjports/bmp/t-bran1l.bmp~ ~override~
	 ~adjports/bmp/t-bran1m.bmp~ ~override~
	 ~adjports/bmp/t-bran1s.bmp~ ~override~

ACTION_FOR_EACH npc IN ~_branwe~ ~_branwe5~ ~branwe~ ~branwe5~ ~cb3513bw~ ~dl#bwn~ ~ttbran~ ~wlbran0~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
	COPY_EXISTING ~%npc%.cre~ ~override~ //Branwen
	  PATCH_IF SOURCE_SIZE > 0x2d3 BEGINWeiDU documentation
		WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
		WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
		WRITE_BYTE 0x2e 2 //Major color (dark gold, was 37 dark dirty yellow)
		WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
		WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
		WRITE_BYTE 0x31 30 //Armor color (light iron gray)
		WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
		WRITE_ASCII 0x34 ~t-bran1s~ #8 //Small portrait
		WRITE_ASCII 0x3c ~t-bran1m~ #8 //Large portrait
	  END
	BUT_ONLY_IF_IT_CHANGES
  END
END

BEGIN ~Purple Robe~
SUBCOMPONENT ~Branwen as Priestess of Tempus~
DESIGNATED 105
REQUIRE_PREDICATE ((FILE_EXISTS_IN_GAME ~_plat06.itm~) OR (FILE_EXISTS_IN_GAME ~plat06.itm~)) ~Branwen not found~

COPY ~adjports/bmp/t-bran2l.bmp~ ~override~
	 ~adjports/bmp/t-bran2m.bmp~ ~override~
	 ~adjports/bmp/t-bran2s.bmp~ ~override~

ACTION_FOR_EACH npc IN ~_branwe~ ~_branwe5~ ~branwe~ ~branwe5~ ~cb3513bw~ ~dl#bwn~ ~ttbran~ ~wlbran0~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%npc%.cre~ BEGIN
	COPY_EXISTING ~%npc%.cre~ ~override~ //Branwen
	  PATCH_IF SOURCE_SIZE > 0x2d3 BEGIN
		WRITE_BYTE 0x2c 67 //Metal color (shiny gold, was 27 gray)
		WRITE_BYTE 0x2d 47 //Minor color (pure dark red, was 41 dark brown)
		WRITE_BYTE 0x2e 60 //Major color (dark purple, was 37 dark dirty yellow)
		WRITE_BYTE 0x2f 12 //Skin color (light carnation pink)
		WRITE_BYTE 0x30 16 //Leather color (silver gold, was 93 dark cement gray)
		WRITE_BYTE 0x31 104 //Armor color (dark chrome purple)
		WRITE_BYTE 0x32 115 //Hair color (sunkissed, was 3 light gold)
		WRITE_ASCII 0x34 ~t-bran2s~ #8 //Small portrait
		WRITE_ASCII 0x3c ~t-bran2m~ #8 //Large portrait
	  END
	BUT_ONLY_IF_IT_CHANGES
  END
END
And that's it for a simple component with two different portrait options.

Folks have also asked me how to change the colours of items. Say you've changed the hue of an NPC's special armour in your portrait and you want the item to follow suit. I won't get into how to change the icons. BAM Batcher and your favourite graphics program can do that easily enough, and there are probably other tutorials for that. This changes the colours on the paperdoll and animation or avatar when equipping the item.
BEGIN ~Ankheg Plate matches its icon~
DESIGNATED 25

ACTION_FOR_EACH ank IN ~_plat06~ ~plat06~ BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%ank%.itm~ BEGIN
	COPY_EXISTING ~%ank%.itm~ ~override~ //Ankheg Plate
	  PATCH_IF SOURCE_SIZE > 0x71 BEGIN //Ensures valid .itm file size
		READ_LONG 0x6a eq_off //Equipped effects offset
		READ_SHORT 0x70 eq_cnt //Equipped effects count
		FOR (i1 = 0; i1 < eq_cnt; i1 += 1) BEGIN
		  READ_SHORT (i2 * 0x30 + eq_off) opcode
		  READ_LONG (i2 * 0x30 + eq_off + <img src='http://www.shsforums.net/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='8)' /> param2
		  PATCH_IF (opcode = 7) AND (param2 = 5) BEGIN //If armor color
			WRITE_SHORT (i2 * 0x30 + eq_off + 4) 7 //Dark metallic green
		  END
		  PATCH_IF (opcode = 7) AND (param2 = 4) BEGIN //If strap color
			WRITE_SHORT (i2 * 0x30 + eq_off + 4) 1 //Light pure gold
		  END
		  PATCH_IF (opcode = 7) AND (param2 = 0) BEGIN //If belt color
			WRITE_SHORT (i2 * 0x30 + eq_off + 4) 36 //Light dirty yellow
		  END
		END
	  END
	BUT_ONLY
  END
END
Fairly straightforward example for the Ankheg Plate. Following the ACTION... logic described above, the code loops through each version of the item, looks for equipped effects matching certain conditions (opcode 7 for colour effects) and sets them to the relevant colours when it finds the right effects (for armour, strap and belt in this case).

What about the creature that cannot be palleted ?

like dragons or wyverns?



#14 Thimblerig

Thimblerig
  • Member
  • 25 posts

Posted 10 April 2015 - 03:08 AM

So I've found when playing with creature patching, that when assigning some colours to a creature, any area that holds that creature will crash the game before loading.

 

Which I sorta don't want to happen...

 

Is there a list somewhere that says which colours are 'out of bounds'?

 

EDIT:

 

Was informed elsewhere that colours under about 68-69 are for character sprites.


Edited by Thimblerig, 10 April 2015 - 12:56 PM.


#15 Miloch

Miloch

    Barbarian

  • Modder
  • 6579 posts

Posted 25 April 2015 - 11:08 PM

Color values 66 and below are typical character colors. However, you should also be able to get away with 79 and up (to about 115 or so) as well; as per the IESDP, these should be valid colors. If you install (or incorporate) 1PP's extended palette entries, you should be able to use the full range of expanded colors up to about 200 or so, at which point the randcolr.2da entries take over (random colors). However, you can also use fixed color entries up to 255 for items after that, just not for CREs (which will use random colors via randcolr.2da instead).


Infinity Engine Contributions
Aurora * BG1 NPC * BG1 Fixpack * Haiass * Infinity Animations * Level 1 NPCs * P5Tweaks
PnP Free Action * Thrown Hammers * Unique Containers * BG:EE * BGII:EE * IWD:EE
================================================================
Player & Modder Resources
BAM Batcher * Creature Lister * Creature Checker * Creature Fixer * Tutu/BGT Area Map & List * Tutu Mod List
================================================================
"Infinity turns out to be the opposite of what people say it is. It is not 'that which has nothing beyond itself' that is infinite, but 'that which always has something beyond itself'." -Aristotle


#16 Thimblerig

Thimblerig
  • Member
  • 25 posts

Posted 27 April 2015 - 02:29 PM

Thanks, Miloch.







Also tagged with one or more of these keywords: NPCs creatures, items