cmorgan Posted April 3, 2007 Share Posted April 3, 2007 (edited) Crossing the Great Divide: Single-source modding for Tutu, BGT, and Beyond A Beginner's Introduction to Coding for both Tutu and BGT We have two solid, viable approaches to playing Baldurs Gate using the BG2 engine. Currently, it is common practice to build your mod for one or the other, and then convert the program (either manually, or by asking Ascension64 to assist). This is great for the community, allowing both audiences the content of your mod. It also leaves you with a challenge; maintaing two sets of code, one of which you may not quite understand. After all, someone else converted it! Luckily for us, only three obstacles fall in the path of writing just one code to cover both platforms; resource/file names, chapter numbers, and actual state numbers. The vast majority of coding can be used on both Tutu and BGT. Baldurs Gate (BG1) is a different matter, as the scripting actions and triggers available differ, so for now we will deal with just Tutu and BGT). The ideas used in this tutorial are currently utilized in The BG1 NPC Project internal versions. The ideas are compiled from many different modders in both the BGT and Tutu modding circles, and represent one way of consolidating some of the best ideas from the IE Modding community. It assumes the following: It seems easier for folks to read/check plain language long names than to remember area numbers or script/dialogue names. It seems easier to code using one file and "transparently" adapt to different installs on install. It appears either quicker or the same to use a single EVALUATE_BUFFER then it is to process multiple platform pairings of copy/patch actions on any computer capable of running BG2. It is easiest to code your ideas when you have had almost all the legwork done for you in a template, so you can copy/paste and concentrate on the important stuff... writing your story, for others to enjoy. Part 1. An Introduction to The Magic of Variables For us non-codewarriors, OUTER_SPRINT might as well be Swahili. Using variable substitution looks like magic. Here is the good news; variables are just cool ways of swapping out one thing for another. A good example is making a good salad. We can create one using lettuce, nuts, and fruit. To make things more specific, we can use lettuce, walnuts, and apples; or we can use lettuce, hazelnuts, and oranges. The placeholders "fruit" and "nuts" can be defined many different ways. We can do this using WeiDU relatively easily. Let's start with an example, a check to see if your actor is in a specific area. In your myMod.BAF file, you might have the code (simplifed for examples) IF AreaCheck("FW1900") InParty("cmorgan") THEN RESPONSE #100 SetGlobal("CmorganInBanditCamp","GLOBAL",1) END In Tutu, areas are named differently from BGT, so the Bandit Camp in Tutu is FW1900, while in BGT it is AR8700. Wouldn't it be nice if we could just tell the darned mod that we want "BanditCamp" as the area? Then we have a nice, readable name. So let's use WeiDU to make this happen. We can declare BanditCamp a variable, by putting it in %'s: %BanditCamp%. So far, so good. Now we just write our code, IF AreaCheck("%BanditCamp%") InParty("cmorgan") THEN RESPONSE #100 SetGlobal("CmorganInBanditCamp","GLOBAL",1) END "Whooot!", you say,"wicked easy! I can do that!" except... we need to tell WeiDU what possible values there are for %BanditCamp%. Right now, there is nothing there. You have said "fruit" without defining when you want "fruit" to be "apple", and when you want it to be "orange". So back to WeiDU. The first step is to tell the player's machine that we want to substitute things in the tp2. ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN tells WeiDu to check to see if the player has the file FW0100.are in their install. Since this is only on Tutu installs, we can now say "ok, we want fruit=apple": OUTER_SPRINT "BanditCamp" "FW1900" Now we have something! On a Tutu install, WeiDU will see %BanditCamp%, and will understand it as FW1900. But we still need to help out the BGT side: END ELSE BEGIN tells WeiDU to stop the section where the Tutu file exists. If it didn't exist, then it is ok to go ahead and use the BGT value: OUTER_SPRINT "BanditCamp" "AR8700" After we close this action, the resulting code looks like this: ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN OUTER_SPRINT "BanditCamp" "FW1900" END ELSE BEGIN OUTER_SPRINT "BanditCamp" "AR8700" END And voila - you have now told WeiDU "If Tutu is the install, say FW1900 for %BanditCamp%; if it is not Tutu, say AR8700 for %BanditCamp%". Part 2. WeiDU's Magic SaladSpinner If you are with me so far, there is really only one more step to making the variables work. You have to tell WeiDU to actually use the definitions for the variables. You have fruit=apple or fruit=orange, but you haven't actually put them in the salad. The easiest way of doing this is to use EVALUATE_BUFFER. We do this: ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN OUTER_SPRINT "BanditCamp" "FW1900" END ELSE BEGIN OUTER_SPRINT "BanditCamp" "AR8700" END COMPILE EVALUATE_BUFFER ~myMod/BAF/myBAF.BAF~ EVALUATE_BUFFER is taking your original file and running it through WeiDU's SaladSpinner. WeiDU compiles the file and, well, "evaluates the buffer". Basically, it creates a new file, translated into whatever the player's install type is, based on what you have defined. Remember, while myDialogue.D is able to use AUTO_TRA, myBaf.BAFs are not, so if you had text to display you would add the command USING: ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN OUTER_SPRINT "BanditCamp" "FW1900" END ELSE BEGIN OUTER_SPRINT "BanditCamp" "AR8700" END COMPILE EVALUATE_BUFFER ~myMod/PLATFORM/myBAF.BAF~ USING ~myMod/TRA/myBAF.tra For a list of values to declare, and a copy of an operational ALWAYS section of a tp2 that uses this method set up for your Copy & Paste (or study and change) pleasure, follow this link to the G3 Development Wikki for OUTER_SPRINT Tutu and BGT values. OK, so that is pretty straightforward... now how about myMod.D files? After all, those resources are different. What do we do here? Well, let's start backwards. You can use the single line COMPILE EVALUATE_BUFFER for both .D and .BAF files: ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN OUTER_SPRINT "myVariable" "TutuValue" END ELSE BEGIN OUTER_SPRINT "myVariable" "BGTValue" END COMPILE EVALUATE_BUFFER ~myMod/DLG/myDialogueFile.D~ You can extend the variable substitution pretty much as far as you want. For example, there are different assigned NPC Banter files between versions. Easy - just declare what you want them to be up front. You declare any and all things that you want to change between the two versions. In the file myMod.tp2, ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN /* so if WeiDU sees one it doesn't 'hiccup' */ OUTER_SPRINT "percentage_sign" "%" /* BGT-only shutdown of D and BAF after BG1 content */ /* note the alternate ~, so we can use " in our variable */ OUTER_SPRINT ~BGT_VAR~ ~~ /* DVs are the same for Tutu/BGT, except for Imoen */ OUTER_SPRINT "IMOEN_DV" "imoen" /* Set Tutu BanterFiles */ OUTER_SPRINT "SAFANA_BANTER" "_BSAFAN" END ELSE BEGIN /* so if WeiDU sees one it doesn't 'hiccup' */ OUTER_SPRINT "percentage_sign" "%" /* BGT-only shutdown of D and BAF after BG1 content */ /* note the alternate ~, so we can use " in our variable */ OUTER_SPRINT ~BGT_VAR~ ~!Global("ENDOFBG!","GLOBAL",2)~ /* DVs are the same for Tutu/BGT, except for Imoen */ OUTER_SPRINT "IMOEN_DV" "imoen2" /* Set Tutu BanterFiles */ OUTER_SPRINT "SAFANA_BANTER" "BSAFAN" END By declaring anything that changes between the two mods as a variable, we can set up both BAF and D files for single-file cross-platform usage. Using the variables declared above, we can do some interesting things. The most entertaining is a full Global check for a trigger that only needs to show up on one side. Tutu folks don't want to add unnessesary Global chacks, but BGT folks need BG1 content to shut down and not clutter up their BGT game. Irreconcileable differences? Divorce? Alimony? I say verily unto thee *NO*! IF %BGT_VAR% Global("EdwinGetsFleas","GLOBAL",2) InParty("edwin") compiles as IF Global("EdwinGetsFleas","GLOBAL",2) InParty("edwin") on Tutu, and IF !Global("ENDOFBG1","GLOBAL",2) Global("EdwinGetsFleas","GLOBAL",2) InParty("edwin") on BGT. Imoen is the only different dv between platforms, but that doesn't stop us using only one file: == ~%IMOEN_JOINED%~ IF ~InParty("%IMOEN_DV%") InMyArea("%IMOEN_DV%") !StateCheck("%IMOEN_DV%",CD_STATE_NOTVALID)~ THEN ~Plus, folks can just copy and paste this code.~ becomes Tutu's == ~_IMOEN2~ IF ~InParty("imoen") InMyArea("imoen") !StateCheck("imoen",CD_STATE_NOTVALID)~ THEN ~Plus, folks can just copy and paste this code.~ and BGT's == ~IMOEN2~ IF ~InParty("imoen2") InMyArea("imoen2") !StateCheck("imoen2",CD_STATE_NOTVALID)~ THEN ~Plus, folks can just copy and paste this code.~ (((Advanced note: while we could just declare the underscore blank for BGT and _ for Tutu and use this everywhere, we don't want to do this with resources that we want to be able to easily read and troubleshoot, especially when some require major modification. This idea means the big consistent items are fully declared, like %VICONIA_BCS%.bcs))) Part 3. Translating Translation Files OK, well, what about my Translation files? Well, other than sound references and your actual tp2 if you are reassigning sounds or using percent signs (%), .tra files do not need manipulation. If you have AUTO_TRA set, your COMPILE EVALUATE_BUFFER will happily chug away, and WeiDU will use the correct .tra references. The main exception is if you are calling existing sound references from BG1. Mod-added sounds and BG2 sounds will reference directly without manipulation, but a line that calls on existing BG1 sound references looks like this on Tutu @204 = ~[ZOMBIE 03]~ [_ZOMBI03] and this on BGT @204 = ~[ZOMBIE 03]~ [ZOMBI03] If you use BG2 resources, you do not need to evaluate the .tra file. If you want to create this, though, @204 = ~[ZOMBIE 03]~ [%tutu_var%ZOMBI03] you will also need to set any item descriptions that use things like "+10% Electrical Resistance", so that WeiDU will not start looking on the wrong side of the percent sign, and happily create all your creatures with corrupted sound references of %TUTU_VA (the first eight places of the variable). If you need to evaluate your .tra file(s) for your target platform, you need an extra manipulaton. The first step here is to understand that WeiDU needs a variable-free zone to start up. For that, we separate the initial .tra into a setup.tra and a myMOD.tra. In setup.tra we put all the strings that have to do with component names, error messages, etc., etc., and we have no variables at all. Here is a sample of a setup.tra: @1000 = ~Tutu detected: support at www.gibberlings3.net.~ @1001 = ~BGT detected: support at www.spellholdstudios.net.~ @1002 = ~This mod should be installed in your BG2, Tutu, EasyTutu, or BGT folder, after Tutu/BGT conversion.~ @1003 = ~Please remember to start a new game to access the contents of this component.~ @1004 = ~BG1 NPC Required Changes component is not installed.~ @1005 = ~The BG1 NPC Project: Required Modifications for v12 Beta4, March 10, 2007~ @1006 = ~The BG1 NPC Project: Banters, Quests, and Interjections~ In myMod_tmp.tra, we put item descriptions, creature .tra references, and anything we want to have use variables. We can then evaluate this secondary file on install, renaming it myMod.tra so that AUTO_TRA can do its job. Sample from myMod_tmp.tra: @77 = ~This is a plain looking short spear with a leaf-shaped point. It was balanced for a slender elven hand. Mage Thalantyr enchanted the weapon for Kivan of Shilmista. STATISTICS: Combat Abilities: 10%percent% chance with every hit that opponent is entangled for 24 seconds, no save THAC0: +2 bonus Damage: 1D6 +2 Damage type: piercing Weight: 3 Speed Factor: 4 Proficiency Type: Spear Type: 2-handed Requires: 5 Strength Only Usable By: Elves Not Usable By: Cleric Mage~ @93 = ~ Prepare to meet your DOOOOM! heh...~ [JANJAN11] @253 = ~[WOLF, DIRE 03]~ [%tutu_var%DWOLF03] @346 = ~Flaming Fist Officer~ Here's a breakdown of the code to use the above .tra files. In the ALWAYS section of the .tp2, /* prep tras for sound references */ COPY ~BG1NPC/TRA/%LANGUAGE%/BG1NPC_tmp.tra~ ~BG1NPC/TRA/%LANGUAGE%/BG1NPC.tra~ EVALUATE_BUFFER LOAD_TRA ~BG1NPC/TRA/%LANGUAGE%/BG1NPC.tra~ Here we copy an unevaluated temporary file with variables to a new file where the variables have all been evaluated for the player's platform. We do this so that we do not overwrite the original file, and so that the file ends up named the same as the .tp2 for AUTO_TRA. In the language declaration section, /* Language Settings */ AUTO_TRA ~BG1NPC/TRA/%s~ LANGUAGE ~English~ ~english~ ~BG1NPC/TRA/english/setup.tra~ This tells WeiDU that the "clean" file is called "setup.tra", and that it should start with setup.tra, then follow on with the evaluated myMod.tra file that we just created. The final code would look like this: /* Backup folder */ BACKUP ~BG1NPC/backup~ /* Author */ AUTHOR ~The BG1 NPC Project Team~ ALWAYS ACTION_IF FILE_EXISTS_IN_GAME ~FW0100.ARE~ THEN BEGIN OUTER_SPRINT "BanditCamp" "FW1900" END ELSE BEGIN OUTER_SPRINT "BanditCamp" "AR8700" END /* prep tras for sound references */ COPY ~BG1NPC/TRA/%LANGUAGE%/BG1NPC_tmp.tra~ ~BG1NPC/TRA/%LANGUAGE%/BG1NPC.tra~ EVALUATE_BUFFER LOAD_TRA ~BG1NPC/TRA/%LANGUAGE%/BG1NPC.tra~ /* launch the ReadMe file on exit from install */ AT_INTERACTIVE_EXIT ~VIEW BG1NPC/BG1NPCReadMe.html~ END /* Language Settings */ AUTO_TRA ~BG1NPC/TRA/%s~ LANGUAGE ~English~ ~english~ ~BG1NPC/TRA/english/setup.tra~ Some coding notes; we need to reload the .tra after evaluating it, so that WeiDU knows that changes have been made. We use the ALWAYS section because we want this run even if the player only decides to use Component #750, or comes back and reruns the installer and modifies the install. The AT_INTERACTIVE_EXIT waits until the mod has finished its business and then launches the ReadMe for the user to ignore . Part 4. Give Me the Code, and I'll Change The (Fantasy) World. Let's see some examples of this in practice. The following code samples are based on The BG1 NPC Project files, and represent an extreme usage of this idea. For the setup of variables, and plenty of data to use for cut and paste into your own mod, materials on the G3 Development Wikki provide the values for the next block of code. tp2 setting flags: example of usage for area variables /* Area Flagging */ /* OUTDOOR ONLY: Tutu and BGT */ COPY_EXISTING ~%GnollStronghold%.are~ ~override~ ~%NashkelMines%.are~ ~override~ ~%FriendlyArmInn%.are~ ~override~ ~%Temple%.are~ ~override~ ~%NashkelCarnival%.are~ ~override~ READ_BYTE "0x48" "flags" WRITE_BYTE "0x48" ("%flags%" BOR "0b00000001") BUT_ONLY_IF_IT_CHANGES For an expanded sample set of code for patching all areas, please follow this link to the G3 Development Wikki showing actual code in use. Sample Banter CHAIN using this idea In this next example, we have set everything between to % signs at the top of the tp2. The values used here were set in the ALWAYS section described here. In myMod.tp2, COMPILE EVALUATE_BUFFER ~myMod\DLG\AddBanterToImoen.D~ in AddBanterToImoen.D CHAIN IF WEIGHT #-1 ~%BGT_VAR% Global("UseNewCrossmodVariables","GLOBAL",0) GlobalGT("Chapter","GLOBAL",%tutu_chapter_3%) InParty("%IMOEN_DV%") InMyArea("%IMOEN_DV%") !StateCheck("%IMOEN_DV%",CD_STATE_NOTVALID) InParty("alora") InMyArea("alora") !StateCheck("alora",CD_STATE_NOTVALID)~ ~%IMOEN_BANTER~ RandomlyCalledBanterFileEntry1 ~I am going to try that new variable substitution in a random banter, Alora.~ == ~%ALORA_BANTER%~ IF ~InParty("alora") InMyArea("alora") !StateCheck("alora",CD_STATE_NOTVALID)~ THEN ~I want to interject too!~ == ~%IMOEN_BANTER%~ IF ~InParty("%IMOEN_DV%") InMyArea("%IMOEN_DV%") !StateCheck("%IMOEN_DV%",CD_STATE_NOTVALID)~ THEN ~Here I respond again!~ == ~%ELDOTH_BANTER%~ IF ~InParty("eldoth") InMyArea("eldoth") !StateCheck("eldoth",CD_STATE_NOTVALID)~ THEN ~Idiots.~ == ~%XAN_BANTER%~ IF ~InParty("xan") InMyArea("xan") !StateCheck("xan",CD_STATE_NOTVALID)~ THEN ~We are all doomed.~ == ~%MINSC_BANTER%~ IF ~InParty("minsc") InMyArea("minsc") !StateCheck("minsc",CD_STATE_NOTVALID)~ THEN ~Boo want's to interject too!~ == ~%VICONIA_BANTER%~ IF ~InParty("viconia") InMyArea("viconia") !StateCheck("viconia",CD_STATE_NOTVALID)~ THEN ~Stupid surface-dwellers.~ END ++ ~There, that wasn't so bad, and you can just copy and paste!~ DO ~SetGlobal("UseNewCrossmodVariables","GLOBAL",1)~ EXIT ++ ~I dunno about this...~ DO ~SetGlobal("UseNewCrossmodVariables","GLOBAL",1)~ EXTERN ~%EDWIN_BANTER%~ Naysayers1 ++ ~I think I need a second opinion.~ DO ~SetGlobal("UseNewCrossmodVariables","GLOBAL",1)~ EXTERN ~%DYNAHEIR_BANTER%~ Yeasayers1 CHAIN ~%EDWIN_BANTER%~ Naysayers1 ~This is beneath even you, <CHARNAME>. (Simians. When I learned coding, we still had to write all strings hardcoded in ASCII and insert them using a hex editor!).~ == ~%DYNAHEIR_BANTER%~ IF ~InParty("dynaheir") InMyArea("dynaheir") !StateCheck("dynaheir",CD_STATE_NOTVALID)~ THEN ~*casts Silence, 10' radius*~ == ~%EDWIN_BANTER%~ IF ~InParty("dynaheir") InMyArea("dynaheir") !StateCheck("dynaheir",CD_STATE_NOTVALID)~ THEN ~...~ END IF ~~ THEN JOURNAL ~Banters down, now Called States from Joined Dialogue File and BCS.~ EXIT "HEY!", you say, "Wait a minute!". There was an odd looking variable back there - %tutu_chapter_3% "What the heck is *that*?" Well, take a look at the end of the discussion, under Advanced Considerations, and I will tell you. But for now, let's keep on task. For a fully coded example using the values declared in the sample OUTER_SPRINT section, ready for cut and paste for all BG1 NPCs,follow this link to the G3 Development Wikki. Sample Called Dialogue from BCS and D using this idea Again, this sample uses the OUTER_SPRINT values set by the sample section. In the file myMod.tp2 EXTEND_BOTTOM ~%IMOEN_BCS%.bcs~ ~myMod\BAF\AddToImoenJ.baf~ EVALUATE_BUFFER COMPILE EVALUATE_BUFFER ~myMod\DLG\AddToImoenJ.D~ in the file AddToImoenJ.baf /* activate joined file dialogue */ IF %BGT_VAR% //this will only result in anything showing on his line if it is BGT GlobalGT("Chapter","GLOBAL",%tutu_chapter_3%) // 3 for Tutu, 4 for BGT Global("UseNewCrossmodVariables","GLOBAL",0) AreaCheck("%CloakwoodWyverns_WyvernCave%") InParty(Myself) !StateCheck(Myself,CD_STATE_NOTVALID) InParty("alora") InMyArea("alora") !StateCheck("alora",CD_STATE_NOTVALID) InMyArea(Player1) !StateCheck(Player1,CD_STATE_NOTVALID) THEN RESPONSE #100 SetGlobal("UseNewCrossmodVariables","GLOBAL",1) END /* initiate joined file dialogue */ IF %BGT_VAR% GlobalGT("Chapter","GLOBAL",%tutu_chapter_3%) // 3 for Tutu, 4 for BGT Global("UseNewCrossmodVariables","GLOBAL",1) InParty(Myself) !StateCheck(Myself,CD_STATE_NOTVALID) InMyArea(Player1) !StateCheck(Player1,CD_STATE_NOTVALID) InParty("alora") InMyArea("alora") !StateCheck("alora",CD_STATE_NOTVALID) CombatCounter(0) !See([ENEMY]) THEN RESPONSE #100 StartDialogueNoSet("alora") END In the file AddtoImoen.D CHAIN IF WEIGHT #-2 ~%BGT_VAR% Global("UseNewCrossmodVariables","GLOBAL",1)~ ~%IMOEN_JOINED~ SpecificallyCalledBanterFileEntry1 ~I am going to try that new variable substitution on the J file, Alora.~ == ~%ALORA_JOINED%~ IF ~InParty("alora") InMyArea("alora") !StateCheck("alora",CD_STATE_NOTVALID)~ THEN ~Wheee! This is just as easy as using the old system!~ == ~%IMOEN_JOINED%~ IF ~InParty("%IMOEN_DV%") InMyArea("%IMOEN_DV%") !StateCheck("%IMOEN_DV%",CD_STATE_NOTVALID)~ THEN ~Plus, folks can just copy and patse cmorgan's code.~ == ~%SAFANA_JOINED%~ IF ~InParty("safana") InMyArea("safana") !StateCheck("safana",CD_STATE_NOTVALID)~ THEN ~Of course, they will want to edit out the parts they don't want, daaaahling.~ END ++ ~There, that wasn't so bad, and you can just copy and paste!~ DO ~SetGlobal("UseNewCrossmodVariables","GLOBAL",1)~ EXIT ++ ~I dunno about this...~ DO ~SetGlobal("UseNewCrossmodVariables","GLOBAL",2)~ EXTERN ~%EDWIN_JOINED%~ Naysayers1 ++ ~I think I need a second opinion.~ DO ~SetGlobal("UseNewCrossmodVariables","GLOBAL",2)~ EXTERN ~%DYNAHEIR_JOINED%~ YeaSayers1 For a full treatment of this BAF/J-file sample code ready for cut and paste, please follow this link to the G3 Development Wikki. EXTEND_* versus COMPILE EVALUATE_BUFFER For those of you who notcied something different about the EXTEND_BOTTOM coding, yes, there is a different setup in the tp2 for actions in the EXTEND_* family. The usage is just like the COPY usage found in the .tra examples. While we can say COMPILE EVALUATE_BUFFER ~myMod\DLG\myDialogue.D~ or COMPILE EVALUATE_BUFFER ~myMod\BAF\myBAF.BAF~ we need to say EXTEND_BOTTOM ~targetToChange.bcs~ ~myMod\BAF\myBAF.BAF~ EVALUATE_BUFFER or EXTEND_TOP ~targetToChange.bcs~ ~myMod\BAF\myBAF.BAF~ EVALUATE_BUFFER For most mods, the usages presented here will be enough to get most, if not all, of the work done for a single-source install. As you go, you may run into exceptions, which is why at the end of this tutorial you will find the section Advanced Considerations. Part 5. Straw-Man Questions (Real ones are too hard to answer General Notes Q: Won't doing this slow things down? A: In current testing, so far, no. With a huge, overblown, way-too-many variables set install running in an Always section, an archaeic P4 1.7 with 762 MB operating RAM compiles the code as quickly as a straight copy of two sets of files. BG1 NPC is a hugely singular case, as it interjects into thousands (yep, I counted) of existing states, requiring hundreds of variables to operate completely (at least until we learn what we can pare down and not delare!). The average mod would need far less, and produce far less load on any machine. Q: Isn't this hard to remember stuff, all this %THIS% and %THAT%? A: Well, if you can remember that _CORANP is Coran's Post-joining dialogue and that area FW3499 is the Sekreet Samurai Stronghold of Doom, then no. After all, while there is a set of variables available for copy/paste on the Development Wikki, and a set of materials in Phase2 of this tutorial, the good news is you could name the variables anything you want! (My favorite is %*****% which is not printable by the filters here and probably should not be used in polite company. I just cannot stand Skie's snivelling .) Q: But I don't know what changes between Tutu and BGT!!! A: Which is why we have a community. This tutorial has links to the G3 Development Wikki where many basic lists of differences are already worked out. Some searching, a little copy/paste, and you are in business. For more advanced materials, if you are a BGT modder you can contact a Tutu modder and ask, and vice versa - just because we have our own personal preferences does not preclude sharing ideas. For die-hard modders willing to throw themselves into the task, you can do the unthinkable... put both installs on your machine, and compare the differences yourself. (Most folks would prefer not to do this last, which is why contacting a fellow modder across the fence is probably a good idea.) Q: But %MYFavoritePLATFORM% Sucks and %MYhatedPLATFORM% Rocks - why would I bother with any of this? A: Well, why are you reading this, then! Seriously, we write for an audience. If we want the widest possible audience, we write for as many implementations as we can. This method is designed to make it easy for folks to be able to do that. We can all stick to our own choices, but stories are much bigger than code. If you have written it, why not let the widest audience possible enjoy it? Q: Hey - you said there were three obstacles - resources, chapters, and statenames. I don't see all of those represented here. What gives? A: Aaaahhhh.... the answers to these and further questions follow in... Part 6. Advanced Considerations Resource/File Names We have discussed that there are different sound resource names, Banter/BCS/Joined/Post names, etc. The big standard NPCs should be easy to read and troubleshoot, so we go ahead and set these as "_VICONI" vs "BGVICNIA". The innumerable lesser actors, like Red Shirt/uard #475, _RONLIT vs IRONLIT, may need just a "tutu_scriptI" = "_" vs "I". While the vast majority of these are a difference of one simple underscore, there are exceptions. For a list of ones we have identified, and to contribute more differences, please join us [iNSERT DEV WIKKI LINK]. Many of these can be completely ignored!. Unless your mod does a good bit of I_C_T or manipulation of existing in-game actors, you may not need to deal with a single one of these. The modding way around even having to deal with this is to simply create your own cast of characters for the player to interact with - which is what many mods do already. Chapter Numbers The concern here is that Tutu and BGT treat the Prologue differently. Tutu uses 0 (null, unused, no reference),1,2,3,4,5,6,7. BGT uses 1,2,3,4,5,6,7,8. This is quickly accomplished in chapter checks by declaring and using "tutu_chapter_3" as "3" on Tutu and "4" on BGT. State Numbers State names are a little tougher, and may require either research or a check to see if someone has helped out on the [iNSERT DEV WIKKI LINK]. BGT adds the BG1 strings to any NPC that is set to travel on into BG2 with you. That means that (for instance) if you need to manipulate Edwin's dialogue by adding a new EXTEND_BOTTOM, you will need to look up the differences and declare them: in a .D file set up to modify Edwin, EXTEND_BOTTOM ~%tutu_var%EDWIN~ %EdwinUnjoined77% IF ~~ THEN REPLY @0 + X#EdwinJoinsAlone END Here, we have found that Tutu has Edwin's dialogue state 0, which is BGT's state 77 in the same file. If your mod deals with Edwin Jaheira's unjoined dialogue or some other NPC that carries directly forward in BGT, then it is probably wise to do some research and make sure that a person more familiar with the platform you do not use takes a look at the state numbers and makes sure that you re adjusting the state you really want. The OUTER_SPRINT, EVALUATE_BUFFER, and you are good to go for both platforms. Edited April 5, 2007 by cmorgan Quote Link to comment
EiriktheScald Posted April 4, 2007 Share Posted April 4, 2007 (edited) Does Weidu Mac offer the same functionality? The mac version usually follows the PC updates. Edited April 4, 2007 by EiriktheScald Quote Link to comment
the bigg Posted April 4, 2007 Share Posted April 4, 2007 Does Weidu Mac offer the same functionality? The mac version usually follows the PC updates. Yes, all versions of WeiDU are compiled from the same source code (well, unless devSin has some diffs that haven't been merged in). cmorgan: you don't need to COPY EVAL_BUFFER when you're compiling a BAF, COMPILE EVAL_BUFFER works both for BAF and D. After checking the source, I found out that you can put arbitrary patches after an EXTEND_*, so you can use EXTEND_TOP ~something.bcs~ ~my/mod/something.baf~ EVALUATE_BUFFER as opposed to EXTEND_TOP EVALUATE_BUFFER ~something.bcs~ ~my/mod/something.baf~ Quote Link to comment
CamDawg Posted April 4, 2007 Share Posted April 4, 2007 Question: rather than using variables like %FishingVillage% for the areas, why not use the original BG designations like %ar0100%? With a quick copy and paste, you could make a full set of the variables (BGT has a doc with the mappings, for Tutu you just sub FW for AR) and then drop it in as a library as needed. Quote Link to comment
berelinde Posted April 4, 2007 Share Posted April 4, 2007 I think the logic was that it is easier for the modder to remember the English name of the area. I have to admit that I prefer it. Quote Link to comment
cmorgan Posted April 4, 2007 Author Share Posted April 4, 2007 (edited) @ the bigg - I was having some trouble with those EXTEND TOP/BAF usages, but I bet it was me... I will go test it out on my install, and update the tutorial. Thank you! @CamDawg - as berelinde commented, for the tutorial purposes, it seemed easier to do the english equivalents (easier for folks who haven't lived with the code awhile to see "BanditCamp"). For someone who has the basic idea down, I agree it would be much easier to produce a list using your idea (in fact, I bet Ascension64's cool rebuild tool uses something similar, or a 2da lookup.). For a new person trying out things, though, since I built the references using Miloch's area list, it seemed easiest to set up a "copy/paste" structure folks could use wholesale (or retail) and then skip the whole step of learning area references. I just need to put the link in to the actual code on the Wikki, as I seem to keep running into the post size limit here. You are absolutely on target as to a library structure, but before folks use a huge library of references that they don't need (which we are right now) I figured it was an opportunity to get across the basic idea in a friendly manner. We could extend the "Advanced" tutporial with these ideas, including both the library usage and the ALWAYS usage. We also need to include the darned AUTO_TRA manipulations and oddities with people using single delimeters throwing the variable evaluation off. (I am still trying to rewrite it, as I can't seem to get the right balance for new folks - gotta find ways to slow it down and break it down step by step.). Any comments on ways of making this more tutorial more complete and (preferably) more simple/step by step? I don't know if I broke it down far enough, or too far. After all, I teach middle-schoolers, non-abstract thinkers all. p.s. I forgot the area script naming differences - not sure if that is a good extension of this idea or not, though. I guess if we use %JAHEIRA_BCS%.bcs and %FishingVillage%.are, we might as well set %FishingVillage_BCS%.bcs, too. Currently we stick to the standard method, naming/extending scripts with platform-specific files. Edited April 4, 2007 by cmorgan Quote Link to comment
Guest erik Posted April 4, 2007 Share Posted April 4, 2007 Too long examples at the end, you're losing people there. Pare them down a little? You don't need an example with all sixteen npcs or twenty areas to show the technique. Apart from that, understandable tutorial for a not-quite-newbie-anymore. Quote Link to comment
berelinde Posted April 4, 2007 Share Posted April 4, 2007 The reason all the NPCs and areas are included is for the convenience of people who want to copy and paste the list, rather than having to type it all out. Quote Link to comment
Guest erik Posted April 4, 2007 Share Posted April 4, 2007 Understood. I prefer learning the techniques and extending them myself, rather than doing cargo-cult programming, but to each their own... (and since you don't actually define the variables anywhere, I'd think it of limited use, and hurtful for readability) Quote Link to comment
Guest erik Posted April 4, 2007 Share Posted April 4, 2007 s/you/cmorgan/ of course. Quote Link to comment
cmorgan Posted April 5, 2007 Author Share Posted April 5, 2007 Actually, that is a good idea - since I can't get it all on the post, I will reduce the "example" code to make it pretty simple, but them right after it link to the Wikki entries with something like [Full Code for Copy/Paste Here]. I had better get that link up for the demo "ALWAYS" too... you are right, erik, it is of no real use without reference to the actual OUTER_SPRINT settings used. Quote Link to comment
Miloch Posted April 5, 2007 Share Posted April 5, 2007 Good stuff, Captain Morgan. Wasn't there a reason to use REPLACE_TEXTUALLY [EXACT_MATCH] instead of EVALUATE_BUFFER, apart from trying to evaluate the odd % as a variable? I'll admit I prefer stupidly short (but unique) variables to long, descriptive ones (particularly in scripts, where it might make a difference in runtimes, or so I've read). But I guess everyone will have there personal preference there, and it probably makes little difference, unless we're really going to have some sort of community standards. Quote Link to comment
cmorgan Posted April 5, 2007 Author Share Posted April 5, 2007 The only problem we ran into (requiring EXACT_MATCH and REPLACE_TEXTUALLY) was in evaluating .tra files. I finally tracked down one place where " was used singly, and followed Nythrun's suggestion of declaring "precent_sign", so we still could use +10% and such in the ,tra file. That's why we need the advanced tutorial section to get into the details of tra,AUTO_TRA, and file manipulation. I am not sure it needs to be a community standard thing for the actual variables, any more than folks do now with regular patching; my bet is only a few folks will ever really just cut & paste code (I will, but that is because I set it up ). The biggest hurdle for me was understanding what most of you folks seem to already know somehow; abstract manipulation of placeholders (yeah, I know it is just fancy ways of doing algebra, but it didn't translate well for my brain!) For people who only rreluctantly deal with code, either from lack of time or from really just wanting to write stories, it is there for the copy/paste. When I am testing stuff out, I shamelessly use %tsu% or whoever I am learning from at the moment. You should have seen the tp2 when I was cribbing from Nythrun, CamDawg, Ascension64, Grim Squeaker, and pro5 all at the same time! Quote Link to comment
cmorgan Posted April 5, 2007 Author Share Posted April 5, 2007 (edited) edited for content and to reflect the comments posted. I gave up on a separate "advanced" section, and rolled it into one. Edited April 5, 2007 by cmorgan Quote Link to comment
berelinde Posted April 5, 2007 Share Posted April 5, 2007 I have 2 choices when it comes to deciding how to spend my precious modding time. I can write or I can learn weidu-fu. There are people who will always be better than me at coding *anything*. I'll leave them to it. I see how it all works, and what needs to happen for this all to work out. It only took me 30 seconds to figure out how the %tutu_var% worked, once I understood the basic concept, so I can do it on the fly if I have to. Buy why? Left to my own devices, I'd just go and generate the same list all over again. and copy and paste from that. I may as well just let someone else do the typing. I'm a chemist by trade. I've got a dozen template lab reports for the testing I do. Sure, I could generate the same report over and over, but then my boss would be paying me to type. My boss seems to feel that would be a waste of money, so I spend most of my day in the lab, and use the templates. Quote Link to comment
Recommended Posts
Join the conversation
You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.