Author Topic: Attack Target Theory  (Read 720 times)

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Attack Target Theory
« Reply #15 on: December 20, 2011, 02:46:14 am »


               

wyldhunt1 wrote...

And, ShaDoOoW's patch is good. Fixes a lot of stuff...
Not sure that it would help you code custom AI stuff, but the default behavior is better with it.

To clarify and maybe justify myself '<img'> -> reason why I suggested this is that if OP would actually decided to do modifications in core AI, then it would be better for him to start with version from 1.70 which fixes lots of weirdiness and bugs. If he would do that based on 1.69 includes it would later overwrited and took priority over the 1.70 version. As I said im not sure what is OP want to do whether its solely for his PW or he wants to do something more global. If the second it would be probably better to base it on the includes from 1.70 - and BTW you don't have to install patch for that at all. All scripts, libraries and 2das for custom content building can be downloaded in "builders resources" package.
               
               

               


                     Modifié par ShaDoOoW, 20 décembre 2011 - 02:47 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
Attack Target Theory
« Reply #16 on: December 20, 2011, 03:28:00 am »


               If this is something that you don't mind waiting on for about a month or so, I can work something like this in to my custom AI. It would be an interesting addition to it.
My AI is not released on the vault. It was made for our old PW, Ariochus. It does replace the entire AI system because I decided that the default scripts were so full of stupid logic that it would be faster to start over than to fix it all. It's a mashup of every decent AI script that I've found(CODI, Olander, Jasperre's, Tonyk's, Legacy NWN... etc). I took all the good functionality out of them all and put all the best parts in to a single AI... Then added my own stuff to it, did some chanting, waved a dead chicken, and it worked.
Anyway, I can probably add a proper threat based targeting system to it and give it to you if you like... It just may be a month or so. I'm in the process of integrating all of the old Ariochus scripts with the new CEP/PRC. So, it'll be a bit...
That, and I'm not sure how modular it is. I'll have to see how many of my subsystems it makes use of and maybe do some simplifying to get it extracted in a useable form...
<Shrug> If you're interested, I'll see what I can do. I may or may not manage a version that you can import easy.

Since I've no idea if I can even craft a modular version, you're probably best using an item or conversation based command like you're planning on for now though.
If I do manage it and you're interested, I'll let you know.
               
               

               


                     Modifié par wyldhunt1, 20 décembre 2011 - 03:31 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Attack Target Theory
« Reply #17 on: December 20, 2011, 03:37:26 am »


               @Dragon:  No you have not pisses any one off.  But Trying to modify the Bioware include files can introduce many unforseen bugs.  The includes are used by many of the bioware functions and chaseing down all of the scripts that use them to recompile them all in not an easy task.  And can lead to hours of bug hunting.   No one should mess with a making a  Custom AI unless they are willing to spend the hours in getting it right.  
Now what I am sugesting is in my opion not a custom AI.   Is it Custom functionality,  Yes.  It is a Standard hook into the Standard IA.   Leaving the Standard AI untoched and hooking into it with the Tools that Bioware set in Place.      



Now i do not know if the Standard hook will work in your module, It sounds like you are using a custom AI.  So it basicly comes down to if its creater left the hooks in place of not.  Or if they did not follow the General rule of calling a centeral function for all combat actions, It can compound the ability to change the AI behavior.  

Here are the three scripts that would work with the standard AI.   One include, One TagBased Script for the widget and one AI hook.

include:  inc_cmd_underlin

const string UNDERLING_AI_OVERRIDE = "underling_ai";
 const string UND_TARGET            = "und_target";
 const string UNDERLING_AI_BYPASS   = "By_Pass_AI";

  void SetUnderlingTargetFromWidget(object oSlave,object oWidget)
  {
     object oTarget = GetLocalObject(oWidget,UND_TARGET);
     SetLocalObject (oSlave,UND_TARGET ,oTarget);
     if (GetIsObjectValid(oTarget))
       FloatingTextStringOnCreature("Me Kill " + GetName(oTarget), oSlave);
     else
       FloatingTextStringOnCreature("Me Kill By own choice" , oSlave);
  }

  void SetTargetOnWidget(object oTarget,object oWidget)
  {
    SetLocalObject(oWidget,UND_TARGET, oTarget);
  }
 
 int ScriptBypassSecondRun()
 {
    return GetLocalInt(OBJECT_SELF,UNDERLING_AI_BYPASS);
 }

void SetScriptBypass()
{
   SetLocalInt(OBJECT_SELF,UNDERLING_AI_BYPASS,TRUE);
}

void RemoveScriptByPass()
{
   DeleteLocalInt(OBJECT_SELF,UNDERLING_AI_BYPASS);



Tag Based Script

#include "x2_inc_switches"
#include "inc_cmd_underlin"
void main()
{
   if (GetUserDefinedItemEventNumber() != X2_ITEM_EVENT_ACTIVATE) return;
 
  object oTarget = GetItemActivatedTarget();
   object oWidget = GetItemActivated();
   object oUser  = GetItemActivator();

   // If the target is an underling get His perferred target from the Local stored
   // on the widget and set The AI override script.
   if (GetMaster(oTarget) == oUser)
   {
      SetUnderlingTargetFromWidget(oTarget,oWidget);
      SetCreatureOverrideAIScript(oTarget,UNDERLING_AI_OVERRIDE);
   }
   else
   {
      SetTargetOnWidget(oTarget,oWidget);
      string sName;
      if (GetIsObjectValid(oTarget)) sName = GetName(oTarget);
      else sName = "INVALID";
      SendMessageToPC(oUser,sName + " stored as target on widget" );
   }
}   


AI Hook: underling_ai  // or what ever you change the name to in the include.

#include "x2_inc_switches"
#include "inc_cmd_underlin"
#include "NW_I0_GENERIC"
void main()
{
   //This is needed encase we called DeterminCombatRound from this script
   //to change the target. without it an we would get an endless loop.
   if(ScriptBypassSecondRun()) return;

   //Get Our Targets
   object oMastersCommand = GetLocalObject(OBJECT_SELF,UND_TARGET);
   object oCurrentTarget =  GetCreatureOverrideAIScriptTarget();

   // If our commanded target is not valid there is nor reason to even run this
   // script again, remove the hook from the AI and return.
   if (!GetIsObjectValid(oMastersCommand))
   {
      SetCreatureOverrideAIScript(OBJECT_SELF,"");
      return;
   }
   // Are we already attacking our intended target?
   if (oMastersCommand == oCurrentTarget) return;

   // Our target is not the target we where commanded to attack Can we even see it?
   if(GetObjectType(oMastersCommand) != OBJECT_TYPE_CREATURE || GetObjectSeen(oMastersCommand))
   {
      // We reset the target by recalling the DCR function.  we do not
      // want this script to run again when we do.
      SetScriptBypass();
      DetermineCombatRound(oMastersCommand);

      // Ok the target has been changed. DetermineCombatRound has alrady ran its
      //cource no reason for it to continue from here.
      SetCreatureOverrideAIScriptFinished();

      // remove the bypass so this script will again run on the next call to DCR.
      RemoveScriptByPass();
   }
}  


               
               

               
            

Legacy_DragonTayl

  • Newbie
  • *
  • Posts: 40
  • Karma: +0/-0
Attack Target Theory
« Reply #18 on: December 20, 2011, 04:27:42 am »


               Well phew. I'm glad I haven't upset anyone because I find these threads absolutely fascinating. Seeing how (forgive me for applauding you all) masters work it out helps *tremendously* when trying to come to a good solution.

I think there is one thing I'm not sure I have everyone seeing, though I think some of us are all working the same way:

I am not trying to affect henchmen. What I'm trying to do is in multiplayer, let's say you are playing alongside two or three of your friends, if you want to make the monster you're fighting as a group focus on a specific PC, what the best way is to do that. How do you flag the monster to target a specific PC. I think the widget may be the best way because that's how the PC can introduce themselves into the code. It takes a standard action, they've targetted the monster with their widget, and the widget uses DetermineCombatRound() passing the activating PC as the monster's target.

I've looked through the AI and I'm reasonably sure that for the most part the monster doesn't change targets often. I'm just hoping that by running DetermineCombatRound() I can set the monster's "object" to be the PC in question, at least for a few rounds.
               
               

               
            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
Attack Target Theory
« Reply #19 on: December 20, 2011, 05:08:36 am »


               You can do that with an item that has whatever that cast unique spell power is called (I don't build in the toolset much... '<img'>) and have it run a script that calls
ClearActions();
AssignCommand(oTargetedObject, DetermineCombatRound(oPC));

or just a DoCommand if you don't want to lose their current action stack... Shouldn't matter in combat though.
That'll force the monster to attack the player who used the item.

However, you could make it server wide and automatic fairly easy... A lot of it could be handled by an AI override probably.
The parts that I mentioned in my post about what I would do doesn't actually consist of very much code. If you have a decent amount of experience, I bet you could make a system that is trully great in a few days or less.

Begin by deciding what actions should make a player gain threat...
Example:
Attacking: +1 Threat
Damaging Melee: DamageInflicted/5
Damaging Spell: TotalDamageInflicted/5
OtherHarmfulSpell: SpellLevel (Things like Sleep that are offensive but no damage)
BuffsOnFriendlies: SpellLevel

Now, take a look at the creature events that would handle those things. That list would require OnAttacked, OnDamaged, and OnSpellCastAt.
Add a bit of code that adds the correct amount to a variable on the PC = to whatever is on your list. This will probably only wind up being a few lines of code in each of the events.

The exception is the Buffs on Friendlies. That would require small bit of code in a spell hook, which can be done in the default scripts in much the same way as the AI override. If you don't know how to hook spells, it's easy once you've done it.

Add a bit of code to the modules hb event that cycles through each PC and subtracts 1 or 2 points from their threat score (Minimum 0, of course).

Use an AI Override script like Lightfoot's, or replace the targetting code I mentioned.
The targetting code should cycle through each percieved PC and check their threat variable.
Whomever has the highest threat score is set as the NPC's combat target(Set the target the same way as the original code, just choose the target differently)

Add a line to the OnCombatRoundEnd or your AI Override script that deletes your old target each round. This will force them to allways attack whomever has the highest threat rating.

That'll give you a basic and universal threat based targetting system that'll work way better than the default for, probably, less than 50 lines of code.

Once you have that, you can start to think of ways to improve it and add new bits.
               
               

               


                     Modifié par wyldhunt1, 20 décembre 2011 - 05:17 .