Jump to content

Home

Porting Master Force Drain and Master Force Scream to Kotor 1


WRFan

Recommended Posts

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_TYPE_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_TYPE_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_TYPE_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_TYPE_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_TYPE_INSTANT, eLink1, oTarget));
                           }
                       }
                   }
                   else
                   {
                       DelayCommand(0.0f,ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectForceFizzle(), OBJECT_SELF));
                   }

               }

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




           } //While End
       }
       break;

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 ;)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...