PDA

View Full Version : Porting Master Force Drain and Master Force Scream to Kotor 1


WRFan
06-17-2009, 11:59 AM
I am going to turn Kotor 1 into Kotor 2. Yep. Cause I hate vanilla Kotor 1, hardly any spells, no tactical depth in this game. In addition to my Force Confusion spell (see another post on this forum) I now also added Master Force Drain and Master Force Scream to Kotor 1.

Differences between Kotor 1 and TSL:

TSL spell Master Force Drain actually costs Force points (5+alignment adjustment), but then Obsidian goes ahead and gives those points back to the caster. lol. This is stupid and besides, there's no function in Kotor 1 that would check for ForcePowerCost. I just set the force points cost to 0. If the subjects fail their save, you get 30 FPs per subject (provided they have force points), otherwise you get nothing, but you also lose nothing. The TSL spell works the same way, it's just more fussy.

TSL Master Force Scream uses d7() function, but it was created specifically for TSL, not present in Kotor 1, so instead of d7(6) I use d6(7) in my script to determine the actual sonic damage to the targets. It's not that different from TSL, right?

TSL checks the Force Resistance before checking if oTarget is oEnemy, so every time you cast an area spell, your own character gets affected by the Force Resistance check as well. This is incredibly annoying if you have Force Immunity effect on the spellcaster. Check this out in TSL, cast Force Immunity on self, then cast Master Force Scream on enemy, you get affected by the Resistance check as well. Stupid! I moved the resist check further down, after the GetIsEnemy check. Should be changed in TSL scripts as well.

GetNextObjectInShape function is still bugged in Kotor 1, cause Bioware never bothered to fix it, so the script loses current oTarget object on oTarget death, which ends the while loop, ignoring all targets apart from the one that just died.

This problem affects all mass damaging spells in Kotor, like Death Field or Force Storm!

Solution: Use the DelayCommand function, instead of applying effect to object directly:

DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYP E_TEMPORARY, eLink1, oTarget, 30.0));

This is an old well-known problem, so I won't go any further into this.

Usefulness of the spells:

Master Force Drain is useful if you want to prevent enemies from casting spells on you. Use stasis field and drain them completely of force points. Successfully tried it on the Sith Master on Manaan. Cast Stasis field on him and drained his force points until he had 0 left. What a moron, lol. Could have killed him right away, but I am sadistic, lol. He had to suffer a little:

Stasis field
Choke on selkath apprentices
Master Drain Force on Sith Master
Improved Energy Resistance to resist his lightsabre
Don't renew Stasis field, let him attack you
Drain Life on him, using his own force points
When his health is low, Plague on him, it's like Cloudkill in NWN2, it simply killed him by energy draining his constitution. lol. I laughed my ass off, fighting him

Master Force Scream in TSL has a higher SpellSaveDC than other spells: 10+lvl+Wis mod+Char mod. I implemented my script in the same way. This spell is indeed very useful if you want to reduce an enemy's saving throws. Kotor 1 lacked this kind of spell so far. If you don't have 100 per cent chance of success when casting spells on powerful enemies, cast Master Force Scream first, followed by Plague, followed by Choke. This will reduce all saving throws. This combination is particularly damaging to Constitution (fortitude basically).

I'll post the scripts here, may be interesting for modders, I can also provide compiled versions and modified spells.2da if anybody is interested:

Master Force Drain:

case 133: //FORCE_POWER_MASTER_DRAIN_FORCE:
{

int nFPAmount;
SWFP_HARMFUL = TRUE;
SWFP_PRIVATE_SAVE_TYPE = SAVING_THROW_WILL;


object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 10.0, GetLocation(OBJECT_SELF), FALSE, OBJECT_TYPE_CREATURE );
while(GetIsObjectValid(oTarget))
{

nFPAmount = 30;


// Determine the number of Force Points the target has. If it is
// less than the steal amount, decrease the steal amount.
int nTargetFP = GetCurrentForcePoints( oTarget );

//SendMessageToPC(GetFirstPC(), GetTag( oTarget ) + " : " + IntToString(nTargetFP));

if( nTargetFP < nFPAmount ) {
nFPAmount = nTargetFP;
}

// Create a temporary Force Point Damage effect in order to
// see if the target is immune for some reason.
eLink1 = EffectDamageForcePoints( nFPAmount );


SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), SWFP_HARMFUL));
if( ( GetRacialType(oTarget) != RACIAL_TYPE_DROID ) &&
GetIsEnemy(oTarget) )
{
int nResist = Sp_BlockingChecks(oTarget, eLink1, eInvalid, eInvalid);
if(nResist == 0)
{
int nSaves = Sp_MySavingThrows(oTarget);
if(nSaves > 0)
{
nFPAmount /= 2;
}

// Apply a Force Point Damage effect to the target.
eLink1 = EffectDamageForcePoints( nFPAmount );
ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink1, oTarget);

}
else
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectForceFizzle(), OBJECT_SELF);
}
}
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 10.0, GetLocation(OBJECT_SELF), FALSE, OBJECT_TYPE_CREATURE );
}

// Finally, give the player the FP they've drained

eLink2 = EffectHealForcePoints( nFPAmount );
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect( 2026 ), OBJECT_SELF);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink2, OBJECT_SELF);
}
break;


Master Force Scream:

case 134: //FORCE_POWER_MASTER_FORCE_SCREAM:
{
// Force Scream and Improved Force Scream both affect
// targets in a cone extending from the caster's location. Master FS uses sphere
SWFP_HARMFUL = TRUE;
//SWFP_PRIVATE_SAVE_TYPE = SAVING_THROW_WILL;
SWFP_PRIVATE_SAVE_VERSUS_TYPE = SAVING_THROW_TYPE_SONIC;

// Each version of the spell causes differing amounts of damage.
int nDamageRolls;
int nAttributeDamage;
int nIconID;
int nShape;
float fShapeSize;
int nVFXID;
location lTargetLoc;

nDamageRolls = 7;
nAttributeDamage = 6;
nIconID = 81;
nShape = SHAPE_SPHERE;
// DJS-OEI 1/14/2004
// Increase the range slightly. Since the range for this spell
// is 10m, the pathing system fudging will in some cases not
// cause any valid targets to be within 10m to get damaged.
fShapeSize = 12.0 ;
nVFXID = 3002;
lTargetLoc = GetLocation( OBJECT_SELF );

DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYP E_INSTANT, EffectVisualEffect( nVFXID ), OBJECT_SELF));

object oTarget = GetFirstObjectInShape(nShape, fShapeSize, lTargetLoc, TRUE, OBJECT_TYPE_CREATURE );
while (GetIsObjectValid(oTarget))
{

// int nTotalDamage = Sp_CalcDamage( oTarget, nDamageRolls, 6 );
int nTotalDamage = d6(7); // no d7() function in Kotor 1

// Create the damage effects.
eLink1 = EffectDamage( nTotalDamage, DAMAGE_TYPE_SONIC );
eLink2 = EffectAbilityDecrease(ABILITY_STRENGTH, nAttributeDamage);
eLink2 = EffectLinkEffects(eLink2, EffectAbilityDecrease(ABILITY_DEXTERITY, nAttributeDamage));
eLink2 = EffectLinkEffects(eLink2, EffectAbilityDecrease(ABILITY_INTELLIGENCE, nAttributeDamage));
eLink2 = EffectLinkEffects(eLink2, EffectAbilityDecrease(ABILITY_WISDOM, nAttributeDamage));
eLink2 = EffectLinkEffects(eLink2, EffectAbilityDecrease(ABILITY_CHARISMA, nAttributeDamage));
eLink2 = EffectLinkEffects(eLink2, EffectAbilityDecrease(ABILITY_CONSTITUTION, nAttributeDamage));
eLink2 = SetEffectIcon(eLink2, nIconID);

// Check resistances.

SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), SWFP_HARMFUL));

if( ( GetRacialType(oTarget) != RACIAL_TYPE_DROID ) &&
GetIsEnemy(oTarget))
{
int nResist = Sp_BlockingChecks(oTarget, eLink1, eLink2, eInvalid);
if(nResist == 0)
{
// SpellSaveDC = SpellSaveDC()+5 for this power!
int nSaves = WillSave(oTarget, Sp_GetJediDCSave()+5, SWFP_PRIVATE_SAVE_VERSUS_TYPE);
if(nSaves <= 0)
{
// Apply physical damage effect to the target.
DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYP E_INSTANT, eLink1, oTarget));

// Do not apply the effects of this power if a more powerful
// version is already attached to the target.
if (!GetHasSpellEffect(GetSpellId(), oTarget))
{ // Apply the attribute damage effect.
DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYP E_TEMPORARY, eLink2, oTarget, 30.0));

}
}
else {
int nApply;
nApply = nTotalDamage/2;

if( nApply > 0 ) {
// The target saved, so the attribute damage is ignored.
// Rebuild the damage effect with the new damage.
eLink1 = EffectDamage( nApply, DAMAGE_TYPE_SONIC );
DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYP E_INSTANT, eLink1, oTarget));
}
}
}
else
{
DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYP E_INSTANT, EffectForceFizzle(), OBJECT_SELF));
}

}

oTarget = GetNextObjectInShape(nShape, fShapeSize, lTargetLoc, TRUE, OBJECT_TYPE_CREATURE );




} //While End
}
break;

DarthCyclopsRLZ
06-23-2009, 05:31 PM
I'm curious, which effect are you using for the Scream FP?

Just reinstalled the game and finished Tatooine. Don't remember if any monster has an effect similar to the TSL FP.

Tobirulz
06-24-2009, 03:50 AM
sounds really good will you be making them separate releases if so i would really like a copy of the force drain version, awsome will there be the lower levels aswell like just force drain

darthriddick
06-24-2009, 04:34 PM
You could use the sonic effect from the sonic weapon you use to kill sharks on manaan.

jonathan7
06-24-2009, 05:40 PM
I just wished to clarify your use of "porting" - it is both against forum policy to allow discussion of porting materials between games, and also illegal. Are you talking about making the same spells in K1 from K2, which is allowed, or are you talking about taking things from K2 and putting it in K1? -- j7

WRFan
06-26-2009, 10:04 AM
I'm curious, which effect are you using for the Scream FP?


well, you can see it in the script I posted above, the effects that are used are:


EffectDamage( nTotalDamage, DAMAGE_TYPE_SONIC );
EffectAbilityDecrease(ABILITY_ ...



Are you talking about making the same spells in K1 from K2, which is allowed, or are you talking about taking things from K2 and putting it in K1? -- j7


the code I provide only uses effects that are part of the Kotor 1 engine. It is simply not possible to use effects from Kotor 2, since they are hardcoded into the engine


will you be making them separate releases


sure, download the source files and the compiled versions here:

http://home.arcor.de/wrfan/files/kotor/kotor1_spells.rar

Extract the files into the Override folder. Dialog.tlk goes into the main Kotor 1 folder (backup the original first).

This Kotor 1 mod contains the following new spells:

FORCE_POWER_CONFUSION
FORCE_POWER_MASTER_DRAIN_FORCE
FORCE_POWER_MASTER_FORCE_SCREAM
FORCE_POWER_INVISIBILITY
FORCE_POWER_DIVINATION

See my posts on this forum for spell descriptions

I also fixed some errors in the original Bioware scripts that prevented the spells from functioning properly

jonathan7
06-26-2009, 10:24 AM
the code I provide only uses effects that are part of the Kotor 1 engine. It is simply not possible to use effects from Kotor 2, since they are hardcoded into the engine

Thanks for the clarification; being only a skinner - I'm unaware of coding limitations between the games ;)

DarthCyclopsRLZ
06-26-2009, 05:05 PM
well, you can see it in the script I posted above, the effects that are used are:

No I meant the video fx.

As I said, it's been a while and I don't remember monsters using effects that look like TSL's force scream. Also, I was too lazy to check it out.

WRFan
06-26-2009, 05:59 PM
No I meant the video fx.


I am using the effect 3002, which is the VFX_FNF_PLOT_MAN_SONIC_WAVE effect, as defined in visualeffects.2da. It's the same effect as the one that is used for MONSTER_ABILITY_SONIC_HOWL, though I don't think it's actually used in this game. I think the shadow mastiff in NWN2 uses this sonic ability, even though the effects are completely different in that game