linus04 Posted September 8, 2023 Share Posted September 8, 2023 Hey guys, I need a little help with abi_base.gda. There is a column for conditions that must be met for spell/talent to be available for use. For example, 128 for 2h weapon equipped, 3 for 1h+shield, 16 for specific modal to be active etc. I'm trying to create a new condition, one that requires a specific modal to NOT be activated, but I can't get it to work. I found out that these conditions are specified in 'ability_h.nss', but when I try to add a new condition number or edit one that is already there, it doesn't work. I got an error in the toolset when I tried to export the script: "script must contain either a main or startingconditional" And even when I managed to export it, it had no effect. Is there something I am doing wrong? Is there something else I need to do? Any help would be appreciated. Link to comment Share on other sites More sharing options...
HollownessDevoured Posted September 8, 2023 Share Posted September 8, 2023 _h scripts do not get compiled, you only need their .nss. But if it doesn't work there might be something wrong with the script. Link to comment Share on other sites More sharing options...
Pasquale1223 Posted September 8, 2023 Share Posted September 8, 2023 Based on what you've said, I'm going to assume you're trying to edit the function Ability_CheckUseConditions in ability_h.nss to add a condition for modal ability NOT active. Assuming you've done that correctly and the code is all well and good... this message: "script must contain either a main or startingconditional" generally just tells you that the toolset didn't detect anything wrong with your code but also did not compile it into an executable. Files with _h at the end of the name are aka "header" files, aka "include" files. They don't create executables by themselves, but are included in other executables when they are compiled. In order for the code you've changed to take effect, the other files that use that header file need to be re-compiled. If you right-click on the name of the file and select properties, you'll see "References" (other files included by this file) and "Referenced By" (other files that include this file) tabs - and there are usually quite a few other files that include these _h files. They'll need to be recompiled. I would suggest "export with dependent resources". Link to comment Share on other sites More sharing options...
linus04 Posted September 9, 2023 Author Share Posted September 9, 2023 Thanks for advices guys, I tried to get it working, but still had no success... What I'm trying to do in the end, is that with Combat Magic active you can't use primal spells. I edited this part from "ability_h.nss", just to see if it works: // ------------------------------------------------------------------------- // CONDITION_ACTIVE_MODAL_ABILITY - A specific modal ability needs to be active // ------------------------------------------------------------------------- if ((nCondition & 16) == 16) { int nModalAbility = GetM2DAInt(TABLE_ABILITIES_TALENTS,"condition_mode",nAbility); if (nModalAbility != 0) { bRet = bRet && IsModalAbilityActive(oCaster,nModalAbility); #ifdef DEBUG Log_Trace(LOG_CHANNEL_COMBAT_ABILITY,"CheckUseConditions", "Mode Active: "+ ((bRet)?"TRUE":"FALSE")); #endif } if (!bRet) { return FALSE; } } and changed it to: // ------------------------------------------------------------------------- // CONDITION_ACTIVE_MODAL_ABILITY - A specific modal ability needs to be active // ------------------------------------------------------------------------- if ((nCondition & 16) == 16) { int nModalAbility = GetM2DAInt(TABLE_ABILITIES_TALENTS,"condition_mode",nAbility); if (nModalAbility == 0) { bRet = bRet && IsModalAbilityActive(oCaster,nModalAbility); #ifdef DEBUG Log_Trace(LOG_CHANNEL_COMBAT_ABILITY,"CheckUseConditions", "Mode Active: "+ ((bRet)?"TRUE":"FALSE")); #endif } if (!bRet) { return FALSE; } } Then I recompiled all scripts that use ability_h (quite a few of them, do I really need to recompiled them all?): abi_templates.nssability_core.nssability_summon_h.nssai_conditions_h.nssai_main_h_2.nssaoe_effects_h.nssbhn200tr_gilmore_entrance.nssitem_aoe_duration.nssitem_trap.nssitem_trap_lure.nssmodule_core.nssmonster_aoe_duration.nssmonster_poison_spit.nssmonster_talent_aura.nssmonster_talent_brood.nssmonster_talent_dog_charge.nssmonster_talent_dog_grab.nssmonster_talent_dog_growl.nssmonster_talent_dragon.nssmonster_talent_grab.nssmonster_talent_large.nssmonster_talent_ogre.nssmonster_talent_overwhelm.nssmonster_talent_sylvan.nssmonster_talent_web.nssntb330cr_ghostly_elf.nssnull_spell.nssorz540_gas_aoe.nssorz540_lava_aoe.nssplayer_core.nsspuzzle_aoe.nssrules_core.nssrules_h.nssscattershot_singletarget.nssshoweffects.nssskill_crafting.nssskill_shapeshift.nssskill_stealth.nssskill_trap.nssspell_aoe_duration.nssspell_aw2_aoe.nssspell_aw2_blizzard.nssspell_aw2_chain.nssspell_balance_aoe.nssspell_balance_blizzard.nssspell_blizzard.nssspell_branka1.nssspell_chainlightning.nssspell_deathmagic.nssspell_deathsyphon.nssspell_shapeshift.nsstalent_aoe_duration.nsstalent_arrow_slaying.nsstalent_null.nsstalent_pet.nsstalent_scattershot.nsstest_petert.nss Then I created abi_base_test.gda just for Flame Blast with condition 16 and condition_mode 17023 (Combat Magic), but it did not work. It's like if the game doesn't recognize my changes and I still need to activate Combat Magic to use Flame Blast (like original condition 16). Link to comment Share on other sites More sharing options...
Pasquale1223 Posted September 9, 2023 Share Posted September 9, 2023 The routine you are modifying - Ability_CheckUseConditions - is supposed to return TRUE if the conditions to use the talent/spell are met and FALSE if they are not. I would also point out that there is a note at the top of it: "This is temporary, it will go into the engine at some point". It does not appear that ever happened, and this routine is still being used, but I think I would put a print statement in there just to be sure. To do that, create a plain text file named ECLog.ini in the bin_ship subdirectory of your game install directory, and make this the content of the file: [LogTypes] Script=1Then temporarily insert a print statement at the top of that function so it will print to your log file, which will prove that the game is running the new code you have edited. The log file is in your Documents subdirectory, under BioWare > Dragon Age > Logs. Here's a sample print statement: PrintToLog("============== THE CODE I HAVE EDITED IS RUNNING! ===============");Now let's look at your code changes and what they would do. Firstly, I notice you're changing the behavior of condition value 16, which would break anything that already uses that value. Perhaps "break" isn't the correct word - it would use the new functionality you are creating, and if that is not your intent you might want to use a new value for the new functionality you intend to create here. Since the logic here uses bitwise operators (the single ampersand) and is using values that have a single bit set, I would suggest using 256, as it is the next value that fits that pattern. The existing code looked for modal ability not zero:if (nModalAbility != 0)because it needed to check whether a modal ability was currently active to decide whether to allow a talent/spell to be used. Your replacement code is looking for modal ability zero:if (nModalAbility == 0)even though you do want to check whether a modal ability is currently active to decide whether to allow a talent/spell to be used. So that's an error. The logic bracketed by that condition would never execute for anything that had the condition_mode in the database (gda) set to anything other than 0. The existing code checked whether a modal ability was activebRet = bRet && IsModalAbilityActive(oCaster,nModalAbility);because that is what the check was for. It wanted to make sure a certain modal ability was active before it would allow a talent/spell to be used. Your replacement code does the same thing, even though you want to make sure a modal ability is NOT active. So you'll need to flip it, and you can do that by inserting an exclamation point to "not" it: bRet = bRet && !IsModalAbilityActive(oCaster,nModalAbility);Hope I helped. Link to comment Share on other sites More sharing options...
HollownessDevoured Posted September 9, 2023 Share Posted September 9, 2023 (edited) Oh when you compile, all connected scripts export too (re-compiling can find errors in the corresponding scripts, I am not saying to not do this, it is helpful to make sure they work). You do not need the scripts/files you didn't change. I am constantly cleaning/deleting the extra files. So it looks like condition 16 is when Blood Control is active. You probably should be creating your own condition number, instead of editing a pre-existing one.conditions (looks like it is defined in the ability_h)condition_mode (defined in the ai_abilities_cond.gda, if applicable)And you want the reversed effect, so you'd have to switch the script around (at least in theory). I find in thinking and in execution can be tricky with scripting (at least for me LOL). But I'd think it be something like this: // ------------------------------------------------------------------------- // CONDITION_ACTIVE_MODAL_ABILITY - A specific modal ability needs to be active // ------------------------------------------------------------------------- if ((nCondition & 333) == 333) //try to use a number currently not used on ABI_Base.gda { int nModalAbility = GetM2DAInt(TABLE_ABILITIES_TALENTS,"condition_mode",nAbility); if (nModalAbility != 0) // != 0 probably means if you have a AI_abilities_cond.gda # defined (aka 17023) under "condition_mode", so do not remove the ! { bRet = bRet && IsModalAbilityActive(oCaster,nModalAbility); #ifdef DEBUG Log_Trace(LOG_CHANNEL_COMBAT_ABILITY,"CheckUseConditions", "Mode Active: "+ ((bRet)?"TRUE":"FALSE")); #endif } if (bRet) //!bRet should mean not this condition and bRet should mean this condition { return FALSE; } } Edited September 9, 2023 by HollownessDevoured Link to comment Share on other sites More sharing options...
Pasquale1223 Posted September 9, 2023 Share Posted September 9, 2023 Contrary to other advice you may receive, you really do need to re-compile any executables that use source code you've changed in order for your changes to take effect in the game. If you think about it, it should be self-evident. Just as an fyi, this line in source code: #include "filename" is a compiler directive. It tells the pre-compiler to replace that line with the content of the named file before compiling the source code to create the executable. Does that mean you have to re-compile every single file that includes ability_h? Not necessarily, though it's usually considered good engineering practice to do so. But in practice, not every file that includes another file actually uses all of it. Some source files may be including ability_h only for its constants or to use some function(s) other than the specific one you're changing. What matters is that the files that include ability_h and *do* use the function you've changed get recompiled. Link to comment Share on other sites More sharing options...
linus04 Posted September 9, 2023 Author Share Posted September 9, 2023 I works now, thank you both so much! Strangely though, spells under this new condition are not "grey out" and unclickable like with other conditions, but when I try to cast them with Combat Magic active I get a "Can not use this ability." error. But that does not matter, I'm just happy it works :) I did recompile every script that uses ability_h and then by trying to move them out one by one I found out that the only one important is "ability_core". Link to comment Share on other sites More sharing options...
HollownessDevoured Posted September 9, 2023 Share Posted September 9, 2023 Glad it works! Link to comment Share on other sites More sharing options...
Pasquale1223 Posted September 9, 2023 Share Posted September 9, 2023 I see that ability_core calls the function Ability_CheckUseConditions on line 213. That's why it was key to your changes showing up in game. The other files that reference ability_h probably just use the constants or maybe some other function(s). In any case, congrats on your success. Link to comment Share on other sites More sharing options...
Recommended Posts