Aller au contenu

Photo

Request : Advice on scripting AI - Walk Waypoints and do nothing else... (Solved - Then Brought Back To Life - Then Solved Again :)


  • Veuillez vous connecter pour répondre
23 réponses à ce sujet

#1
Morbane

Morbane
  • Members
  • 1 883 messages
I came up with this script but it doesnt work right - the creature just sits there - I guess it is too simple - but what is needed to reach the goal of unwaivering obedience and just follow the waypoints: 1 -2 -3 - 4 -3 -2 -1 etc?

OnSpawn.nss
#include "x0_i0_walkway"

void main()
{
// Run this campaign's standard creature spawn modifications script (set in module load)   
string sScriptSpawnCreature = GetGlobalString("N2_SCRIPT_SPAWN_CREATURE");   

if (sScriptSpawnCreature != "")   
{
ExecuteScript(sScriptSpawnCreature, OBJECT_SELF);   
}
WalkWayPoints(TRUE);

effect eImmuneToNonMagicWeapons = EffectDamageReduction(1000, DAMAGE_POWER_PLUS_ONE);

eImmuneToNonMagicWeapons = ExtraordinaryEffect(eImmuneToNonMagicWeapons);

ApplyEffectToObject(DURATION_TYPE_PERMANENT, eImmuneToNonMagicWeapons, OBJECT_SELF);

ExecuteScript("jugg_AI", OBJECT_SELF);}


Modifié par Morbane, 09 mai 2012 - 09:05 .


#2
kevL

kevL
  • Members
  • 4 056 messages
back up a step, How are you spawning the actual creature? ( i can't see anything ..)

#3
Morbane

Morbane
  • Members
  • 1 883 messages
I solved this part by giving my creature the appearance of an air elemental and the visual effect of the model I wanted.

Well - I have this custom appearance: a model of an elephant Hellfire made

Aside from that - I will have to go off topic to explain:

The elephant appears in the toolset - and just to be sure I reverted back to the default scripts - but to no avail. The elephant still has a sound set and thumps when it walks and can attack the PC - but it is not visible - I dont know what went wrong because I had it showing up in game the last time I was working on the encounter (months ago)

Also when the PC attacks and hits the game crashes.

So I will next be checking my appearance.2da because something is likely wrong in there

But, back on topic:
The idea is to limit the behaviour to simply walking a set of 4 waypoints without stopping for anything - it is just supposed to mow down anyone too slow to get away, take damage until destroyed and then fade away when dead.

So I thought I would strip all of the various "enhancements" that make a creature more realistic in it behaviour - so in my limited understanding of creature AI, I was attempting to rewrite the most critical event scripts; onspawn, ondamage, onspell, hb, onattack - basically those 5 plus an AI script that is supposed to handle its trample attack that knocks down and does bludgeoning damage.

The answer to the actual spawn - it gets called by CreateObject when the PC opens a door down around a corner from the waypoint - it works except for the elephant being invisible or more technically termed : buggered.


Modifié par Morbane, 06 mai 2012 - 10:43 .


#4
kevL

kevL
  • Members
  • 4 056 messages
i remember this !!

i had an invisible Ogre once, and it was an Appearance.2da issue but I didn't crash (just couldn't target it)


anyway, I'm really not adept with these things although i suggest taking *all* scripts off and just get the dang critter to appear. ( actually, its unlikely scripts have anything to do with it -- prob. 2da/model )

#5
Morbane

Morbane
  • Members
  • 1 883 messages
So here I move on to the edited post question:

I plan to give my creature an AOE that simulates the trample attack I am going for and included within will be any other simulated behaviours the creature needs.

I still have yet to figure out how to script the relentless behaviour of simply walking waypoints and having the creature doing nothing else - leaving all of its "attack" to the AOE.

Which event scripts do I need to achieve this behaviour? Are any of the event scripts potentially unnecessary?

#6
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
In the canned AI, the walkwaypoint coding happens from the heartbeat script, I think. Try clearing out all the creature's events, and making a simple script for the HB which makes it walkwaypoints - similar to what you have above. Alternatively, just try adding a delay on the command to walkwaypoints in the on spawn script.

#7
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
Walkwaypoints will only work when there is no enemy present, you'll have to script your own version of it for it to work. Since you're just talking about a simple four-point pattern, it doesn't need to be that complicated. Define the current waypoint as "wp_" + GetTag(OBJECT_SELF) + "_" + IntToString(N), where N is your integer. Each heartbeat, check the distance to the current waypoint, if close, switch to the next one, if the next doesn't exist, switch to the first one. Then just move to the waypoint.

The trickier thing is the not attacking. Every attack by another creature puts the elephant into combat, so you'll have to rescript the on-physically-attacked and on-spell-cast-at to clear all actions and continue with the waypoints.

#8
kamal_

kamal_
  • Members
  • 5 240 messages

Lugaid of the Red Stripes wrote...

Walkwaypoints will only work when there is no enemy present, you'll have to script your own version of it for it to work. Since you're just talking about a simple four-point pattern, it doesn't need to be that complicated. Define the current waypoint as "wp_" + GetTag(OBJECT_SELF) + "_" + IntToString(N), where N is your integer. Each heartbeat, check the distance to the current waypoint, if close, switch to the next one, if the next doesn't exist, switch to the first one. Then just move to the waypoint.

The trickier thing is the not attacking. Every attack by another creature puts the elephant into combat, so you'll have to rescript the on-physically-attacked and on-spell-cast-at to clear all actions and continue with the waypoints.

Couldn't you just put in blank physically attacked and spell cast at scripts, since the creature's not supposed to react?

#9
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
@kamalpoe: No, combat is a two-way street. Once you're attacked, you get that little sword icon in your action queue, and automatically attack. The scripted AI just adjusts your weapons, switches targets, and uses the various combat abilities. It's even possible for an attacker to fail their initiative check and have the passive NPC land the first blow.

#10
Morbane

Morbane
  • Members
  • 1 883 messages
Ok, so Lugaid - you suggest modifying onattacked, onspell and the hb. Does that mean all the others can be ignored and simply be left blank?

Also in the script I posted above - is it close or perhaps not really best for the onspawn but ok for say the hb?

Actually, when I look at it - it just doesnt seem quite right. Any further advice is welcome.

Modifié par Morbane, 06 mai 2012 - 09:13 .


#11
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
The others can probably be safely left blank. The HB, though, needs to keep the creature moving. The on-spawn might not be so useful here, except that's where the standard walkwaypoints gets initialized.

Another thought: You could use the on-spawn script to look up the four waypoints and then store their locations as local locations. Then your HB script could just order the beast to run to one of those locations, randomly selected, or in order, if you want to keep the elephant on a set path.

#12
kevL

kevL
  • Members
  • 4 056 messages
ok, i think I've got it:

To make a monomaniacal Umber Hulk walkwaypoints, and never miss a wp. The only thing that trips him up is that he occasionally does an AoO on my PC. Then trudges off again ...

--- Heartbeat ---

#include "x0_i0_walkway"

void main()
{
//  object oDebug = GetFirstPC(FALSE);
//  SendMessageToPC(oDebug, ". HeartBeat");

  if (GetIsObjectValid(GetAttemptedAttackTarget()))
  {
//    SendMessageToPC(oDebug, ". Combat");
    ClearAllActions(TRUE);

    int nNextWayLast = GetLocalInt(OBJECT_SELF, "nNextWayLast");

    if (!GetLocalInt(OBJECT_SELF, "bWpDone"))
    {
      SetLocalInt(OBJECT_SELF, "bWpDone", TRUE);

      if (GetWalkCondition(NW_WALK_FLAG_BACKWARDS))
      {
        nNextWayLast ++;
      }
      else
      {
        nNextWayLast --;
      }
      SetLocalInt(OBJECT_SELF, VAR_WP_NEXT, nNextWayLast);
    }
  }
  else
  {
//    SendMessageToPC(oDebug, ". NOT Combat");
    DeleteLocalInt(OBJECT_SELF, "bWpDone");

    int nNextWay = GetLocalInt(OBJECT_SELF, VAR_WP_NEXT);
    SetLocalInt(OBJECT_SELF, "nNextWayLast", nNextWay);
  }

  // this also initializes the WWPController ...
  MoveToNextWaypoint();

//  int iNext = GetNextWaypoint();
//  int iCurrent = GetCurrentWaypoint();
//  int iPrevious = GetPreviousWaypoint();
//  SendMessageToPC(oDebug, ". Next wp : " + IntToString(iNext));
//  SendMessageToPC(oDebug, ". Current wp : " + IntToString(iCurrent));
//  SendMessageToPC(oDebug, ". Previous wp : " + IntToString(iPrevious));
//  SendMessageToPC(oDebug, ". ___ .");
}


--- Spawn ---

void main()
{
  // etc. here //

  // bSuppressMakeAOO does not work on nonPlot creatures; if it did this would be *much* simpler.
  SetCombatOverrides(OBJECT_SELF, OBJECT_INVALID, 1, 1, OVERRIDE_ATTACK_RESULT_MISS, 0, 0, TRUE, FALSE, FALSE, FALSE);
}


__
All other event slots blank -- faction, Hostile

#13
Morbane

Morbane
  • Members
  • 1 883 messages
KevL: Who's the man? YOU ARE!

That works great!
So awesome - Thanks for taking the time...

#14
kevL

kevL
  • Members
  • 4 056 messages
np Morbane


i like elephants ...

Ps. if you want to get really picky, make sure there's six seconds for the first HB to happen,

Modifié par kevL, 07 mai 2012 - 07:30 .


#15
Morbane

Morbane
  • Members
  • 1 883 messages
OK - so if a party member attacks the elephant - how can it be made to head back toward a wp in the direction of the attacker?

(Yes - getting picky)

#16
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
One option is to look through all the waypoints and find the one that is closest to the attacker, and reset that as the current waypoint. If you're really good with the geometry and vector math, you could even find the waypoint whose direction (bearing) is closest to the attacker's direction from the elephant.

Another approach is to set the attacker's location as a new, temporary waypoint, so the elephant stops walking waypoints and instead charges towards the attacker, then reverts back to waypoints once the target is reached. Using the vector functions, you could even find a location behind the attacker, so that the elephant tries to run past them, rather than to them.

For the math, you use GetPosition to get a vector out of a location:

vector vMark = GetPosition(oAttacker);

then you can use ".x" and ".y" to get the components of the vector:

vMark.x
vMark.y

After you've done your math, you can use the Location() function to take the modified vector and turn it back into a location.

#17
kevL

kevL
  • Members
  • 4 056 messages
this is working pretty darn good ( not perfect )

--- Heartbeat ---

#include "x0_i0_walkway"

void main()
{
  int nNextWay = GetLocalInt(OBJECT_SELF, VAR_WP_NEXT);
  int nNextWayLast = GetLocalInt(OBJECT_SELF, "nNextWayLast");

  if (nNextWay != nNextWayLast)
  {
    DeleteLocalInt(OBJECT_SELF, "bTurnDone");
  }

  if (GetIsObjectValid(GetAttemptedAttackTarget()))
  {
    ClearAllActions(TRUE);

    if (!GetLocalInt(OBJECT_SELF, "bWpDone"))
    {
      SetLocalInt(OBJECT_SELF, "bWpDone", TRUE);

      if (GetWalkCondition(NW_WALK_FLAG_BACKWARDS))
      {
        nNextWayLast ++;
      }
      else
      {
        nNextWayLast --;
      }
      SetLocalInt(OBJECT_SELF, VAR_WP_NEXT, nNextWayLast);
    }
  }
  else
  {
    DeleteLocalInt(OBJECT_SELF, "bWpDone");

    SetLocalInt(OBJECT_SELF, "nNextWayLast", nNextWay);
  }

  MoveToNextWaypoint();
}


--- onPhysAttacked & onSpellCastAt ---

#include "x0_i0_position"
#include "x0_i0_walkway"

void main()
{
  if (!GetLocalInt(OBJECT_SELF, "bTurnDone"))
  {
    object oAttacker = GetLastHostileActor();
    if (!IsFacingWithin(90.f, oAttacker))
    {
      SetLocalInt(OBJECT_SELF, "bTurnDone", TRUE);

      if (!GetWalkCondition(NW_WALK_FLAG_BACKWARDS))
      {
        SetWalkCondition(NW_WALK_FLAG_BACKWARDS);
      }
      else
      {
        SetWalkCondition(NW_WALK_FLAG_BACKWARDS, FALSE);
      }
    }
  }
}



it works short of doing the math as Lugaid points out (GetNearest/GetStrings/GetDistance/etc) but i've also got some faction functions that need investigating ( to see if PersonalReputation is still feasible .. )

btw, SpawnScript remains the same .....

#18
Morbane

Morbane
  • Members
  • 1 883 messages
Thanks again KevL - that should make a big difference in how the elephant's "attack" challenges the PC and comps.

I have been working on the details of the AOE for my trample/bludgeoning attack - it is going well - add to that the improvements you developed above - the encounter should prove interesting...

#19
Morbane

Morbane
  • Members
  • 1 883 messages
Now if I could only find a way to stop the elephant from going around the fallen PCs - I am thinking about using SetBumpState - but I havent tried it out yet - hopefully the fallen PC will get pushed aside when the elephant continues on its relentless advance.

#20
kevL

kevL
  • Members
  • 4 056 messages
another idea, maybe put extra wps in even along the straight paths ( numbered correctly ) - it would give more randomness to exactly when Elephant turns around, and perhaps if you put some on bit of a zig-zag then the 'phant walking around PCs & corpses may seem less out-of-place

I was also thinking about the possibility of creating the AoE out in front of the elephant, but ... no, much easier to just stick it to the critter and let him carry it around as it were. Don't fret too much over it,

#21
Morbane

Morbane
  • Members
  • 1 883 messages
Hmm, just as I was pulling in the carport I was thinking the same thing: more waypoints to enable ol ele to spin around with less effort in deciding which wp was closer. Good call KevL...

#22
kevL

kevL
  • Members
  • 4 056 messages
great minds n all that :)

or just two obsessed freaks ..

#23
Morbane

Morbane
  • Members
  • 1 883 messages
Having more waypoints has noticeably helped - as did the SetBumpState - I also found out that once the PC is inside the AOE and manages to get up in time (like when another is attacking, keeping the ele in place) they would be "immune" - so I added another call to the AOE in the modified onattack - and bango - they get squashed as the ele spins around to get to the next nearest waypoint.

#24
kevL

kevL
  • Members
  • 4 056 messages
hehe