Aller au contenu

Photo

Can a NPC teach the PC a spell?


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

#1
Barnabas2

Barnabas2
  • Members
  • 65 messages
Hi all,
I try to create a quest. At the end of the quest the PC should get a magical spell from the questgiving NPC during the debriefing as a kind of questreward - is that possible? Of course the PC is a magician, so the PC should be able to use the spell he "learned" from the NPC....

#2
MasterChanger

MasterChanger
  • Members
  • 686 messages
In theory, SetSpellKnown should be able to handle this.

The comments on this function suggest that it's problematic in most applications when used with "Enforce Legal Characters", though this shouldn't be an issue on the single-player side, and probably shouldn't be an issue for Wizard-type progression at all.

#3
MammonTheViscount

MammonTheViscount
  • Members
  • 35 messages
I think what you're looking for is SetSpellKnown, but according to the toolset it's pretty dangerous.



Otherwise if you're looking to add a specific spell as a spell like ability you can set it up in the 2das as a feat and use FeatAdd.

#4
Barnabas2

Barnabas2
  • Members
  • 65 messages
Hmm - can´t find a SetSpellKonown in conversation actions....

#5
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
Give them a scroll.

#6
Barnabas2

Barnabas2
  • Members
  • 65 messages
hmm, good idea, but unfortunally, the scrolls are for one use....

#7
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
This is what i am using, it's a givespell function, where you type in dm_givespell ### and it gives you a spell of that id.

//::////////////////////////////////////////////////////////////////////////:://
//:: Chat Handler Script                                                    :://
//::////////////////////////////////////////////////////////////////////////:://
/*
	This code assumes a player does not have a really complicated builds, and will focus on the first class they took which can actually use the given spell which makes they syntax very easy.
*/
#include "_SCInclude_Chat"
#include "_HkSpell"

void main()
{
	object oDM = CSLGetChatSender();
	object oTarget = CSLGetChatTarget();
	string sParameters = GetStringLowerCase(CSLGetChatParameters());
	if ( !CSLCheckPermissions( oDM, CSL_PERM_DMONLY ) )
	{
		return;
	}
	
	if ( sParameters == "" || sParameters == "help" )
	{
		SendMessageToPC( oDM, "Type in: DM_givespell [999] where [999] is a valid spell id, use DM_ListSpell to get a valid spell id." );
		return;
	}
	
	
	if ( !GetIsObjectValid( oTarget ) )
	{
		SendMessageToPC( oDM, "Select a valid target, via a tell or setting them as your current target." );
		return;
	}
	
	
	string sLevelofSpell, sSpellName, sclassSpellBook, sSpell, sOptions;
	int iSpellLevel, iMaxSpellLevel, iSlotNumber, iclass, iclassLevel, iSpell;
	
	sSpell = CSLNth_GetNthElement( sParameters, 1, " ");
	sOptions = CSLNth_GetNthElement( sParameters, 2, " ");
	
	if ( GetStringLeft(sSpell,1) == "-" )
	{
		sOptions = "Remove";
	}
	//string 
	if ( CSLGetIsNumber( sSpell ) )
	{
		iSpell = StringToInt( sSpell );
	}
	
	sSpellName = CSLGetSpellDataName( iSpell );
	
	if ( sSpellName == "" )
	{
		SendMessageToPC(oDM, "<color=indianred>"+"Please select a valid spell id, that spellid does not correlate to a spell!"+"</color>");
		return;
	}
	
	if ( sOptions == "Remove" && !GetSpellKnown( oTarget, iSpell) )
	{
		SendMessageToPC(oDM, "<color=indianred>"+GetName(oTarget)+" already does not know "+sSpellName+" so it did not have to be removed!"+"</color>");
		return;
	}
	
	
	for (iSlotNumber = 1; iSlotNumber <= 4; iSlotNumber++) 
	{
		iclass = GetclassByPosition( iSlotNumber, oTarget );
		if ( iclass == 255 )
		{
			continue;
		}
		iclassLevel = GetLevelByclass( iclass, oTarget );
		sclassSpellBook = CSLGetSpellBookNameByclass( iclass );
		if ( iclassLevel > 0 && sclassSpellBook != "" )
		{
			string sLevelofSpell = Get2DAString ("spells", sclassSpellBook, iSpell);
			if ( sLevelofSpell != "" ) // make sure spell is available for this class
			{
				iSpellLevel = StringToInt(sLevelofSpell);
				iMaxSpellLevel = HkGetCasterMaxSpellLevel( oTarget, iclass );
				if ( iMaxSpellLevel >= iSpellLevel )
				{
					if ( sOptions == "Remove" )
					{
						SetSpellKnown( oTarget, (iSlotNumber-1), iSpell, FALSE, FALSE );
						SendMessageToPC(oDM, "<color=indianred>"+"Removed spell "+ sSpellName+" from "+GetName(oTarget) + "!"+"</color>");
					}
					else
					{
						SetSpellKnown( oTarget, (iSlotNumber-1), iSpell, TRUE, FALSE );
						SendMessageToPC(oDM, "<color=indianred>"+"Added spell "+ sSpellName+" to "+GetName(oTarget) + "!"+"</color>");
					}
					
					return;
				}
			}
		}
	}
	

	
	
	SendMessageToPC(oDM, "<color=indianred>"+"Failed to add spell "+ sSpellName+" to "+GetName(oTarget) + " as no classes the character has are advanced enough learn it!"+"</color>");
	

}

Modifié par painofdungeoneternal, 30 octobre 2010 - 04:06 .


#8
Barnabas2

Barnabas2
  • Members
  • 65 messages
looks good - thanks, I´l try it.


#9
Shallina

Shallina
  • Members
  • 1 011 messages
You can give a spell in the spell book but you'll probably have to write the script yourself.

But if you did it this way, you'll only be able to give to a caster.

If you want to give a spell to anyone you have to do it like in the OC, you link the spell to a feat and give the feat to players. This can be done with 2DA editing.

Also keep in mind that when you start on a path like this one, and advanced feature, it's going to be difficult to do what you want without writting yourself the scripts you need.

Modifié par Shallina, 30 octobre 2010 - 06:29 .


#10
Morbane

Morbane
  • Members
  • 1 883 messages

painofdungeoneternal wrote...

Give them a scroll.


The idea is that the caster could scribe the scroll into their spellbook?

Or make an item with charges that has the spell you want...

#11
Barnabas2

Barnabas2
  • Members
  • 65 messages

painofdungeoneternal wrote...

This is what i am using, it's a givespell function, where you type in dm_givespell ### and it gives you a spell of that id.

//::////////////////////////////////////////////////////////////////////////:://
//:: Chat Handler Script                                                    :://
//::////////////////////////////////////////////////////////////////////////:://
/*
	This code assumes a player does not have a really complicated builds, and will focus on the first class they took which can actually use the given spell which makes they syntax very easy.
*/
#include "_SCInclude_Chat"
#include "_HkSpell"

void main()
{
	object oDM = CSLGetChatSender();
	object oTarget = CSLGetChatTarget();
	string sParameters = GetStringLowerCase(CSLGetChatParameters());
	if ( !CSLCheckPermissions( oDM, CSL_PERM_DMONLY ) )
	{
		return;
	}
	
	if ( sParameters == "" || sParameters == "help" )
	{
		SendMessageToPC( oDM, "Type in: DM_givespell [999] where [999] is a valid spell id, use DM_ListSpell to get a valid spell id." );
		return;
	}
	
	
	if ( !GetIsObjectValid( oTarget ) )
	{
		SendMessageToPC( oDM, "Select a valid target, via a tell or setting them as your current target." );
		return;
	}
	
	
	string sLevelofSpell, sSpellName, sclassSpellBook, sSpell, sOptions;
	int iSpellLevel, iMaxSpellLevel, iSlotNumber, iclass, iclassLevel, iSpell;
	
	sSpell = CSLNth_GetNthElement( sParameters, 1, " ");
	sOptions = CSLNth_GetNthElement( sParameters, 2, " ");
	
	if ( GetStringLeft(sSpell,1) == "-" )
	{
		sOptions = "Remove";
	}
	//string 
	if ( CSLGetIsNumber( sSpell ) )
	{
		iSpell = StringToInt( sSpell );
	}
	
	sSpellName = CSLGetSpellDataName( iSpell );
	
	if ( sSpellName == "" )
	{
		SendMessageToPC(oDM, ""+"Please select a valid spell id, that spellid does not correlate to a spell!"+"");
		return;
	}
	
	if ( sOptions == "Remove" && !GetSpellKnown( oTarget, iSpell) )
	{
		SendMessageToPC(oDM, ""+GetName(oTarget)+" already does not know "+sSpellName+" so it did not have to be removed!"+"");
		return;
	}
	
	
	for (iSlotNumber = 1; iSlotNumber <= 4; iSlotNumber++) 
	{
		iclass = GetclassByPosition( iSlotNumber, oTarget );
		if ( iclass == 255 )
		{
			continue;
		}
		iclassLevel = GetLevelByclass( iclass, oTarget );
		sclassSpellBook = CSLGetSpellBookNameByclass( iclass );
		if ( iclassLevel > 0 && sclassSpellBook != "" )
		{
			string sLevelofSpell = Get2DAString ("spells", sclassSpellBook, iSpell);
			if ( sLevelofSpell != "" ) // make sure spell is available for this class
			{
				iSpellLevel = StringToInt(sLevelofSpell);
				iMaxSpellLevel = HkGetCasterMaxSpellLevel( oTarget, iclass );
				if ( iMaxSpellLevel >= iSpellLevel )
				{
					if ( sOptions == "Remove" )
					{
						SetSpellKnown( oTarget, (iSlotNumber-1), iSpell, FALSE, FALSE );
						SendMessageToPC(oDM, ""+"Removed spell "+ sSpellName+" from "+GetName(oTarget) + "!"+"");
					}
					else
					{
						SetSpellKnown( oTarget, (iSlotNumber-1), iSpell, TRUE, FALSE );
						SendMessageToPC(oDM, ""+"Added spell "+ sSpellName+" to "+GetName(oTarget) + "!"+"");
					}
					
					return;
				}
			}
		}
	}
	

	
	
	SendMessageToPC(oDM, ""+"Failed to add spell "+ sSpellName+" to "+GetName(oTarget) + " as no classes the character has are advanced enough learn it!"+"");
	

}


Thanks for the script - but I have a stupid question - how am I able to use it? And another stupid question: Am I able to set another character in the toolset? Means: how do I change to default char, when I run the module for testing it via toolset?

#12
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
1. it is an example of what i am using -->

SetSpellKnown( oTarget, (iSlotNumber-1), iSpell, TRUE, FALSE );



iSlotNumber is the class you are adding to for the player, iSpell is the rownumber based on spells.2da and also should match the spell constant.



The way i use it is as a chat command which figures out which class can take the spell and adding it to that class.



Other than that you need to learn some scripting basics really, unless someone wants to volunteer and write the script for you. You can learn how this all works via Scripting for noobs which covers the basics.



2. You don't launch from toolset and run nwn2 separately, as you need to test new things you reload the module by exiting, removes the overall startup time and provides better testing since it's more like end users will deal with things. How you are launching it removes the choices and i think you'd have to delete character except the one you want to test with to make it use the one you want.


#13
_Knightmare_

_Knightmare_
  • Members
  • 643 messages
To set default testing PC:

Characters in your local vault folder get listed there in alphabetical order by file name. When you run the module from the toolset, the game chooses and loads the first character in that list. Go find the PC you want to use in that folder and rename the file to something so its "lowest" alphabetically (ex. "aaaaaaaa_my_test_pc"). Changing this file name will not change the name of your character in game. However, follow pain's advice above as its right on.

Modifié par _Knightmare_, 05 novembre 2010 - 09:16 .