Author Topic: scripting a NPC vs NPC fight  (Read 362 times)

Legacy_DM_Vecna

  • Hero Member
  • *****
  • Posts: 501
  • Karma: +0/-0
scripting a NPC vs NPC fight
« on: June 25, 2011, 08:02:13 pm »


               I have created my own peacetime AI script set of behaviors that add a little color to areas when PCs are walking around. For my orcs I am thinking that I want one behavior to be to walk up to another orc and punch them (POSSIBLY fight for a couple of rounds) then shake it off and walk their separate ways. I am looking for suggestions on how to script this without them fighting to the death and without adjusting their factions permanantly.

My first thoughts are to just have orc(1) walk up to nearest orc(2), punch him and then run a few effects like  dae vfx, speakstring, and fall forward. I just need to figure out how long to let the mock fight go. and the factions. Also if one is plot will that ever in laggy conditions get stuck on plot. 

As a bonus any thoughts on other fun orcish behaviors would be cool.
               
               

               
            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #1 on: June 25, 2011, 08:22:14 pm »


               The problem with scripting fights really lies in that Bioware decided to keep the combat animations as private functions.
 I ended up doing what someone in another post had mentioned as their work around, and made a null spell with the attack casting animation (in the CastAnim row), which I call when I need someone to make a fake attack.
 As long as you don't attach a hostile spellcast event to it, it won't affect faction settings doing it that way.
               
               

               
            

Legacy_Snarkblat

  • Full Member
  • ***
  • Posts: 104
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #2 on: June 25, 2011, 08:23:20 pm »


               You could make them members of different factions such as ORC1 and ORC2, SetIsTemporaryEnemy, have them fight for a bit, and add a delay to make them go friendly again. Of course, there are other ways of doing this.
               
               

               
            

Legacy_DM_Vecna

  • Hero Member
  • *****
  • Posts: 501
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #3 on: June 26, 2011, 12:07:35 am »


               failed.bard: would you be willing to post that script so I could take a look at how you did that. Any other instructions would help as well.

Snarkblat. Unless there is a better way to do this your suggestion was my starting point.
               
               

               
            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #4 on: June 26, 2011, 12:52:08 am »


                 You have to add another line to your spells.2da file in order to do it.  I'll copy the line I added it on, though it'll likely lose the proper formatting getting squashed into the reply window.

913   NULL_ATTACK                         ****     ****             V        L       -      0x00        0x09         ****               ****   ****     ****    ****      ****     ****       ****     ****       ****       ****              ****              ****              ****              ****               ****               attack     500        ****             ****             ****             ****               0      wamar_001          homing         hand            ****               path              ****             0              ****           ****           ****           ****           ****           3          ****     2          ****        0                  0                   ****         1                ****        ****       ****       1


  In my case, I'd already added spells up to 912, the line just goes at the end.

  To play the animation, I just used:

 ActionCastFakeSpellAtObject  (SPELL_ATTACK_ANIMATION, oTarget);

which reference back to this line in my main constants include:

const int SPELL_ATTACK_ANIMATION          = 913;


  The spell could also be cast purely off its line number, which removes the need for the constant to be set.  Obviously, if your spell is on a different line, you would need to change the constant or spell number cast accordingly.
               
               

               
            

Legacy_Axe_Murderer

  • Full Member
  • ***
  • Posts: 199
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #5 on: June 26, 2011, 01:02:43 pm »


               This is really old but I found it lying around. Maybe you can tweak it to get what you're looking for:
Ok here's what you do...
Make a custom faction based on Hostile. Set it neutral (50) in both directions vs all other factions including itself.
Paint down two chairs facing each other about 10-15m or so apart.
- Set one's TAG to "DuelChair1", set the other's TAG to "DuelChair2"
- In their properties set them both on static, and make all their script slots blank.
Paint down two NPCs that will duel each other.
- Set one's TAG to "DuelGuy1", set the other's TAG to "DuelGuy2"
- In their properties, set them to Immortal and assign them to the custom faction you just made.
- Aside from that, you can customize the NPCs however you like.
- Set their scripts like so:
[nwscript]
                                          DuelGuy1                DuelGuy2
OnBlocked                      nw_c2_defaultd     nw_c2_defaultd
OnCombatRoundEnd   nw_c2_default3     nw_c2_default3
OnConversation             nw_c2_defaultd     nw_c2_defaultd
OnDamaged                   nw_c2_default6     nw_c2_default6
OnDeath                          nw_c2_defaultd     nw_c2_defaultd
OnDisturbed                   nw_c2_defaultd     nw_c2_defaultd
OnHeartbeat                   ** see below **       nw_c2_defaultd
OnPerception                 nw_c2_default2      nw_c2_default2
OnPhysicalAttacked      nw_c2_default5      nw_c2_default5
OnRested                       nw_c2_defaulta      nw_c2_defaulta
OnSpawn                        ** see below **       nw_c2_defaultd
OnSpellCast                   nw_c2_defaultb     nw_c2_defaultb
OnUserDefined             nw_c2_defaultd      nw_c2_defaultd
[/nwscript]
Change DuelGuy1 to use the following heartbeat and spawn scripts. You can tweak the time they spend resting vs. fighting by changing the constants called ROUNDS_OF_RESTING and ROUNDS_OF_DUELING at the top of the two scripts -- the one in the spawn script should match the one in the heartbeat script, but it's ok if they don't.
[nwscript]
// Heartbeat script for Duel Guy 1.
//:://///////////////////////////////////
// Make a custom faction based on Hostile. Set it neutral (50) in both directions vs all other factions including itself.
//
// Create the following objects...
//   Two NPCs, one has TAG "DuelGuy1" the other "DuelGuy2". Set them both to Immortal. Assign them both to your new custom faction.
//   Two chairs, one has TAG "DuelChair1" the other "DuelChair2" make them both static.
//
// Put the script "nw_c2_defaultd" in the following event slots on both NPCs:
//   OnBlocked, OnDeath, OnConversation, OnDisturbed, OnHeartbeat, OnSpawn, OnUserDefined
//
// Use this script for DuelGuy1's OnHeartbeat. Leave DuelGuy2's heartbeat at "nw_c2_defaultd".
// Use the accompanying script for DuelGuy1's OnSpawn. Leave DuelGuy2's spawn script at "nw_c2_defaultd".
//
// Change the values of the two constants at the top to tweak how
// long they duel vs. how long they rest. Make sure to match it up
// with the accompanying OnSpawn script.
//
//:://///////////////////////////////////
#include "nw_i0_plot"
 
const int ROUNDS_OF_DUELING = 7;  // Duel for 7 game rounds (= 42 seconds)
const int ROUNDS_OF_RESTING = 3;  // Rest for 3 game rounds (= 18 seconds)
 
void main()
{ object oDuelGuy1 = OBJECT_SELF;
  object oDuelGuy2 = GetNearestObjectByTag( "DuelGuy2", oDuelGuy1);
  if( !GetIsObjectValid( oDuelGuy2)) return;
 
  object <span class="highlight">oChair1</span> = GetNearestObjectByTag( "DuelChair1");
  object oChair2 = GetNearestObjectByTag( "DuelChair2");
  if( !GetIsObjectValid( <span class="highlight">oChair1</span>) || !GetIsObjectValid( oChair2)) return;
 
  if( GetLocalInt( oDuelGuy1, "RestCycle") && !GetLocalInt( oDuelGuy1, "Resting"))
  { DeleteLocalInt( oDuelGuy1, "Dueling");
    SetLocalInt( oDuelGuy1, "Resting", TRUE);
   
    ClearPersonalReputation( oDuelGuy1, oDuelGuy2);
    ClearPersonalReputation( oDuelGuy2, oDuelGuy1);
   
    float fRestDuration = RoundsToSeconds( ROUNDS_OF_RESTING); // rest for 4 rounds.
   
    if( GetSittingCreature( <span class="highlight">oChair1</span>) != oDuelGuy1)
    { if( GetIsObjectValid( GetSittingCreature( <span class="highlight">oChair1</span>))) AssignCommand( GetSittingCreature( <span class="highlight">oChair1</span>), ClearAllActions( TRUE));
     
      if( GetCurrentHitPoints( oDuelGuy1) < GetMaxHitPoints( oDuelGuy1)) ForceRest( oDuelGuy1);
     
      AssignCommand( oDuelGuy1, ClearAllActions( TRUE));
      AssignCommand( oDuelGuy1, ActionForceMoveToObject( <span class="highlight">oChair1</span>, FALSE, 1.0, 6.0));
      AssignCommand( oDuelGuy1, ActionDoCommand( AssignCommand( GetArea( oDuelGuy1), DelayCommand( fRestDuration, DeleteLocalInt( oDuelGuy1, "RestCycle")))));
      AssignCommand( oDuelGuy1, ActionSit( <span class="highlight">oChair1</span>));
    }
   
    if( GetSittingCreature( oChair2) != oDuelGuy2)
    { if( GetIsObjectValid( GetSittingCreature( oChair2))) AssignCommand( GetSittingCreature( oChair2), ClearAllActions( TRUE));
     
      if( GetCurrentHitPoints( oDuelGuy2) < GetMaxHitPoints( oDuelGuy2)) ForceRest( oDuelGuy2);
     
      AssignCommand( oDuelGuy2, ClearAllActions( TRUE));
      AssignCommand( oDuelGuy2, ActionForceMoveToObject( oChair2, FALSE, 1.0, 6.0));
      AssignCommand( oDuelGuy2, ActionSit( oChair2));
    }
  }
  else if( !GetLocalInt( oDuelGuy1, "RestCycle") && !GetLocalInt( oDuelGuy1, "Dueling"))
  { DeleteLocalInt( oDuelGuy1, "Resting");
    SetLocalInt( oDuelGuy1, "Dueling", TRUE);
    DeleteLocalInt( oDuelGuy1, "RestCycle");
   
    float fDuelDuration = RoundsToSeconds( ROUNDS_OF_DUELING); // duel for 6 rounds.
   
    ClearAllActions( TRUE);
    ActionDoCommand( SetFacingPoint( GetPosition( oDuelGuy2)));
    ActionWait( 3.0);
    ActionPlayAnimation( ANIMATION_FIREFORGET_BOW);
    ActionWait( 2.0);
    ActionDoCommand( AssignCommand( GetArea( oDuelGuy1), DelayCommand( fDuelDuration, SetLocalInt( oDuelGuy1, "RestCycle", TRUE))));
    ActionDoCommand( SetIsEnemy( oDuelGuy2));
   
    AssignCommand( oDuelGuy2, ClearAllActions( TRUE));
    AssignCommand( oDuelGuy2, ActionDoCommand( SetFacingPoint( GetPosition( oDuelGuy1))));
    AssignCommand( oDuelGuy2, ActionWait( 4.0));
    AssignCommand( oDuelGuy2, ActionPlayAnimation( ANIMATION_FIREFORGET_BOW));
    AssignCommand( oDuelGuy2, ActionWait( 1.0));
    AssignCommand( oDuelGuy2, ActionDoCommand( SetIsEnemy( oDuelGuy1)));
  }
  else if( !GetLocalInt( oDuelGuy1, "RestCycle") && GetLocalInt( oDuelGuy1, "Dueling") && (!GetIsInCombat( oDuelGuy1) || !GetIsInCombat( oDuelGuy2) || (GetAttackTarget( oDuelGuy1) != oDuelGuy2) || (GetAttackTarget( oDuelGuy2) != oDuelGuy1)))
  { SetIsEnemy( oDuelGuy2);
    AssignCommand( oDuelGuy2, SetIsEnemy( oDuelGuy1));
  }
}
[/nwscript]
[nwscript]
// OnSpawn script for Duel Guy 1.
//:://///////////////////////////////////
// Make a custom faction based on Hostile. Set it neutral (50) in both directions vs all other factions including itself.
//
// Create the following objects...
//   Two NPCs, one has TAG "DuelGuy1" the other "DuelGuy2". Set them both to Immortal. Assign them both to your new custom faction.
//   Two chairs, one has TAG "DuelChair1" the other "DuelChair2" make them both static.
//
// Put the script "nw_c2_defaultd" in the following event slots on both NPCs:
//   OnBlocked, OnDeath, OnConversation, OnDisturbed, OnHeartbeat, OnSpawn, OnUserDefined
//
// Use this script for DuelGuy1's OnSpawn. Leave DuelGuy2's spawn script at "nw_c2_defaultd".
// Use the accompanying script for DuelGuy1's OnHeartbeat. Leave DuelGuy2's heartbeat at "nw_c2_defaultd".
//
// Change the values of the constant at the top to tweak how long
// they duel vs. how long they rest. Make sure to match it up with
// the accompanying OnHeartbeat script.
//
//:://///////////////////////////////////
#include "nw_i0_plot"
 
const int ROUNDS_OF_DUELING = 7;  // Duel for 7 game rounds (= 42 seconds)
 
void main()
{ object oDuelGuy1 = OBJECT_SELF;
  object oDuelGuy2 = GetNearestObjectByTag( "DuelGuy2");
  if( GetIsObjectValid( oDuelGuy2))
  { SetLocalInt( oDuelGuy1, "Dueling", TRUE);
   
    float fDuelDuration = RoundsToSeconds( ROUNDS_OF_DUELING); // duel for 6 rounds.
   
    ClearAllActions( TRUE);
    ActionDoCommand( SetFacingPoint( GetPosition( oDuelGuy2)));
    ActionWait( 3.0);
    ActionPlayAnimation( ANIMATION_FIREFORGET_BOW);
    ActionWait( 2.0);
    ActionDoCommand( AssignCommand( GetArea( oDuelGuy1), DelayCommand( fDuelDuration, SetLocalInt( oDuelGuy1, "RestCycle", TRUE))));
    ActionDoCommand( SetIsEnemy( oDuelGuy2));
   
    AssignCommand( oDuelGuy2, ClearAllActions( TRUE));
    AssignCommand( oDuelGuy2, ActionDoCommand( SetFacingPoint( GetPosition( oDuelGuy1))));
    AssignCommand( oDuelGuy2, ActionWait( 4.0));
    AssignCommand( oDuelGuy2, ActionPlayAnimation( ANIMATION_FIREFORGET_BOW));
    AssignCommand( oDuelGuy2, ActionWait( 1.0));
    AssignCommand( oDuelGuy2, ActionDoCommand( SetIsEnemy( oDuelGuy1)));
  }
}
[/nwscript]
               
               

               


                     Modifié par Axe_Murderer, 26 juin 2011 - 12:04 .
                     
                  


            

Legacy_DM_Vecna

  • Hero Member
  • *****
  • Posts: 501
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #6 on: June 26, 2011, 08:38:33 pm »


               Thanks Axe, I am going to try this out
               
               

               
            

Legacy_Vivienne L

  • Full Member
  • ***
  • Posts: 130
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #7 on: March 11, 2012, 06:22:48 pm »


               Thanks, this works except it's giving a compile error on line  30 of the heartbeat script

 object <span class="highlight">oChair1</span> = GetNearestObjectByTag( "DuelChair1");

ERROR: PARSING VARIABLE LIST

The scripts seem to be working but should I be worried about fixing this?
Thanks in advance.
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #8 on: March 11, 2012, 06:32:19 pm »


               

vivienne.l wrote...

Thanks, this works except it's giving a compile error on line  30 of the heartbeat script

 object <span class="highlight">oChair1</span> = GetNearestObjectByTag( "DuelChair1");

ERROR: PARSING VARIABLE LIST

The scripts seem to be working but should I be worried about fixing this?
Thanks in advance.


You're cutting and pasting search highlights which are still in the original script.

<span class="highlight">

and

</span>

Remove all of them you come across.

FP!
               
               

               


                     Modifié par Fester Pot, 11 mars 2012 - 06:33 .
                     
                  


            

Legacy_Vivienne L

  • Full Member
  • ***
  • Posts: 130
  • Karma: +0/-0
scripting a NPC vs NPC fight
« Reply #9 on: March 12, 2012, 08:32:37 pm »


               Thank you Fester Pot!  I'm a newbie and didn't know what

<span class="highlight">

and

</span>

actually meant for the script but thought they must be doing something as I don't know what half the functions do though I am slowly learning thanks to people like you!!
               
               

               


                     Modifié par vivienne.l, 12 mars 2012 - 08:35 .