Contents of the effect struct?
#1
Posté 09 juin 2013 - 01:49
Is there any way to figure out what properties it contains?
#2
Posté 09 juin 2013 - 03:49
void main()
{
object oPC = OBJECT_SELF;
effect eEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eEffect))
{
if (GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_RESISTANCE)
{
SendMessageToPC(oPC, "Found Damage Resistance Effect Type : "
+ IntToString(GetEffectType(eEffect)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Sub Type : "
+ IntToString(GetEffectSubType(eEffect)));
SendMessageToPC(oPC, "Found Damage Resistance Effect SpellID : "
+ IntToString(GetEffectSpellId(eEffect)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 0 : "
+ IntToString(GetEffectInteger(eEffect, 0)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 1 : "
+ IntToString(GetEffectInteger(eEffect, 1)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 2 : "
+ IntToString(GetEffectInteger(eEffect, 2)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 3 : "
+ IntToString(GetEffectInteger(eEffect, 3)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 4 : "
+ IntToString(GetEffectInteger(eEffect, 4)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 5 : "
+ IntToString(GetEffectInteger(eEffect, 5)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 6 : "
+ IntToString(GetEffectInteger(eEffect, 6)));
SendMessageToPC(oPC, "Found Damage Resistance Effect Integer 7 : "
+ IntToString(GetEffectInteger(eEffect, 7)) + "\\n");
}
else
{
SendMessageToPC(GetFirstPC(FALSE), "Found Other Effect : "
+ IntToString(GetEffectType(eEffect)));
}
eEffect = GetNextEffect(oPC);
}
}G'luck
ps. add these and i Think that's pretty much all of it (it might hold a DC also..)
int GetEffectDurationType(effect eEffect); object GetEffectCreator(effect eEffect);
Modifié par kevL, 09 juin 2013 - 03:55 .
#3
Posté 09 juin 2013 - 04:38
The effect struct is... well, a struct. And what I am wondering is if it is like all the other structs in the scripting library or if it is actually something wholly unique (like a special object with no public properties)
You can create your own structs in the script language and access their properties via "dot notation". And if I knew what the properties were I could just access them via dot notation.
Obviously the effect struct is compiled into the actual app, because there's no definition anywhere for it in the scripts (grepped it, no joy). So it makes sense that there are several Get() methods that reveal properties of the struct, because there is no other way to discover what the properties of the struct really are.
What I am curious about is whether the properties are logically named or whether they are obfuscated in some way. If the properties are logically named then the dot notation should still work. But if the properties are named with some sort of non public, non-obvious naming convention then it might be impossible to ever get at them without some decompiler magic...
I'll just have to try a few tests and see if I can get at a property. If I can narrow down the naming convention it should be possible.
#4
Posté 09 juin 2013 - 04:51
#5
Posté 09 juin 2013 - 04:56
It's like a bunch of values stored in some array.. .
#6
Posté 09 juin 2013 - 11:34
I'm hazy and haven't worked with this for a while ( ie. it's a headache ) but let's see:
if investigating DAMAGE_RESISTANCE, it's applied w/
EffectDamageResistance(int nDamageType, int nAmount, int nLimit=0
the Type is EFFECT_TYPE_DAMAGE_RESISTANCE
the subType is magical/extraordinary/supernatural
the duration is whatever (permanent/temporary)
then the array (for Damage_Resistance) should hold DAMAGE_TYPE_*, nAmount, nLimit
The headache happens if/when you find yerself hunting through a score of .2da's trying to figure out which one holds the right value ... ( i don't think any of this is documented, but if you come across something for NwN1 it probably holds true for 2 by and large though there are one or two differences )
#7
Posté 09 juin 2013 - 05:40
This is all in regards to trying to refresh spell buffs after a long conversation - something I really want to do in my campaign. I decided to try a different tact and I think it's going to work. It's a bit complicated and requires some array data structures to store information, but so far so good.
#9
Posté 10 juin 2013 - 12:55
But like I said, I think there is a better way to go about it. It's clear to me now that manipulating the countdown isn't going to happen. The properties and methods necessary to properly extend a spell's duration simply aren't exposed through the scripting interface. They are buried too far in the code.
But as Pain mentioned in one of my first threads about this months ago, the way to do it is store the pertinent information about the spell so you can essentially re-cast it on the target. Done right, this works.
This is the route I'm taking now. Being able to use the spell hook is helping a lot to capture the data when the spell is actually cast (who cast it and did they use any metamagic? - those are the two big things). I have a way to store all the data and I have a way to recast the spell. I'm in the middle of testing that aspect of it now to make sure the re-casting is accurate. So far, so good.
The final trick in all of this is determining how you go about re-casting the spells and when. I only want it to happen during conversations - essentially those conversation cut scenes that happen before a boss mob fight. This makes it easier, because it means I only want to re-cast buffs in a specific situation.
So my first choice is an area heartbeat that checks if the PC is in a conversation. If it is, the script cycles through the party members and their effects and rebuffs them every heartbeat tick. This gets a little involved with the logic because a single spell can provide several enhancements, so you don't want to overbuff. I'm working that logic out now.
So far it seems to work. By the time the conversation is over, the characters are still buffed and ready to go.
What I am doing is not a true "refresh" however - because the buffs have been recast like new, the duration for each is going to be the max, as if you'd just cast it. But I'm okay with that, because the boss mobs are going to be instantly casting numerous buffs via my AI as if they had a sequencer at work.
So far, testing is working it out... seems like it's going to work. If it does... it solves a huge issue for me.
#10
Posté 10 juin 2013 - 02:32
but yeah, eventually i intend to get to the sort of things CSL does as part'n'parcel of my stock game .... And, for me, that means dealing with the scripts directly,
( link to previous thread )
#11
Posté 10 juin 2013 - 02:59
I'm giving up on this. I've invested way too much time in something that clearly the game designers just didn't account for.
It irks the heck out of me that they didn't build this into the game by default. Conversations shouldn't cause time to pass and buffs to fade. It's just too annoying for actual gameplay.
#12
Posté 10 juin 2013 - 07:09
Can it run from the EndConversation slot (dialog properties)? Even trigger it from the BossAI....
sure it's colorful (sic) but that can be kinda cool and give the player a needed shot of adreneline.
Modifié par kevL, 10 juin 2013 - 07:12 .
#13
Posté 10 juin 2013 - 01:25
The way I'm doing it now, I'm looping through the effects on the character and getting the Spell ID, then checking to see if the spell has any meta data stored on the creature (it does - because that gets stored from the spell hook code when the spell is actually cast) and then recasting the spell. Problem is - if the spell wears off during the conversation.. the effect is gone. Which is why I was doing it on heartbeat.
What I'd have to do is perform the loop at the start of the conversation and store the Spell ID's then , and then at the end of the conversation do the rebuff.
It's doable. I'm already using an array to store the Spell ID's when I do the looping. I'd only have to do it one time now and it wouldn't require a heartbeat... It would just be tied to the actual conversation, which I kind of like.
Okay. I'll give it a shot.
There's one more issue though: I can't get the companions to fire the spell hook script in the area. I have the X2_L_WILD_MAGIC =1 on the area per the Lilac Soul Tutorial, but so far the script doesn't fire for them. Do you know of anything else I could be missing? The spell hook script fires for the PC.
Modifié par ColorsFade, 10 juin 2013 - 01:25 .
#14
Posté 10 juin 2013 - 02:42
should fire up the spellhook for companions likety split.
..typo?
#15
Posté 10 juin 2013 - 04:09
kevL wrote...
X2_L_WILD_MAGIC = 1 on the area,
should fire up the spellhook for companions likety split.
..typo?
I wish, but I copied and pasted it and checked again.
I know when a paste a variable name in the variable section that sometimes I accidentally end up with a whitespace character on the very end, which makes it not work. But I checked... seems correct.
I'll have to verify this afternoon. Morning real job work has me swamped.
#16
Posté 10 juin 2013 - 05:17
ColorsFade wrote...
The way I'm doing it now, I'm looping through the effects on the character and getting the Spell ID, then checking to see if the spell has any meta data stored on the creature (it does - because that gets stored from the spell hook code when the spell is actually cast) and then recasting the spell. Problem is - if the spell wears off during the conversation.. the effect is gone. Which is why I was doing it on heartbeat.
Don't the ga_clock_off & ga_clock_on scripts work?
#17
Posté 10 juin 2013 - 06:46
rjshae wrote...
Don't the ga_clock_off & ga_clock_on scripts work?
From looking at the code, it looks like all those methods do is turn on/off the GUI - they don't actually affect the internal clock of the game. I'd have to test to verify it.
#18
Posté 10 juin 2013 - 07:52
kevL wrote...
X2_L_WILD_MAGIC = 1 on the area,
should fire up the spellhook for companions likety split.
..typo?
Got it working. I think it was just a quirk of the Toolset - sometimes CTRL-S just doesn't seem to "save" everything.
I just tried the whole thing and it worked. It's not perfect - but really close.
I have two scripts: ga_save_buffs and ga_restore_buffs. I call those at the start and end of the conversation. I use a low level caster to make sure the buffs wear off. And at the end of the conversation it rebuffs my characters completely.
I thought it might bug me having the buffs re-cast like that at the end of the conversation, but it's actually pretty cool. And if you're doing a NWN2 cut-scene conversation (which is when I would use these little scripts) then it's not really noticable anyway.
It's kind of neat. The NPC's are going to insta-buff themsevles anyway. And PC and party are insta-buffed and ready for battle. It's showtime.
Thanks for the assist KevL. This fixes a huge issue.
Oh, but like I said, it's not perfect. The one issue is summons. It doesn't work on summoned creatures - it won't re-cast them. And I think that's because the summoned creature isn't an effect, so when the conversation starts and I cycle through effects on the creature to figure out what spells were cast, there is no effect for the summoned creature, hence it can't be tracked to be re-cast.
But I'm okay with that.
This makes me much happier. And it's pretty easy to manage. A spellhook script and to action scripts for conversations. That's not much maintenance effort at all.
#19
Posté 10 juin 2013 - 09:34
Things like a recently quaffed Haste potion might be nigh impossible; but then, AutomaticFailure on a natural 1 for Will & Reflex saves don't actually fail either.
tallyho! ( I just got a message that 'they' turned off PM's -- then they wished me a nice day, Lol )
#20
Posté 10 juin 2013 - 09:55
What I don't know for certain is the level of the potion before it gets re-cast.
When I "re-buff" the characters, I keep track of whoever initially cast the spell (or in the case of a potion, it tracks whoever used it). The game engine needs that information in the function call and internally it uses the creature to determine spell level.
So, for instance, with the Bless potion, my main PC was the character that used the potion. Thus, my main PC is the object that gets passed when the call is made to ActionCastSpellAtObject() by my rebuff script. When each of the members of my party get rebuffed for Bless, my PC is the object being passed to the function and used as the source of the spell/potion (it seems the scripts don't differentiate).
I'd have to sit down with a timer and watch the potion wear off to be sure. But judging from the scripting, they should be the same thing...
I think I remember reading something about effects from wands/items are set at level 10 though. I'll have to check into it.
Right now this works. I'll probably allow for some kind of global flag to be set if people don't like it and want to turn this behavior off. But for me - this is nice. I really enjoy the cut scenes right before a big boss battle, but I hate having my buffs go away. And this solves it.
A bit more testing and I might have to post the scripts.
#21
Posté 10 juin 2013 - 10:24
anyway, your scripts, you pick the nits
edit: knits
Modifié par kevL, 10 juin 2013 - 10:26 .
#22
Posté 11 juin 2013 - 12:38
kevL wrote...
It struck me as odd because, i thought, potions (& items) don't have valid SpellID's ( or valid Creator-objects ). Am pretty sure 10 is default for potions/wands, although casts from special items have pre-defined Level ( in Iprp_Spells.2da, fwiw )
anyway, your scripts, you pick the nits
It's interesting to dig into this stuff.
I took the Bull's Strength spell script and put it into my Module folder and edited it. All I did was add a SendMessageToPC() call so I could see my local version fire.
Guess what?
Doesn't matter if you cast from a spell or a potion - the same script fires. I got the message both ways.
And hence, the SpellHookScript also fires...
So that got me curious. There's a call in nearly every spell script to GetCasterLevel, which is an internal (blue) function. I decided to check caster levels.
I had my party of me, Elanee, and Z, all at level 5. Elanee casts Bull's Strength and it correctly reports the CasterLevel as lEvel 5.
I then went to use a potion of Bull's Strength. Same script fired, but it reported the CasterLevel as 3. Yet, it considered Elanee (the creature using the spell) as the caster...
So something fishy is happening inside GetCasterLevel. And of course, we'll never be privvy to it.
But that's cool. I now know that buffs from potions, items or spells are going to work with this. They will all be re-cast at the end of the conversation.
#23
Posté 11 juin 2013 - 01:19
[Edit: I think it's the 'Innate' column: http://nwn2.wikia.com/wiki/Spells.2da ]
Modifié par DannJ, 11 juin 2013 - 01:22 .
#24
Posté 11 juin 2013 - 01:21
(edit) It's iprp_spells.2da
Some spells are already in there at different CLs. Greater Heroism, for example, can be set for CL 13, 17, or 20.
Modifié par I_Raps, 11 juin 2013 - 01:24 .
#25
Posté 11 juin 2013 - 01:33





Retour en haut






