Aller au contenu

Photo

How to grant a companion an extra Feat?


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

#1
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

How does one go about granting an extra Feat? Not a specific Feat mind you; I know that can be done via scripting. 

 

I'm more curious to know if, on level up, you can grant a character a bonus Feat, that the player could then choose any from the available list for that character's race/class?



#2
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

Does this have to trigger from every level up? Or only once? Or only on specific intervals?

And does this have to apply to everyone who has levels in that class or only to specific individuals?


  • ColorsFade aime ceci

#3
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

Does this have to trigger from every level up? Or only once? Or only on specific intervals?

And does this have to apply to everyone who has levels in that class or only to specific individuals?

 

I'm only interested in doing this to a very specific companion, and only on certain level ups (like-4th level, 8th-level, etc.). 

 

Adding a specific Feat is really easy; there's a script and function call just for that. But I just want to give a certain companion an extra feat opportunity in a couple instances. 

 

I can go the specific feat route, but I'd rather the player have a bit more control over what gets selected. 



#4
kevL

kevL
  • Members
  • 4 052 messages
offhand, two ideas occur to me. Create a custom class.

okay, the second ... popup a Gui with selection btns. Am not sure where to hook that


Either method strikes me as more time-consuming than it might be worth, unless a fella gets into that sorta thing.
  • ColorsFade aime ceci

#5
kamal_

kamal_
  • Members
  • 5 238 messages
Custom class: since it would be a stock class with extra feats, not really that hard because it's mostly copying lines in 2das. Would interfere with custom class packs unless you make the 2das compatible with or include them, if that concerns you.

Altering the regular class to grant extra feats at given level: pretty easy, but all characters with that class are affected.

Custom module level up script: possible, MotB uses this with Okku to remove feats (armor / weapon proficiency in Okku's case. You could definitely add specific feats this way, and maybe can add the player choosing the feats (launch the feat selecting gui or something?).

When I had a question about removing feats ala Okku, people directed me to that last option.

#6
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

I can see what the problem with a custom class could be though. Even though this is a companion, he/she may be intended to access all regular classes and gain access to bonus feats based solely on those.

With a custom class you either give access to all feats (as bonus) or you only give a specific set to them, but it cannot dinamically change based on what other classes he picked.

 

That said, I had done something similar a few years ago, the problem is, the code was so long and complex that right now I would not even know where to begin to take a look to modify it to suit your need. Still, if you feel you have the patience to toy around with it follow the instructions below (to be continued *dramatic music*)



#7
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

This one is used to call the UI, make a new feat, associate it to a new spell, and use this as impact script.

 

Script "gui_clangeddin_bonusfeats_1"

void main()
{
	object oPC = GetControlledCharacter(OBJECT_SELF);
	
	// Only PCs and Henchmen are allowed to select feats
	
	if ((GetAssociateType(oPC) == ASSOCIATE_TYPE_FAMILIAR)||
		(GetAssociateType(oPC) == ASSOCIATE_TYPE_DOMINATED)||
		(GetAssociateType(oPC) == ASSOCIATE_TYPE_ANIMALCOMPANION)||
		(GetAssociateType(oPC) == ASSOCIATE_TYPE_SUMMONED))
	{
		FloatingTextStringOnCreature("Only non-dominated PCs and Henchmen are allowed to select bonus feats.", oPC, FALSE);
		return;
	}
	
	DisplayGuiScreen(oPC, "SCREEN_BONUS_FEATS", TRUE, "clangeddin_bonusfeats.xml");
}


#8
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

"gui_clangeddin_bonusfeats_2"

//:://////////////////////////////////////////////
//:: Created By: Clangeddin 
//:: Created On: 2015
//:://////////////////////////////////////////////

void main(string sPAGE, string sCATEGORY)
{
	object oPC = GetControlledCharacter(OBJECT_SELF);
	int N = 1;
	while (N < 9)
	{
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "FEAT_BUTTON_" + IntToString(N), TRUE);
		N = N + 1;
	}
	
	int nPAGE = StringToInt(sPAGE);
	int nTOTAL = GetTotalLevels(oPC, FALSE);
	int nUSED = GetLocalInt(oPC, "CLANGEDDIN_BONUS_FEATS");
	int nROWS = GetNum2DARows("feat");
	int nFEATS = nTOTAL - nUSED;
	if (sCATEGORY == "NOTHING")
	{
		SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "GENERAL_TEXT", -1, "Select a category.");
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_PREVIOUS", TRUE);
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_NEXT", TRUE);
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_CONFIRM", TRUE);
		return;
	}
	
	SetLocalGUIVariable(oPC, "SCREEN_BONUS_FEATS", 20, sCATEGORY);
	
	if (nPAGE == 1)
	{
		SetLocalGUIVariable(oPC, "SCREEN_BONUS_FEATS", 1, sPAGE);
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_PREVIOUS", TRUE);
	}
	else
	{
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_PREVIOUS", FALSE);
	}
	
	SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_NEXT", FALSE);
	SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_CONFIRM", TRUE);
	SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "GENERAL_TEXT", -1, "You may select up to " + IntToString(nFEATS) + " bonus feats.");
	
	string sICON;
	
	int ID;
	int nTEXT;
	int nDESCRIPTION;
	string sCHECK_REMOVED;
	string sCHECK_ALL;
	string sCHECK_CATEGORY;
	
	N = 1;
	if (nPAGE > 1)
	{
		while (N <= 8*(nPAGE-1))
		{
			sCHECK_REMOVED = Get2DAString("feat", "REMOVED", ID);
			sCHECK_ALL = Get2DAString("feat", "ALLCLASSESCANUSE", ID);
			sCHECK_CATEGORY = Get2DAString("feat", "FeatCategory", ID);
			if ((sCHECK_REMOVED!="1")&&(sCHECK_ALL=="0")&&(sCHECK_CATEGORY==sCATEGORY))
			{
				N = N + 1;
			}
			ID = ID + 1;
		}
		N = 1;
	}
	
	while (N < 9)
	{
		
		sCHECK_REMOVED = Get2DAString("feat", "REMOVED", ID);
		sCHECK_ALL = Get2DAString("feat", "ALLCLASSESCANUSE", ID);
		sCHECK_CATEGORY = Get2DAString("feat", "FeatCategory", ID);
		if ((sCHECK_REMOVED!="1")&&(sCHECK_ALL=="0")&&(sCHECK_CATEGORY==sCATEGORY))
		{
			SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "FEAT_BUTTON_" + IntToString(N), FALSE);
			sICON = Get2DAString("feat", "ICON", ID);
			nTEXT = StringToInt(Get2DAString("feat", "FEAT", ID));
			SetGUITexture(oPC, "SCREEN_BONUS_FEATS", "FEAT_ICON_" + IntToString(N), sICON + ".tga" );
			SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "FEAT_NAME_" + IntToString(N), nTEXT, "");
			SetLocalGUIVariable(oPC, "SCREEN_BONUS_FEATS", 2 + N, IntToString(ID));
			N = N + 1;
		}
		else if (ID > nROWS)
		{
			SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_NEXT", TRUE);
			N = N + 1;
		}
		ID = ID + 1;
	}
}


#9
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

Script "gui_clangeddin_bonusfeats_3"

//:://////////////////////////////////////////////
//:: Created By: Clangeddin 
//:: Created On: 2015
//:://////////////////////////////////////////////

void main(string sCOMMAND, string sPAGE, string sCATEGORY)
{
	object oPC = GetControlledCharacter(OBJECT_SELF);
	int nPAGE = StringToInt(sPAGE);
	if (sCOMMAND == "NEXT")
	{
		nPAGE = nPAGE + 1;
	}
	else if (sCOMMAND == "PREVIOUS")
	{
		nPAGE = nPAGE - 1;
	}
	else
	{
		return;
	}
	SetLocalGUIVariable(oPC, "SCREEN_BONUS_FEATS", 1, IntToString(nPAGE));
	sPAGE = IntToString(nPAGE);
	AddScriptParameterString(sPAGE);
	AddScriptParameterString(sCATEGORY);
	ExecuteScriptEnhanced("gui_clangeddin_bonusfeats_2", oPC);
}


#10
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

Script "gui_clangeddin_bonusfeats_5"

//:://////////////////////////////////////////////
//:: Created By: Clangeddin 
//:: Created On: 2015
//:://////////////////////////////////////////////

int CheckRequirement(object oCHAR, int nID)
{
	int nAB = StringToInt(Get2DAString("feat", "MINATTACKBONUS", nID));
	int nSTR = StringToInt(Get2DAString("feat", "MINSTR", nID));
	int nDEX = StringToInt(Get2DAString("feat", "MINDEX", nID));
	int nCON = StringToInt(Get2DAString("feat", "MINCON", nID));
	int nINT = StringToInt(Get2DAString("feat", "MININT", nID));
	int nWIS = StringToInt(Get2DAString("feat", "MINWIS", nID));
	int nCHA = StringToInt(Get2DAString("feat", "MINCHA", nID));
	int nFT1 = StringToInt(Get2DAString("feat", "PREREQFEAT1", nID));
	int nFT2 = StringToInt(Get2DAString("feat", "PREREQFEAT2", nID));
	int nSK1 = StringToInt(Get2DAString("feat", "REQSKILL", nID));
	int nSR1 = StringToInt(Get2DAString("feat", "ReqSkillMinRanks", nID));
	int nSK2 = StringToInt(Get2DAString("feat", "REQSKILL2", nID));
	int nSR2 = StringToInt(Get2DAString("feat", "ReqSkillMinRanks2", nID));
	int nEPIC = StringToInt(Get2DAString("feat", "PreReqEpic", nID));
	
	if (GetBaseAttackBonus(oCHAR) < nAB)
	{
		return FALSE;
	}
	
	if ((GetAbilityScore(oCHAR, ABILITY_STRENGTH, TRUE) < nSTR)||
		(GetAbilityScore(oCHAR, ABILITY_DEXTERITY, TRUE) < nDEX)||
		(GetAbilityScore(oCHAR, ABILITY_CONSTITUTION, TRUE) < nCON)||
		(GetAbilityScore(oCHAR, ABILITY_INTELLIGENCE, TRUE) < nINT)||
		(GetAbilityScore(oCHAR, ABILITY_WISDOM, TRUE) < nWIS)||
		(GetAbilityScore(oCHAR, ABILITY_CHARISMA, TRUE) < nCHA))
	{
		return FALSE;
	}
	
	if (((nFT1 > 0)&&(GetHasFeat(nFT1, oCHAR, TRUE) == FALSE))||
		((nFT2 > 0)&&(GetHasFeat(nFT2, oCHAR, TRUE) == FALSE))||
		((nSR1 > 0)&&(GetSkillRank(nSK1, oCHAR, TRUE) < nSR1))||
		((nSR2 > 0)&&(GetSkillRank(nSK2, oCHAR, TRUE) < nSR2))||
		((nEPIC == 1)&&(GetTotalLevels(oCHAR, FALSE) < 21)))
	{
		return FALSE;
	}
	
	
	return TRUE;
}

void main(string sFEAT)
{
	object oPC = GetControlledCharacter(OBJECT_SELF);
	int nTOTAL = GetTotalLevels(oPC, FALSE);
	int nUSED = GetLocalInt(oPC, "CLANGEDDIN_BONUS_FEATS");
	int nFEAT = StringToInt(sFEAT);
	int nDESCRIPTION = StringToInt(Get2DAString("feat", "DESCRIPTION", nFEAT));
	
	SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_CONFIRM", TRUE);
	SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "FEAT_DESCRIPTION", nDESCRIPTION, "");
	SetLocalGUIVariable(oPC, "SCREEN_BONUS_FEATS", 2, IntToString(nFEAT));
	if (GetHasFeat(nFEAT, oPC, TRUE) == TRUE)
	{
		SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "WARNING_TEXT", -1, "You already have this feat.");
	}
	else if (nTOTAL - nUSED <= 0)
	{
		SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "WARNING_TEXT", -1, "You ran out of bonus feats.");
	}
	else if (CheckRequirement(oPC, nFEAT) == TRUE)
	{
		SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "WARNING_TEXT", -1, "");
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_CONFIRM", FALSE);
	}
	else
	{
		SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "WARNING_TEXT", -1, "You don't meet the prerequisites for this feat.");
	}
	
}


#11
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

Script "gui_clangeddin_bonusfeats_5"

//:://////////////////////////////////////////////
//:: Created By: Clangeddin 
//:: Created On: 2015
//:://////////////////////////////////////////////

void main(string sFEAT)
{
	object oPC = GetControlledCharacter(OBJECT_SELF);
	int nFEAT = StringToInt(sFEAT);
	int nTOTAL = GetTotalLevels(oPC, FALSE);
	int nUSED = GetLocalInt(oPC, "CLANGEDDIN_BONUS_FEATS");
	int nADDED = FeatAdd(oPC, nFEAT, FALSE, TRUE);
	if (nADDED == TRUE)
	{
		SetLocalInt(oPC, "CLANGEDDIN_BONUS_FEATS", nUSED + 1);
		SetLocalInt(oPC, "CLANGEDDIN_HB_FEATID_" + IntToString(nUSED), nFEAT);
		SetGUIObjectText(oPC, "SCREEN_BONUS_FEATS", "GENERAL_TEXT", -1, "You may select up to " + IntToString(nTOTAL - nUSED - 1) + " bonus feats.");
		SetGUIObjectHidden(oPC, "SCREEN_BONUS_FEATS", "BUTTON_CONFIRM", TRUE);
	}
}


#12
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

And finally, the xml of the UI itself

 

"clangeddin_bonusfeats.xml"

<?xml version="1.0" encoding="NWN2UI">

<UIScene name="SCREEN_BONUS_FEATS" x=ALIGN_CENTER y=ALIGN_CENTER width=600 height=440 scriptloadable="true" idleexpiretime=0.1
	OnAdd=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","NOTHING")	/>

	<!-- Frames -->
	<UIIcon  x=0 y=0 width=1 height=PARENT_HEIGHT img="fx_white.tga" />
	<UIIcon  x=299 y=80 width=1 height=360 img="fx_white.tga" />
	<UIIcon  x=599 y=0 width=1 height=PARENT_HEIGHT img="fx_white.tga" />
	<UIIcon  x=0 y=0 width=PARENT_WIDTH height=1 img="fx_white.tga" />
	<UIIcon  x=0 y=40 width=PARENT_WIDTH height=1 img="fx_white.tga" />
	<UIIcon  x=0 y=80 width=PARENT_WIDTH height=1 img="fx_white.tga" />
	<UIIcon  x=0 y=400 width=PARENT_WIDTH height=1 img="fx_white.tga" />
	<UIIcon  x=0 y=399 width=PARENT_WIDTH height=1 img="fx_white.tga" />
	
	<!-- Close Button -->
	<UIButton name="CloseButton" x=ALIGN_RIGHT y=ALIGN_TOP style="STYLE_CLOSE_BUTTON" 
		OnLeftClick=UIButton_Input_ScreenClose()>
	</UIButton>

	<!-- General Text -->
	<UIText name="GENERAL_TEXT" x=0 y=0 width=PARENT_WIDTH height=40 align=center valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
	
	<!-- Categories -->
	<UIButton text="General" x=35 y=45 width=80 style="STYLE_SMALL_TAB" groupid=1 groupmemberid=1
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","GENERAL_FT_CAT") >
	</UIButton>
	
	<UIButton text="Skills" x=125 y=45 width=80 style="STYLE_SMALL_TAB" groupid=1 groupmemberid=2
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","SKILLNSAVE_FT_CAT") >
	</UIButton>
	
	<UIButton text="Spells" x=215 y=45 width=80 style="STYLE_SMALL_TAB" groupid=1 groupmemberid=3
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","SPELLCASTING_FT_CAT") >
	</UIButton>
	
	<UIButton text="Meta" x=305 y=45 width=80 style="STYLE_SMALL_TAB" groupid=1 groupmemberid=4
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","METAMAGIC_FT_CAT") >
	</UIButton>
	
	<UIButton text="Divine" x=395 y=45 width=80 style="STYLE_SMALL_TAB" groupid=1 groupmemberid=5
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","DIVINE_FT_CAT") >
	</UIButton>
	
	<UIButton text="Epic" x=485 y=45 width=80 style="STYLE_SMALL_TAB" groupid=1 groupmemberid=6
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_2","1","EPIC_FT_CAT") >
	</UIButton>
	
	<!-- Feat Buttons -->

	<UIPane name="FEAT_BUTTON_1" x=0 y=80 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_1" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_1" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=1
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:3)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_2" x=0 y=120 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_2" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_2" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=2
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:4)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_3" x=0 y=160 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_3" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_3" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=3
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:5)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_4" x=0 y=200 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_4" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_4" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=4
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:6)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_5" x=0 y=240 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_5" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_5" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=5
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:7)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_6" x=0 y=280 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_6" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_6" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=6
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:8)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_7" x=0 y=320 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_7" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_7" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=7
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:9)> 
		</UIButton>
	</UIPane>
	
	<UIPane name="FEAT_BUTTON_8" x=0 y=360 width=300 height=40 >					
		<UIIcon name="FEAT_ICON_8" x=10 y=5 width=30 height=30 />
		<UIText name="FEAT_NAME_8" x=50 y=0 width=250 height=40 align=left valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true maxlines=2 />
		<UIButton  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT style="STYLE_CHARGEN_TAB" groupid=2 groupmemberid=8
			OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_4",local:10)> 
		</UIButton>
	</UIPane>
	
	<!-- Feat Description -->
	<UIListBox name="INFOPANE_LISTBOX" x=300 y=80 width=300 height=320 yPadding=0 xPadding=0 showpartialchild="true" unequalcontrols="true" scrollsegmentsize="30" hidescrollbarwhennotneeded="true" >
		<UIText name="FEAT_DESCRIPTION" width="PARENT_WIDTH" height="DYNAMIC" align="left" valign="top" fontfamily="Floating_Text_Default" multiline="true" indent=5 hangingindent=5 />
		<UIScrollBar name="SB" style="STYLE_SB_THIN"></UIScrollBar>
	</UIListBox>
	
	<!-- Pages Button -->
	<UIButton name="BUTTON_PREVIOUS" text="Previous" x=20 y=405 width=80 style="STYLE_SMALL_BUTTON" 
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_3","PREVIOUS",local:1,local:20) >
	</UIButton>
	
	<UIButton name="BUTTON_NEXT" text="Next" x=200 y=405 width=80 style="STYLE_SMALL_BUTTON" 
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_3","NEXT",local:1,local:20) >
	</UIButton>
	
	<!--Confirm Button -->
	
	<UIButton name="BUTTON_CONFIRM" text="Confirm" x=460 y=405 style="STYLE_SMALL_BUTTON" width=80
		OnLeftClick=UIObject_Misc_ExecuteServerScript("gui_clangeddin_bonusfeats_5",local:2) >
	</UIButton>
	
	<UIText name="WARNING_TEXT" x=300 y=400 width=300 height=40 align=center valign=middle fontfamily="Title_Font" style="1" indent=0 hangingindent=0 multiline=true color="red" />

	<!-- Background -->
	<UIIcon  x=0 y=0 width=PARENT_WIDTH height=PARENT_HEIGHT img="fx_white.tga" color="black" />


#13
kamal_

kamal_
  • Members
  • 5 238 messages

I can see what the problem with a custom class could be though. Even though this is a companion, he/she may be intended to access all regular classes and gain access to bonus feats based solely on those.
With a custom class you either give access to all feats (as bonus) or you only give a specific set to them, but it cannot dinamically change based on what other classes he picked.
 )

I am confused by this. When I did the archetype class system I opened up the feat list for each class quite a bit, but never had a problem with class based pre-reqs. Likewise for the custom class I made, which I gave its own feat list, basically duplicating another class' s list and then editing it for the additions/subtractions I wanted.

While adding brand new feats/abilities takes work and a custom player available class needs work on balance, making a variant class based off existing classes and abilities wasnt too bad once I figured out how the 2das related.
  • ColorsFade aime ceci

#14
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

I am confused by this. When I did the archetype class system I opened up the feat list for each class quite a bit, but never had a problem with class based pre-reqs. Likewise for the custom class I made, which I gave its own feat list, basically duplicating another class' s list and then editing it for the additions/subtractions I wanted.

While adding brand new feats/abilities takes work and a custom player available class needs work on balance, making a variant class based off existing classes and abilities wasnt too bad once I figured out how the 2das related.

 

kamal_, how hard is it to do that? What you did - basically copy a class, and then add a couple feats as options?

 

The problem I have going to automatic assignment route (which for the most part would actually work really well) is that if the player were to multiclass this character, they could potentially end up with the feat twice, which would be. 

 

What I'd really love to do is prevent this companion from being multiclassed. I have the variable on in my campaign, so all companions can be multiclassed. And for some companions, that's a good idea; I'm trying to setup attributes on some companions so that the player could multiclass them if they wish (I always recount Imoen from Baldur's Gate 2, who made a fine thief/mage because she had the stats for it). 

 

Is there a way to turn the multiclassing off for specific companions? Because so far, what I've seen, is that it's just a global setting for the entire campaign. 



#15
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

I may have found an answer to the multiclassing issue. If this works, then auto-assignment of specific feats for this companion shouldn't be an issue. 

 

Restricted Companion Multiclassing



#16
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

EDIT: Oh well, I did not see you had found another solution while I was typing the code, nevermind then.

 

If you intend to do it with a companion being single classed and not having access to other classes then it's much easier, and kamal_'s approach is indeed the best one, you make a new custom class from scratch with more bonus feats on the tables and you're set.

To prevent him from taking levels in other classes, make this script and put it on Player Level Up of module properties:

const int NEW_CLASS = 9999; //you decide the number here, but it should be the row ID of your new class in class.2da

void RunLevels(object oPC)
{
	int nCLASS_2 = GetClassByPosition(2, oPC);
	if (nCLASS_2 == CLASS_TYPE_INVALID) return;
	int nLEVEL = GetTotalLevels(oPC, FALSE);
	int nEXP = GetXP(oPC);
	int nTABLE = StringToInt(Get2DAString("exptable", "XP", nLEVEL - 2));
	SetXP(oPC, nTABLE + 1);
	SetXP(oPC, nEXP);
	DelayCommand(0.1, RunLevels(oPC));
}
void main()
{
	object oPC = GetPCLevellingUp();
	int nCLASS_1 = GetClassByPosition(1, oPC);
	if (nCLASS_1 != NEW_CLASS) return;
	DelayCommand(0.1, RunLevels(oPC));
}


#17
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

 

you make a new custom class from scratch with more bonus feats on the tables and you're set.

 

I guess I need to look at this approach, because it would be the most robust, and ideally the best way to handle it. 

 

I've never opened the class.2da file before. Time to dig I suppose. 



#18
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

Related question, in case anyone knows: 

 

When you're leveling up, sometimes your class automatically gets a feat (like Paldins get Remove Disease). And it's shown in the Feats gui as automatically selected, in the 2nd panel. 

 

Is there a way to do that in code, in a script, or is that a function of the 2DA and class packages?



#19
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

Another question, if people are still reading: 

 

Default classes.2da goes to 105, with most of the latter being padding. Kaedrin's PRC starts at 106 and goes to 187. 

 

If I were to add a custom class, and desire to make it compatible with Kaedrin's PRC, would it be wise of me to use one of the padding spots, at 105, or add padding after Kaedrin's and start with something like 190?

 

What's the best way to handle this?



#20
kevL

kevL
  • Members
  • 4 052 messages

What's the best way to handle this?


http://nwn2.wikia.co...da_Reservations

http://nwn2.wikia.co.../Cls_feat_*.2da
http://nwn2.wikia.co...Cls_bfeat_*.2da

But really, i'd be more tempted to hook a script from the Finish btn on levelup, that opens a Gui (for a/the appropriate character) with a pre-defined list of available 'bonus' feats, click one and that character gets that feat. A bit of text at the top of the Gui would be used to notify player that something special has happened:

"Congratulations, since you <have done blah-de-blah or met blah-de-blah conditions> choose an extra Feat!"

The script that fires at Finish levelup could check for local vars on various Companions and so they can become eligible for extra feats based on plot state. Or level. Or anything 'cause it's a script.


( note, said Char might get an "illegal character" flag in any case /shrug )
  • ColorsFade aime ceci

#21
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

kevL, I really like that idea, but how would I do that? 

 

I'm no good at the custom UI stuff. The XML gives me a headache. 



#22
Clangeddin86

Clangeddin86
  • Members
  • 220 messages

It's the scripts I showed above. They call custom UI that allows you to select feats.


  • ColorsFade aime ceci

#23
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

It's the scripts I showed above. They call custom UI that allows you to select feats.

 

Okay Clangeddin86, I'll give it a try. 

 

It sounds simple enough. It would be easier than a custom class. I'm trying a custom class right now, but it's not going so well. And it's not really the right solution; this companions class shouldn't be a different one, it just needs a few extra feats. 



#24
ColorsFade

ColorsFade
  • Members
  • 1 267 messages

So where's the best place to hook this if I want to call these scripts? I'm trying to figure that out... 



#25
kevL

kevL
  • Members
  • 4 052 messages
levelup_summaryx2.xml - rinse & repeat for *x1 and * for players without SoZ.

copy to Campaign folder (or wherever you want to keep this override). Scroll down to

<UIButton name="CHOICE_FINISH" ... ( i think.. )

add into that element another OnLeftClick hook; here's what mine looks like with TonyK's AI Kaedrin's enhancement:


<UIPane name="CHARGEN_BUTTONS" x="ALIGN_RIGHT" y="723" width="520" height="45" >
    <UIButton name="CHOICE_FINISH" strref="113712" x="336" y="0" style="STYLE_MENU_BUTTON_SML"
    OnLeftClick='UIButton_Input_CharGenCommit("LEVELUP","CHARGEN_FINISH")'
    OnLeftClick0='UIObject_Misc_ExecuteServerScript("gui_ccs_player_levelup")'
    update="true" OnUpdate='UIButton_OnUpdate_CheckCharGenStage("LEVELUP","CHARGEN_FINISH")' />
</UIPane>
So if you get the drift -- keep additional event-calls (callbacks?) sequential -- add

OnLeftClick1='UIObject_Misc_ExecuteServerScript("gui_extra_feats")'

where "gui_extra_feats" is your custom script that decides if/when/what/why a particular companion gets an extra feat. This script will also create the Gui popup ... see Clangeddin's above ...

various tricks can be used there to show/hide overlapping elements so it looks good yet allows different choices to show or not show up.
  • ColorsFade aime ceci