Force Power Scripting - Part I
I am writing this guide to help anyone out who is interested in writing their very own Force Power script. This guide assumes that you have a very basic knowledge of the script system used by KOTOR. You need to understand how to declare a variable, how the IF statement works, and how to distinguish between the different variables types such as a integer, object, effect, string and a float.
If you have no idea what I am talking about, and would like to learn more then you should see the NWN Lexicon. Even though it was written for Neverwinter Nights, the script engine used for KOTOR is pretty much the same. Here is a link to the Lexicon:
http://www.nwnlexicon.com/) You can either view it online or download it. If you are serious about scripting you should download it. At a minimum you should click on the Lyceum link and read the primer section. If you want to learn more then I would recommend reading Celowin's Beginners Tutorials in the Lexicon.
Also, before you use this guide you MUST read TK102's Post - How to Create a Custom Force Power. In that post TK covers the actual creation of your Force Power in Spells.2da and making your own icon. Since he did a very nice job with this I see no reason to cover it here. Here is the link
http://www.lucasforums.com/showthread.php?s=&threadid=130898)
I am planning on making three different guides. Each one will cover a different type of Force Power Script - a buff script, a script that targets one enemy and a area of effect script. This particular guide will focus exclusively on writing a buff script. By the end of all three guides you should be able to script almost any type of force power, plus it will prepare you for the more advanced scripting.
How to Script a Buff Force Power:
This type of power is the easiest of all force power scripts to make. You do not need to worry about saving throws and force resistance with this type of scripts. There are five basic parts to a buff script. First, you need to declare the variables you are going to use. Second, you need to remove the spell effects to prevent stacking. Third you need to signal the game engine that you cast a spell. Fourth, you need to set the effects. And finally you need to apply the effects.
For this tutorial we are going to make a new Dark Side power - Sith Rage. Sith Rage will be a Darkside power that gives the caster a huge increase in strength, but also makes them easier to hit by decreasing their armor class. Since the PC already has a number of different spells to pick at level up we are going to make this Power level up with the Character. This way the PC will only use one spell slot to get the power.
Before we cover the scripting you should follow TK102 post and create a new line item in the spells.2da file. Make sure you set the Good/Evil column to E (For evil of course) and set the range to P.
Here are the effects of the Power Sith Rage: Characters that are under sixth level will gain 6 extra strength points and suffer a AC penalty of 4. Characters between levels six and twelve will gain 8 extra strength points and suffer a AC penalty of 3. True Sith Lords - characters level twelve and up will gain 10 extra strength points and suffer a AC penalty of only 2.
Here is the script along with a detailed explanation of what each line is doing.
#include "k_inc_force"
// Include file of the original Bioware Force Scripts
// We are including this to gain access to a number of very useful functions
// developed by Bioware
// See Notes below
int FORCE_POWER_SITH_RAGE = 132;
// This variable must match the Row ID of your power in spells 2da, so change this to match your spells.2da
void main()
{
/*****************************************/
/* STEP 1 - DECLARE THE VARIABLES NEEDED */
/*****************************************/
object oTarget = GetSpellTargetObject();
// This will set oTarget equal to who you cast the spell at
// In this case it will be yourself
effect eTargetVisual;
// This variable will be used to set the visual effects
effect eBuff;
// This variable will be used to set the actual buff
int CasterLevel = GetHitDice(OBJECT_SELF);
// This variable will get the casters level
SWFP_HARMFUL = FALSE;
// The variable SWFP_HARMFUL has already been declared in the include file
// It is used by the signal event command to let the target know if this is
// an attack spell or not.
/************************************************** *******/
/* STEP 2 - REMOVE THE SPELL EFFECTS TO PREVENT STACKING */
/************************************************** *******/
// Check for and remove this power if the character is already under the effects
// This is to prevent the power from stacking after multiple casting
if(GetHasSpellEffect(FORCE_POWER_SITH_RAGE))
{
Sp_RemoveSpellEffectsGeneral(FORCE_POWER_SITH_RAGE , oTarget);
// This is a function call to one of Bioware's original scripts
// it will check all of the effects oTarget has and remove them if they were
// given by the Sith Rage power
}
/****************************************/
/* STEP 3 - SIGNAL THE SPELL CAST EVENT */
/****************************************/
// Signal SpellCast Trigger
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), SWFP_HARMFUL));
/**********************************/
/* STEP 4 - DETERMINE THE EFFECTS */
/**********************************/
// Set Character Icon Effect
eBuff = SetEffectIcon(eBuff, 7);
// This is the Force Armor Icon
// A complete Listing of All Valid Icons is in the 2da File - effecticon.2da
// Build Visual Effects
// These are the visual effects that will be played when the spell is cast
// A listing of all visual effects is in the 2da visualeffects
eTargetVisual = EffectVisualEffect(VFX_PRO_FORCE_ARMOR);
// Use the command EffectLinkEffects to merge multiple effects into one variable
eTargetVisual = EffectLinkEffects(eTargetVisual, EffectVisualEffect(VFX_PRO_FORCE_SHIELD));
//Determine actual effects based on the casters level
if(CasterLevel < 6) // This effect will be applied if the caster is under level 6
{
eBuff = EffectLinkEffects(eBuff, EffectAbilityIncrease(ABILITY_STRENGTH, 6));
eBuff = EffectLinkEffects(eBuff, EffectACDecrease(4, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
}
else if(CasterLevel < 12) // This effect will be applied if the caster is over level 6 and under level 12
{
eBuff = EffectLinkEffects(eBuff, EffectAbilityIncrease(ABILITY_STRENGTH, 8));
eBuff = EffectLinkEffects(eBuff, EffectACDecrease(3, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
}
else // This effect will be applied if the caster is level 12 and up
{
eBuff = EffectLinkEffects(eBuff, EffectAbilityIncrease(ABILITY_STRENGTH, 10));
eBuff = EffectLinkEffects(eBuff, EffectACDecrease(2, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
}
/******************************/
/* STEP 5 - APPLY THE EFFECTS */
/******************************/
//Apply Visual Effects - they will last 3 seconds
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eTargetVisual, oTarget, 3.0);
//Apply Icon and Buff - the buff will last 60 seconds
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBuff, oTarget, 60.0);
}
Notes:
#include "k_inc_force_"
This line 'includes' the file "k_inc_force_utility" in your script. By adding this line, your program will include all of the functions and variable declarations in the file k_inc_force. I would HIGHLY recommend that you use this include file in ALL of your force power scripting. It will give you access to a number of very useful functions that will really simplify your own scripting. Here is a listing of some of the more useful functions:
Sp_MySavingThrows(object oTarget)
Sp_GetJediDCSave()
Sp_RemoveSpellEffectsGeneral(int nSpell_ID, object oTarget)
SP_CheckForcePushViability(object oTarget, int Whirlwind);
We will not be using the Bioware scripts to apply the Force Power Effect, because I would like to go over how to do it with your own script.
Effects
There are a ton of effects available in SWKOTOR. I will post a link here to all of the possible effects you could use shortly.
Here is the same script without all of the comments:
#include "k_inc_force"
int FORCE_POWER_SITH_RAGE = 132;
void main()
{
object oTarget = GetSpellTargetObject();
effect eTargetVisual;
effect eBuff;
int CasterLevel = GetHitDice(OBJECT_SELF);
SWFP_HARMFUL = FALSE;
if(GetHasSpellEffect(FORCE_POWER_SITH_RAGE))
{
Sp_RemoveSpellEffectsGeneral(FORCE_POWER_SITH_RAGE , oTarget);
}
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), SWFP_HARMFUL));
eBuff = SetEffectIcon(eBuff, 7);
eTargetVisual = EffectVisualEffect(VFX_PRO_FORCE_ARMOR);
eTargetVisual = EffectLinkEffects(eTargetVisual, EffectVisualEffect(VFX_PRO_FORCE_SHIELD));
if(CasterLevel < 6) // This effect will be applied if the caster is under level 6
{
eBuff = EffectLinkEffects(eBuff, EffectAbilityIncrease(ABILITY_STRENGTH, 6));
eBuff = EffectLinkEffects(eBuff, EffectACDecrease(4, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
}
else if(CasterLevel < 12) // This effect will be applied if the caster is over level 6 and under level 12
{
eBuff = EffectLinkEffects(eBuff, EffectAbilityIncrease(ABILITY_STRENGTH, 8));
eBuff = EffectLinkEffects(eBuff, EffectACDecrease(3, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
}
else // This effect will be applied if the caster is level 12 and up
{
eBuff = EffectLinkEffects(eBuff, EffectAbilityIncrease(ABILITY_STRENGTH, 10));
eBuff = EffectLinkEffects(eBuff, EffectACDecrease(2, AC_DODGE_BONUS, AC_VS_DAMAGE_TYPE_ALL));
}
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eTargetVisual, oTarget, 3.0);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBuff, oTarget, 60.0);
}
To create your own Force Power substitute your own effects for the effects I have above. One word of caution - try to keep your powers balanced. This game is already easy and playing around with a super kick-butt force power is fun for about ten minutes it will quickly get boring. So try to make your powers balanced!
Writing tutorials is not my speciality, so please post any comments or thoughts you had that could improve them.