Jump to content

create recurring enemy within same interior


Maylle

Recommended Posts

Hi there,

 

So I'm wondering how I could go about creating an enemy that visits the player's house on a regular interval.

 

Scenario:

I have a small mod in the works where you find a cave beneith Breezehome. In the cave, you encounter an enemy (the skeleton of the previous owner of the house), that you have to kill. When you get back up into the house, I ask the player whether the entrance to the cve should be sealed or kept open. In the latter case, the empty cave can be used as storage area, but I want the skeleton to return every few days or weeks.

 

Any ideas on how this could be done ?

 

Thank you in advance,

Maylle

Link to comment
Share on other sites

Alright, for anyone out there who might look to do the same thing, figured it out myself:

At first I laid our several patrolIdleMarkers, linked them together and set their ownership to the skeleton. Then I added a custom patrol AI-package, with a condition that checks for the right quest stage and a schedule of "Day/Month/Date: Any, Time of Day: Any, Duration: 5 hrs". That's the patrol part.

Now, I wanted to handle the actor dying during his patrol by disabling it and re-spawning it regularly. First, I tried doing this via Papyrus fragments in the Begin/End/Change section of the AI package...that did no work since I learned that AI-Packages do _not_ run on disabled and / or dead actors. So I ended up with this script:

 

 

Actor Property thisActor Auto

Quest Property thisQuest Auto

Package Property patrolPackage  Auto  


Event onCellAttach()
    if(thisActor.isDead())
        thisActor.disable()
    endIf
    if(thisActor.isDisabled())
        registerForUpdateGameTime(0.25)
    endIf
endEvent

Event onUpdateGameTime()
    ;debug.notification("Day: " + getCurrentDay() + ", Time: " + getCurrentHourOfDay() as int)
    if((thisQuest.getStage() == 100) && (thisActor.isDisabled()))
        if(((getCurrentDay() == 1) || (getCurrentDay() == 3)) && (getCurrentHourOfDay() as int == 0))
            thisActor.enable()
            if(thisActor.isDead())
                thisActor.resurrect()
            endIf
            unregisterForUpdateGameTime()
        endIf
    endIf
endEvent

Event onPackageChange(Package akOldPackage)
    if(akOldPackage == patrolPackage)
        ;debug.notification("patrol just ended")
        thisActor.disable()
    endIf
endEvent


int function getCurrentDay()
    int day = Math.floor(Utility.getCurrentGameTime()) % 7
    return day
endFunction

float Function GetCurrentHourOfDay() 
    float Time = Utility.GetCurrentGameTime()
    ;Remove "previous in-game days passed" bit
    Time -= Math.Floor(Time)
    ;Convert from fraction of a day to number of hours
    Time *= 24
    Return Time
EndFunction

 

 

 

What this script does:

Whenever the Cell is attached (further explanation here):

- check whether the actor is dead

- if so, then disable it

- regardless of the actor being dead or alive, check whether it's disabled

- if so, register to be notified of updated game time every 15 ingame-minutes (time spent in menus and wait/sleep/fast travek does not count)

 

Whenever the onUpdateGameTime() event is fired:

- check for both the right quest stage and for the actor to be disabled

- then check if it is (either Monday or Wednesday) and if the current time is somewhere between 00:00 AM and 01:00 AM...if both are true, then:

- enable the actor

- check qhether the actor is dead

- if so, then resurrect it

- in any case, unregister from receiving the onUpdateGameTime() event

 

Whenever the actor switches away from their current AI-Package:

- check whether the package they switched away from was our patrolPackage

- if so, disable the actor since that means their patrol is over and we don't want them standing around or sandboxing where they stand for two days :smile:

 

The two functions at the bottom:

getCurrentDay() returns an integer representing the number of the current day in a week, ranging from 0 (=Sunday) to 6 (=Saturday)

getCurrentHourOfDay() returns a float value representing the current time (I get the rounded hour by casting that value to an integer within my if-statement)

 

And that was basically it.

What one could also do is to replace the two hard-coded days within the if-statement above with two Math.random() calls so that the actor randomly spawns to times a week - the same could be done for the time of day of course. Another option might be to never really unregister from the onUpdateGameTime() event so that the spawning cycle is started regardless of whether the player just entered the cell the actor was last disabled in. However, these are just options - I'm using the script as is atm.

 

If you have any questions or feedback, just out with it :]

 

- Maylle

Edited by Maylle
Link to comment
Share on other sites

  • Recently Browsing   0 members

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