What's wrong with my AITravel scripting?

Post » Fri May 27, 2011 11:25 pm

So I wanted my NPC to travel from Gnisis Barracks (interior) towards Gnisis Eggmine through a targeted script that starts from the dialogue. I made her leave barracks, but when I follow her outside, she stops. What's wrong, I think? Oh, right, geographically the eggmine is very close to barracks, but on different heights. All right, I added an additional waypoint where the upper path towards mines starts, beyond Tansumiran Cave Dwelling. She walks towards that waypoint and stops. Then I added one *more* waypoint - above that but somewhat aside, so that she would walk a long U-turn - from barracks straight to Tansumiran Cave Dwelling, then above towards Almu Cave Dwelling, then straight once again towards the eggmine. Instead, she goes to the first waypoint, makes few steps upwards to Almu, then turns down... and then her debugging messageboxes show that she already reached mines. Right now the script looks like this:
Spoiler
begin _Brenith_travelshort statusif ( MenuMode == 1 )	returnendifif ( GetPCCell "Gnisis" == 0 )	returnendifif ( status == 0 )			; Letter's got, go to the barracks doorMessageBox "Brenith:status  2, goto the door"	set status to 2	AITravel -256 -123 -41endifif ( status == 2 )	if ( GetAIPackageDone == 1 )MessageBox "Brenith:status  3, door reached"		set status to 3		PlaySound "Wooden Door Close 1"		PositionCell -82687 91821 1088 274 "Gnisis" ; outside the door		return	endif	if ( CellChanged == 1 ) ; in case player reaches the door and leaves sooner than herMessageBox "Brenith:status  3, door reached"		set status to 3		PositionCell -82687 91821 1088 274 "Gnisis"		return	endifendifif ( GetInterior == 1 )	returnendifif ( status == 3 )	MessageBox "Brenith:status  4, goto mines"	set status to 4	AITravel -86916 95074 1083 ;waypoint beyond Tansumiran	returnendifif ( status == 4 )		if ( GetAIPackageDone == 1 )MessageBox "Brenith:status  5, Tansumiran reached, goto Almu"		set status to 5		AITravel -86436 96932 1686		return	endifendifif ( status == 5 )		if ( GetAIPackageDone == 1 )MessageBox "Brenith:status  6, Almu reached, goto mines"		set status to 6		AITravel -80987 93307 2307		return	endifendifif ( status == 6 )	if ( GetAIPackageDone == 1 )MessageBox "Brenith:status  7, mines reached"		set status to 7	endifendifif ( status == 7 )			; Quest moved, go back to barracks	if ( GetJournalIndex ALM_Brenith_miners >= 30 )		set status to 8MessageBox "Brenith:status  8, go to Tansumiran"		AITravel -86916 95074 1083		return	endifendifif ( status == 8 )	if ( GetAIPackageDone == 1 )MessageBox "Brenith:status  9, halfway back"		set status to 9		AITravel -82687 91821 1088		return	endif	if ( CellChanged == 1 ) ;if player walks somewhere else during her walk, transfer straight to barracksMessageBox "Brenith:status  9, barracks"		set status to 10	endifendifif ( status == 9 )	if ( GetAIPackageDone == 1 )MessageBox "Brenith:status  9, barracks"		set status to 10		PositionCell 741, 689, -356, 132, "Gnisis, Barracks"		return	endif	if ( CellChanged == 1 )MessageBox "Brenith:status  9, barracks"		set status to 10	endifendifif ( status == 10 )	set status to 11	PositionCell 741, 689, -356, 132, "Gnisis, Barracks"	AIWander, 128, 0, 0, 60, 30, 10, 0, 0, 0, 0, 0, 0	StopScript "_Brenith_travel"	returnendifend

She's supposed to display messagebox #6 near Almu, then walk towards mines, then display messagebox #7 and wait until the quest turns her back to barracks. In reality, after reaching Almu, messageboxes #6 and #7 are displayed immediately one after another and she stops there. What am I doing wrong?

UPD: I divided the last segment with two more waypoints - before and after the bridge between the "pavilion" beyond Almu and the mines. Yet before reaching the bridge she stops and throws three remaining messageboxes up to the former #7 (I didn't edit the script in the post after update). Is there something wrong with pathgrids in "upper Gnisis" preventing her from correct walking, or my script can be made to work by itself?
User avatar
stevie critchley
 
Posts: 3404
Joined: Sat Oct 28, 2006 4:36 pm

Post » Sat May 28, 2011 9:17 am

An intact pathgrid greatly improves the reliability of AITravel, but the Gnisis Barracks and Gnisis Eggmine are in two different cells - pathgrids do not extend across cell boundaries. I can see in the construction set that the grid ends near the end of the mine side of the bridge.

In my experience it can be tricky crossing the cell boundary leaving a pathgrid - the grid seems to take a hold on the NPC. Travel up to the end of the grid (make it the destination) and then issue new AITravel instructions from there. Without a pathgrid to guide the NPC, you will need more intermediate waypoints. I suggest one at the end of the bridge (particularly if the NPC is going to eventually return along this route) and at least one more (at the change in direction of the path) before arriving at the mine entrance. It can be tricky negotiating the entrance to the bridge (the pathgrid should help).

The behavior you have observed with all of your messages displaying at once is familiar to me, but I am not certain I know exactly what is going on. I believe that GetAIPackageDone is true for one frame so without your returns (or a different script structure) the script is expected to return true at each stage and cascade through all the messages. One would think your returns would fix that problem, but it may not. I tried to consolidate a travel script by issuing the new AITravel instructions in the same block as GetAIPackageDone was true and I recall having problems similar to yours. I returned to using GhanBuriGhan's original structure with greater success. You might try something like this - it places AITravel instructions and GetAIPackageDone checks in separate logical blocks:

Begin Brenith_travelshort statusif ( menumode == 1 )    returnendifif ( GetPCCell "Gnisis" == 0 ) ; this solve problem of player resting or fast travel since global    returnendifif ( status == 0 ) ; Letter's got, go to the barracks door    MessageBox "Brenith:status  2, goto the door"    AITravel -256 -123 -41    set status to ( status + 10 )elseif ( status == 10 )    if ( GetAIPackageDone == 1 ) ; at door        MessageBox "Brenith:status  3, door reached"        set status to ( status + 10 )    elseif ( CellChanged == 1 ) ; in case player reaches the door and leaves sooner than her        MessageBox "Brenith:status  3, door reached"        set status to ( status + 10 )    endifelseif ( status == 20 )    PlaySound "Wooden Door Close 1"    PositionCell -82687 91821 1088 274 "Gnisis" ; outside the door;   PositionCell -82687 91821 1088 274 "Gnisis" ; why do you issue this instruction twice?    set status to ( status + 10 )endifif ( GetInterior == 1 ) ; nice touch for a global script    returnendifif ( status == 30 )	    MessageBox "Brenith:status  4, goto mines"    AITravel -86916 95074 1083 ;waypoint beyond Tansumiran    set status to ( status + 10 )elseif ( status == 40 )    if ( GetAIPackageDone == 1 )        MessageBox "Brenith:status  5, Tansumiran reached, goto Almu"        set status to ( status + 10 )    endifelseif ( status == 50 )    AITravel -86436 96932 1686    set status to ( status + 10 )elseif ( status == 60 )    if ( GetAIPackageDone == 1 )        MessageBox "Brenith:status  6, Almu reached, goto mines"        set status to ( status + 10 )    endifelseif ( status == 70 )    AITravel -80987 93307 2307    set status to ( status + 10 )elseif ( status == 80 )    if ( GetAIPackageDone == 1 )        MessageBox "Brenith:status  7, mines reached"        set status to ( status + 10 )    endifelseif ( status == 90 ) ; Quest moved, go back to barracks    if ( ( GetJournalIndex ALM_Brenith_miners ) >= 30 )        MessageBox "Brenith:status  8, go to Tansumiran"        set status to ( status + 10 )    endifelseif ( status == 100 )    AITravel -86916 95074 1083    set status to ( status + 10 )elseif ( status == 110 )    if ( GetAIPackageDone == 1 )        MessageBox "Brenith:status  9, halfway back"        set status to ( status + 10 )    elseif ( CellChanged == 1 ) ; if player leaves during her walk, back to barracks        MessageBox "Brenith:status  9, barracks"        set status to 150    endifelseif ( status == 120 )    AITravel -82687 91821 1088    set status to ( status + 10 )elseif ( status == 130 )    if ( GetAIPackageDone == 1 )        MessageBox "Brenith:status  9, barracks"        set status to ( status + 10 )    endifelseif ( status == 140 )    PositionCell 741, 689, -356, 132, "Gnisis, Barracks"    set status to ( status + 10 )elseif ( status == 150 )    if ( CellChanged == 1 )        MessageBox "Brenith:status  9, barracks"        set status to ( status + 10 )    endifelseif ( status == 160 )    set status to 1000    PositionCell 741, 689, -356, 132, "Gnisis, Barracks"    AIWander, 128, 0, 0, 60, 30, 10, 0, 0, 0, 0, 0, 0    StopScript "Brenith_travel"endifEnd


It is not a good idea to begin scripts (or perhaps anything ID) with an underscore, but it is not the source of your problems this time.

You had your travel instructions initiate on status == 0. Since this is described as a targeted global script I assume it is started from dialog at the same time the NPC has acquired the letter.

After studying your code more closely it looks like you do have a return journey to make, so the suggestions for the mine end of the journey (and perhaps some other intermediate waypoints) may be in order.

Scripts like this are vulnerable to the player resting and fast traveling in the cell where the script is running. As a targeted global script it may be more resilient to this sort of player behavior, but you will want to test those situations.
User avatar
Steve Smith
 
Posts: 3540
Joined: Sat Jun 30, 2007 10:47 am


Return to III - Morrowind