Jump to content

running npcs


Warbird1

Recommended Posts

I know almost nothing about scripting, but according to Morrowind Scripting for Dummies, the Follow AI package can make an NPC follow another NPC, so it's just a matter of scripting the first NPC's movement. There's also a ForceRun script that was added by Tribunal to make characters run.

For waypoints, you have to specify the coordinates in the cell. For example, the script that makes Fargoth sneak around Seyda Neen when you're on the lighthouse includes lines like:

Fargoth->AiTravel -11468.595,-71511.531,173.728 ; goes to tree

Fargoth->AiTravel -11410.590,-72057.188,133.644 ; goes to wall

Edited by ProfArmitage
Link to comment
Share on other sites

Ok so I ran into a problem. What I did is this:

1) I made an activator. It works ok. The npcs are spawned in their correct locations:

f161165db8920.jpg

2) But both npcs don't move, I mean Fargoth doesn't go to his waypoint which is a couple of meters before him. Taros looks like he is about to chase him (the running animation kicks in) but suddenly stops, because Fargoth doesn't move. Why is that so? I took coordinates by prior placing some static objects (plant pots), writing down their coordinates (few non-complicated runs around Balmora on short distance), typing them into the script and then obviously deleting all those „plant pots”:

398ff4d592405.jpg

 

Could somebody please take a look into my script and tell me what's wrong? It compiles all right though.

The script:

 

 

Begin poscig

short state
short jeden_raz

if ( MenuMode == 1 )
return
endif

if ( OnActivate == 1 )

"player"->Say "Vo\w\m\Fle_WM005.mp3" "WAAAAAAAOOOOOOOOOOAAAAAAAAAGGGHHHHHH!!!!!"
"taros dral"->PositionCell, -18906, -10545, 185, 97.4, "Balmora"
"fargoth"->PositionCell, -18901, -10762, 186, 97.4, "Balmora"
set state to 10

endif

if ( "taros dral"->OnDeath == 1 )
set jeden_raz to -1
return
endif

if ( jeden_raz == -1 )
return
endif

if ( state == 10 )

"fargoth"->ForceRun
"taros dral"->ForceRun
"fargoth"->AiTravel -18976, -1096, 190
"fargoth"->AiTravel -19462, -11917, 206
"fargoth"->AiTravel -19806, -12695, 206
"fargoth"->AiTravel -19992, -13028, 206
"fargoth"->AiTravel -19381, -12970, 304
"fargoth"->AiTravel -18607, -12929, 201
"fargoth"->AiTravel -18171, -12162, 201
"fargoth"->AiTravel -18063, -11718, 201
"fargoth"->AiTravel -17606, -11120, 201
"fargoth"->AiTravel -17138, -11911, 189
"fargoth"->AiTravel -17943, -12318, 189
"fargoth"->AiTravel -18312, -12962, 189
"fargoth"->AiTravel -19224, -12944, 302
"fargoth"->AiTravel -19992, -13028, 206
"fargoth"->AiTravel -20235, -12673, 175
"fargoth"->AiTravel -19910, -11628, 175
"fargoth"->AiTravel -20148, -10561, 225
"fargoth"->AiTravel -20119, -9858, 225
"fargoth"->AiTravel -19864, -10577, 225
"fargoth"->AiTravel -19216, -10966, 225
"fargoth"->AiTravel -19002, -10657, 215

endif






end poscig

 

 

Of course Taros Dral has the appriopriate „AI Package” set to Follow target "fargoth". The problem is why the Wood Elf fetcher does not move his ass.

Link to comment
Share on other sites

Okay, so I expanded the script by adding „walkstate” checks EVERY single waypoint, but all to naught. At least I know the script doesn't go pass the first step, because in the second step there should be heard Wood Elf shout going on, but there isn't such thing at all.

 

The script:

 

Begin poscig

short walkstate

set walkstate to 1

if ( MenuMode == 1 )
return
endif

if ( OnActivate == 1 )

"player"->Say "Vo\d\m\Atk_DM004.mp3" "You n'wah!"
"taros dral"->PositionCell, -18906, -10545, 185, 97.4, "Balmora"
"fargoth"->PositionCell, -18901, -10762, 186, 97.4, "Balmora"

elseif ( walkstate == 1 )
"taros dral"->ForceRun
set walkstate to 2

elseif ( walkstate == 2 )
"player"->Say "Vo\d\m\Hit_WM015.mp3" "Aaaaaaha!"
"fargoth"->ForceRun
"fargoth"->AiTravel -18976,-1096,190
set walkstate to 3

elseif ( walkstate == 3 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 4
endif

elseif ( walkstate == 4 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19462,-11917,206
set walkstate to 5

elseif ( walkstate == 5 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 6
endif

elseif ( walkstate == 6 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19806,-12695,206
set walkstate to 7

elseif ( walkstate == 7 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 8
endif

elseif ( walkstate == 8 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19992,-13028,206
set walkstate to 9

elseif ( walkstate == 9 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 10
endif

elseif ( walkstate == 10 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19381,-12970,304
set walkstate to 11

elseif ( walkstate == 11 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 12
endif

elseif ( walkstate == 12 )
"fargoth"->ForceRun
"fargoth"->AiTravel -18607,-12929,201
set walkstate to 13

elseif ( walkstate == 13 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 14
endif

elseif ( walkstate == 14 )
"fargoth"->ForceRun
"fargoth"->AiTravel -18171,-12162,201
set walkstate to 15

elseif ( walkstate == 15 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 16
endif

elseif ( walkstate == 16 )
"fargoth"->ForceRun
"fargoth"->AiTravel -18063,-11718,201
set walkstate to 17

elseif ( walkstate == 16 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 17
endif

elseif ( walkstate == 17 )
"fargoth"->ForceRun
"fargoth"->AiTravel -17606,-11120,201
set walkstate to 18

elseif ( walkstate == 18 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 19
endif

elseif ( walkstate == 19 )
"fargoth"->ForceRun
"fargoth"->AiTravel -17138,-11911,189
set walkstate to 20

elseif ( walkstate == 20 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 21
endif

elseif ( walkstate == 21 )
"fargoth"->ForceRun
"fargoth"->AiTravel -17943,-12318,189
set walkstate to 22

elseif ( walkstate == 23 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 24
endif

elseif ( walkstate == 24 )
"fargoth"->ForceRun
"fargoth"->AiTravel -18312,-12962,189
set walkstate to 25

elseif ( walkstate == 25 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 26
endif

elseif ( walkstate == 26 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19224,-12944,302
set walkstate to 27

elseif ( walkstate == 27 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 28
endif

elseif ( walkstate == 28 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19992,-13028,206
set walkstate to 29

elseif ( walkstate == 29 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 30
endif

elseif ( walkstate == 30 )
"fargoth"->ForceRun
"fargoth"->AiTravel -20235,-12673,175
set walkstate to 31

elseif ( walkstate == 31 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 32
endif

elseif ( walkstate == 32 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19910,-11628,175
set walkstate to 33

elseif ( walkstate == 33 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 34
endif

elseif ( walkstate == 34 )
"fargoth"->ForceRun
"fargoth"->AiTravel -20148,-10561,225
set walkstate to 35

elseif ( walkstate == 35 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 36
endif

elseif ( walkstate == 36 )
"fargoth"->ForceRun
"fargoth"->AiTravel -20119,-9858,225
set walkstate to 37

elseif ( walkstate == 37 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 38
endif

elseif ( walkstate == 38 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19864,-10577,225
set walkstate to 39

elseif ( walkstate == 39 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 40
endif

elseif ( walkstate == 40 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19216,-10966,225
set walkstate to 41

elseif ( walkstate == 41 )
if ("fargoth"->GetAiPackageDone == 1 )
set walkstate to 42
endif

elseif ( walkstate == 42 )
"fargoth"->ForceRun
"fargoth"->AiTravel -19002,-10657,215
set walkstate to 43

elseif ( walkstate == 43 )
if ("fargoth"->GetAiPackageDone == 1 )
"fargoth"->ClearForceRun
PlaySound "mysticism hit"
"fargoth"->disable
"taros dral"->disable
MessageBox "KONIEC"
endif


endif





end poscig

 

 

It looks like this AiTravel thingy doesn't work at all.

 

Could somebody shed some light om this weird situation and share his insights, please?

Link to comment
Share on other sites

it could be many things...
I'd start replacing (" with ( ", generally try using MWEdit strong syntax checking if possible

try splitting elseifs e.g. from
if ( cond1 )
blah
elseif ( cond2 )
blah
elseif ( cond3 )
blah
elseif ( cond4 )
blah
endif

 

to

 

if ( cond1 )
blah
elseif ( cond2 )
blah
endif
; split
if ( cond3 )
blah
elseif ( cond4 )
blah
endif


sometimes too long elseifs are simply not executed correctly

Also AITravel usually does not work between cell boundaries, in this case you may have to position the npc or use a "stronger " Ai package (e.g. AIActivate or StartCombat) but position/setPos is probably simpler

[EDIT] to see cell boundaries/borders, B in Construction set, TB in game console
[EDIT2]probably examples about trying to solve AI wander/follow could be in the traveling merchants mod

Edited by abot
Link to comment
Share on other sites

The last script you posted has the right structure: you issue the travel package in one state and check for its completion in the next state before traveling to the next waypoint.

 

One thing (there may be other issues) that is preventing your NPCs from moving is the first line after your declaration of variables. Every game cycle you are setting walkstate to 1 which means it repeatedly reassigns the same travel package. If you are coming from Skyrim modding, the error is understandable. Unlike with Papyrus, Morrowind scripts run every frame until they are stopped (that is why the early 'returns' on the menumode check are so important). There is no need to set walkstate to 1. You could make your first logic block check walkstate == 0. But if for some reason you need to set walkstate to 1 before stating the travel code try this:

 

if ( walkstate == 0 )

set walkstate to 1

endif

 

There is no difficulty with using AITravel to cross (exterior) cell boundaries, but it won't work if traveling between interior and exterior cells. AIWander will not cross cell boundaries since pathgrids are restricted to one cell and an adjacent cell would have its own distinct pathgrid. It appears that your script is running on the activator rather than the NPC (Fargoth) himself. This will introduce a limit to how far Fargoth can run since if the player moves too far from the cell where the script is running a point will be reached when the object's cell is no longer 'loaded' and the script will stop executing. You could make it a 'targeted' script to run directly on the NPC if you do not want to add scripts to the NPCs in the editor.

 

Check out the code for the mod that abot linked. You will discover the scripts are more complicated - in part to handle an interruption in the AI by waiting in the cell or fast travel. You may not require that code for your project.

Link to comment
Share on other sites

Hey thanks!

That thing with assigning 0 to walkstate did the trick! Thank you! Who could have thought of that? Nope, I don't come from Skyrim, never played it.

Fortunately those provisional waypoints (coordinates) I set were within the boundaries of a single cell so no, no interruptions, but thanks for that pointer.

Yeah, AiTravel is complicated (or perhaps very limited), especially taking into account all variables that might occur in the process. No wonder developers had seldomly used it! (I can recall only two instances to be honest, except Fargoth the next one is Mehra Milo walking few meters away from the player and that's that!)

I'm still using the activator, because I don't understand how to use the targeted script… what would trigger the script to fire? I am not very knowledgable in this matter I'm afraid.

Link to comment
Share on other sites

You are welcome. It seems the more complicated a script the more likely that we overlook the simple errors. Just to be clear, all variables have an initial value of 0 except for global variables and only if they are set to have a different value in the editor.

 

Because Fargoth is not running very far you are fine running the script off of the activator. However, if that is not the most natural way of triggering the action or if you want to have more options in the future I will explain how to apply a targeted script.

 

A targeted script is a global script that runs on an object like an NPC. The common way of starting a targeted script on an NPC is through dialogue with that NPC. You could create a new greating for Fargoth (filter it so it does not happen all the time). For example, you could make it so he only freaks out at night. Fargoth might say: "What are you doing? Don't touch me!" Then in the dialogue results window for that new greeting you type:

 

Goodbye

if ( ( ScriptRunning "poscig" ) == 0 )

StartScript "poscig"

endif

 

Goodbye forces the player to close the dialogue window. The check is to make certain the script is not already running on Fargoth. It is possible to have multiple targeted scripts running on an object, but two that are the same could give some strange (and undesirable) results.

 

You could also start the targeted script from the activator. The code for the script you would attach to the activator might look like this:

Begin ActivatorScript
 
short doOnce
 
if ( doOnce == 1 )
  return
endif
 
if ( OnActivate == 1 )
  set doOnce to 1
  "Fargoth"->StartScript "poscig"
endif
 
End

At some point you will want to stop the script from executing. Use the line:

 

StopScript "poscig"

 

If you do not already have it, Morrowind Scripting for Dummies is the single, most valuable scripting reference.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...