Skip to content
Scrab Joséline edited this page May 30, 2024 · 42 revisions

Acheron, by default, does not provide any complex Events on its own. Instead it relies on external mods to create their own quest and append them to Acherons internal event storage. These events will then be started when combat is ending iff their respective conditions apply.

Types of Events

In Skyrim, there are many ways for how combat can end and now all of them can be easily identified or universally applied to some specific interaction. A bandit walking up to you after you lost to them in battle would likely treat you more roughly than a group of soldiers that just rescued you from a forsworn ambush. To accommodate this, Acheron natively divides events in 5 categories, each representing a unique situation in which combat has ended:

  • Hostile
    You (and all your companions) have been defeated by some enemy faction (bandits, forsworn, ...).

  • Follower
    You are defeated in combat, but at least one of your companion is still standing and saved the day!

  • Civilian
    A group of travelers or soldiers passed by and saved you from your predicament and helped you push back against the bandits that attacked you.

  • Guard
    You started a fight against a group of civilians, but a group of loyal guards/soldiers stood up against you and defeated you.
    (Similar to Hostile, except that the enemies that brought you to your knees are local soldiers)

  • NPC
    The player was not involved in the encounter.
    (Note: "Not involved" means that no NPC engaged in combat with either you OR your follower. A common example to this would be a group of Stormcloaks engaging combat with Imperials. If you do not get involved, not attacking either faction, then the Event Type will be this one.)

Adding an Event

Events are stored as yaml files in Data\\SKSE\\Acheron\\Consequences\\<EventType>. When you want to add a new Event to Acheron, you hence create a new event.yaml file and add it to appropriate folder.
For example, a "Hostile" type event would go into Data\\SKSE\\Acheron\\Consequences\\Hostile\\MyCoolEvent.yml

Creating the Config File

Example

Version: 2

Name: Example Name
Description: Some description to describe Event "Example Name"
Quest: 0xABC|Example.esp

Priority: 2
Cooldown: 0
StartTeleport: false
Teleport: true
InCombat: false
Hidden: false

Requirements:
    - Temples.esm
    - Horses.esp

Conditions:
    Assailant:
        RaceType:
            - Human
        Faction:
            - 0x7F30E|Temples.esm: true
            - 0xA7EF|Example.esp: false
        Keyword:
            - 688827|Skyrim.esm: true
        CrimeFaction:
            - None

    Victim:
        Faction:
            - 0x7F30E|Temples.esm: false
        Keyword:
            - 0xA82BB: false
        Location:
            - 0x976ABC|Horses.esp: false
        Worldspace:
            - 0x3C

    Quest:
        Running:
            - 0x01EA51|Skyrim.esm: false
        Completed:
            - 0x01EA51|Skyrim.esm: false
            - 0x1EA50|Skyrim.esm

Attributes

List of Attributes

Bold attributes are mandatory.

  • Version:
    The version of the parser to use, i.e. how your file should be interpreted and read by Acheron. Unless you know what you are doing, it is recommended to leave this at the same version as the guide you are using as reference.

  • Name:
    The (human readable) name of your event. This is the name displayed the the User in Acherons MCM. The name should be unique across all other events in that category, hence I recommend using the following naming scheme: (<Prefix>) Name

  • Description:
    A short (human readable) description for your event. This should be at most 1 sentence long and will be displayed in the MCM as the description text when your event is hovered.

  • Quest Acheron Events are all stored as quests. This here should point at the quest form containing the event Acheron should start.

  • Priority
    The priority of your event. Should be one of the following:

    1. Default Events (0);
      Simple fallback events that require little to no context to be played. No story, short, fully radiant.
    2. Common Events (1);
      Generic events which may include some story telling or recognize the surrounding environment but are otherwise radiant.
    3. Story Events (2);
      Events which want to start or continue some story. These events are usually not radiant and are intended to advance character/story progression in some way, but aren't time sensitive, i.e. don't break the underlying story when the event isn't played on the very next defeat.
    4. Priority Events (3);
      Story Events which are time sensitive. This priority is reserved for events which require to be played at the first valid occasion in order to maintain some intended story path. E.g. when invading a castle, you want the (first) defeat from guards to always capture you and throw you into the prison of that castle. Use this to essentially override the event selection to always have your event played.
  • Cooldown:
    The time (in in-game hours) that should pass before your event can start a second time. (Default: 0)

  • StartTeleport:
    If this event teleports the player to some different location when the event starts.

  • Teleport:
    If this event teleports the player to some different location at any point while playing. (Implied 'true' if 'StartTeleport' is set).

  • InCombat:
    If this event is allowed to start while combat is still ongoing.

  • Requirements:
    Mods this event depends on and that should be present for this event to play out correctly.

  • Conditions:
    Conditions are used to further specify when your event is allowed to start. The higher the priority of your event, the most strict your conditions should be, to still allow events of lower priority to be played correctly. Use them to make sure that your event can be played out correctly if its being started.
    Conditions can either be inclusive (true) to signify that the condition must hold for some applicable object or exclusive (false) to state that the condition should be invalid for all applicable objects. If the attribute is emitted, it is assumed that the specific condition is inclusive (true)

    • Assailant:
      Conditions to run on the party that decided the most recent combat for themselves.

    • Victim:
      Conditions to run on the victim of the most recent encounter. This is either the player or (if the player has not been defeated) the actor that has been defeated most recently.

      • RaceType:
        The Race of some actor. This condition only makes sense for the assailants, as the victim will always be a human. Should be one of the following:

        • Human
        • Wolf
        • Dog
        • Chicken
        • Hare
        • FlameAtronach
        • FrostAtronach
        • StormAtronach
        • Bear
        • Chaurus
        • Cow
        • Deer
        • ChaurusHunter
        • Gargoyle
        • Lurker
        • Boar
        • DwarvenBallista
        • Seeker
        • Netch
        • Riekling
        • AshHopper
        • Dragon
        • DragonPriest
        • Draugr (includes Skeletons and other Draugr-like creatures)
        • DwarvenSphere
        • DwarvenSpider
        • DwarvenCenturion
        • Falmer
        • Spider
        • Giant
        • Goat
        • Hagraven
        • Horker
        • Horse
        • IceWraith
        • Mammoth
        • Mudcrab
        • Sabrecat
        • Skeever
        • Slaughterfish
        • Spriggan
        • Troll
        • VampireLord
        • Werewolf (includes Werebears)
        • Wispmother
        • Wisp
      • Faction:
        A list of factions to check the condition target against

      • CrimeFaction:
        A list of possible crime factions the that the condition target should (not) be part of

      • Keyword:
        A list of keywords to check the condition target against

      • Location:
        A list of valid locations that some actor should be in. Recommended to only use this for the victim.

      • Worldspace:
        A list of valid worldspaces that some actor should be in. Recommended to only use this for the victim.

    • Quest:
      The following conditions are all run on specific quests, checking if their current status is the same as the one specified by the condition:

      • Running:
        If the given quest is currently running.
      • Completed:
        If the given quest has already been completed.

Event Start

When Acheron calls for your event, the following exposition holds:

  • All actors which are not defeated will be in combat by the time your quest is started
  • Hostility remains unchanged. The "IsHostileToActor" condition/papyrus function will continue to return the expected result

Using these two pieces of information, you can collect every actor of the winning party by filling your first quest alias with some actor which is still in combat and not defeated:

// Assailant
subject.IsInCombat() == 1 AND subject.HasKeyword( AcheronDefeated ) == 0

and the remaining aliases by looking for allies of that actor:

// Assailant_Ally
subject.IsHostileToActor( Assailant ) == 0 AND subject.HasKeyword( AcheronDefeated ) == 1 OR subject.IsInCombat()

similarly, you can obtain the actors the winning party was fighting against, by asking for:

// Victim_Party
subject.IsHostileToActor( Assailant ) == 1 AND subject.HasKeyword( AcheronDefeated ) == 1
// Victim_Ally
subject.IsHostileToActor( Assailant ) == 1 AND subject.IsHostileToActor( Victim_Party ) == 0 AND subject.HasKeyword( AcheronDefeated ) == 1

notice how we do not need to check for combat here, as the assailants enemies are all either defeated or dead by the time your event is called

You can also find the actors of a third party by cross checking hostility, and similar for any other n'th party:

// Third_Party
subject.IsHostileToActor( Assailant ) == 1 AND subject.IsHostileToActor( Victim_Party ) == 1 AND subject.HasKeyword( AcheronDefeated ) == 1
// Fourth_Party
subject.IsHostileToActor( Assailant ) == 1 AND subject.IsHostileToActor( Victim_Party ) == 1 AND subject.IsHostileToActor( Third_Party ) == 1 AND subject.HasKeyword( AcheronDefeated ) == 1
// Fifth_Party...

However, there is also an important detail to remember here:
By the time your quest starts, you are in combat. This means that any combat specific events as well as Scenes which stop on combat will fire/stop the moment your quest starts. For that matter, I recommend starting your Quest with an RegisterForSingleUpdate(0.5) and putting your actual initialization into the OnUpdate code instead and potentially condition combat specific events on some Quest Stage that you set once the OnUpdate event is invoked

Best Practices

Events for Acheron can become quite complicated. Most importantly, once your event starts, Acheron will no longer manage the defeat status of actors around you. Who stays defeated and who stands up is entirely your responsibility which will allow you to add any detail to your mod, but also makes you responsible if some actor never recovers from their status.
Also keep in mind that your events may be played while surrounded by a large variety of potentially hostile actors. Combat may be suppressed for the most part, but this suppression is kept rather loose to allow NPC to still behave in a way that feels intuitive and realistic.

  • Rescue the player
    As mentioned, once your event starts, you are in charge of what happens to defeated actors. The absolute most important part of this "being in charge" is that you make sure here that the player is always rescued and released at the end of an event. Not doing so will soft lock the player or create other oddities.

  • Friend Factions
    Acheron itself will never adjust the hostility of Actors, which allows you to still use the "IsHostileToActor()" function the way its supposed to. However, this also means that actively making 2 hostile Actors aware of each other will cause these 2 Actors to engage into combat.
    In some cases, it is impossible to reliably avoid this, for example: When you want to have the enemy engage with their victim in dialogue. Hence, to avoid this, use friend factions! These simple factions mark themselves as friends, and because you are working with a quest, you can simply add all of your aliases to this faction allowing you to work with all of the relevant actors as you're used to. And once the quest ends, the faction is cleared and hostility is back to normal.

  • Beware of Combat
    While Acheron will leave you in charge of cleaning up the aftermath of a recent battle, Acheron itself won't just disable itself for some unknown period of time.
    Should combat out again during your event, Acheron will continue working as you'd expect and potentially start another event once combat has calmed down again. This obviously creates conflicts, because you don't want 2 events to handle the same battlefield at the same time, probably. So make sure to properly account for this:

    • You can either shut down your own event silently when combat breaks out again, and surrender the field to whichever event is started next once combat cooled down again
    • or you can disable Acheron, partially or entirely. See Acheron.psc for 2 functions to disable Acheron either entirely or only its consequences.

    Which one of these options is ideal entirely depends on your context. If you expect combat to break out during your event. Perhaps you force the player to fight for their freedom in some pit fighter arena? In such cases, it seems more logical to just disable Acheron than to completely shut down your own event, of course it essential here that you re-enable Acheron again once your event shuts down.
    ..Other times, perhaps during a negotiation with some bandits, a combat breaking out again may be considered as a failed negotiation and in such cases silently shutting down the event is a better approach.

Clone this wiki locally
  翻译: