Aller au contenu

Photo

Custom script assist, please - effect will not remove unless rest is performed - resolved


  • Veuillez vous connecter pour répondre
19 réponses à ce sujet

#1
ghowriter

ghowriter
  • Members
  • 21 messages
Would someone review my script and tell me why it will not remove the effects as it is written to:


#include "x2_inc_switches"
#include "nw_i0_spells"
#include "x2_inc_spellhook"
#include "nwn2_inc_spells"

void main()
{
    object oPC = OBJECT_SELF;
 int FEAT_TWIN_WEAPON_FIGHTING = GetSpellFeatId();
 int SPELL_TWIN_WEAPON_FIGHTING = GetSpellId();
  
 //if (!GetHasFeat(FEAT_TWO_WEAPON_FIGHTING, oPC)) return; //The feat shouldn't be selectable without first having Two Weapon Fighting, but just in case...
 if (!GetHasFeat(FEAT_TWIN_WEAPON_FIGHTING, oPC)) return; //If the PC doesn't have the Twin Weapon Feat, do not run
 
 object oRHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
  if (!GetIsObjectValid(oRHand))
  {
   RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
   return;
  }
 object oLHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
  if (!GetIsObjectValid(oLHand))
  {
   RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
   return;
  } 
 int iRHand = GetBaseItemType(oRHand);
  if (iRHand == BASE_ITEM_INVALID)
  {
   RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
   return;
  }
 int iLHand = GetBaseItemType(oLHand);                     
  if (iLHand == BASE_ITEM_INVALID)
  {
   RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
   return;
  }
  if (iRHand != iLHand) //Make sure both items of the same type; if not, remove effect.
  {
   RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
   return;
  }
 //The above ought to filter out all ranged weapons since it is not possible to
 //have anything equipped in the left hand when using one. This should also filter
 //any non-weapons since it isn't possible to equip non-weapons in both hands.
 int nBonus = 0;
 string sWeapon = "";
 if (iRHand == BASE_ITEM_DAGGER && iLHand == BASE_ITEM_DAGGER)
 {
  sWeapon = "Dagger";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_HANDAXE && iLHand == BASE_ITEM_HANDAXE)
 {
  sWeapon = "Handaxe";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_KAMA && iLHand == BASE_ITEM_KAMA)
 {
  sWeapon = "Kama";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_KUKRI && iLHand == BASE_ITEM_KUKRI)
 {
  sWeapon = "Kukri";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_LIGHTHAMMER && iLHand == BASE_ITEM_LIGHTHAMMER)
 {
  sWeapon = "Light Hammer";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_MACE && iLHand == BASE_ITEM_MACE)
 {
  sWeapon = "Mace";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_SHORTSWORD && iLHand == BASE_ITEM_SHORTSWORD)
 {
  sWeapon = "Short Sword";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_SICKLE && iLHand == BASE_ITEM_SICKLE)
 {
  sWeapon = "Sickle";
  nBonus = 2;
 }
 if (iRHand == BASE_ITEM_BASTARDSWORD && iLHand == BASE_ITEM_BASTARDSWORD)
 {
  sWeapon = "Bastard Sword";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_BATTLEAXE && iLHand == BASE_ITEM_BATTLEAXE)
 {
  sWeapon = "Battleaxe";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_DWARVENWARAXE && iLHand == BASE_ITEM_DWARVENWARAXE)
 {
  sWeapon = "Dwarven Waraxe";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_FALCHION && iLHand == BASE_ITEM_FALCHION)
 {
  sWeapon = "Falchion";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_FLAIL && iLHand == BASE_ITEM_FLAIL)
 {
  sWeapon = "Flail";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_GREATAXE && iLHand == BASE_ITEM_GREATAXE)
 {
  sWeapon = "Greataxe";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_GREATCLUB && iLHand == BASE_ITEM_GREATCLUB)
 {
  sWeapon = "Great Club";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_GREATSWORD && iLHand == BASE_ITEM_GREATSWORD)
 {
  sWeapon = "Greatsword";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_HEAVYFLAIL && iLHand == BASE_ITEM_HEAVYFLAIL)
 {
  sWeapon = "Heavy Flail";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_KATANA && iLHand == BASE_ITEM_KATANA)
 {
  sWeapon = "Katana";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_LONGSWORD && iLHand == BASE_ITEM_LONGSWORD)
 {
  sWeapon = "Longsword";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_MORNINGSTAR && iLHand == BASE_ITEM_MORNINGSTAR)
 {
  sWeapon = "Morningstar";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_RAPIER && iLHand == BASE_ITEM_RAPIER)
 {
  sWeapon = "Rapier";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_SCIMITAR && iLHand == BASE_ITEM_SCIMITAR)
 {
  sWeapon = "Scimitar";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_WARHAMMER && iLHand == BASE_ITEM_WARHAMMER)
 {
  sWeapon = "Warhammer";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_WARMACE && iLHand == BASE_ITEM_WARMACE)
 {
  sWeapon = "Warmace";
  nBonus = 4;
 }
 if (iRHand == BASE_ITEM_TWOBLADEDSWORD && iLHand == BASE_ITEM_TWOBLADEDSWORD)
 {
  sWeapon = "Two-Bladed Sword";
  nBonus = 4;
 }
 
 if (nBonus == 0)
 {
  RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
  return;
 }
 
 effect eRHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_ONHAND);
 effect eLHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_OFFHAND);
 effect eLink = EffectLinkEffects(eLHand, eRHand);
   
 RemoveEffect(oPC, eLink);
 ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oPC);
}

--This is the most recent version of the script. I once tried using my own CancelEffect function that used RemoveEffect and a while loop that searched the pc's effects for the one in question.... despite having the effect in question, the script returned -1 on the first check... I am at a loss as to how I was able to make this irreversible...

Modifié par ghowriter, 30 septembre 2011 - 07:07 .


#2
kevL

kevL
  • Members
  • 4 061 messages
just a guess here

at the bottom: Are you sure that eLink can be removed? Since effects are linked, wouldn't you just remove one of those linked effects from the previous application (like,

RemoveEffect(oPC, ATTACK_BONUS_ONHAND);

and ATTACK_BONUS_OFFHAND gets automatically removed also??? not wanting to open the whole can here ..)


ps. might help to say, where this script gets called from;
pps. might help to put in some debug that checks and re-checks for given effect(s), at tactical places in your script. For example, to find out which (or both) is not working:

1. RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
2. RemoveEffect(oPC, eLink);

ppps. Has SPELL_TWIN_WEAPON_FIGHTING been set up properly as a spell with a SpellID that RemoveEffectsFromSpell( ) even recognizes


Posted Image

Modifié par kevL, 26 septembre 2011 - 04:14 .


#3
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
 Remove effect only works when you iterate effects, GetFirst, GetNext, inside of that it can remove an effect. RemoveEffectsFromSpell i am pretty sure is a function that just does that for you ( i have a revamped version of that )

You will want to change the following

..snip

 if (nBonus == 0)
 {
  RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
  return;
 }
 
 effect eRHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_ONHAND);
 effect eLHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_OFFHAND);
 effect eLink = EffectLinkEffects(eLHand, eRHand);
   
 RemoveEffect(oPC, eLink);
 ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oPC);
}

to something more like this

..snip

  RemoveEffectsFromSpell(oPC, SPELL_TWIN_WEAPON_FIGHTING);
  if (nBonus > 0)
  {
     effect eRHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_ONHAND);
     effect eLHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_OFFHAND);
     effect eLink = EffectLinkEffects(eLHand, eRHand);
      eLink = SetEffectSpellId(eLink, SPELL_TWIN_WEAPON_FIGHTING );
     ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oPC);
   }
}

Something more like the above, note that i've redone RemoveEffectsFromSpell with a more effective function in my CSL, but it should work usually if there are not multiple effects.

Note, pretty sure you don't need to do on hand and off hand and link the two, if you just do both hands it works too, but that should work how you have it.

Modifié par painofdungeoneternal, 26 septembre 2011 - 08:27 .


#4
kevL

kevL
  • Members
  • 4 061 messages

painofdungeoneternal wrote...

eLink = SetEffectSpellId(eLink, SPELL_TWIN_WEAPON_FIGHTING );


ah :^)

#5
ghowriter

ghowriter
  • Members
  • 21 messages

kevL wrote...

painofdungeoneternal wrote...

eLink = SetEffectSpellId(eLink, SPELL_TWIN_WEAPON_FIGHTING );


ah :^)


I tried this and had my own function written to check all effects to find this one and the function ran, it just wouldn't/couldn't remove the effect. I saved the game with the effect acrive and opened the ifo in the gff editor and there are a number of effects all having the same spell ID as this script. When the script searches the oPC, it never "finds" any effects at all on the oPC. I assume this is why the RemoveEffect() and RemoveEffectFRromSpell won't work. They both search for the specific effect based on SpellID which the engine cannot find on oPC.

The problem with this is the feat gives either a +2 or +4 bonus. Equip weapons that grant the +4 and switch to a set that gives +2 and the oPC still gets the +4. Worse yet, unequipping all weapons still grants the +4.

This is just too weird and I am out of ideas - I have spent nearly 64 hours on this problem alone.

Modifié par ghowriter, 27 septembre 2011 - 02:00 .


#6
ghowriter

ghowriter
  • Members
  • 21 messages
Okay, I had me a thought and changed the duration type from instant to temporary. This kind of worked. The effect does cancel, however, it cancels immediately after applying it. Time to review the script.

#7
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
download my csl and use it's effects functions to remove effects.

#8
ghowriter

ghowriter
  • Members
  • 21 messages

painofdungeoneternal wrote...

download my csl and use it's effects functions to remove effects.



Link?

#9
ghowriter

ghowriter
  • Members
  • 21 messages
I am going to have to rethink this out. I changed the duration type and that seemed to fix the issue as I posted but found that the only reason the effect cancelled was because I didn't put a duration in the script. The script is called from the OnEquip and OnUnequip scripts. I set these so when the oPC equips it checks if it was a weapon (either hand) and if so run my script. Everything works except the cancel effect. As written now witht the duration type set to temporary, once the script a +4 bonus, the oPC keeps it till he rests. I am thinking about using a seperate script for the OnUnequip and have it only remove the effect and not bother to add new since that can be handled by the OnEquip. Also, I have realized that my script is applying the bonus as a magical effect rather than as a simple bonus. This makes the effect removable by dispelling when it shouldn't be. It should work like weapon focus,

#10
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Community Script Library and code can be downloaded here

You just need to include and use the _CSLCore_Magic.nss, and use the CSLRemoveEffectSpellIdSingle function. The only files you need are in the CSLLibrary folder, that begin with "_CSLCore_", but all of that folder is useful. ( most of what you are downloading is using the core library to implement a lot of different systems. ) You can also just grab that one function out and get the 4 constants it refers to, but not sure how adept you are at doing things yet.

// at the top
#include "_CSLCore_Magic"


// instead of remove effects from spell
CSLRemoveEffectSpellIdSingle( SC_REMOVE_ALLCREATORS, oPC, oPC, SPELL_TWIN_WEAPON_FIGHTING );


What you are doing is an equip script, kaedrin has those implemented for almost exactly what you are describing.

As for dispel, set the spell id to negative ( put a minus in front of the constant every where you use it and use these functions ( just like setspellid ))
effect SupernaturalEffect ( effect eEffect )
Set the subtype of eEffect to Supernatural and return eEffect.
(Effects default to magical if the subtype is not set) Permanent supernatural effects are not removed by resting

effect ExtraordinaryEffect ( effect eEffect )
Set the subtype of eEffect to Extraordinary and return eEffect.
(Effects default to magical if the subtype is not set) Extraordinary effects are removed at the end of resting, but not by dispel magic

#11
ghowriter

ghowriter
  • Members
  • 21 messages

painofdungeoneternal wrote...

Community Script Library and code can be downloaded here

You just need to include and use the _CSLCore_Magic.nss, and use the CSLRemoveEffectSpellIdSingle function. The only files you need are in the CSLLibrary folder, that begin with "_CSLCore_", but all of that folder is useful. ( most of what you are downloading is using the core library to implement a lot of different systems. ) You can also just grab that one function out and get the 4 constants it refers to, but not sure how adept you are at doing things yet.


Curses. I discarded the script and started over. I was under the impression that my error was in using a spell to turn on the effects so I deleted the spell from the 2da and left it as a passive feat which the OnEquip and OnUnequip scripts look for whenever the character equips a weapon. It works exactly as before though. The script applies the bonus when the PC equips dual weapons but when the weapons change the script fails to remove the effect.

Using SpeakString for debugging, I found this problem:

When applying the effect, the EffectSpellID = -1, the EffectType = 0 and the EffectSubType = 24. When the removal script runs it checks the same values and returns EffectSpellID = -1, EffectType = 40, and EffectSubType = 24. Iam now thinking that the reason the effect is proving difficult to remove is because I am linking two effects. Someone here said I should be able to combine this into a single effect which should be as follows:

effect eEffect = EffectAttackIncrease(nBonus, ATTACK_BONUS_MISC);
eEffect = ExtraordinaryEffect(eEffect);

What I am worried about, though, is if the character has this effect and then drinks a potion os uses a spell that also gives an attack bonus, will my cancel script also cancel those?

Lastly, when I was making the feat in the 2da, I wanted to make weapon focus a requirement for the feat, however, I do not want to limit it to a specific weapon focus, just weapon focus (melee weapon). How would I do this? I mean, I could script it, easily, but that wouldn't prevent someone from taking the feat when they haven't taken the required weapon focus. I thought about using the or feat requires slots but there aren't enough. Any idea would be appreciated.

#12
ghowriter

ghowriter
  • Members
  • 21 messages
I figured that since I essentially rewrote the script(s), I should post them for review (in the event I made a mistake which is causing my headache).


void main()
{
	object oPC = OBJECT_SELF;
	int HasTwinWeaponEffect = GetLocalInt(oPC, "HasTwinWeapon");
	int TWBonus = GetLocalInt(oPC, "TWBonus");
    int FEAT_TWIN_WEAPON_FIGHTING = 2275;
	
	object oRHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
		if (!GetIsObjectValid(oRHand))
		{
			if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
			return;
		}
	object oLHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
		if (!GetIsObjectValid(oLHand))
		{
			if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
			return;
		}
	int iRHand = GetBaseItemType(oRHand);
		if (iRHand == BASE_ITEM_INVALID)
		{
			if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
			return;
		}
	int iLHand = GetBaseItemType(oLHand);
		if (iLHand == BASE_ITEM_INVALID)
		{
			if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
			return;
		}
	
		if (iRHand != iLHand)
		{
			if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
			return;
		}

	//The above ought to filter out all ranged weapons since it is not possible to 
	//have anything equipped in the left hand when using one. This should also filter
	//any non-weapons since it isn't possible to equip non-weapons in both hands.
	
	int nBonus = 0;
	if (iRHand == BASE_ITEM_DAGGER && iLHand == BASE_ITEM_DAGGER) nBonus = 2;
	if (iRHand == BASE_ITEM_HANDAXE && iLHand == BASE_ITEM_HANDAXE) nBonus = 2;
	if (iRHand == BASE_ITEM_KAMA && iLHand == BASE_ITEM_KAMA) nBonus = 2;
	if (iRHand == BASE_ITEM_KUKRI && iLHand == BASE_ITEM_KUKRI) nBonus = 2;
	if (iRHand == BASE_ITEM_LIGHTHAMMER && iLHand == BASE_ITEM_LIGHTHAMMER) nBonus = 2;
	if (iRHand == BASE_ITEM_MACE && iLHand == BASE_ITEM_MACE) nBonus = 2;
	if (iRHand == BASE_ITEM_SHORTSWORD && iLHand == BASE_ITEM_SHORTSWORD) nBonus = 2;
	if (iRHand == BASE_ITEM_SICKLE && iLHand == BASE_ITEM_SICKLE) nBonus = 2;
	
	if (iRHand == BASE_ITEM_BASTARDSWORD && iLHand == BASE_ITEM_BASTARDSWORD) nBonus = 4;
	if (iRHand == BASE_ITEM_BATTLEAXE && iLHand == BASE_ITEM_BATTLEAXE) nBonus = 4;
	if (iRHand == BASE_ITEM_DWARVENWARAXE && iLHand == BASE_ITEM_DWARVENWARAXE) nBonus = 4;
	if (iRHand == BASE_ITEM_FALCHION && iLHand == BASE_ITEM_FALCHION) nBonus = 4;
	if (iRHand == BASE_ITEM_FLAIL && iLHand == BASE_ITEM_FLAIL) nBonus = 4;
	if (iRHand == BASE_ITEM_GREATAXE && iLHand == BASE_ITEM_GREATAXE) nBonus = 4;
	if (iRHand == BASE_ITEM_GREATCLUB && iLHand == BASE_ITEM_GREATCLUB) nBonus = 4;
	if (iRHand == BASE_ITEM_GREATSWORD && iLHand == BASE_ITEM_GREATSWORD) nBonus = 4;
	if (iRHand == BASE_ITEM_HEAVYFLAIL && iLHand == BASE_ITEM_HEAVYFLAIL) nBonus = 4;
	if (iRHand == BASE_ITEM_KATANA && iLHand == BASE_ITEM_KATANA) nBonus = 4;
	if (iRHand == BASE_ITEM_LONGSWORD && iLHand == BASE_ITEM_LONGSWORD) nBonus = 4;
	if (iRHand == BASE_ITEM_MORNINGSTAR && iLHand == BASE_ITEM_MORNINGSTAR) nBonus = 4;
	if (iRHand == BASE_ITEM_RAPIER && iLHand == BASE_ITEM_RAPIER) nBonus = 4;
	if (iRHand == BASE_ITEM_SCIMITAR && iLHand == BASE_ITEM_SCIMITAR) nBonus = 4;
	if (iRHand == BASE_ITEM_WARHAMMER && iLHand == BASE_ITEM_WARHAMMER) nBonus = 4;
	if (iRHand == BASE_ITEM_WARMACE && iLHand == BASE_ITEM_WARMACE) nBonus = 4;
	if (iRHand == BASE_ITEM_TWOBLADEDSWORD && iLHand == BASE_ITEM_TWOBLADEDSWORD) nBonus = 4;
	
	if (nBonus == 0)
	{
		if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
		return;
	}
	if (HasTwinWeaponEffect == TRUE && nBonus == 2 && nBonus != TWBonus) ExecuteScript ("ww_twin_off",oPC);
	if (HasTwinWeaponEffect == TRUE && nBonus == 4 && nBonus != TWBonus) ExecuteScript ("ww_twin_off",oPC);

	effect eRHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_ONHAND);
	effect eLHand = EffectAttackIncrease(nBonus, ATTACK_BONUS_OFFHAND);
	effect eTwin = EffectLinkEffects(eLHand, eRHand);
	eTwin = ExtraordinaryEffect(eTwin);
			
	SetLocalInt(oPC, "HasTwinWeapon", TRUE);
	SetLocalInt(oPC, "TWBonus", nBonus);
	
	SetLocalInt(oPC, "nTwinEffectSpellID", GetEffectSpellId(eTwin));
	SetLocalInt(oPC, "nTwinEffectType", GetEffectType(eTwin)); 
	SetLocalInt(oPC, "nTwinEffectSubType", GetEffectSubType(eTwin));
	SetLocalObject(oPC, "oTwinEffectCreator", GetEffectCreator(eTwin));
	
	ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eTwin, oPC, HoursToSeconds(24));

}


#13
ghowriter

ghowriter
  • Members
  • 21 messages
void main()
{
	object oPC = OBJECT_SELF;
	int HasTwinWeaponEffect = GetLocalInt(oPC, "HasTwinWeapon");
	int TWBonus = GetLocalInt(oPC, "TWBonus");
    int FEAT_TWIN_WEAPON_FIGHTING = 2275;
	int nTwinEffectSpellID = GetLocalInt(oPC, "nTwinEffectSpellID");
	int nTwinEffectType = GetLocalInt(oPC, "nTwinEffectType");
	int nTwinEffectSubType = GetLocalInt(oPC, "nTwinEffectSubType");
	object oTwinEffectCreator = GetLocalObject(oPC, "oTwinEffectCreator");
	
	SpeakString("Stored data.", TALKVOLUME_SHOUT);
	SpeakString("EffectSpellID: "+IntToString(nTwinEffectSpellID), TALKVOLUME_SHOUT);
	SpeakString("EffectType: "+IntToString(nTwinEffectType), TALKVOLUME_SHOUT);
	SpeakString("EffectSubType: "+IntToString(nTwinEffectSubType), TALKVOLUME_SHOUT);
	SpeakString("Attempting removal.", TALKVOLUME_SHOUT);
		
	effect eEffect = GetFirstEffect(oPC);
	while (GetIsEffectValid(eEffect))
	{
		int nType = GetEffectType(eEffect);
		int nSubType = GetEffectSubType(eEffect);
		int nSpellID = GetEffectSpellId(eEffect);
		object oCreator = GetEffectCreator(eEffect);
		
		SpeakString("EffectSpellID: "+IntToString(nSpellID), TALKVOLUME_SHOUT);
		SpeakString("EffectType: "+IntToString(nType), TALKVOLUME_SHOUT);
		SpeakString("EffectSubType: "+IntToString(nSubType), TALKVOLUME_SHOUT);
	
		if (oCreator == oTwinEffectCreator && nSpellID == nTwinEffectSpellID && nType == nTwinEffectType && nSubType == nTwinEffectSubType) //This never fires because nType fails to match nTwinEffectType (nType = 40; nTwinEffectType = 0)
		{
			RemoveEffect(oPC, eEffect);
			SetLocalInt(oPC, "HasTwinWeapon", FALSE);
			SetLocalInt(oPC, "TWBonus", 0);
		}
	eEffect = GetNextEffect(oPC);
	return;
	}
}

The scripts are seperate now. One to apply the effect, one to remove it.

#14
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
If you remove an effect, you mess up the iterator, and you need to GetFirstEffect again to ensure nothing goes a bit crazy on you. ( Not going to be an issue every time, but it's how you are supposed to be doing it. )

#15
ghowriter

ghowriter
  • Members
  • 21 messages

painofdungeoneternal wrote...

If you remove an effect, you mess up the iterator, and you need to GetFirstEffect again to ensure nothing goes a bit crazy on you. ( Not going to be an issue every time, but it's how you are supposed to be doing it. )


The script uses the GetFirstEffect function, right before the While loop. Anyway, I downloaded the infor but haven't implemented it yet. I redid the removal script while loop to match the effect type and subtype using the built in variables for attack increase and extrodinary and I also redid the other script so that it was applying a single effect rather than two and tested. Success. Equipping twin weapons applies the bonus, equipping an unlike weapon removes the bonus. Unequipping either weapon also removes the bonus. I guess when effects are linked they're harder to remove.

Also, since I haven't been able to find a way to make general weapon focus a requirement, I decided to make my twin weapon feat specific to a single weapon type like weapon focus. Of course, this requires a bit more scripting on my part in the OnEquip script, but it ought to be straight forward.

Thanks a bunch for helping to everyone;especially painofdungeoneternal, you were quite helpful.

Posted Image

#16
Morbane

Morbane
  • Members
  • 1 883 messages
Hmm "*image removed*" wonder what it was.......

#17
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
You do ( pseudocode )

getfirsteffect()
while effect is valid
{
if ( i need to remove )
{
removeeffect() // this messes up getnexteffect iterator
getfirsteffect() // start over when this happens
}
getnexteffect
}


If you don't do this, getnexteffect actually skips an effect - this is documented in various functions but is not done universally.

#18
ghowriter

ghowriter
  • Members
  • 21 messages

Morbane wrote...

Hmm "*image removed*" wonder what it was.......


A smiley from the bottom of the post window.

#19
ghowriter

ghowriter
  • Members
  • 21 messages

painofdungeoneternal wrote...

You do ( pseudocode )

getfirsteffect()
while effect is valid
{
if ( i need to remove )
{
removeeffect() // this messes up getnexteffect iterator
getfirsteffect() // start over when this happens
}
getnexteffect
}


If you don't do this, getnexteffect actually skips an effect - this is documented in various functions but is not done universally.


Wow, someone ought to be slapped for that one. I'll make the adjustment in my script.

I did mention that it's working perfectly now?

On to Ambidexterity and not the one from NWN1, my version simply gives the oPC full str bonus to off hand damage and is a prereq for twin weapon fighting.

#20
ghowriter

ghowriter
  • Members
  • 21 messages
Just an aside, I found and fixed a bug in the script. I was applying bonus based entirely on medium size PCs. When I made a halfling fighter and took all the reuired feats, he lost 4 points when dual weilding short swords and other medium size weapons. So, to fiz this, I decided that I didn't want a bunch of if statements in my script. I even remove those that were there and got the data the script needed direct from the 2da files. Since there is no function (that I am aware of) that will return the weapons size, I simply read it into the script using Get2daString and converting it to an integer. Worked perfectly. I am attaching the script here for anyone who wants to see (or critique):

[code=auto:0]
void main()
{
object oPC = OBJECT_SELF;
int HasTwinWeaponEffect = GetLocalInt(oPC, "HasTwinWeapon");
int TWBonus = GetLocalInt(oPC, "TWBonus");

object oRHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
if (!GetIsObjectValid(oRHand))
{
if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
return;
}
object oLHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
if (!GetIsObjectValid(oLHand))
{
if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
return;
}
int iRHand = GetBaseItemType(oRHand);
if (iRHand == BASE_ITEM_INVALID)
{
if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
return;
}
int iLHand = GetBaseItemType(oLHand);
if (iLHand == BASE_ITEM_INVALID)
{
if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
return;
}

if (iRHand != iLHand)
{
if (HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);
return;
}

//The above ought to filter out all ranged weapons since it is not possible to
//have anything equipped in the left hand when using one. This should also filter
//any non-weapons since it isn't possible to equip non-weapons in both hands.
//The only items that might slip through are throwing weapons, however, the calling
//script ought to filter those out.

int nBonus = 0;
string sWeaponSize = Get2DAString("baseitems", "WeaponSize", iRHand);
string sPCSize = Get2DAString("appearance", "SIZECATEGORY", GetAppearanceType(oPC));

int nWeaponSize = StringToInt(sWeaponSize);
int nPCSize = StringToInt(sPCSize);

if (nPCSize == 2)
{
switch(nWeaponSize)
{
case 1: nBonus = 2;
break;
case 2: nBonus = 4;
break;
case 3: nBonus = 4;
break;
default: FloatingTextStringOnCreature("An error occurred reading the 2da files. Line 65.", oPC, FALSE);
}
}
if (nPCSize == 3)
{
switch(nWeaponSize)
{
case 1: nBonus = 2;
break;
case 2: nBonus = 2;
break;
case 3: nBonus = 4;
break;
default: FloatingTextStringOnCreature("An error occurred reading the 2da files. Line 78.", oPC, FALSE);
}
}

int nArmor = GetArmorRank(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC));

if (nArmor == ARMOR_RANK_HEAVY)
{
ExecuteScript ("ww_twin_off",oPC);
return;
}
if (nBonus == 0 && HasTwinWeaponEffect == TRUE)
{
ExecuteScript ("ww_twin_off",oPC);
return;
}
if (nBonus != TWBonus && HasTwinWeaponEffect == TRUE) ExecuteScript ("ww_twin_off",oPC);

if (nBonus == 0)
{
FloatingTextStringOnCreature("An error occurred reading the 2da files. Line 96.", oPC, FALSE);
return;
}

effect eTwin = EffectAttackIncrease(nBonus, ATTACK_BONUS_MISC);
eTwin = ExtraordinaryEffect(eTwin);

SetLocalInt(oPC, "HasTwinWeapon", TRUE);
SetLocalInt(oPC, "TWBonus", nBonus);

ApplyEffectToObject(DURATION_TYPE_PERMANENT, eTwin, oPC);
SpeakString("Twin Weapon Fighting Active", TALKVOLUME_SHOUT);
}

I added a restriction to the feat in that if the PC wears heavy armor she gets no bonus. I am going to add a medium armor 50% penalty as well. I want to do encumbered too but I haven't gotten that far yet.

Modifié par ghowriter, 29 septembre 2011 - 09:07 .