tagbased problems
#1
Posté 12 mai 2012 - 08:04
In my pw i have items (tagabased) that once worn,give a little boost to the new characters.
The problem are that when the character lv up, or when dies and then respwan,the effect provided by this items goes away, even if it is still worn.
how can I fix this issue?
#2
Posté 12 mai 2012 - 10:00
Example:
#include "x2_inc_switches"
void main()
{
int iEvent = GetUserDefinedItemEventNumber();
if (iEvent == X2_ITEM_EVENT_EQUIP)
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDeaf()), oPC));
}
if (iEvent == X2_ITEM_EVENT_UNEQUIP)
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
effect eEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eEffect))
{
if (GetEffectCreator(eEffect) == oItem)
RemoveEffect(oPC, eEffect);
eEffect = GetNextEffect(oPC);
}
}
}
Your Level up and your OnDeath scripts are removing effects from players. You need to alter these scripts to ignore the effects created by these items. Or you could alter your level up and respawn scripts to re-add the effects if a certain item is equpped.
Modifié par GhostOfGod, 12 mai 2012 - 11:01 .
#3
Posté 12 mai 2012 - 11:05
GhostOfGod wrote...
You will need to make sure that in your tagbased script that you put the effect inside an assign command to the item so that it will be considered the effect creator.
Example:
#include "x2_inc_switches"
void main()
{
int iEvent = GetUserDefinedItemEventNumber();
if (iEvent == X2_ITEM_EVENT_EQUIP)
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDeaf()), oPC));
}
if (iEvent == X2_ITEM_EVENT_UNEQUIP)
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
effect eEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eEffect))
{
if (GetEffectCreator(eEffect) == oItem)
RemoveEffect(oPC, eEffect);
eEffect = GetNextEffect(oPC);
}
}
}
Your Level up and your OnDeath scripts are removing effects from players. You need to alter these scripts to ignore the effects created by these items. Or you could alter your level up and respawn scripts to re-add the effects if a certain item is equpped.
thx a lot.
even if i have applied the effect in another way
#include "x2_inc_switches"
void main()
{
object oPC = GetPCItemLastEquippedBy();
object oMod = GetModule();
int nEvent = GetUserDefinedItemEventNumber();
int nSpeed = 30;
if(GetLevelByclass(class_TYPE_MONK, oPC)>=6)// ._.
{
nSpeed-= 25;
}
if (nEvent == X2_ITEM_EVENT_EQUIP)
{
effect eEffect = EffectMovementSpeedIncrease(nSpeed);
//eEffect = SupernaturalEffect(eEffect);
AssignCommand(GetObjectByTag("tagbb") ,ApplyEffectToObject(DURATION_TYPE_PERMANENT,SupernaturalEffect(eEffect), oPC));
return;
}
cut...
but I find your solution much simpler:
object oItem = GetPCItemLastEquipped();
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDeaf()), oPC));
Now I guess I'll have to enter somenthing like this on Lv Up/respwan:
object oItem = GetPCItemLastEquipped();
object oPC = GetPCLevellingUp();
effect eSpeed = GetFirstEffect(oPC);//<- pc Lv_UP
while (GetIsEffectValid(eSpeed))//eSpeed
{
if (GetEffectType(eSpeed) == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE))
{
if(GetEffectCreator(eSpeed)) != oItem)
{
//do stuff
}
}
}
I did well?
EDIT
Modifié par Cursed_Eclipse, 12 mai 2012 - 11:51 .
#4
Posté 12 mai 2012 - 01:38
Modifié par _Guile, 12 mai 2012 - 01:38 .
#5
Posté 13 mai 2012 - 07:23
Cursed_Eclipse wrote...
even if i have applied the effect in another way
#include "x2_inc_switches"
void main()
{
object oPC = GetPCItemLastEquippedBy();
object oMod = GetModule();
int nEvent = GetUserDefinedItemEventNumber();
int nSpeed = 30;
if(GetLevelByclass(class_TYPE_MONK, oPC)>=6)// ._.
{
nSpeed-= 25;
}
if (nEvent == X2_ITEM_EVENT_EQUIP)
{
effect eEffect = EffectMovementSpeedIncrease(nSpeed);
//eEffect = SupernaturalEffect(eEffect);
AssignCommand(GetObjectByTag("tagbb") ,ApplyEffectToObject(DURATION_TYPE_PERMANENT,SupernaturalEffect(eEffect), oPC));
return;
}
cut...
If you wanted to use a placeable object/npc you could do that to. You just need to make sure you don't declare the effect outside the "AssignCommand" function or in this case the module would be considered the effect creator (which would also be fine unless the module is creating some other effects that you don't want removed). If you keep the actual effect inside the "AssignCommand" then who/whatever you assign the command to will be the "creator".
Now I guess I'll have to enter somenthing like this on Lv Up/respwan:
object oItem = GetPCItemLastEquipped();
object oPC = GetPCLevellingUp();
effect eSpeed = GetFirstEffect(oPC);//<- pc Lv_UP
while (GetIsEffectValid(eSpeed))//eSpeed
{
if (GetEffectType(eSpeed) == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE))
{
if(GetEffectCreator(eSpeed)) != oItem)
{
//do stuff
}
}
}
Yep. But you would need to find the item specifically equipped in whatever slot since the last equipped item at the point of death might no longer be the same item that created the effect.
Modifié par GhostOfGod, 13 mai 2012 - 07:30 .
#6
Posté 14 mai 2012 - 09:50
GhostOfGod wrote...
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDeaf()), oPC));
Something doesn't seem right about this. GetEffectCreator() gets the creator of the effect, not the applier. In order to make this work one should have to do something like this.
void ApplyDeaf(object oTarget)
{
//This is where the effect is created
effect eDeaf = SupernaturalEffect(EffectDeaf());
//This is where the effect is applied
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eDeaf, oTarget);
}
void main()
{
object oItem =GetItemActivated();
object oPC = GetItemActivator();
AssignCommand(oItem, ApplyDeaf(oPC));
}
Modifié par WhiZard, 14 mai 2012 - 10:06 .
#7
Posté 14 mai 2012 - 10:28
At least that is what my memory says, without testing.
The same reason you would normaly create the effect before assigning and pass it as a Var to allow the object running the script to be the creator.
#8
Posté 15 mai 2012 - 03:06
Lightfoot8 wrote...
Both work out the same way. In ghost's assignment the effect is not created untill after it is assigned, Therefore the Item will still be the creator, not the object the script is running on.
At least that is what my memory says, without testing.
The same reason you would normaly create the effect before assigning and pass it as a Var to allow the object running the script to be the creator.
You are partially correct. This would work if the effect was defined in the assign command, but it isn't. SupernaturalEffect() does not create a new effect, it merely updates the effect's listing. If you applied an effect and then used SupernaturalEffect() all instances of that effect on creatures would return supernatural by GetEffectSubtype() even if they are not supernatural.
#9
Posté 15 mai 2012 - 03:28
#10
Posté 15 mai 2012 - 03:37
#11
Posté 15 mai 2012 - 05:00
GhostOfGod wrote...
Have you tested it WhiZard? I've used this method quite a bit and so far it seems to work fine with "GetEffectCreator". I use it for things like partially cursed items. Ones that you can still unequip but while equipped have some negative effect like blindness or deafness, etc.
Yes, I tested it.
This works
AssignCommand(...,ApplyEffectToObject(...,..., SupernaturalEffect(EffectDazed())));
This does not
effect eDaze = EffectDazed();
AssignCommand(...,ApplyEffectToObject(....,..., SupernaturalEffect(eDaze)));
Modifié par WhiZard, 15 mai 2012 - 05:02 .
#12
Posté 15 mai 2012 - 05:09
Modifié par GhostOfGod, 15 mai 2012 - 05:11 .
#13
Posté 15 mai 2012 - 05:16
apologies to you and Lightfoot
#14
Posté 15 mai 2012 - 05:18
Modifié par GhostOfGod, 15 mai 2012 - 05:19 .
#15
Posté 15 mai 2012 - 05:56
#include "x2_inc_switches"
void main()
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
int nEvent = GetUserDefinedItemEventNumber();
int nSpeed = 30;
if(GetLevelByclass(class_TYPE_MONK, oPC)>=6)// ._.
{
nSpeed-= 25;
}
if (nEvent == X2_ITEM_EVENT_EQUIP)
{
AssignCommand(oItem,ApplyEffectToObject(DURATION_TYPE_PERMANENT,
SupernaturalEffect(EffectMovementSpeedIncrease(nSpeed)), oPC));
return;
}
else if (nEvent == X2_ITEM_EVENT_UNEQUIP)
{
effect Effect = EffectMovementSpeedIncrease(nSpeed);
effect eEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eEffect))
{
if(GetEffectCreator(eEffect) == oItem)
{
if (GetEffectType(eEffect) == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE)
{
RemoveEffect(oPC, eEffect);
eEffect = GetNextEffect(oPC);
}
}
}
}
}
I have not tested yet.
are still very confused about how to act,anyway i put this code On Lv UP
-cut-
object oPC = GetPCLevellingUp();
if (!GetIsPC(oPC)) return;
if(IsInConversation(oPC)== TRUE)return;
//object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
-cut-
if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)
{
SetUserDefinedItemEventNumber(X2_ITEM_EVENT_EQUIP);
object oBra = GetItemInSlot(INVENTORY_SLOT_ARMS, oPC);
//object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oPC);
//object oWeap = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
int nRet = ExecuteScriptAndReturnInt(GetUserDefinedItemEventScriptName(oItem),OBJECT_SELF);
if(GetTag(oBra) == "1_brac_speed")
{
//effect eEffect = EffectMovementSpeedIncrease(30);
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectMovementSpeedIncrease(30)), oPC));
}
if (nRet == X2_EXECUTE_SCRIPT_END)
{
return;
}
}
in this way the effect remains.
But i'm not sure this is the right way to re-apply the effects.
The problem is that I am experiencing other errors
Modifié par Cursed_Eclipse, 15 mai 2012 - 06:05 .
#16
Posté 15 mai 2012 - 07:56
#include "x2_inc_switches"
void main()
{
int iEvent = GetUserDefinedItemEventNumber();
if (iEvent == X2_ITEM_EVENT_EQUIP)//PC equips item
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
//Everything else
}
else if (iEvent == X2_ITEM_EVENT_UNEQUIP)//PC unequips item
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
//Everythihng else
}
//You can keep going with this is you want something to happen with other
//events as well.
else if (iEvent == X2_ITEM_EVENT_ACQUIRE)//PC picks up, buys, gets item
{
object oPC = GetModuleItemAcquiredBy();
object oItem = GetModuleItemAcquired();
//Everything else
}
else if (iEvent == X2_ITEM_EVENT_UNACQUIRE)//PC sells, drops, loses item
{
object oPC = GetModuleItemLostBy();
object oItem = GetModuleItemLost();
//Everything else
}
//else if (iEvent == etc...
}
You will notice that we put any variables that pertains specifically to one of those events inside the "if". In your script you define oPC at the top as "GetPCItemLastEquippedBy()". But what happens when the player is UNequipping it? He then needs to be defined differently as "GetPCItemLastUnequippedBy()".
Hopefully that makes sense.
So your script might look more like:
#include "x2_inc_switches"
void main()
{
int nEvent = GetUserDefinedItemEventNumber();
if (nEvent == X2_ITEM_EVENT_EQUIP)
{
object oPC = GetPCItemLastEquippedBy();
object oItem = GetPCItemLastEquipped();
int nSpeed = 30;
if(GetLevelByclass(class_TYPE_MONK, oPC)>=6)// ._.
{
nSpeed-= 25;
}
AssignCommand(oItem,ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectMovementSpeedIncrease(nSpeed)), oPC));
}
else if (nEvent == X2_ITEM_EVENT_UNEQUIP)
{
object oPC = GetPCItemLastUnequippedBy();
object oItem = GetPCItemLastUnequipped();
effect eEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eEffect))
{
if(GetEffectCreator(eEffect) == oItem)
{
if (GetEffectType(eEffect) == EFFECT_TYPE_MOVEMENT_SPEED_INCREASE)
{
RemoveEffect(oPC, eEffect);
}
}
eEffect = GetNextEffect(oPC);
}
}
}
Modifié par GhostOfGod, 15 mai 2012 - 08:15 .
#17
Posté 15 mai 2012 - 09:14
//0. Activate item, occurs when using any unique power on an item: names of unique powers include activate item, unique power, and manipulate portal stone
const int X2_ITEM_EVENT_ACTIVATE = 0;
//1. Equip item, occurs when the item is equipped
const int X2_ITEM_EVENT_EQUIP = 1;
//2. Unequip item, occurs when the item is unequipped
const int X2_ITEM_EVENT_UNEQUIP = 2;
//3. On-Hit: occurs when the item hits a target (or is hit by a target for armor) in this script OBJECT_SELF is the PC possessing the item
const int X2_ITEM_EVENT_ONHITCAST = 3;
//4. Acquire item, occurs when the item is gained in the inventory
const int X2_ITEM_EVENT_ACQUIRE = 4;
//5. Unacquire item, occurs when the item is removed from the inventory
const int X2_ITEM_EVENT_UNACQUIRE = 5;
//6. Occurs when a spell is cast at the target, OBJECT_SELF is the caster of the spell
const int X2_ITEM_EVENT_SPELLCAST_AT = 6;
Modifié par WhiZard, 15 mai 2012 - 09:23 .
#18
Posté 15 mai 2012 - 09:45
object oItem;
int nSlot;
for (nSlot=0; nSlot<NUM_INVENTORY_SLOTS; nSlot++)
{
oItem=GetItemInSlot(nSlot, oPC); //(oPlayer, oDead, oLevelupper, etc..)
if (GetIsObjectValid(oItem))
{
string sTag = GetTag(oItem);
if (sTag == "Helm_of_Blind")
{
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectBlindness()), oPC));
}
if (sTag == "Helm_of_Deaf")
{
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDeaf()), oPC));
}
if (sTag == "Pants_of_Poo")
{
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectAbilityDecrease(ABILITY_CHARISMA, 1)), oPC));
}
//etc..
}
}
Basically all this does is loop through equipped items and gets the tag & readds effects. If the tag matches something in particular, then it has that equipped item add the effects again. You will need to list all or your items that need to have effects while equipped and add it to a list like above.
As far as I remember the default level up script doesn't remove effects. But then again I haven't actually played the game for about a year so don't quote me on that. But if the default behavior or your script IS removing effects then you will bascially use the same chunk of script as above. If it is a script in particular that is removing the effects OnLevelUp then make sure this chunk of script gos after that part. Proabaly safest just to stick it on the bottom.
Anyhow, good luck. Hope this helps.
P.S. I just highlighted oPC to make sure you put in the correct name of the declaration based on whichever script you are adding this to. oPC, oPlayer, oDead, etc..
Modifié par GhostOfGod, 15 mai 2012 - 09:51 .
#19
Posté 17 mai 2012 - 03:21
I have not tried yet these script but I have included in my module.
I can not understand why the effect goes away when the player lv up,there is no remove effect in my OnLv_UP event.
I thought that another solution could be to force the pc to requip the item when he lv_UP.
What about this solution?
and what do you think is the best?
#20
Posté 17 mai 2012 - 03:56
So just re-adding the effects if a certain item is already equipped is probably the simplest solution.
Modifié par GhostOfGod, 17 mai 2012 - 03:57 .
#21
Posté 17 mai 2012 - 05:55
SetUserDefinedItemEventNumber(X2_ITEM_EVENT_EQUIP);
EcxuteScript(OBJECT_SELF, GetTag(oEquip) ); // OBJECT_SELF should be the module for onPCLevelup.
Excuse any errors Im not at the house right now.
#22
Posté 17 mai 2012 - 08:19
This way of doing it has also crossed my mind but I don't use it probably from bad information I've picked up along the way or lack of information more likely. So your reply brings up a question for me L8.
Let's say the player has 5 of these items equipped. Then when the player levels up wouldn't 6 scripts then run? Or if you execute a script from a script does it just consider it part of that one script?
The reason I didn't and haven't used your approach L8 is because of my stingy use of resources. I'd rather just run the 1 level up script than run 6 scripts.
I'd like to know your opinion and knowledge on this.
Thanks L8.
Modifié par GhostOfGod, 17 mai 2012 - 08:20 .
#23
Posté 20 mai 2012 - 03:06
GhostOfGod wrote...
I already know L8 is the better scripter here so his solution is most likely the best approach.
This way of doing it has also crossed my mind but I don't use it probably from bad information I've picked up along the way or lack of information more likely. So your reply brings up a question for me L8.
Let's say the player has 5 of these items equipped. Then when the player levels up wouldn't 6 scripts then run? Or if you execute a script from a script does it just consider it part of that one script?
The reason I didn't and haven't used your approach L8 is because of my stingy use of resources. I'd rather just run the 1 level up script than run 6 scripts.
I'd like to know your opinion and knowledge on this.
Thanks L8.
I am not quite following you logic here. Yes if there are 5 items with Tag based events equipted, Then when the Level up evet runs the 5 additonal events scripts will run durning the level up. The 5 scripts will be ran before the first one finishes, I do not know if you would, I guess you could concider that one script. I myself would still call it six scripts running.
What I do not see is any extra resources, since the TagBased scripts for the events already exsist. If you really do not like the extra resources, the option is then to disable Tag Based Scripting all together and going back to the system of putting all the code for module events back into the ModuleEvent scripts. In that case you could still have the OnLevelUp run the Module event script. It will just take a little more set up . You would need to create a way for the correct item being equipted to passes to the Module On Equiped event.
I guess takling a little about the differances between Tag Based Scripting and Just packing all the code into the Module Events is in orfer at this point.
Advantages To Tagbased scripting as I see them.
1) All code For a Single Item is in a single Script. This makes it eaiser to code and debug what is going on with a single item.
2) There is no massive chained if statments ( if... else if...) to serarch through. Will discuss this more below.
DisAdvantages to Tag Based scripting.
1) Massive resource count. There Are Two resource per Item with Module Events. Well Mabey one I have never been clear on if the source code even counts towards the resource count. never heard any one talk about it and have never looked into it.
2) Harder to Debug what is going on in the module. A missfireing TBS due to a bad filter can be hard to track down.
Advantages of NON-Tagbased scripting.
1) Lower Resource Count. The only Resources are the Original Module Events.
2) Easier to debug module events. basicly there is no way for an aquire event to be bugged to run an activate/equiped event by mistake. short of placing the code in the wrong script.
disadvantages of NON-Tagbased Scripting.
1) Items with multiple Item events have there code scattered across several large scripts.
2) The massive conditional statment ( if.. else if...) making rather large scripts harder to search through. .
3) The Massive conditional adding to the Instruction limit ( Too Many Instructions Error). In Events with a lot of conditionals this can cause you to have to either keep Item events with lots of instructions at the begining of the 'if chain' or split them out into there own scripts anyway.
I know there are more advantages and dis advantages then I have listed, I am just drawing a blank right now.
As hented above will now talk about ' if... else if...' vs the Executescript aspect of the two systems. I feel that this is what your question was really about anyway.
The ExecuteScript, as used in TBS, is an emulation of how switch case statments should work, minus the ability of leaving out the break to allow excution to fall through to the next case. In order to explain this I will first explain how if... else if... statments work and how the switch... case:... statments work in NWScript vs other languages.
.........
Hmmm. Out of time right now. I will try and continue this tonight. if not it might be next weekend before I can get back to it. Sorry for the delays in answering.
#24
Posté 21 mai 2012 - 03:33
No worries L8. I work full time and got 2 kids. I know how it gos.Lightfoot8 wrote...
Sorry for the delays in answering.
I was just wondering if there was any disadvantage or advantage in using my idea of readding the effects in the level up script like so (one script; level up):
object oItem;
int nSlot;
for (nSlot=0; nSlot<NUM_INVENTORY_SLOTS; nSlot++)
{
oItem=GetItemInSlot(nSlot, oPC);//(oPlayer, oDead, oLevelupper, etc..)
if (GetIsObjectValid(oItem))
{
string sTag = GetTag(oItem);
if (sTag == "Helm_of_Blind")
{
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectBlindness()), oPC));
}
if (sTag == "Helm_of_Deaf")
{
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDeaf()), oPC));
}
if (sTag == "Pants_of_Poo")
{
AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT,
SupernaturalEffect(EffectAbilityDecrease(ABILITY_CHARISMA, 1)), oPC));
}
//etc..
}
}
As apposed to your idea (which I like) of re-running the tag based scripts on level up (six scripts; level up + 5 tag based in the example I mentioned previously).
I haven't done it the way you suggested because it "seems" like it'd be inefficient. Which is also why I don't use the ExecuteScript function if I can do without it in that particular script. But I don't know how the execute script works exactly. Is there any efficiency loss when using ExecuteScript several times or often in other scripts as apposed to just putting what you need in the one script?
The less scripts that run, the better?
Hopefully this makes more sense.
Modifié par GhostOfGod, 21 mai 2012 - 03:48 .
#25
Posté 27 mai 2012 - 07:28





Retour en haut






