Overview


1pp Note for modders is intended for modders who wish to make their mods compatible with 1pp. This document is organized using a tutorial approach, in which you are guided through each step of accomplishing particular modding tasks without breaking compatibility.


1ppv4: Note for modders > OverviewBACK TO TOP

Modding with the extended palette


1ppv4 Extended palette entries component [102] adds new colour gradients to Infinity Engine games, raising the count of available colours from 116 to 256. It also includes a new random colour table making use of them for Baldur's Gate II and new colour set files for Icewind Dale II, giving you more skin/hair colour choices for the various races.

Keep in mind that if you include a new entry in a mod (120+) it *will* crash installs that do not have extended MPALETTE and MPAL256 files (the 1pp palette tool will also warn you if you are setting new gradients).

Since the content of these files is not touched by any other mods (that I am aware of) and replacing them is as non-intrusive as it gets the easiest way to avoid this is to include them with your mod and install them.

To avoid unnecessary overwriting of the files it would be best to add a simple file size check. If the file sizes are 9,272 bytes (MPALETTE) and 196,664 bytes (MPAL256) they already contain a full 256 colour set and need no further patching:

      ACTION_FOR_EACH GWPalette IN MPALETTE MPAL256 BEGIN

          ACTION_IF FILE_EXISTS_IN_GAME ~%GWPalette%.bmp~ BEGIN

              COPY_EXISTING - ~%GWPalette%.bmp~	~override~
                  PATCH_MATCH ~%GWPalette%~ WITH
                      MPALETTE BEGIN  SET size1PP = 9272 END
                      DEFAULT         SET size1PP = 196664
                  END
              OUTER_SET sizePal = %SOURCE_SIZE%
              PRINT ~CONTROL %GWPalette%.bmp palette size = %sizePal% - 1PP = %size1PP%~

              ACTION_IF (sizePal != %size1PP%) BEGIN
                  PRINT ~Copying 1PP extended palette file %SOURCE_FILE%.~
                  COPY ~%MY_MOD%/resources/%GWPalette%.bmp~ ~override~
              END

          END

      END


Of course, if you use them for a major character colour (and this is the only situation where it would be noticeable) this will not fix the dialogue font colour.


1ppv4: Note for modders > Modding with the extended paletteBACK TO TOP

Patching Items and Spells


As of v4.2.0, the main 1pp update component [400] includes improved compatibility with third party mods. Modders are strongly recommended to borrow this simple way of coding to provide compatibility with 1pp, as Bolsa, Darron, Improved HaerDalis Swords, Rolles, Ruad, Song and Silence, Stuff of the Magi and The Unusual Oddities Shop mods already do.
Below is a brief step by step process to complete it.


⚠️ Warning: It will only work fine if 1pp components needed by your mod are installed.


➽   1. Detecting 1pp
➽   2. Loading macros and functions
➽   3. Patching an item
a. Defining its own colors.
b. Using 1pp Staff of the Magi settings.
c. Using 1pp Glowing Staff of the Magi settings.
➽   4. Customizing 1pp_compatibility library
➽   5. Using new 1pp projectiles
a. Setting a new 1pp projectile to your itm or your spl if 1pp is installed.
b. Updating protection from projectiles with new 1pp projectiles.
➽   6. Using Smart Avatar & Armour Switching component




1. Detecting 1pp

As 1pp update component patches items and provides additional content depending on which components are installed, detecting if 1pp is installed is not enough and you need to detect which components are installed to fine tune compatibility. Copy the following code in your ALWAYS block:

      // 1ppv4: Additional Helmet Animations (core)
      OUTER_SET is_1pp_helmet =  (MOD_IS_INSTALLED ~1pp.tp2~ ~208~) ? 1 : 0
      // 1ppv4: Additional Helmet Animations (core)
      OUTER_SET is_1pp_helmet  = (MOD_IS_INSTALLED ~1pp.tp2~ ~208~) ? 1 : 0
      // 1ppv4: Increased paperdoll object variety (core) with Additional Shield Animations (core)
      OUTER_SET is_1pp_shld    = ((MOD_IS_INSTALLED ~1pp.tp2~ ~206~) AND (MOD_IS_INSTALLED ~1pp.tp2~ ~400~)) ? 1 : 0
      // 1ppv4: Restored flame sword animations is installed
      OUTER_SET is_1pp_fswords = (MOD_IS_INSTALLED ~1pp.tp2~ ~203~) ? 1 : 0
      // 1ppv4: Wizards' Staves (core)
      OUTER_SET is_1pp_staff   = ((MOD_IS_INSTALLED ~1pp.tp2~ ~207~) AND (MOD_IS_INSTALLED ~1pp.tp2~ ~400~)) ? 1 : 0
      // 1ppv4: Colourable Quarterstaves without 1ppv4: Wizards' Staves (core)
      OUTER_SET is_1pp_staff0  = ((MOD_IS_INSTALLED ~1pp.tp2~ ~204~) AND (is_1pp_staff = 0)) ? 1 : 0
      // 1ppv4: Increased paperdoll object variety (core)
      OUTER_SET is_1pp_swblbw  = ((MOD_IS_INSTALLED ~1pp.tp2~ ~210~) AND (MOD_IS_INSTALLED ~1pp.tp2~ ~400~)) ? 1 : 0
      // 1ppv4: Core updates and item patches
      OUTER_SET is_1pp_400     = (MOD_IS_INSTALLED ~1pp.tp2~ ~400~) ? 1 : 0                                           
      // 1ppv4: Improved projectile effects
      OUTER_SET is_1pp_401     =  (MOD_IS_INSTALLED ~1pp.tp2~ ~401~) ? 1 : 0
      // 1ppv4: Smart Avatar & Armour Switching
      OUTER_SET is_1pp_switch  =  (MOD_IS_INSTALLED ~1pp.tp2~ ~113~) ? 1 : 0




2. Loading macros and functions

Once it is done, you must load 3 libraries that will do the job:

      ACTION_IF (is_1pp_helmet OR is_1pp_shld OR is_1pp_staff OR is_1pp_staff0 OR is_1pp_fswords OR is_1pp_swblbw OR is_1pp_400 OR is_1pp_401) BEGIN
          INCLUDE ~%MOD_FOLDER%/lib/1pp_macros.tpa~
          LAM ~Locations~                  // DEFINES location field values to alter items' colors  MUST BE RUN ONLY ONCE
          INCLUDE ~%MOD_FOLDER%/lib/1pp_compatibility.tph~
          INCLUDE ~%MOD_FOLDER%/lib/1pp_functions.tpa~
      END

with

  • 1pp_macros.tpa: list of macros dealing with items coloring.
  • 1pp_compatibility.tph: Loads functions restoring items coloration for EE games or if 1PP relevant components are installed.
  • 1pp_functions.tpa: Loads miscellaneous macros and functions library used by 1pp v4.2.0.



3. Patching an item

Now comes the real part. If you want to create an item using 1pp features, let's say a special Staff of the Magi, the process is fairly simple: First, create it as a "normal" Staff of the Magi, and install it with your tp2:

      COPY ~%MY_MOD%/itm/mystaff.itm~ ~override~
          SAY NAME1 @1
          SAY NAME2 @2
          SAY UNIDENTIFIED_DESC @3
          SAY DESC @4


Then you have three choices: modify its colors to fit your new icon or use the 1pp Staff of the Magi setting (using 1pp ISTAF11 icon).




a. Defining its own colors.

It is very easy: use 1pp homemade functions defined in 1pp_macros.tpa library.

      COPY ~%MY_MOD%/itm/mystaff.itm~ ~override~
          SAY NAME1 @1
          SAY NAME2 @2
          SAY UNIDENTIFIED_DESC @3
          SAY DESC @4
          PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
              PATCH_IF (is_1pp_staff0 OR is_1pp_staff) BEGIN
                  LPM ~clear~           // REMOVES all existing items' coloration opcodes before setting new ones
                  SET gradient = 112    // 112 SEA_FOAM
                  SET location = wgrey  // location (Head/Blade/Staff major)
                  LPM ~colour~          // ADDS a new item global effect (op#7: Set Character colours by Palette)
                  SET gradient = 113    // sets colour index 113 FOG
                  SET location = wteal  // location (Staff minor)
                  LPM ~colour~
                  SET gradient = 93     // sets colour index 93 DARK_CEMENT_GRAY
                  SET location = wpink  // location (Bolt-Mace-Staff)
                  LPM ~colour~
                  SET gradient = 98     // sets colour index 98 LEAF_GREEN
                  SET location = wblue  // location (Head/Blade minor)
                  LPM ~colour~
                  SET gradient = 27     // sets colour index 27 GRAY
                  SET location = wred   // location * compatibility
                  LPM ~colour~
              END
          END
     BUT_ONLY 




b. Using 1pp Staff of the Magi settings.

It is very easy: use 1pp homemade functions defined in 1pp_compatibility.tph library.

      COPY ~%MY_MOD%/itm/mystaff.itm~ ~override~
          SAY NAME1 @1
          SAY NAME2 @2
          SAY UNIDENTIFIED_DESC @3
          SAY DESC @4
          PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
              PATCH_IF (is_1pp_staff0) BEGIN
                  LPF ~1pp_staf11_0~ END      // Uses 1pp Colourable Quarterstaves settings (component 204)
              END
          END
     BUT_ONLY 

with

  ► 1pp_staf11_0 function (defined in 1pp_compatibility.tph library):

DEFINE_PATCH_FUNCTION ~1pp_staf11_0~ BEGIN
    PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
        SET opcode_to_delete = 7
        LPM DELETE_ITEM_EQEFFECT
        SET opcode_to_delete = 8
        LPM DELETE_ITEM_EQEFFECT
        SET gradient = 112      // 112 SEA_FOAM replaces colour index 25 DARK_PURE_GOLD
        SET location = wgrey    // location (Head/Blade/Staff major)
        LPM ~colour~
        SET gradient = 113      // sets colour index 113 FOG
        SET location = wteal    // location (Staff minor)
        LPM ~colour~
        SET gradient = 93      // sets colour index 93 DARK_CEMENT_GRAY
        SET location = wpink   // location (Bolt-Mace-Staff)
        LPM ~colour~
        SET gradient = 98      // sets colour index 98 LEAF_GREEN
        SET location = wblue   // location (Head/Blade minor)
        LPM ~colour~
        SET gradient = 27      // sets colour index 27 GRAY
        SET location = wred    // location * compatibility
        LPM ~colour~
    END
END 





c. Using 1pp Glowing Staff of the Magi settings.

Always with 1pp homemade functions defined in 1pp_compatibility.tph library.

      COPY ~%MY_MOD%/itm/mystaff.itm~ ~override~
          SAY NAME1 @1
          SAY NAME2 @2
          SAY UNIDENTIFIED_DESC @3
          SAY DESC @4
          PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
              PATCH_IF (is_1pp_staff) BEGIN
                  LPF ~1pp_staf11~ END        // Uses 1pp Wizards' Staves settings (component 207)
              END
          END
     BUT_ONLY 

with

  ► 1pp_staf11 function (defined in 1pp_compatibility.tph library):

DEFINE_PATCH_FUNCTION ~1pp_staf11~ BEGIN
    PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
        WRITE_ASCII 0x22 ~GS~           // Glowing staff
        WRITE_ASCII 0x44 ~1GSTAFGS~ #8  // replaces GSTAF01
        LPM ~clear~
        SET gradient = 127              // sets colour index 93 DARK_CEMENT_GRAY
        SET location = wpink            // location (Bolt-Mace-Staff)
        LPM ~colour~
        SET gradient = 207              // sets colour index 207 NOBLE_MINOR2-CHROME_GOLD
        SET location = wteal            // location (Staff minor)
        LPM ~colour~
        SET gradient = 192              // 192 CHROME_TEAL replaces colour index 25 DARK_PURE_GOLD
        SET location = wgrey            // location (Head/Blade/Staff major)
        LPM ~colour~
        SET setr = 0
        SET setg = 0
        SET setb = 0
        SET location = wblue            // location (Head/Blade minor)
        LPM ~glow~
        SET gradient = 250              // sets colour index 250 SHADOW_DRUID_MAJOR-YELLOW_ORANGE
        SET location = wblue            // location (Head/Blade minor)
        LPM ~colour~
        SET gradient = 220              // 220 ELF_MAJOR-MIDNIGHT_BLUE replaces colour index 27 GRAY
        SET location = wred            // location (Grip/Staff minor - vanilla = whole staff)
        LPM ~colour~
    END
END 



Note: you can mix the last two options and even add EE compatibility:

      COPY ~%MY_MOD%/itm/mystaff.itm~ ~override~
          SAY NAME1 @1
          SAY NAME2 @2
          SAY UNIDENTIFIED_DESC @3
          SAY DESC @4
          PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
              PATCH_IF (is_ee OR is_1pp_staff) BEGIN
                  LPF ~1pp_staf11~ END               // Uses 1pp Wizards' Staves settings (component 207)
              END
              PATCH_IF (is_1pp_staff0) BEGIN
                  LPF ~1pp_staf11_0~ END             // Uses 1pp Colourable Quarterstaves settings (component 204)
              END
          END
     BUT_ONLY 

with is_ee defined like this in your ALWAYS block:

  ► is_ee variable:

OUTER_SET is_ee = (GAME_IS ~bgee bg2ee eet~) ? 1 : 0 // EE game





4. Customizing 1pp_compatibility library

As 1pp_compatibility library has been written to improve 1pp compatibility with a few mods installed before it (if ever!), it does not contain all patches and you may need to customize it to fit your needs.

Let's say you want to create an upgraded version or another version of Celestial Fury +3. All you have to do is to check the code used in 400_update_bgii_swords.tpa and copy-paste it in 1pp_compatibility.tph, like this:

      // Celestial Fury +3
      DEFINE_PATCH_FUNCTION ~1pp_sw1h51~ BEGIN
          PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
              LPM ~clear~
              SET gradient = 25       // sets colour index 25 DARK_PURE_GOLD
              SET location = wgrey    // location (Head/Blade/Staff major)
              LPM ~colour~
              SET gradient = 223      // 223 DROW_SKIN-MOSS_GREEN replaces colour index 16 SILVERISH_GOLD
              SET location = wblue    // location (Head/Blade minor)
              LPM ~colour~
              SET gradient = 47       // sets colour index 47 PURE_DARK_RED
              SET location = wred     // location (Grip/Staff minor - vanilla = whole staff)
              LPM ~colour~
          END
      END 

And install your sword like this:

      COPY ~%MY_MOD%/itm/mysword.itm~ ~override~
          SAY NAME1 @1
          SAY NAME2 @2
          SAY UNIDENTIFIED_DESC @3
          SAY DESC @4
          PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
              PATCH_IF (is_ee OR is_1pp_swblbw) BEGIN
                  LPF ~1pp_sw1h51~ END
              END
          END
     BUT_ONLY 




5. Using new 1pp projectiles

And now comes the easiest part of all: make your spells or items either using 1pp new projectiles or protecting from projectiles compatible with 1pp. In both cases, you can either use innate WeiDU functions or use 1pp_functions.tpa library that was written specially for 1pp Improved projectile effects component [401]. It includes:

  • Function GW_DEF_OFFSETS_FILE: DEFINES the main offsets used to patch SPL, ITM and CRE files.
  • Function GW_CLEAR_DUPLICATED_OPCODES: LOOKS for a specific opcode in a file and DELETES duplicated effects.
  • Function GW_MODIFY_PROJ: MODIFIES an item's or spell's projectile.



a. Setting a new 1pp projectile to your itm or your spl if 1pp is installed.

You can use the way Rolles mod adds 1pp compatibility:

      // Sling +4 Arla's Dragonbane
      COPY ~rolles/itm/s#slng01.itm~ ~override~
          SAY NAME2 @1000
          SAY DESC @1001
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              LPF ALTER_ITEM_HEADER INT_VAR projectile = (IDS_OF_SYMBOL (projectl 1bull06) + 1) END
          END
          PATCH_IF (is_ee OR is_1pp_400) BEGIN
              LPF ~1pp_slng05~ END
          END
      BUT_ONLY

      // Battle Axe +4 Ice and Fire
      COPY ~rolles/itm/s#ax1h01.itm~ ~override~
          SAY NAME2 @1012
          SAY DESC @1013
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              LPF ALTER_ITEM_HEADER INT_VAR header_type = 2 projectile = (IDS_OF_SYMBOL (projectl 1axe08) + 1) END
          END
          PATCH_IF (is_ee OR is_1pp_400) BEGIN
              LPF ~1pp_ax1h13~ END
          END
      BUT_ONLY

or install them a la mode 1pp:

      COPY ~%MY_MOD%/items/mydagger.itm~ ~override~
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              PATCH_IF (SOURCE_SIZE > 0x71) BEGIN  // protects against invalid files
                  LPF ~GW_MODIFY_PROJ~ STR_VAR old_proj = "DAGGER" new_proj = "1dagg16" END
              END
          END
      BUT_ONLY

      COPY ~%MY_MOD%/spells/myspell.spl~ ~override~
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              PATCH_IF (SOURCE_SIZE > 0x71) BEGIN  // protects against invalid files
                  LPF ~GW_MODIFY_PROJ~ STR_VAR old_proj = CLOUDKIL new_proj = 1pgspore END
              END
          END
      BUT_ONLY




b. Updating protection from projectiles with new 1pp projectiles.

Once again, you can use 1pp homemade functions defined in 1pp_functions.tpa library:

      // Added missing protections from new normal 1pp amo projectiles.
      COPY ~%MOD_FOLDER%/items/%item%.itm~ ~override~
          LPF ~GW_DEF_OFFSETS_FILE~ RET GW_oe GW_oc GW_al GW_fx GW_fi GW_fc GW_min_size END
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              LPF ~GW_CLEAR_DUPLICATED_OPCODES~ INT_VAR GW_opcode_to_check = 83 GW_effects_type = 2 RET GW_param2_55 END
              PATCH_FOR_EACH proj IN 1arow01 1bolt01 1dagg05 1dart01 BEGIN
                  SET projnb = IDS_OF_SYMBOL (~projectl~ ~%proj%~)
                  PATCH_IF projnb > 0 BEGIN
                    LPF CLONE_EFFECT INT_VAR silent = 1 check_headers = 0 multi_match = 1 match_opcode = 83 parameter2 = projnb STR_VAR insert = last END
                  END
              END
              // Special case: SPEAR (55) needs a special treatment because some items do not bestow protection from spear projectile (used by the new javelin weapon).
              PATCH_IF GW_param2_55 = 0 BEGIN
                  LPF CLONE_EFFECT INT_VAR silent = 1 check_headers = 0 multi_match = 1 match_opcode = 83 parameter2 = 55 STR_VAR insert = last END
              END
			END
         END
      BUT_ONLY

      // Physical Mirror - Gwen fix: cleared duplicate entries and added SR compatibility (SR replaces opcode #197 with opcode #83).
      COPY_EXISTING ~sppr613.spl~ ~override~
          LPF ~GW_DEF_OFFSETS_FILE~ RET GW_oe GW_oc GW_al GW_fx GW_fi GW_fc GW_min_size END
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              PATCH_FOR_EACH GW_opcode IN 83 197 BEGIN
                  LPF ~GW_CLEAR_DUPLICATED_OPCODES~ INT_VAR GW_opcode_to_check = GW_opcode GW_effects_type = 2 RET GW_param2_55 END
                  PATCH_FOR_EACH proj IN      // 1pp new projectiles
                      1arow01 1arow02 1arow03 1arow04 1arow05 1arow07 1arow10 1arow11 1arow15 1axe05 1axe08 1axe09 1axe10 1axe16
                      1bolt01 1bolt02 1bolt03 1bolt04 1bolt05 1bolt06 1bolt09 1bull02 1bull03 1bull04 1bull05 1bull06
                      1dagg05 1dagg11 1dagg12 1dagg16 1dart01 1dart02 1dart03 1dart04 1dart05 1dart08 BEGIN
                      SET projnb = IDS_OF_SYMBOL (~projectl~ ~%proj%~)
                      PATCH_IF projnb > 0 BEGIN
                          LPF CLONE_EFFECT INT_VAR silent = 1 check_globals = 0 multi_match = 1 match_opcode = GW_opcode parameter2 = projnb STR_VAR insert = last END
                      END
                  END
                  // Special case fix: SPEAR (55) needs a special treatment.
                  PATCH_IF GW_param2_55 = 0 BEGIN
                      LPF CLONE_EFFECT INT_VAR silent = 1 check_globals = 0 multi_match = 1 match_opcode = GW_opcode parameter2 = 55 STR_VAR insert = last END
                  END
              END
          END
      BUT_ONLY

or use innate WeiDU functions:

      // Enhanced Shield of Balduran (Rolles mod)
      COPY ~rolles/itm/s#shld01.itm~ ~override~
          SAY NAME2 @1002
          SAY DESC @1003
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              PATCH_FOR_EACH proj IN      // 1pp new projectiles
                  1arow01 1arow02 1arow03 1arow04 1arow05 1arow07 1arow10 1arow11 1arow15 1axe05 1axe08 1axe09 1axe10 1axe16
                  1bolt01 1bolt02 1bolt03 1bolt04 1bolt05 1bolt06 1bolt09 1bull02 1bull03 1bull04 1bull05 1bull06
                  1dagg05 1dagg11 1dagg12 1dagg16 1dart01 1dart02 1dart03 1dart04 1dart05 1dart08 BEGIN
                  SET projnb = IDS_OF_SYMBOL (~projectl~ ~%proj%~)
                  PATCH_IF projnb > 0 BEGIN
                      LPF CLONE_EFFECT INT_VAR silent = 1 check_headers = 0 multi_match = 1 match_opcode = 197 parameter2 = projnb STR_VAR insert = above END
                  END
             END
         END
          PATCH_IF (is_ee OR is_1pp_shld) BEGIN
              LPF ~1pp_wa2shiel~ END
          END
          PATCH_IF (is_1pp_shld0) BEGIN
              LPF ~1pp_shld27_0~ END
          END
      BUT_ONLY

      // Girdle of the Magi (Stuff of the Magi mod)
      COPY ~%MOD_FOLDER%/items/wzrdbelt.itm~ ~override~
          SAY NAME2 @141
          SAY DESC @143
          PATCH_IF (is_ee OR is_1pp_401) BEGIN
              PATCH_FOR_EACH proj IN 1arow01 1bolt01 1dagg05 1dart01  // 1pp new projectiles
                   SET projnb = IDS_OF_SYMBOL (~projectl~ ~%proj%~)
                  PATCH_IF projnb > 0 BEGIN
                      LPF CLONE_EFFECT INT_VAR silent = 1 check_headers = 0 multi_match = 1 match_opcode = 83 parameter2 = projnb STR_VAR insert = last END
                  END
             END
         END
      BUT_ONLY




6. Using Smart Avatar & Armour Switching component

If you want your robes and armors benefit from this component which allows armour and robes to properly show up for characters of any class when equipped, use the following code (from Darron mod):

      // Aurumvorax Armor +2
      COPY ~darron/item/esliarm0.itm~ ~override~
          SAY NAME12 @108
          SAY DESC @110
          PATCH_IF (is_1pp_switch) BEGIN
              // armor spell effect
              LPF ADD_ITEM_EQEFFECT INT_VAR insert_point = "-1" opcode = 146 target = 1 timing = 2 parameter1 = 1 parameter2 = 1 STR_VAR resource = lcarmor END
          END
      BUT_ONLY




I guess now it's time to... Enjoy! 😉


1ppv4: Note for modders > Patching Items and SpellsBACK TO TOP