Aller au contenu

Photo

Song of Freedom?! - I got your Song of Freedom right here.


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

#1
I_Raps

I_Raps
  • Members
  • 1 262 messages
Here is something I've wanted for a long, long time - a Song of Freedom that actually works.  Well, it does something - "works" may be a bit overstated.  Someone was working on something similar on the old forum but never got his final version posted.


//:://////////////////////////////////////////////////////////////////////////
//:: Bard Song: Song of Freedom
//:: nw_s2_sngfreedm.nss
//:: Created By: Brock Heinz - OEI
//:: Created On: 09/06/05
//:: Copyright © 2005 Obsidian Entertainment Inc.
//:://////////////////////////////////////////////////////////////////////////
/*
Song of Freedom (Req: 12th level, Perform 15):
At 12th level a bard gains this ability which allows them to do the
equivalent of a Break Enchantment spell, with the caster level being
equal to the bard's spell level.
 
Break Enchantment
Abjuration
Level: Brd 4, Clr 5, Luck 5, Pal 4, Sor/Wiz 5
Components: V, S
Casting Time: 1 minute
Range: Close (25 ft. + 5 ft./2 levels)
Targets: Up to one creature per level, all within 30 ft. of each other
Duration: Instantaneous
Saving Throw: See text
Spell Resistance: No
This spell frees victims from enchantments, transmutations, and curses.
Break enchantment can reverse even an instantaneous effect. For each
such effect, you make a caster level check (1d20 + caster level,
maximum +15) against a DC of 11 + caster level of the effect. Success
means that the creature is free of the spell, curse, or effect. For a
cursed magic item, the DC is 25.
If the spell is one that cannot be dispelled by dispel magic, break
enchantment works only if that spell is 5th level or lower.
If the effect comes from some permanent magic item break enchantment
does not remove the curse from the item, but it does frees the victim
from the items effects.
*/
//:://////////////////////////////////////////////////////////////////////////
//:: PKM-OEI 07.13.06 VFX Pass
//:: AFW-OEI 07/14/2006: Check to see if you have bardsong feats left; if you do, execute
//:: script and decrement a bardsong use.
//:: PKM-OEI 07.20.06 Added Perform skill check
 
#include "x0_i0_spells"
#include "nwn2_inc_spells"
 
void main()
{
if ( GetHasEffect(EFFECT_TYPE_SILENCE, OBJECT_SELF) )
{
FloatingTextStrRefOnCreature(85764,OBJECT_SELF); // not useable when silenced
return;
}
 
// if(!AttemptNewSong(OBJECT_SELF))
// {
// return; // Failed
// }
 
if (!GetHasFeat(FEAT_BARD_SONGS, OBJECT_SELF))
{
FloatingTextStrRefOnCreature(STR_REF_FEEDBACK_NO_MORE_BARDSONG_ATTEMPTS,OBJECT_SELF); // no more bardsong uses left
return;
}

int nPerform = GetSkillRank(SKILL_PERFORM);

if (nPerform < 15 ) //Checks your perform skill so nubs can't use this song
{
FloatingTextStrRefOnCreature ( 182800, OBJECT_SELF );
return;
}
//Declare major variables
string sTag = GetTag(OBJECT_SELF);
int nLevel = GetLevelByclass(class_TYPE_BARD);
int nRanks = GetSkillRank(SKILL_PERFORM);
int nChr = GetAbilityModifier(ABILITY_CHARISMA);
location lTarget = GetSpellTargetLocation();

 
effect eBreakOther = EffectBreakEnchantment( nLevel );
effect eVisOther = EffectVisualEffect( VFX_HIT_BARD_SONG_FREEDOM );
effect eLinkOther = EffectLinkEffects( eVisOther, eBreakOther );
//effect eBreakBard = EffectBreakEnchantment( nLevel );
//effect eVisBard = EffectVisualEffect( VFX_DUR_SPELL_GREATER_SPELL_BREACH );
//effect eLinkBard = EffectLinkEffects( eVisBard, eBreakBard );

eLinkOther = ExtraordinaryEffect(eLinkOther);
//eLinkBard = ExtraordinaryEffect(eLinkBard);
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lTarget);
 
while(GetIsObjectValid(oTarget))
{
if(!GetHasFeatEffect(FEAT_BARD_SONGS, oTarget) && !GetHasSpellEffect(GetSpellId(),oTarget))
{
// * GZ Oct 2003: If we are silenced, we can not benefit from bard song
if (!GetHasEffect(EFFECT_TYPE_SILENCE,oTarget) && !GetHasEffect(EFFECT_TYPE_DEAF,oTarget))
{
if(oTarget == OBJECT_SELF)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eLinkOther, oTarget);
effect eBad = GetFirstEffect(oTarget);
object oCasterBad = GetEffectCreator(eBad);
int iLevelBad = GetCasterLevel(oCasterBad);
int iRoll = nLevel + d20(1) - 11;

//Search for negative effects
while(GetIsEffectValid(eBad))
{
if ((
GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||
GetEffectType(eBad) == EFFECT_TYPE_DEAF ||
GetEffectType(eBad) == EFFECT_TYPE_CURSE ||
GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
GetEffectType(eBad) == EFFECT_TYPE_CHARMED ||
GetEffectType(eBad) == EFFECT_TYPE_DOMINATED ||
GetEffectType(eBad) == EFFECT_TYPE_DAZED ||
GetEffectType(eBad) == EFFECT_TYPE_CONFUSED ||
GetEffectType(eBad) == EFFECT_TYPE_FRIGHTENED ||
GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
GetEffectType(eBad) == EFFECT_TYPE_SLOW ||
GetEffectType(eBad) == EFFECT_TYPE_STUNNED ||
GetEffectType(eBad) == EFFECT_TYPE_INSANE ||
GetEffectType(eBad) == EFFECT_TYPE_MESMERIZE ||
GetEffectType(eBad) == EFFECT_TYPE_PETRIFY ||
GetEffectType(eBad) == EFFECT_TYPE_POLYMORPH ||
GetEffectType(eBad) == EFFECT_TYPE_SLEEP ||
GetEffectType(eBad) == EFFECT_TYPE_ENTANGLE)
&& iRoll > (iLevelBad - 1))
{
RemoveEffect(oTarget, eBad);
eBad = GetFirstEffect(oTarget);
}
else
eBad = GetNextEffect(oTarget);
}
}
else if(spellsIsTarget( oTarget, SPELL_TARGET_ALLALLIES, OBJECT_SELF))
{
float fDist = GetDistanceBetween( OBJECT_SELF, oTarget );
float fDelay = fDist * 0.15;
DelayCommand( fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eLinkOther, oTarget) );
effect eBad = GetFirstEffect(oTarget);
object oCasterBad = GetEffectCreator(eBad);
int iLevelBad = GetCasterLevel(oCasterBad);
int iRoll = nLevel + d20(1) - 11;

//Search for negative effects
while(GetIsEffectValid(eBad))
{
if ((
GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||
GetEffectType(eBad) == EFFECT_TYPE_DEAF ||
GetEffectType(eBad) == EFFECT_TYPE_CURSE ||
GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
GetEffectType(eBad) == EFFECT_TYPE_CHARMED ||
GetEffectType(eBad) == EFFECT_TYPE_DOMINATED ||
GetEffectType(eBad) == EFFECT_TYPE_DAZED ||
GetEffectType(eBad) == EFFECT_TYPE_CONFUSED ||
GetEffectType(eBad) == EFFECT_TYPE_FRIGHTENED ||
GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
GetEffectType(eBad) == EFFECT_TYPE_SLOW ||
GetEffectType(eBad) == EFFECT_TYPE_STUNNED ||
GetEffectType(eBad) == EFFECT_TYPE_INSANE ||
GetEffectType(eBad) == EFFECT_TYPE_MESMERIZE ||
GetEffectType(eBad) == EFFECT_TYPE_PETRIFY ||
GetEffectType(eBad) == EFFECT_TYPE_POLYMORPH ||
GetEffectType(eBad) == EFFECT_TYPE_SLEEP ||
GetEffectType(eBad) == EFFECT_TYPE_ENTANGLE)
&& iRoll > (iLevelBad - 1))
{
RemoveEffect(oTarget, eBad);
eBad = GetFirstEffect(oTarget);
}
else
eBad = GetNextEffect(oTarget);
}
}
}
}
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lTarget);
}

DecrementRemainingFeatUses(OBJECT_SELF, FEAT_BARD_SONGS);
}


The problem is in the die rolling:  int iRoll = nLevel + d20(1) - 11;

This doesn't seem to do anything.  With a caster of the bad effect (Stinking Cloud in my trial) and the singing bard of the same level, SOF should work just over 50% of the time.  In practice, it's about 100% (the only time it didn't work, there was a bit of an off/on flash of the status icon that leads me to believe the rogue was restored and immediately failed a die roll and succombed again).

Any insight would be appreciated.

p.s.  While Greater Restoration cannot remove a Sea Hag's Evil Eye, this SOF scoffs at such limitations.  All you evil Sea Hags out there - 'ware the bard!

Modifié par I_Raps, 22 mars 2012 - 06:51 .


#2
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Have you tried my version, i seem to remember working on this a long long time ago.

Your code there seems like it has the level of the check after it checks for all the effect types, which is wasting a lot of resources. Should put that in the outside of the loop as it's own if and check effects only if it does teh simple dc check. Probably make it more like the DC is supposed to be instead of doing it via algebra up front. That way you can echo out the roll to the player.

The caster level of the given effect is probably wrong to begin with, this is something i created the CSL library to fix.

Need to look at the code for restoration as done by kaedrin and many others for the negative effects "if then" there - really should almost use the same code. ( ie should not make it affect iron body spells for example )

Modifié par painofdungeoneternal, 22 mars 2012 - 07:53 .


#3
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
This is my version, no idea how helpful this is as i used quite a few custom systems here.

The spell break enchantment is used to create the effects and do the proper dc rolls. I have largely redone dispels using a lot of ideas from folks in NWN1 who did something similar.

Largely how this is implemented is in this reference which is my code for all abjuration like dispels.

This is the function that pulls in the proper effects on the target
when the category is ENCHANTMENTEFFECTS ( 2 ).
//:://////////////////////////////////////////////////////////////////////////
//:: Bard Song: Song of Freedom
//:: nw_s2_sngfreedm.nss
//:: Created By: Brock Heinz - OEI
//:: Created On: 09/06/05
//:: Copyright (c) 2005 Obsidian Entertainment Inc.
//:://////////////////////////////////////////////////////////////////////////
/*
	Song of Freedom (Req: 12th level, Perform 15):
	At 12th level a bard gains this ability which allows them to do the
	equivalent of a Break Enchantment spell, with the caster level being
	equal to the bard's spell level.

A bard of 12th level or higher with 15 or more ranks in a Perform skill can
use music or poetics to create an effect equivalent to the break
enchantment spell (caster level equals the character’s bard level). Using
this ability requires 1 minute of uninterrupted concentration and music,
and it functions on a single target within 30 feet. A bard can’t use song
of freedom on himself.


		Break Enchantment
		Abjuration
		Level:   Brd 4, Clr 5, Luck 5, Pal 4, Sor/Wiz 5
		Components:     V, S
		Casting Time:      1 minute
		Range:            Close (25 ft. + 5 ft./2 levels)
		Targets:        Up to one creature per level, all within 30 ft. of each other
		Duration:         Instantaneous
		Saving Throw:      See text
		Spell Resistance:  No

		This spell frees victims from enchantments, transmutations, and curses.
		Break enchantment can reverse even an instantaneous effect. For each
		such effect, you make a caster level check (1d20 + caster level,
		maximum +15) against a DC of 11 + caster level of the effect. Success
		means that the creature is free of the spell, curse, or effect. For a
		cursed magic item, the DC is 25.

		If the spell is one that cannot be dispelled by dispel magic, break
		enchantment works only if that spell is 5th level or lower.

		If the effect comes from some permanent magic item break enchantment
		does not remove the curse from the item, but it does frees the victim
		from the items effects.

*/

/////////////////////////////////////////////////////
//////////////// Includes //////////////////////////
////////////////////////////////////////////////////
#include "_HkSpell"
#include "_SCInclude_Songs"
#include "_SCInclude_class"
#include "_SCInclude_Abjuration"





void main()
{
	//scSpellMetaData = SCMeta_SG_songfree();
	//if (!X2PreSpellCastCode()) { return; }  // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
	//--------------------------------------------------------------------------
	//Prep the spell
	//--------------------------------------------------------------------------
	object oCaster = OBJECT_SELF;
	int iSpellId = HkGetSpellId();
	int iclass = class_TYPE_NONE;
	int iSpellLevel = HkGetSpellLevel( iSpellId, iclass );
	int iImpactSEF = VFX_DUR_BARD_SONG;
	int iAttributes = SCMETA_ATTRIBUTES_MAGICAL | SCMETA_ATTRIBUTES_VOCALCOMP | SCMETA_ATTRIBUTES_BUFF | SCMETA_ATTRIBUTES_TURNABLE;
	//--------------------------------------------------------------------------
	//Run Precast Code
	//--------------------------------------------------------------------------
	if (!HkPreCastHook( oCaster, iSpellId, SCMETA_DESCRIPTOR_NONE, iclass, iSpellLevel, SPELL_SCHOOL_GENERAL, SPELL_SUBSCHOOL_NONE, iAttributes ) )
	{
		return;
	}

	//--------------------------------------------------------------------------
	//Declare major variables
	//--------------------------------------------------------------------------
	
	float fRadius = HkApplySizeMods(RADIUS_SIZE_MEDIUM);
	
	if (!SCGetCanBardSing(oCaster)) return; // Awww :(
	if (!GetHasFeat(FEAT_BARD_SONGS, oCaster)) {
		FloatingTextStrRefOnCreature(SCSTR_REF_FEEDBACK_NO_MORE_BARDSONG_ATTEMPTS, oCaster); // no more bardsong uses left
		return;
	}
	if (GetSkillRank(SKILL_PERFORM)<15) { //Checks your perform skill so nubs can't use this song
		FloatingTextStrRefOnCreature (182800, oCaster);
		return;
	}

	DecrementRemainingFeatUses(oCaster, FEAT_BARD_SONGS);

	//int iLevel = GetLevelByclass(class_TYPE_BARD);
	int iLevel = GetBardicclassLevelForUses(oCaster);
	
		
	//--------------------------------------------------------------------------
	//Apply effects
	//--------------------------------------------------------------------------
	location lImpactLoc = HkGetSpellTargetLocation(); // GetLocation( oCreator );
	object oTarget = HkGetSpellTarget();
	effect eImpactVis = EffectVisualEffect( iImpactSEF );
	ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpactVis, lImpactLoc);
	
	location lLocal = HkGetSpellTargetLocation();
	float fDelay;
	int nStripCnt = SCGetDispellCount(iSpellId, FALSE);
	if (  GetIsObjectValid(oTarget)  )
	{
		fDelay = 0.15 * GetDistanceBetween(oCaster, oTarget);
		DelayCommand( fDelay, SCDispelTarget(oTarget, oCaster, nStripCnt, SPELL_BREAK_ENCHANTMENT) );
		nStripCnt--;
	}
	else
	{
		oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, lImpactLoc, FALSE, OBJECT_TYPE_CREATURE );
		while (GetIsObjectValid(oTarget) && nStripCnt > 0)
		{
			if (SCGetIsObjectValidSongTarget(oTarget))
			{
				if (oTarget != oCaster && CSLSpellsIsTarget( oTarget, SCSPELL_TARGET_ALLALLIES, oCaster) )
				{
					fDelay = 0.15 * GetDistanceBetween(oCaster, oTarget);
					DelayCommand( fDelay, SCDispelTarget(oTarget, oCaster, nStripCnt, SPELL_BREAK_ENCHANTMENT) );
					nStripCnt--;
					
				}
			}
			oTarget = GetNextObjectInShape(SHAPE_SPHERE, fRadius, lImpactLoc, FALSE, OBJECT_TYPE_CREATURE );
		}
	}	
		

	
	HkPostCast(oCaster);
}


#4
I_Raps

I_Raps
  • Members
  • 1 262 messages

painofdungeoneternal wrote...

Need to look at the code for restoration as done by kaedrin and many others for the negative effects "if then" there - really should almost use the same code. ( ie should not make it affect iron body spells for example )


I used the Restoration spells as the basis for this.  After revising their list of bad effects, none of their exclusions mattered any more - except  the Slow effect from stone/iron body.  I decided to go ahead and remove that effect because Freedom of Movement - a spell that is available well before this Song - immunizes against that Slowness;  besides, Dorothy was able to get the Tin Man to dance, after all.

painofdungeoneternal wrote...

Your code there seems like it has the level of the check after it checks for all the effect types, which is wasting a lot of resources. Should put that in the outside of the loop as it's own if and check effects only if it does teh simple dc check. Probably make it more like the DC is supposed to be instead of doing it via algebra up front. That way you can echo out the roll to the player.


That form for the level check is the result of a hunt for a stray bracket.  Once the thing is working, I could tidy it up ... except that I think everything is about to change.

painofdungeoneternal wrote...

The caster level of the given effect is probably wrong to begin with, this is something i created the CSL library to fix.


This is the crux of the matter, I think.

Looking at that CSL function, I will have to do a lot more groundwork before approaching that.  In the meantime, I think I'll just assign each eBad a constant DC.

Modifié par I_Raps, 23 mars 2012 - 06:45 .