Wiederkehrender Gegner in Spielerhaus

Maylle

Fremdländer
Hallo allerseits!

Ich arbeite gerade an einem kleinen Mod, in dem man als Besitzer von Breezehome in Whiterun dem wütenden Skelett des früheren Hausbesitzers in einer Höhle unterm Haus begegnet. Nachdem man diesen erledigt, wird man vor die Wahl gestellt, die Höhle zu versiegeln oder sie als zusätzlichen Raum zu benutzen. Entscheidet sich der Spieler für die letztere Option, so würde ich es geren so einrichten, dass das Skelett von da an so alle paar Tage oder eher Wochen im Haus vorbeischaut (als kleinen Spuk, sozusagen). Dabei würde ich es gerne vermeiden, das Skelett einfach in der Wildniss herumwandern zu lassen, sondern ich würde es gerne eben in einem regelmäßigen Zeitabstand _im_ Haus spawnen lassen.
Mein Problem: Ich habe bisher nur grundliegende Fähigkeiten, was Papyrus angeht, und mir fehlt derweilen auch noch der Überblick über alle verfügbaren Funktionen, wodurch ich eben vor einem Rätsel stehe, wie ich denn nun so einen regelmäßigen "Spawn-Rhythmus", wenn man so will, einrichten könnte.

Wenn mir dabei jemand behilflich sein könnte, wäre ich euch sehr verbunden
tes_happy.gif


Vielen Dank schonmal im Voraus für jegliche Hilfe,
Maylle
 
Okay, für alle, die etwas ähnliches machen wollen: habs jetzt raus :D

Zuerst habe ich ein paar patrolIdleMarkers ausgelegt, miteinander verlinkt und das Skelett als Besitzer zugeordnet. Dann wurde dem actor (dem Skelett) ein angepasstes patrol AI-Package verpasst, mit einer Condition welche auf die richtige Quest-Stage prüft, und einem Zeitplan à la "Day/Month/Date: Any, Time of Day: Any, Duration: 5 Std.". Soweit, so gut.

Nun wollte ich ja darauf reagieren, wenn der actor während seiner Patrouille getötet wird, sodass ich ihn regelmäßig re-spawnen kann. Da habe ich es eben zuerst mit Papyrus-Fragments in der Begin/End/Change-Section des AI-Package probiert (s. oben), was aber nicht funktioniert hat. Soweit ich jetzt weis, liegt dies daran, dass AI-Packages nicht ausgeführt werden, solange der Actor tot und / oder disabled ist (im Nachhinein eigentlich recht logisch :)). Also habe ich mir letztendlich dieses Script geschrieben:ctors. So I ended up with this script:

Code:
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

Was dieses Script tut:

Jedes Mal, wenn die Zelle, in der sich der actor gerade befinded, "angehängt" / attached (Erklärung zu diesem Zustand hier):
Code:
    - Prüfe, ob der Actor tot ist
        - wenn ja, dann belebe ihn wieder
    - Egal, ob tot oder lebendig, wenn der Actor disabled ist
        - dann enable ihn und trage dich ein, um von jetzt an das Event [URL="http://www.creationkit.com/OnUpdateGameTime_-_Form"]onUpdateGameTime()[/URL] im Abstand von 15 in-game-Minuten zu erhalten.

Jedes Mal, wenn nun das Event onUpdateGameTime() erhalten wird:
Code:
    - Prüfe, ob sowohl die Quest-Stage stimmt also auch ob der Actor disabled ist
        - Prüfe auch, es gerade (entweder Montag oder Mittwoch) ist, und ob es irgendwo zwischen 00:00AM und 01:00AM ist...trifft beides zu, dann:
            - enable den Actor
            - Prüfe, ob der Actor gerade tot ist
                - wenn ja, dann belebe ihn wieder
            - In jedem Fall melde dich wieder davon ab, das Event onUpdateGameTime() weiter zu erhalten

Jedes Mal, wenn der Actor von einem AI-Package wegschaltet:
Code:
    - Prüfe, ob es sich bei dem Package, aus dem der Actor gerade ausgetreten ist, um unser patrolPackage handelt
        - wenn ja, dann disable den Actor, da seine Patrouille zu diesem Zeitpunkt beendet ist und wir nicht wollen, dass er nun zwei Tage lang einfach nur dasteht :)

EDIT: Sorry für die vielen Code-Boxen, aber anscheinend werden hier keine Einrückungen unterstützt Oo

Die beiden Funktionen unten:

getCurrentDay() retourniert mir einen Integer, welcher den Wochentag 0 (=Sonntag) bis 6 (=Samstag) repräsentiert
getCurrentHourOfDay() retourniert einen float-Wert, der die aktuelle Uhrzeit darstellt (ich brauche in meinem IF-statement lediglich die Stundenzahl und nicht die ganze Uhrzeit, weshalb ich das Ergebnis dieser Funktion dort kurzerhand auf int caste).

Und damit hätten wir's eigentlich.

Was man jetzt noch verbessern / verändern könnte:
Man könnte beispielsweise die beiden fix festgelegten Tage Montag und Mittwoch mit zwei Math.random() Aufrufen ersetztn, sodass der Actor zwei mal pro Woche spawnt, wobei eben die beiden Tage dann zufällig wären - dasselbe könnte man natürlich auch für die Tageszeit machen.
Eine weitere Option wäre es, sich nach dem Spawn des Actors nicht mehr vom onUpdateGameTime()-Event abzumelden, sodass der Spawning-Cycle unabhängig davon begonnen wird, ob der Spieler gerade jene Zelle, in welcher der Actor zuletzt disabled worden ist, betritt, oder nicht.
Das sind aber wie gesagt einfach nur zwei Optionen - ich benutze das Script derzeit in seiner obigen Form.

Bei Fragen oder Feedback einfach melden :]

- Maylle
 
Zuletzt bearbeitet: