to go back to your first question,
i don't know much about this, but can't the Classes available on levelup be intercepted? (granted, this isn't possible for base classes since the character isn't created yet) If you can hook that, maybe a custom function can 'ghost' those PrCs that the function itself says are inappropiate
ie:
if (GetDeity() == "joe"
|| GetDeity() == "frank")
// show PrC
else
// ghost the PrC selection
( evading the H-word ..)
FAQ on custom classes, spells, and feats. (Repost)
#26
Escrito 10 abril 2014 - 12:11
#27
Escrito 10 abril 2014 - 12:22
That may be what the VAR option in CLS_PRES_xxx was for, however it seems to be broken in NWN2. If it was as simple as setting a variable to 1 or 0 on the character then all would be tickety-boo.
[Edit: setting the VAR variable to 1 on the party member blocked the prestige class in NWN]
Changing the deity afterward is also problematic for me, since I'm creating an Arvoreen's Warder PrC. Kelemvor is easy, since clerics only have to be lawful, but Arvoreen clerics can only be LG, NG or LN. I was planning to set the PrC alignment restriction to non-evil and non-chaotic, but that would allow NN to slip through. Any NN cleric who tried to take Arvoreen's Warder would be forced to change to Arvoreen (somehow), but if they ever took another cleric level they'd be forced to change deity again. Unless I can also force NN alignments to change to NG or LN on taking the PrC.
#28
Escrito 10 abril 2014 - 01:37
no go. Child of Night, using either 0 or 1 on a simple test_int_variable, and neither ghosted the selection. ( although setting CLASSOR = ShadowDancer did, while ofc PC was not SD )
Now here's an idea: create a set of Feats in Feats.2da.
Each Deity in your NwN2_deities.2da corresponds to a feat, which you then grant properly to PC on module load say, via a custom function.
then just use the FEAT parameter in the Cls_pres_* files
In fact if you do this, pls reserve lines (so I don't have to go swapping out my Feat.2da -- and a simple merge works)
Editado por kevL, 10 abril 2014 - 02:07 .
#29
Escrito 10 abril 2014 - 02:07
Yes, that's one way to do it. I was trying to avoid having to alter any other 2DAs or introduce any special scripting, but I may not be able to.
The PrC description says that you're supposed to be judged worthy by a cleric of Arvoreen before being able to take the class, so I could assign the special feat via a conversation with such a cleric, provided you meet all the criteria (being a halfling and worshipping Arvoreen would usually be sufficient). I could even tie in a special quest that needs to be done to prove your worthiness. You'd still have to satisfy all the other feat/skill/alignment prerequisites though.
Now I'm thinking of creating the Arvoreen's Keeper PrC as well, which is basically the same as a Warder only with divine spell progression. It'd use most of the same CLS_xxx 2DAs, with slightly different prerequisites (at least 1 level of divine spell casting).
#30
Escrito 10 abril 2014 - 02:11
sounds good, sounds doable ![]()
although i'd test that FEAT param first .. just to be sure
#31
Escrito 10 abril 2014 - 02:40
Once you've got a custom feat in, there shouldn't be a problem. The CLS_PRES_xxx.2DA is only looking for a line number in feats.2DA. That's pretty much how the Neverwinter Nine and Shadowthief PrCs originally worked in the OC.
#32
Escrito 13 abril 2014 - 11:13
I can see how Doomguide works now. There's a separate column in NWN2_Deities.2DA specifically for the class, with a 1 in only one row (Kelemvor). If you take a level of Doomguide, you have only one deity choice available. That means you don't actually have to worship Kelemvor to become a Doomguide (but you *will* after that, whether you like it or not). Somehow I doubt I can create a new class column in the deity 2DA and have the game engine recognise it - I suspect the dreaded H-word is involved.
I've now created NWN2 versions for four prestige classes just for halflings; Arvoreen's Keeper (divine spellcaster / trapper), Arvoreen's Warder (shortsword fighter / trapper), Halfling Whistler (bard spellcasting with druid/ranger feats), and Warsling Sniper (bullet-slinging dynamo).
The latter two are probably the most interesting. The Whistler is geared more towards avoiding combat via stealth, while buffing party members. The Sniper packs quite a punch at higher levels, especially if you give them a decent amount of strength. They have a tendency to eat through ammo quickly though. A Sniper with skiprocks is quite useful against mobs.
#33
Escrito 13 abril 2014 - 11:20
those all sound like interesting class.
#34
Escrito 13 abril 2014 - 11:54
I can see how Doomguide works now. There's a separate column in NWN2_Deities.2DA specifically for the class, with a 1 in only one row (Khelemvor). If you take a level of Doomguide, you have only one deity choice available. That means you don't actually have to worship Khelemvor to become a Doomguide (but you *will* after that, whether you like it or not). Somehow I doubt I can create a new class column in the deity 2DA and have the game engine recognise it - I suspect the dreaded H-word is involved.
If you intercept the level up, you can likely add columns to the 2da and get away with it. The default level up process is almost assuredly checking the deities 2da as part of choosing Doomguide. I don't know how to do it but intercepting the level up is something that can be done.
#35
Escrito 01 mayo 2014 - 05:28
Is there any particular reason why one couldn't close Armor Skin or its equivalents, change the TLK references, and then re-use them for other packages, even if the data/scripting called on itself is hardcoded? If so, makes the difference between an elegant feat addition and an inelegant script solution. tnx in advance.
#36
Escrito 01 mayo 2014 - 11:46
Is there any particular reason why one couldn't close Armor Skin or its equivalents, change the TLK references, and then re-use them for other packages, even if the data/scripting called on itself is hardcoded? If so, makes the difference between an elegant feat addition and an inelegant script solution. tnx in advance.
I'm guessing you'd have to modify the original feat entry, as the feat number is probably important to the hardcoding (since hardcoded feats often don't seem to have scripts attached to them).
#37
Escrito 02 mayo 2014 - 01:03
Got it. Thanks, DannJ.
#38
Escrito 03 mayo 2014 - 09:29
If you are making a passive feat that adds bonuses to skills, how should the reflective spells.2da file be st up? What fields should be populated and which ones should be blank?
Also other than the feats.2da, the spell.2da and the actual script, do you need to do anything else to any other game resources (load scripts, on resting scripts, etc.)?
#39
Escrito 04 mayo 2014 - 02:19
If you are making a passive feat that adds bonuses to skills, how should the reflective spells.2da file be st up? What fields should be populated and which ones should be blank?
Also other than the feats.2da, the spell.2da and the actual script, do you need to do anything else to any other game resources (load scripts, on resting scripts, etc.)?
if it's a passive feat, I don't think you really need a corresponding spellscript or Spells.2da entry. Well it depends. If the skill-boost is permanent, fire off a script that has SetBaseSkillRank()
else if the skill-boost is module specific, use the module's OnEnter event to check for the feat and add a permanent supernatural effect or grant an item with an appropriate itemproperty
As to how this is actually done in the .2das, i suggest finding entries for feats and spellabilities that are similar to what you want.
nwn2wiki has a fair bit of good information on Spells.2da and Feat.2da ...
- more than this and the issue should be taken to another thread, cheers
#40
Escrito 06 mayo 2014 - 05:41
I got my first two custom feats to work but now for the third custom feat I need a script that can detect if the PC has a shield in their left hand. Does anyone know how to write such a script? If you do should I put it in the module custom hearbeat or on-rest slots?
#41
Escrito 06 mayo 2014 - 07:37
Well, you can always use a function like the one below (works for me):
int IsShieldEquipped(object oPC)
{
object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
if ((GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD) ||
(GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD) || (GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD))
{
return TRUE;
}
else
{
return FALSE;
}
}
Call IsShiedEquipped after you have set the object oPC in your main script.
If you want to use it from a conversation, replace "int IsShieldEquipped" by "int StartingConditional" and name the script something like gc_is_shield_equipped.
Now, it all depends on when you want to check if the shield is equipped. If you want to know at all times, yes, use the heartbeat. If it's only when a new area is entered, on_enter will do, etc...
- A Laugh out loud le gusta esto
#42
Escrito 07 mayo 2014 - 05:43
I am trying to write a script associated with a feat that will add the characters intelligence modifier to their armor class while they also have a shield in their left hand. Here is my script so far;
#43
Escrito 07 mayo 2014 - 08:02
But I cannnot get it to compile. I do admit that I have gotten a lot of help thus far but, I just need some help to get it to tie together. (I added the SendMessageToPC script to better help me troubleshoot it.)
What error message do you get? Probably something about all paths not returning a value I guess.
If that's the problem you face, I suggest the code below:
int IsShieldEquipped(object oPC)
{
object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
// first change here: check if (holding a shield) and (having the right feat)
if (((GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD) || (GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD)
|| (GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD)) && (GetHasFeat(2858,oPC)))
{
int nAbility = GetAbilityModifier(ABILITY_INTELLIGENCE,oPC)
effect eFF = SupernaturalEffect(EffectACIncrease(nAbility, AC_DEFLECTION_BONUS, AC_VS_DAMAGE_TYPE_ALL,FALSE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, HoursToSeconds(72));
SendMessageToPC(GetFirstPC(), "Defend flank activated!");
// second change here: the function is supposed to return an integer
return TRUE;
}
else
{
return FALSE;
}
}
And, to make sure there's no conflict with the OR (||) and AND (&&), I usually group the checks by nature. In this case, we want the function to return TRUE if the character is holding a shield and has the feat #2858. So, all the BASE_ITEM_*SHIELD are in the same set of parenthesis.
- A Laugh out loud le gusta esto
#44
Escrito 07 mayo 2014 - 01:27
What error message do you get? Probably something about all paths not returning a value I guess.
If that's the problem you face, I suggest the code below:
int IsShieldEquipped(object oPC) { object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC); // first change here: check if (holding a shield) and (having the right feat) if (((GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD) || (GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD) || (GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD)) && (GetHasFeat(2858,oPC))) { int nAbility = GetAbilityModifier(ABILITY_INTELLIGENCE,oPC) effect eFF = SupernaturalEffect(EffectACIncrease(nAbility, AC_DEFLECTION_BONUS, AC_VS_DAMAGE_TYPE_ALL,FALSE)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, HoursToSeconds(72)); SendMessageToPC(GetFirstPC(), "Defend flank activated!"); // second change here: the function is supposed to return an integer return TRUE; } else { return FALSE; } }And, to make sure there's no conflict with the OR (||) and AND (&&), I usually group the checks by nature. In this case, we want the function to return TRUE if the character is holding a shield and has the feat #2858. So, all the BASE_ITEM_*SHIELD are in the same set of parenthesis.
Thanks for the help but I am still getting the same error on row 9 "Parsing varaiable list". I do not know what this is trying to tell me when it is compiling.
#45
Escrito 07 mayo 2014 - 01:53
I should have written the change in the toolset... Add a ; at the end of the line
int nAbility = GetAbilityModifier(ABILITY_INTELLIGENCE,oPC)
- A Laugh out loud le gusta esto
#46
Escrito 08 mayo 2014 - 05:26
I should have written the change in the toolset... Add a ; at the end of the line
int nAbility = GetAbilityModifier(ABILITY_INTELLIGENCE,oPC)
Thanks this managed to compile but it did not fire when I put in the OnHeartbeat slot of the module? Also, how long should I have the temporary duration if I want the effect to turn off shortly after they unequip the shield and then reactivate if they re-equip the shield? (Set the HoursToSeconds to 8 or less?) I do want it to know and fire every time a shiled is equiped and every time it is unequiped. I just made sure that the left hand is the only slot that allows you to equip a shield when I started the process.
#47
Escrito 08 mayo 2014 - 09:25
it did not fire when I put in the OnHeartbeat slot of the module.
Yes, it's a function that returns either TRUE (if shield in left hand and feat available) or FALSE is at least one of the previous conditions is missing. So you'll have to add a line like
if (IsShiedEquipped(GetFirstPC()) == TRUE)
{
// code or message to show when the conditions are met
}
else
{
// code or message to show when they're not
}
in the OnHeartBeat script of you module.
Or change the int IsShieldEquipped(object oPC) by
void main() object oPC = GetFirstPC(FALSE); // copy-paste all the rest of the script
and put the name of the script in the OnHeartbeat slot, but in that case, only the player controlled characters will be checked.
Hope that makes sense, I'm a bit in a hurry.
- A Laugh out loud le gusta esto
#48
Escrito 08 mayo 2014 - 11:41
OK I know that I attempted to go in my own direction but I tried your method before I did. For the OnHeartbeat script I put:
object oPC = GetFirstPC(FALSE);
int IsShieldEquipped(object oPC)
{
object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
// first change here: check if (holding a shield) and (having the right feat)
if (((GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD) || (GetBaseItemType(oItem) ==(BASE_ITEM_SMALLSHIELD)
|| (GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD)) && (GetHasFeat(2858,oPC)))
ExecuteScript("feat_defend_flank", oPC);
}
And for the "feat_defend_flank" script it is instructed to fire on heartbeat I have:
const int FEAT_DEFEND_FLANK = 2858;
object oPC = GetFirstPC(FALSE);
int IsShieldEquipped(object oPC)
{
int nAbility = GetAbilityModifier(ABILITY_INTELLIGENCE,oPC);
effect eFF = SupernaturalEffect(EffectACIncrease(nAbility, AC_DEFLECTION_BONUS, AC_VS_DAMAGE_TYPE_ALL,FALSE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, HoursToSeconds(12));
SendMessageToPC(GetFirstPC(), "Defend flank activated!");
// second change here: the function is supposed to return an integer
return TRUE;
}
I can get both to compile without an error but I cannot get the script to fire on heartbeat even when the character has the shield in hand.
#49
Escrito 09 mayo 2014 - 12:35
Personally I'd just call:
int nType = GetBaseItemType(oItem)
then use nType, rather than making repeated function calls.
#50
Escrito 09 mayo 2014 - 04:39
Personally I'd just call:
int nType = GetBaseItemType(oItem)then use nType, rather than making repeated function calls.
Whatever combination of scripts that will get the game to automatically detect whenever a character with the feat wields a shield and has the feat's bonus active while the character has the shield in their hand. This combination has been harder than it sounds to get to work.





Volver arriba







