Jump to content

Home

Making Enemies Use Shields


blinkyzero

Recommended Posts

Hi folks. I'm working on a souped-up hardcore mod for KotOR1 that randomizes the stats of every enemy you enter combat against. That part's done and working fine, so now I'd like to go a step further and add useful items to enemies at random.

 

I've got enemies chucking grenades that they're given, but for some reason I can't seem to make energy shields work right. I can add the shields to inventories no problem, but they never get used, even if I make a GN_ActivateForceField() call. I suspect there's something ridiculously simple I'm overlooking.

 

I wonder: are the ability flags for the shields listed in spells.2da added at spawn? Since I'm tossing the shields in dynamically -- whenever the enemies enter combat with the player -- I thought maybe that could be the problem. I looked over all of the k_def scripts and k_inc_generic but couldn't quite figure it out.

Link to comment
Share on other sites

I might get around to doing a video once I finish this thing up and test it properly. The gist of it is that every enemy gets random bonuses to its attributes (and saves, consequently), VP, and FP (if applicable). There's some hardcore mod-style scaling involved -- at higher levels, the minimum bonuses get increased -- but even then there's still quite a large possible range. I like never being sure if that Sith soldier is just another chump or some monster with 30+ Strength and a couple hundred VP, heh. So far in my testing it's done a great job keeping me on my toes and preventing combat from becoming routine. Since the bonuses are generated dynamically, they're different from save to save, too; if I die and reload I can't simply adjust my strategy by focusing on the guy that was tough before, as he's been re-randomized.

 

I fixed the shield issue, too, and the grenades are working well (almost too well; I'll have to tone down the random chance of enemies getting grenades because at times I just get swamped by them, lol). I'm debating giving out stims now, too, and possibly developing a system where enemies will occasionally call for help, summoning in friends (with a small chance of a miniboss in the summons carrying nice loot...which you'll only get if you manage to kill him without dying, because, again, randomness laughs at save-reload).

Link to comment
Share on other sites

Hi folks. I'm working on a souped-up hardcore mod for KotOR1 that randomizes the stats of every enemy you enter combat against. That part's done and working fine, so now I'd like to go a step further and add useful items to enemies at random.

 

I've got enemies chucking grenades that they're given, but for some reason I can't seem to make energy shields work right. I can add the shields to inventories no problem, but they never get used, even if I make a GN_ActivateForceField() call. I suspect there's something ridiculously simple I'm overlooking.

 

I wonder: are the ability flags for the shields listed in spells.2da added at spawn? Since I'm tossing the shields in dynamically -- whenever the enemies enter combat with the player -- I thought maybe that could be the problem. I looked over all of the k_def scripts and k_inc_generic but couldn't quite figure it out.

 

1. That sounds awesome and I'd like to see it when it's done(and possibly make the installer for you).

 

2. As to your issue, you might try the following:

void main()
{
   /*
        Here you can do one of two things, depending on how
        are activating or wanting to activate the shields.

      1.
        If you activate the shield whenever an enemy is sighted*
        you'll want to use OBJECT_SELF for the object oPerson.

      2.
        If you want to do it in a dynamic manner, you'll need to
        launch the script for every person in combat and refer
        to them by their tag... Not the better idea.

        *: Instead of on sight, you could also do on attacked, with
            the only difference really just being when the shield is
            activated, since with the on attacked method the shield
            won't be activated until after they're attacked the first time.
   */

   object oPerson = GetObjectByTag("<Tag of person>"); // Could be OBJECT_SELF
   string sShield1 = GetItemInSlot(INVENTORY_SLOT_LEFTARM, oPerson);
   string sShield2 = GetItemInSlot(INVENTORY_SLOT_RIGHTARM, oPerson);

   int iROW = 0;
        if(sShield1 == "g_i_frarmbnds01") { iROW = 99;  }
   else if(sShield1 == "g_i_frarmbnds02") { iROW = 100; }
   else if(sShield1 == "g_i_frarmbnds03") { iROW = 101; }
   else if(sShield1 == "g_i_frarmbnds04") { iROW = 102; }
   else if(sShield1 == "g_i_frarmbnds05") { iROW = 103; }
   else if(sShield1 == "g_i_frarmbnds06") { iROW = 104; }
   else if(sShield1 == "g_i_frarmbnds07") { iROW = 105; }
   else if(sShield1 == "g_i_frarmbnds08") { iROW = 106; }
   else if(sShield1 == "g_i_frarmbnds09") { iROW = 107; }

   // If the Left Arm didn't match any shields, iROW is still 0
   if(iRow == 0) //Now we can check for Right Arm
   {
            if(sShield1 == "g_i_frarmbnds01") { iROW = 99;  }
       else if(sShield1 == "g_i_frarmbnds02") { iROW = 100; }
       else if(sShield1 == "g_i_frarmbnds03") { iROW = 101; }
       else if(sShield1 == "g_i_frarmbnds04") { iROW = 102; }
       else if(sShield1 == "g_i_frarmbnds05") { iROW = 103; }
       else if(sShield1 == "g_i_frarmbnds06") { iROW = 104; }
       else if(sShield1 == "g_i_frarmbnds07") { iROW = 105; }
       else if(sShield1 == "g_i_frarmbnds08") { iROW = 106; }
       else if(sShield1 == "g_i_frarmbnds09") { iROW = 107; }
   }

   // Remove any shield effects
   effect eEffect = GetFirstEffect(oPerson);
   while(GetIsEffectValid(eEffect))
   {
       if(GetEffectSpellID(eEffect) == 99  ||
          GetEffectSpellID(eEffect) == 100 ||
          GetEffectSpellID(eEffect) == 101 ||
          GetEffectSpellID(eEffect) == 102 ||
          GetEffectSpellID(eEffect) == 103 ||
          GetEffectSpellID(eEffect) == 104 ||
          GetEffectSpellID(eEffect) == 105 ||
          GetEffectSpellID(eEffect) == 106 ||
          GetEffectSpellID(eEffect) == 107)
       {
           RemoveEffect(eEffect);
           break;
       }
       else
       {
           eEffect = GetNextEffect(oPerson);
   }

   // Now launch the code for the shield.
   ExecuteScript("k_sup_bands", OBJECT_SELF, iROW);
}

Link to comment
Share on other sites

1. That sounds awesome and I'd like to see it when it's done(and possibly make the installer for you).

 

2. As to your issue, you might try the following:

void main()
{
   /*
        Here you can do one of two things, depending on how
        are activating or wanting to activate the shields.

      1.
        If you activate the shield whenever an enemy is sighted*
        you'll want to use OBJECT_SELF for the object oPerson.

      2.
        If you want to do it in a dynamic manner, you'll need to
        launch the script for every person in combat and refer
        to them by their tag... Not the better idea.

        *: Instead of on sight, you could also do on attacked, with
            the only difference really just being when the shield is
            activated, since with the on attacked method the shield
            won't be activated until after they're attacked the first time.
   */

   object oPerson = GetObjectByTag("<Tag of person>"); // Could be OBJECT_SELF
   string sShield1 = GetItemInSlot(INVENTORY_SLOT_LEFTARM, oPerson);
   string sShield2 = GetItemInSlot(INVENTORY_SLOT_RIGHTARM, oPerson);

   int iROW = 0;
        if(sShield1 == "g_i_frarmbnds01") { iROW = 99;  }
   else if(sShield1 == "g_i_frarmbnds02") { iROW = 100; }
   else if(sShield1 == "g_i_frarmbnds03") { iROW = 101; }
   else if(sShield1 == "g_i_frarmbnds04") { iROW = 102; }
   else if(sShield1 == "g_i_frarmbnds05") { iROW = 103; }
   else if(sShield1 == "g_i_frarmbnds06") { iROW = 104; }
   else if(sShield1 == "g_i_frarmbnds07") { iROW = 105; }
   else if(sShield1 == "g_i_frarmbnds08") { iROW = 106; }
   else if(sShield1 == "g_i_frarmbnds09") { iROW = 107; }

   // If the Left Arm didn't match any shields, iROW is still 0
   if(iRow == 0) //Now we can check for Right Arm
   {
            if(sShield1 == "g_i_frarmbnds01") { iROW = 99;  }
       else if(sShield1 == "g_i_frarmbnds02") { iROW = 100; }
       else if(sShield1 == "g_i_frarmbnds03") { iROW = 101; }
       else if(sShield1 == "g_i_frarmbnds04") { iROW = 102; }
       else if(sShield1 == "g_i_frarmbnds05") { iROW = 103; }
       else if(sShield1 == "g_i_frarmbnds06") { iROW = 104; }
       else if(sShield1 == "g_i_frarmbnds07") { iROW = 105; }
       else if(sShield1 == "g_i_frarmbnds08") { iROW = 106; }
       else if(sShield1 == "g_i_frarmbnds09") { iROW = 107; }
   }

   // Remove any shield effects
   effect eEffect = GetFirstEffect(oPerson);
   while(GetIsEffectValid(eEffect))
   {
       if(GetEffectSpellID(eEffect) == 99  ||
          GetEffectSpellID(eEffect) == 100 ||
          GetEffectSpellID(eEffect) == 101 ||
          GetEffectSpellID(eEffect) == 102 ||
          GetEffectSpellID(eEffect) == 103 ||
          GetEffectSpellID(eEffect) == 104 ||
          GetEffectSpellID(eEffect) == 105 ||
          GetEffectSpellID(eEffect) == 106 ||
          GetEffectSpellID(eEffect) == 107)
       {
           RemoveEffect(eEffect);
           break;
       }
       else
       {
           eEffect = GetNextEffect(oPerson);
   }

   // Now launch the code for the shield.
   ExecuteScript("k_sup_bands", OBJECT_SELF, iROW);
}

 

Thanks, that's quite helpful! It's actually pretty close to the solution I came up with, though more elegant. I get way too lazy with my scripting. I ended up creating my own equip system like the one you wrote.

 

Right now I've got the dynamic randomization script firing whenever an enemy notices the party or the PC through the master AI script's perception check. It occurred to me earlier that this is pretty much the same method that Talchia used for the old hardcore mod years back -- I remember tinkering with that almost a decade ago!

 

I'm actually debating making some new energy shield variations to hand out that have fewer charges built-in (because I end up picking up way too many fully-charged shields otherwise), making the shields no-drop, or even circumventing the entire item and just applying the shield effect directly with EffectForceShield(). The nice part about that last method is the enemies don't have to waste an action to charge at you -- they get their shield bonus immediately. It's not quite fair, but maybe they were on their guard and ready for action. :)

 

I'm tinkering with the call for help/miniboss idea now. I'd like to print a message of some sort to the screen whenever reinforcements get called in, but unfortunately the script engine is pretty lackluster when it comes to that kind of thing. Best I can do right now is a lame message to the log (great for debugging, useless otherwise) or a tiny feedback message over someone's head, like the spell save text.

 

I think there's a way to get a nice text box in the corner, though...BioWare did it on the Endar Spire when you try to follow Trask through the door after he sacrifices himself. Haven't figured out yet how they pulled that off.

Link to comment
Share on other sites

Thanks, that's quite helpful! It's actually pretty close to the solution I came up with, though more elegant. I get way too lazy with my scripting. I ended up creating my own equip system like the one you wrote.

 

Right now I've got the dynamic randomization script firing whenever an enemy notices the party or the PC through the master AI script's perception check. It occurred to me earlier that this is pretty much the same method that Talchia used for the old hardcore mod years back -- I remember tinkering with that almost a decade ago!

 

I'm actually debating making some new energy shield variations to hand out that have fewer charges built-in (because I end up picking up way too many fully-charged shields otherwise), making the shields no-drop, or even circumventing the entire item and just applying the shield effect directly with EffectForceShield(). The nice part about that last method is the enemies don't have to waste an action to charge at you -- they get their shield bonus immediately. It's not quite fair, but maybe they were on their guard and ready for action. :)

 

I'm tinkering with the call for help/miniboss idea now. I'd like to print a message of some sort to the screen whenever reinforcements get called in, but unfortunately the script engine is pretty lackluster when it comes to that kind of thing. Best I can do right now is a lame message to the log (great for debugging, useless otherwise) or a tiny feedback message over someone's head, like the spell save text.

 

I think there's a way to get a nice text box in the corner, though...BioWare did it on the Endar Spire when you try to go back through the door after Trask sacrifices himself. Haven't figured out yet how they pulled that off.

 

Simple:

 

Use tk102's DLGEditor in the Modding Tools section to make a one-line conversation. If you want the text to change or be customizable, then set the text of the one-line conversation to "<CUSTOM20000>", without the quotes.

 

Then, whenever you want the dialogue to show up, just use this:

 

void main()
{
   SetCustomToken(20000, "<Text you want>");
   AssignCommand(GetFirstPC(), ActionStartConversation(GetFirstPC(), "<name of dlg, minus extension"));
}

Link to comment
Share on other sites

Simple:

 

Use tk102's DLGEditor in the Modding Tools section to make a one-line conversation. If you want the text to change or be customizable, then set the text of the one-line conversation to "<CUSTOM20000>", without the quotes.

 

Then, whenever you want the dialogue to show up, just use this:

 

void main()
{
   SetCustomToken(20000, "<Text you want>");
   AssignCommand(GetFirstPC(), ActionStartConversation(GetFirstPC(), "<name of dlg, minus extension"));
}

 

Oh God. /facepalm. Why didn't I think of that? Works perfectly, thanks again.

 

The reinforcement system was ridiculously easy to implement. It certainly makes combat hectic -- that last guy you're cutting down almost as an afterthought suddenly calls in some bruisers, and you're back into the thick of it. In fact I'm thinking of weighting the chance to call for help more heavily if there's only one enemy left in the fight.

 

My only concern thus far is that this system might lead to a lot of XP inflation. I think I can tinker with the XP that the reinforcements grant, which would probably be better than reducing XP across the board, since I'd like to keep this as modular as possible.

 

Now I need creature templates for minibosses and reinforcements! I should start a topic soliciting unique entries for these. I'd like to have a bunch for each faction, so that an enemy calling for help will bring in guys tied to his particular group of baddies.

Link to comment
Share on other sites

Archived

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

×
×
  • Create New...