Nirn.de

Gast

Thema: Wiederkehrender Gegner in Spielerhaus  (Gelesen 1606 mal)

  • Neuling
    • Neuling
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 :)

Vielen Dank schonmal im Voraus für jegliche Hilfe,
Maylle
  28.03.2014, 19:33
  • Offline


  • Graf
    • Adel
Über GetDayOfWeek könntest du das Skelett z.B. jeden Dienstag spawnen lassen.
  31.03.2014, 10:26
  • Offline
  • SCP-Wiki-DE


  • Neuling
    • Neuling
Danke für Deine Hilfe - was ich da stattdessen für eine Idiotenkonstruktion gebaut hätte, das würdest Du nicht glauben :D

Habe jetzt ein paar PatrolIdle-Marker verteilt, miteinander verbunden, und dem Skelett ein Patrol-AI-Package verpasst, welches als Condition auf die entsprechende Quest-Stage prüft und als Zeitplan quasi "jeden Montag, Beginn 0h 05m, Dauer 5h" hat. Funktioniert soweit auch. Mein Problem liegt jetzt jedoch eher bei den Script-Fragments, die ich je am Beginn und am Ende des Package ausführen möchte. Hier das ganze Script:

Klappbox
Code

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment
;NEXT FRAGMENT INDEX 11
Scriptname PF_BE_toiletKeeperPatrol Extends Package Hidden

;BEGIN FRAGMENT Fragment_8
Function Fragment_8(Actor akActor)
;BEGIN CODE
beginFunc()
;END CODE
EndFunction
;END FRAGMENT

;BEGIN FRAGMENT Fragment_10
Function Fragment_10(Actor akActor)
;BEGIN CODE
endFunc()
;END CODE
EndFunction
;END FRAGMENT

;END FRAGMENT CODE - Do not edit anything between this and the begin comment


Actor Property BE_toiletKeeper Auto

function beginFunc()
if(BE_toiletKeeper.isDisabled())
debug.notification("keeper disabled --> ENABLED")
BE_toiletKeeper.enable()
if(BE_toiletKeeper.isDead())
debug.notification("keeper dead --> RESURRECTED")
BE_toiletKeeper.resurrect()
endIf
endIf
endFunction

function endFunc()
BE_toiletKeeper.disable()
debug.notification("keeper's package ended ---> DISABLED")
endFunction

Dieses Script ist unter "attached scripts" angefügt und wie man oben sieht, möchte ich im Begin- und End-Fragment den entsprechenden Code via function calls aufrufen. Das ganze kompiliert auch ohne Fehler oder Warnungen, wird aber nirgends in der Laufzeit des AI-Package ausgeführt...

Eventuell eine Idee, woran dies liegen könnte?
  31.03.2014, 23:49
  • Offline


  • Neuling
    • Neuling
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:

Klappbox
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):

    - 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 onUpdateGameTime() im Abstand von 15 in-game-Minuten zu erhalten.

Jedes Mal, wenn nun das Event onUpdateGameTime() erhalten wird:
    - 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:
    - 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 :)

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
« Letzte Änderung: 03.04.2014, 20:35 von Maylle »
  03.04.2014, 20:21
  • Offline