NPCs, Horses, and you

From the Oblivion ConstructionSet Wiki
Revision as of 00:29, 28 April 2006 by imported>Shepnorfleet
Jump to navigation Jump to search

NPCs, Horses, and You...

Introduction

This how-to was not designed for beginners but for people who have been banging their head against the same bloody wall since they created their first NPC ... When the phrases "MOUNT DA$#@#!" or the equally agitated 'GET OFF THE D^@# HORSE, B#@^H!" issued forth in abundance. If this is you, as it was me, then perhaps this HOW-TO may grant you a measure of sanity.

The purpose of this how-to is...

  • to get your NPC to mount when you mount
  • to get your NPC to dismount when you dismount

It is not:

  • The best solution to the problem, I'm sure.
  • A particular fast or optimized solution.
  • Nor, im sure, is it the best conceptual or compliant solution.

With this in mind, proceed at your own risk....

Important Factors

After hours of tinkering I was able to infer a few things about how horses and NPCs interact. I expect there may be some inaccuracies or perhaps they are simply wrong; regardless, for me they were the secrets to unlocking the mysteries of NPCs, horses, and you. ;)

  • NPCs respond to the TRAVEL package with the 'Use Horse' flag correctly and mount on the horse. The FOLLOW package with the 'Use Horse' flag did not appear to cause the NPC to mount the horse.
  • Likewise, NPCs respond to the TRAVEL package without the horse flag correctly and dismount, if mounted; Again, the FOLLOW package seemingly does not have this effect.
  • Unlike mounting, dismounting cannot be triggered with the addScriptPackage function. Instead, the dismount has to be triggered by an evaluatePackage (evp) command.

The Packages

You need to create four AI packages for your NPC, as follows:

  • PACKAGE 1 - TRAVEL
    • NAME: 'travelToHorse'
    • PURPOSE: To get the NPC moving to the horse. When the NPC is close enough to the horse, the USE HORSE bit will kick in and the NPC will mount.
    • STORAGE: Outside the NPCs Package List
    • FLAGS
      • Use Horse
    • LOCATION: HorseType (ex:E3Horse)
  • PACKAGE 2 - FOLLOW
    • NAME: 'followOnHorse'
    • PURPOSE: After the NPC has mounted this package will be activated, causing the NPC to follow the player.
    • STORAGE: Outside the NPCs Package List
    • FLAGS
      • Use Horse
    • TARGET: ('Abandoned Mine','PlayerRef')
      • DISTANCE: 350 (Main Quests use this)
  • PACKAGE 3 - TRAVEL
    • NAME: 'travelToPlayer'
    • PURPOSE: Causes the NPC to dismount and travel to the player.
    • STORAGE: First in NPCs package list
    • CONDITION: getScriptVariable( CELL , dismountFlag )==1 && isRidingHorse==1
      • Where CELL is the initial cell the NPC was created in, view the USE INFO for the NPC to see where that is.
    • LOCATION: Player
  • PACKAGE 4 - FOLLOW
    • NAME: 'followOnFoot'
    • PURPOSE: Causes the NPC to follow the player on foot.
    • STORAGE: Outside the NPCs Package List
    • TARGET: Player
      • DISTANCE: 0 (default)

The Script

This script should be incorporated into your NPCs primary script.

float mountTimer
short isMountTimerOn
short mounted
short dismountFlag

begin gamemode
    ;dismount section
    if mounted == 1 
        if Player.IsRidingHorse == 0
            if IsRidingHorse == 0
                Message "NPC has dismounted"
                set dismountFlag to 0
                set mounted to 0
                set isMountTimerOn to 0
                set mountTimer to 0
                addScriptPackage followOnFoot
            else
                if isMountTimerOn == 0
                    Message "Trying to get NPC to dismount"
                    set isMountTimerOn to 1
                    set mountTimer to 3
                    set dismountFlag to 1
                    evp
                else
                    if mountTimer <= 0
                        Message "dismountTimer expired"
                        set mountTimer to 3
                        evp 
                    else
                        set mountTimer to mountTimer - getSecondsPassed
                    endif
                endif
            endif
        else ;Timing issues
            if isRidingHorse == 0 ;NPC managed to dismount
                Message "Player has mounted out of turn, NPC dismounted"
                set isMountTimerOn to 0
                set mountTimer to 0
                set dismountFlag to 0
                set mounted to 0
            else
                if isMountTimerOn == 1 ;NPC still trying to dismount
                    Message "Player has mounted out of turn, in the timer."
                    addScriptPackage followOnHorse
                    set isMountTimerOn to 0
                    set mountTimer to 0
                endif
            endif
        endif
    endif

    ;mount section
    if mounted == 0 
        if Player.isRidingHorse==1
            if isRidingHorse==1
                Message "NPC is Mounted"
                set mounted to 1
                set isMountTimerOn to 0
                set mountTimer to 0
                addScriptPackage followOnHorse
            else
                if isMountTimerOn == 0
                    Message "Trying to get NPC to Mount"
                    set isMountTimerOn to 1
                    set mountTimer to 3
                    addScriptPackage travelToHorse
                else
                    if isMountTimerOn <= 0
                        Message "mountTimer expired"
                        set mountTimer to 3
                        addScriptPackage travelToHorse
                    else
                        set mountTimer to mountTimer - getSecondsPassed
                    endif
                endif
            endif
        else ;Timing issues
            if isRidingHorse == 1
                set isMountTimerOn to 0
                set mountTimer to 0
                set mounted to 1
        else ;Timing issues
            if isRidingHorse == 1 ; NPC managed to mount
                Message "Player has dismounted out of turn, NPC mounted"
                addScriptPackage followOnHorse
                set isMountTimerOn to 0
                set mountTimer to 0
                set mounted to 1
            else
                if isMountTimerOn == 1 ; caught while waiting for NPC to mount
                    Message "Player has dismounted out of turn, in the timer."
                    addScriptPackage followOnFoot
                    set isMountTimerOn to 0
                    set mountTimer to 0
                endif
            endif
        endif
    endif		
End

Caveats and Notes

Caveats
  • This script assumes that the NPC's horse is nearby, you could be in for long wait if its far away. You could use the getDistance function to determine if the NPC bothers to mount or not.
  • Obviously the NPC must own the horse either by faction or direct ownership.
  • I used a Unique Horse ID 'E3Horse' so the NPC couldn't be confused by other horses nearby.
  • Do not use 'continue when PC is near' in 'Package 2' or the NPC will never dismount.
Notes
  • The 'mounted' variable in the script is of type short created at the beginning and set to 0. Its just a toggle so that I know to change the package.
  • While mounted is used for mounting and dismounting, the dismountFlag is a special indicator to cause only a particular package to get evaluated, and is only used when dismounting.
  • You may wonder why I have a timer for mounting and dismounting...hehe...its because the darn NPCs keep forgetting what their supposed to be doing. Sometimes you can actually see that they will move for a bit and then stop and then when the "timer up" message appears they will start moving again. Think of it as pretty little cattle prod designed just for NPC fannies. ;)


Hope this was helpful. -- Breave Apr 26, 2006