Spell disruption by level - possible?
#1
Posté 04 décembre 2013 - 04:52
I'm slowly preparing to create my first module, and one of the things I need to do is to set areas where divine casters can't reach their deities and are thus able to cast only first and second level spells. (bear with on why this might have fun value, the adventure idea is unusual).
Are there functions which can set it so that either all divine casters can only do lvl2 and below, or that would be deity-selective in such areas? I can follow a script (usually, slowly and painstakingly), but am not a good coder myself.
#2
Posté 04 décembre 2013 - 09:20
It's not hard as far as scripting goes but def. painstaking
#3
Posté 04 décembre 2013 - 09:28
OW. It'd be easier to go back and make custom classes instead... thanks, kevL.
#4
Posté 04 décembre 2013 - 10:37
They'd still be able to cast divine spells from scrolls or wands though.
I had quells in Shaar Moan that blocked all divine spells if you got too close to them, but that was via a simple 100% spell failure effect.
Modifié par DannJ, 04 décembre 2013 - 10:42 .
#5
Posté 04 décembre 2013 - 10:44
I'll take a look at how to do the on-enter scripting, then.
#6
Posté 05 décembre 2013 - 03:50
void main()
{
if (GetLastSpellCastClass() == CLASS_TYPE_CLERIC
&& GetSpellLevel(GetSpellId()) > 2)
{
SetLocalInt(OBJECT_SELF, "X2_L_BLOCK_LAST_SPELL", TRUE);
}
}the devil is ofc in the details
#7
Posté 05 décembre 2013 - 04:40
Reducing WIS to12 for a second in an OnClientEnter script would be the quick-and-dirty method - easier to script, but less elegant in its execution.
#8
Posté 05 décembre 2013 - 04:52
:\\
i'm thinking the SpellFailure is the method to go...
edit, it seems they all have their problems:
- spellhooking gets complicated
- wis reduction meta-screws the player
- spellfailure doesn't distinguish level of spell on its own..
Modifié par kevL, 05 décembre 2013 - 04:58 .
#9
Posté 05 décembre 2013 - 02:23
Modifié par Surango, 05 décembre 2013 - 02:30 .
#10
Posté 05 décembre 2013 - 11:11
kevL wrote...
yeh, but i'd get p.o'd having to redo my spells, right?
Spell-hooking doesn't require any modifications to existing spell scripts. It's a separate script that runs before any spell that can stop the spell script from firing. Usually that allows you to run a different script to replace it, but it could also be used to simply stop the spell without a replacement.
The downside to spell-hooking is that the player still goes through the casting animation and plays the FXs, and for spells with projectile animations you still get the travelling and impact effects as well. You just don't get the end result (spellus interuptus). That's because the spell script (and therefore the spell-hooking script) doesn't fire until the spell hits it's target. All the other animations and FX before that point are handled by spells.2da, rather than the spell script itself.
I've used spell-hooking to simulate a wild magic area. I wasn't happy with spell failure via spell-hooking because all the FX kept playing, so I decided to apply 25% spell failure to players in the area. That way one out of every four spells failed completely without any animations or effects, with the remaining 3/4 being split between normal casting, casting with a backlash, and spell warping.
#11
Posté 05 décembre 2013 - 11:24
That's the worst part, and the biggest stumbling block for me to use spell hooking. Is there no better method that can stop everything before it begins?DannJ wrote...
The downside to spell-hooking is that the player still goes through the casting animation and plays the FXs, and for spells with projectile animations you still get the travelling and impact effects as well. You just don't get the end result (spellus interuptus). That's because the spell script (and therefore the spell-hooking script) doesn't fire until the spell hits its target.
#12
Posté 06 décembre 2013 - 12:22
here's what i came up with, btw:
// 'spellhook_test'
// Returns TRUE if the spell cast is a divine spell
int GetIsDivineSpell(int iSpellID);
void main()
{
SendMessageToPC(
GetFirstPC(FALSE),
"run ( spellhook_test ) " + GetName(OBJECT_SELF));
// quick out, allow item usage.
if (GetIsObjectValid(GetSpellCastItem())) return;
string sDeity = GetDeity(OBJECT_SELF);
SendMessageToPC(
GetFirstPC(FALSE),
". deity = " + sDeity);
// quick out, for Deity's favor.
if (sDeity == "ILikeTurtles"
|| sDeity == "DoTheTimeWarp"
|| sDeity == "FunkyChickenChipoteSauce") return;
int iClass = GetLastSpellCastClass();
int bDivineCaster =
(iClass == CLASS_TYPE_CLERIC
|| iClass == CLASS_TYPE_PALADIN
|| iClass == CLASS_TYPE_DRUID
|| iClass == CLASS_TYPE_RANGER);
// quick out, not a Divine caster.
// if (!bDivineCaster) return;
// that needs to be joined with !bDivineSpell below;
// polymorphed characters cast as their 1st class-slot type,
// which might not be a divine caster class.
int iSpellID = GetSpellId();
int bDivineSpell = GetIsDivineSpell(iSpellID);
// early out, not a Divine caster or spell.
if (!bDivineCaster && !bDivineSpell) return;
// note that it's possible for a polomorphed character
// whose 1st class-slot isn't Divine_caster type,
// when casting a Domain spell that's not a Divine spell,
// to get away with it.
// okay, finally, let's do this:
int iSpellLevel = GetSpellLevel(iSpellID);
int iSpellLevelCap = 2;
if (iSpellLevel > iSpellLevelCap)
{
SetLocalInt(OBJECT_SELF, "X2_L_BLOCK_LAST_SPELL", TRUE);
}
}
// based on: The Amethyst Dragon
// - http://social.bioware.com/forum/1/topic/192/index/17004145#17004208
//
// Returns TRUE if the spell cast is a divine spell
// iSpellID = line number of the spell in spells.2da, use GetSpellId()
// Note, this does not return whether a spell is exclusively divine;
// some spells are both Arcane and Divine. This does not distinguish:
int GetIsDivineSpell(int iSpellID)
{
string sClass;
int i;
for (i = 0; i < 4; i++)
{
if (i == 0)
{
// 0th level divine spells:
if (iSpellID == SPELL_CURE_MINOR_WOUNDS
|| iSpellID == SPELL_INFLICT_MINOR_WOUNDS
|| iSpellID == SPELL_LIGHT
|| iSpellID == SPELL_RESISTANCE
|| iSpellID == SPELL_VIRTUE)
{
return TRUE;
}
sClass = "Cleric";
}
else if (i == 1)
{
// 0th level divine spells:
if (iSpellID == SPELL_CURE_MINOR_WOUNDS
|| iSpellID == SPELL_LIGHT
|| iSpellID == SPELL_RESISTANCE
|| iSpellID == SPELL_VIRTUE
|| iSpellID == SPELL_FLARE)
{
return TRUE;
}
sClass = "Druid";
}
else if (i == 2) sClass = "Paladin";
else if (i == 3) sClass = "Ranger";
string sLevel = Get2DAString("spells", sClass, iSpellID);
int iLevel = StringToInt(sLevel);
if (iLevel)
{
return TRUE;
}
}
return FALSE;
}yes, the initial animations play from Spells.2da but i notice that a final sound is omitted, and ofc the "spell applied" icon doesn't appear over the recipient's head. It seems appropriate in this case because the OP isn't talking about absolute spell failure ( no Weave at all active in the area ), it seems to me
#13
Posté 06 décembre 2013 - 03:59
I don't actually understand that script or where to put it, but I'll print the puppy out and start parsing it this weekend until I get what's going on. Thanks!
#14
Posté 06 décembre 2013 - 04:28
Nwn wiki Spellhook <- browse
here's the essentials
- in the module Properties, set a string variable "X2_S_UD_SPELLSCRIPT" with the name of your spellhook script.
- on each **area** properties, set an int variable "X2_L_WILD_MAGIC" to 1, if you want the hook to affect more than just the main PC.
note: on that webpage, to stop a spell from casting, it says to call
SetModuleOverrideSpellScriptFinished();
- it is exactly the same as this (above):
SetLocalInt(OBJECT_SELF, "X2_L_BLOCK_LAST_SPELL", TRUE);
( hope i got that right )
Modifié par kevL, 06 décembre 2013 - 04:31 .
#15
Posté 06 décembre 2013 - 03:19
kevL wrote...
yeh, but i'd get p.o'd having to redo my spells, right?
pre-owned metapreppa rod anyone?
going cheap
just add spell book memory
if it doesnt already exist
Modifié par Morbane, 06 décembre 2013 - 03:20 .
#16
Posté 06 décembre 2013 - 04:54
nop. no spellbook memMorbane wrote...
if it doesnt already exist
#17
Posté 08 décembre 2013 - 09:46
It restores all spells via the rest function, then depricates some of them until their number of castings matches the stored snapshot. The downside is that they get fully healed as well. Although if you've just put your divine casters through hell, that's the least you can do to make it up to them.
#18
Posté 08 décembre 2013 - 11:05
Yeah, if I can get this off the ground (it's probably over-ambitious for a first module and then some), Everybody gets to go through hell.
Haven't really been able to crack the script above yet, we were caught in the big ice storm in TX and only got electricity/heat back yesterday. IF I'm reading that right at a cursory glance and spell use can be left untouched in a given area by deity that would be point-perfect (allowing for "holy places" where they're WAY stronger), but I'm a bit behind the conversation here and THEN some atm.
#19
Posté 09 décembre 2013 - 01:37
interesting.Happycrow wrote...
if ... spell use can be left untouched in a given area by deity
just put a string_var on the area's properties, "DEITY" with the string_value of the favored deity. (don't forget you'll probly also want the "X2_L_WILD_MAGIC" int_var TRUE here also, so more than only the PC is affected by the hook) Then, instead of these lines
string sDeity = GetDeity(OBJECT_SELF);
// quick out, for Deity's favor.
if (sDeity == "ILikeTurtles"
|| sDeity == "DoTheTimeWarp"
|| sDeity == "FunkyChickenChipoteSauce") return;
have these:
string sDeity = GetDeity(OBJECT_SELF); string sDeity_area = GetLocalString(GetArea(OBJECT_SELF), "DEITY"); if (sDeity == sDeity_area) return;
note i removed the smidge of debug code, which you can leave in until things are working well enough.
#20
Posté 10 décembre 2013 - 03:46
Thanks, if I can pull this off it should be pretty darned cool.





Retour en haut







