Jump to content

Ambitious Mods - Designing / Planning / Advice - Using [EvilSlaveOwner] as an example.


Evilynn

Recommended Posts

[What Is This?]

 

I'm new to modding, but I have a lot of experience software engineer. 

 

I created this thread to share information on how to design and build an ambitious mod.

 

I don't even want to think about the pain and heartache much of the Skyrim modding community has lived through because most modders do not have a background in programming.

 

I've started working on an ambitious mod called [EvilSlaveOwner]. After receiving some really good advice, I thought It would be a good idea to start a thread about how to approach larger projects.

 

I'm also going to share my thought process as I create [EvilSlaveOwner]. Hopefully it will serve both as an example of "Things you should think about when creating a mod" and as a place for people to give me advice, offer suggestions, and ask questions.

 

Hopefully we can generate some great discussion on the topic.

 

[How To Plan a Large Project]

 

I'm going to use the mod I'm planning as an example here.

 

The project I'm starting is called EvilSlaveOwner for a very good reason, and there is nothing nice about it. My apologies to anyone that is offended here, but that's the example I'm going to use.

 

[step One: Plan Big - Start With Your Requirements]

 

Write your requirements down. Don't try to keep them all in your head.

 

 

 

  1. Capture NPC's as slaves
  2.  
  3. Rape / torture / punish / humiliate / pose slaves (You did see the evil in the mod name right?)
  4.  
  5. Slaves can escape.
    • They might run away.
    •  
    • They might try to kill, capture, rape, and/or torture you instead.
    •  
  6.  
  7. Training a slave takes time and work.
  8.  
  9. Includes a large dungeon.
  10.  
  11. Slaves should automatically be numbered (with slavetats)
  12.  
  13. Have bondage gear, furniture , etc.
  14.  
  15. Slaves can be forced to use said gear.
  16.  
  17. Storyline that gives you the ability to do all of this.
    • ​​You end the storyline with the large dungeon.
    •  
    • You receive the required gear / spells in the storyline.
    •  
  18.  
  19. Ability to change your slaves personality.
    • ​​Change is caused by spells / items followed with rape / torture / humiliation. AKA: You can make a slave like bondage by using a spell to twist her mind and then use a lot of bondage gear with her.
    •  
    • Change is limited. My first though is that you can only change how they feel about one or two things. For example you could make a slave love bondage and posing... but they still hate you and do not cooperate except in the the two areas mentioned.
    •  
  20.  
  21. The ability to assign slaves roles in the dungeon. For example, Paradise Halls - Home Sweet Home does an awesome job with the taskmistresses.
    • Mistress - Can order other slaves around. Exact details would be super complicated, but you could train a slave to love sex, then make her a mistress and she will have sex with other slaves that love sex. Or, you could train the mistress to love sex and to not have empathy - then she would prefer slaves that dislike sex and rape them.
    •  
    • Guard - Prevents slaves from escaping - must be trained in combat.
    •  
    • Crafter - Can create / replace furniture.
    •  
    • Bard - performs songs for you
    •  
    • Overseer - Tells other slaves what do to.
    •  
    • Slaves should have a tattoo showing their current job using slavetats.
    •  
  22.  

 

 

 

 

 

[step Two: Review Your Requirements]

 

Read over your requirements and keeping an eye out for how complex different requirements are, and how different requirements will interact with each other.

 

 

 

 

Isn't that an awesome mod!

 

Anyone want to know when it will be out?? Next Month? 6 Months?

 

The real answer is "never".

 

The scope is HUGE.

The project is complicated to the point of impossibility.

Some requirements will almost certainly be impossible to do in Skyrim.

Ignoring that, this is literally many thousands of unpaid hours of work.

 

It's not going to happen.

 

But lets see what we can do...

 

 

 

 

[step Three: MVP]

 

MVP stands for "Minimum Viable Product".

 

You need to take all of your requirements and strip out everything that isn't absolutely required.

 

That cool feature you want so much might be removed.

 

Be brutal to yourself.

 

The idea is that you can add the features back in one at a time in the next versions of the mod.

 

I looked at my huge list of awesome ideas and brutally stripped it down to just three things.

 

 

 

  1. Capture slaves
  2.  
  3. Free slaves
  4.  
  5. Make slaves pose.
  6.  

 

Why just the three listed?

 

Because the core of the mod is slavery, and I cant have slaves if I cant capture them. Freeing slaves is included because I think it will be a very simple addition once I have capturing working.

 

I then looked at the list and picked out the simplest thing I could do to a slave and decided that telling them to do a pose would be easiest.

 

 

 

 

[step Four: Break Your Project Into Small Pieces]

 

This is something that creation kit and Skyrim will fight against you on, but it's worth the time.

 

With the simple list I have now, it would be easy to skip this step. DON'T do it!

 

I know I plan on adding much more functionality to the mod.

 

I don't just want to fulfill the three requirements I have listed. I want to fulfill them in a way that allows me to add additional functionality in the future.

 

 

 

 

With that in mind, I immediately see a core piece that I need to create.

 

I need a way to store and access slaves using scripts in creation kit.

 

Whatever method I use to capture or free a slave, I need a way to know "This is a slave" and a way to retrieve / modify information about her. In programming terms this is a repository (often called a repo)

 

I also know that all of the pieces of my mod will need the ability to access this.

 

So, part one of my mod is:

 

Part 1: SlaveRepo - Storage & Retrieval of slaves. 

 

I also know that I will end up with many helper utility functions that will be used in many places. 

 

Part 2: SlaveUtility - general functions and properties related to my mod. Mostly to access and pass information between parts of my mod.

 

Next comes capturing and releasing slaves. Lets make this a simple version.

 

Part 3: SimpleSlaveCapture - A dialog option that Captures or Releases a slave NPC.

 

Now we just need a way to pose a slave. Lets keep it simple as well. 

 

Part 4: SlavePosing - A way to make a slave pose and stop posing.

 

 

 

 

[step Five: Organize The Pieces]

 

This is about controlling communication between parts of your mod. Some parts will need to talk to each other, but other parts don't care about each other at all.

 

 

 

SlaveRepo + SlaveUtility:

 

Everything will need access to them. It's really part of the core of the mod.

 

Note: You should create this and flag it as an esm. Creation Kit will fight you here because you can not edit an esm. You will spend an annoying amount of time closing CK, opening TES5Edit, and changing your flag back and forth.

 

SimpleSlaveCapture:

 

Should SlaveRepo care about how a slave was captured? NO!

Should SlavePosing care about how the slave was captured? NO!

 

Nothing else should care about how a slave is captured or released. It doesn't make a difference to the rest of the mod, and this is a prime example of a stand alone piece. Make this a separate esp.

 

One huge example of what this brings to the table is that 6 months from now I could create a new capture/release system and just drop in the new esp without any other code changes. I can even let my users pick and choose which capture system they want by offering both.

 

SlavePosing:

 
This one is harder. It's really two parts. The first is the ability to make slaves do animations. That is something that may parts of the mod will need. The second part is telling the slave which animation to assume. That part doesn't need access to anything else, and nothing should need access to it. This should also be a sand alone mod.
 
After going over all of that, I end up with:
 
SlaveCore - (SlaveRepo, SlaveAnimations, and SlaveUtility)

SimpleSlaveCapture - (Capture and release slaves with dialog options)

SlavePosing - (Tell the slave to use different poses with dialog options)

 

 

 

 

[step Six: Dependencies]

 

Don't create functionality that you don't really need to. For example, in my case I should not create a new animation framework to make the slaves pose. Zaz Animation Pack has already solved this.

 

I can just add Zaz Animation Pack as a dependency, and my SlaveAnimations can call Zaz Animations. This also allows me to add other animations in the future either as a new additional dependency, or as a new animation I create (My SlaveAnimations just needs to konw how to handle each one)

 

People have already soved many of the problems you will run into.

 

SKSE, SkyUI, and SexLab also bring a lot to the table.

 

[step Seven: Write Code]

 

I lied.

 

You have one other thing to do first.

 

 

[step Seven: Backup / Revision History]

 

Think about how you want to backup your project.

 

If 2 months from now your computer dies, will you lose everything?

 

I highly recommend github as an awesome way to keep your code history. Git is far more than simply a backup. It's also a history of changes, and you can tag release versions and change to them. You can also create branches, pull requests, and etc. I'm not covering it in this post at all, but It brings a lot to the table.

 

[step Eight: Write Code]

 

Now you can start writing code. Force yourself to stick to some basic rules.

 

  1. Keep if DRY: "Don't Repeat Yourself" - If your copying and pasting the same code in multiple locations in your mod, stop. Create a utility function that runs the code, and call the utility function instead of copying the code in multiple locations.
  2.  
  3. Keep things modularized. Things that don't need to know about each other, shouldn't know about each other. This makes things slightly harder up front, but also makes things several order of magnitudes easier later.
  4.  
  5. Don't be afraid to rewrite your work - even large parts of it. Programmers call this "Refactoring" and it's sometimes required.
  6.  
  7. Avoid bandaid fixes. When there is a problem you often have a choice between either fixing the source of the problem (rewriting how part of your code works) or by doing some workaround that you will need to remember about next time you deal with that part of the code. Avoid the bandaid when possible - long term it's a lot more work.
  8.  

 

 

 

[step Nine: Beta Test / Soft Release]

 

Once version one is working correctly, release it.

 

Make sure people know it's a WIP.

 

[step Ten: Add A Feature And Fix Bugs]

 

Now you can pick another feature to add in. Remember to balance complexity and difficulty with how important the feature is to you.

 

Over time you will end up with an amazing mod with many features. 

 

[Credits]

 

skyrimll

legume

 

I specifically created this thread to get the advice they gave out to more people (and added in advice of my own)

See this thread for more information.

 

[Ending Comments]

 

Remember to write for yourself first. Your mod, your game, your time.

Creating mods is a labor of love but make no mistake, it is labor!

Coding takes a lot of time. HUGE amounts of time.

 

 

That's all I have time for right now. I hope it helps someone!

 

You can see the github repos related to this mod at: https://github.com/EvilSlaveOwner

I don't even want to think about the pain and heartache much of the Skyrim modding community has lived through because most modders do not have a background in programming.

 

Hopefully we can generate some great discussion on the topic.

Link to comment

All good advice :).

I have a couple of comments.  Nothing too significant but might help get things rolling.

[step One: Plan Big - Start With Your Requirements]

 

Write your requirements down. Don't try to keep them all in your head.

 

6. Slaves should automatically be numbered (with slavetats)

I'm not sure "automatically" should be a requirement.  I can imagine some people would enjoy branding new slaves as a quest.  Perhaps there will be a house, or tattooing parlour you can take your slave to.  And some may not want their slaves branded at all.

This sounds like a good candidate to add to the MCM menu.  I am a big supporter of the theory that most things should be configurable in the MCM options menu.

Regarding the MCM page:

- I highly suggest using the new state (ST) mechanism vs. the older Object Identifier (OID) mechanism.

- You can find the API for the MCM menus here.

- I've done some decent features in my Devious Framework mod.  Some complicated lists, opening the last page by default, version control for the MCM script (which can be troubling if not done correctly), and lockable features the player can't access at times.

Feel free to view the source (and DFW Support) to see examples of some of these things.

I highly recommend incorporating the last page mechanism (search for uses of the _szLastPage variable).

I also recommend not creating variables for the default values as I did.  They get used and change so rarely I don't think they are worth the overhead.  In this rare instance I think "magic numbers" (just using the number instead of a variable) are the way to go.

 

 

[step One: Plan Big - Start With Your Requirements]

 

Write your requirements down. Don't try to keep them all in your head.

 

9. Storyline that gives you the ability to do all of this.
    • ​​You end the storyline with the large dungeon.
    • You receive the required gear / spells in the storyline.

I think it would do wonders to expand the world of Skyrim if this "Dungeon" could be any location that fulfills a set of requirements.

For example, it might be a requirement that the "location" be a single cell or a set of cells.  Perhaps all must be indoor and adjacent.  Perhaps they need to have at least three jail cells and at least five sets of bondage furniture.

Making the location flexible will allow others to create customized houses/dungeons in locations that work for different story lines.  For example a dungeon could be created outside of Solitude when the original dungeon might be created near Whiterun.

 

Happy modding,

legume.

Link to comment

I'm not entirely sure what is that about, it sounds like a planned mod on the one hand, but the description sounds rather like some advice to modders?

Not beeing a modder (means, i don't do coding nor CK work) but somebody who enjoys playing them, maybe i can add something nevertheless:

 

For quest mods (compared to frameworks), details are important. It's the small stuff that gives your mod the depths and makes me loving it. Better use some less NPCs with some background than a bunch of them with no dialogue at all, even few lines make quite some difference imho. For me (currently writing some stories for 2,5 mods) that's also the most difficult and time consuming part, creating a scenario is easy, but filling it with life is hard work. But i think it's worth it. :)

For your mod, i assume you are supposed to capture vanilla NPCs and they don't need a background. But a variance in reaction to be enslaved via some comments/dialogues would be nice to have i think. But i admit that capturing slaves is not that much my fetish, and since i'm usually too lazy to deal even with followers... it's not very likely i'll use your mod beyond "tried it, had fun"

 

And maybe you could collaborate with somebody. Delzaron for example is awesome in creating in- and exteriors, NPCs and stories but he has often some problems to get the coding done. Depends of course, but i could imagine some stuff would actually be faster done if you two would work on two mods and share your work, everybody doing what he's best at.

 

Good luck with your mod and have fun. :)

Link to comment

@legume

 

I was already planning on using MCM, but I completely missed State Options. That's a great improvement, and will make things much easier to handle in the long term as options get complicated.

 

Good point about optional slavetats. I also like the idea of adding a tattooing parlour later on.

 

That might even make for a good role when I reach that far in my plans. I'll add "tattoo artist" to my list.

 

For the dungeon ideas... I think I need more information on what exactly i'm giving up / gaining by opening up using other locations as dungeons.

 

I'm don't have any specific plans right now because I don't know enough about scenes / actor control / markers / etc to make an educated choice. When I reach that far in my plans I'll definitely reevaluate.

 

I like the idea of being able to pick a location to be your dungeon.

 

@Nazzzgul666

 

I'm glad you mentioned that. I changed the title / reworded the start of my first post in hopes of making things clearer. I want this thread to be a great place to come to learn about creating a mod. Reading about why I make the decisions that I do will hopefully help other modders understand how to make the same decisions.

 

Every modder makes many of these decisions, but many don't even understand that they made a decision - for example - if you don't think "How should organize my mod", then your actual decision was "I'm not going to organize my mod." 

 

NPC background is an interesting idea.

 

I'd love for a way to remove all other dialogue options and to completely replace idle comments and things like that.

 

Unfortunately, I don't think that's something you can do in CK.

 

I want the slaves to have a personality, but I don't want them to try to have random conversations about the Khajiit Caravan while trapped in a dungeon!

 

Working with someone is definitely something I'm interested in - I not at that point yet, but I will be!

Link to comment

@Evilynn

 

There is a way to remove all other dialogue options (at least temporarily).

I know Cursed Loot and Sexlab Hormones both do this specific thing (at specific times) in the mods.

 

Cursed Loot does it sometimes depending on settings in the misogyny feature of the mod (male npcs at certain times lose all other options while they use the misogyny dialogue then

they use the regular dialogue after clearing out the misogyny dialogue tree).

 

Sexlab Hormones does it at times with a arousal setting.  (above a certain arousal the pc has a specific dialogue that shows up and has to be cleared to use regular dialogue, and

npcs have to respond to that dialogue before they can use their regular dialogue).

 

I am not sure how they did it (or if it can be done permanently) but from the sound of what you are trying to do it should work in your proposed mod (take away regular dialogues

while the npc is a slave, and return it when they are not a slave any longer).

 

Link to comment

@valcon767

 

Thank you for the suggestion, but I believe they are just using a "blocking dialog". (note: I still need to confirm this)

 

A blocking dialog will make a topic override all other topics that are available.

 

In my case it will not work because I want to have multiple topics available from different dialogs.

 

My current solution is to give my quests priority of 100+ (I'm not sure how high the priority can go). This will at least place my quests above the normal dialog. I did give the capture/release dialog option a priority of "0" so thats at the bottom of the list.

Link to comment

Maybe there is a workaround for the NPCs? At least for generic NPCs like bandits or forsworn and soldiers, you'll need one anyways, i know some mods like display model or Defeat had problems with those NPCs, beeing reset and disappearing or wearing their regular armor instead of beeing naked. Not sure how they solved it, or if my idea would work, what i could imagine:

-make a copy of the NPC for the visuals

-replace the AI & dialogues on the copy

-teleport the original in an empty cell without any doors

 

If somebody captures a quest giver or target s/he can still use console to get the NPC back, if a slave escapes you can just exchange them, and you can manipulate the slaves however you want.

Link to comment
Below are notes from version 0.0.1 - 0.0.4 of [EvilSlaveOwner]
 
You can view the code at: 
[EvilSlaveOwner] - core mod (repo, voices, animations)
[EvilSlaveOwnerSimpleCapture] - Simple capture / release options in dialog
[EvilSlaveOwnerLighting] - A few poses with light (torches)
 
Please note: It's more of a proof of concept than anything else yet.
 
My journey so far: 

[Version 0.0.1]
1. Basic slave repo for up to two slaves.
2. Warning when you try to add more slaves than you have room for.
3. Basic dialog slave capture
4. Basic dialog salve release
 
[Version 0.0.2]
1. Slaves follow closely when captured.
2. Add some poses from my [slaveLight] mod.
3. Add a generic "stop posing" dialog at the [EvilSlaveOwner] core mod level.
 
[Refactor - Version 0.0.3]
Problem To Solve: Adding voices to all of these dialogs is really annoying and takes a lot of time. I need a way to share the same voice dialog options throughout my mod. 
 
1a. I did some research into this problem, and found out that "shared info" topics should solve this issue. I also discovered that I need to add a voice that all my slaves will use so that I'm not forced to save sound for each of the many voices in skyrim.
1b. I added a new actor voice.
1c. I changed NPC enslaving so that it also saves the actors original voice, and then sets the voice to my slave voice.
1d. I added 122 voice dialogs as shared info topics using the slave voice.
 
[Version 0.0.4]
1. Slaves are tattooed when captured
2a. Looked into an issue I ran into where slaves sometimes slide across the floor towards me when they should be stationary. I think that when I change a faction that controls the AI package, the package stack is not updated immediately. For example, changing between pose and follow doesn't happen right away. A rest will trigger the change.
2b. I added a call to EvaluatePackage() when changing a slaves factions so that the AI package stack is reevaluated.

 
Plan for next version:
 
I need to refactor the ESOwnerSlave script.
 
ESOwnerSlave is already trying to do a many different things and it's going to get much worse as time goes on.
 
Full Script

Scriptname ESOwnerSlave extends ReferenceAlias

{Script for providing slave controls.}



State HoldLight

    Function StartBehaviour()

        ESOUtility.log("StartBehaviour - HoldLight")

        Actor slave = GetActorRef()

        slave.AddItem(SlaveLight, 1, true)

        slave.EquipItem(SlaveLight, true)

        slave.AddToFaction(ESOUtility.ESOwnerIsPosing)

        slave.SetDontMove()

        slave.SetRestrained()

        slave.EvaluatePackage()

        debug.SendAnimationEvent(slave, nextAnimation)

        RegisterForSingleUpdate(5)

    EndFunction



    Function BehaviourOnUpdate()

        ; nothing currently.

        Actor slave = GetActorRef()

        RegisterForSingleUpdate(5)

    EndFunction



    Function EndBehaviour()

        ESOUtility.log("EndBehaviour - HoldLight")

        Actor slave = GetActorRef()

        slave.UnequipItem(SlaveLight, true, true)

        slave.RemoveItem(SlaveLight, 1, true)

        slave.RemoveFromFaction(ESOUtility.ESOwnerIsPosing)

        slave.SetDontMove(false)

        slave.SetRestrained(false)

        slave.EvaluatePackage()

        debug.SendAnimationEvent(slave, nextAnimation)

    EndFunction

EndState





; #### ACTIONS ####

Function HoldLight(String animation, Light slaveLightRef)

    if (slaveLightRef != None)

        SlaveLight = slaveLightRef

    else

        SlaveLight = ESOUtility.ESOwnerTorch

    endif

    nextAnimation = animation

    behaviour = "HoldLight"

EndFunction



Function Relax(String animation)

    Actor slave = GetActorRef()

    nextAnimation = animation

    behaviour = ""

    slave.EvaluatePackage()

EndFunction



Function Enslave(actor slave, ESOwnerUtility newUtility, int SlaveCount)

    SlaveNumber = SlaveCount

    ESOUtility = newUtility

    OriginalVoice = slave.GetActorBase().GetVoiceType()

    slave.GetActorBase().SetVoiceType(ESOUtility.ESOwnerSlaveVoiceFemale)

    ForceRefTo(slave)

    ResetFactions()

    AddSlaveNumberTat()

EndFunction



int Function FindNextDigit(int number)



EndFunction



string Function GetTensDigitTat()

    int TensDigit = 0

    if SlaveNumber > 9

        TensDigit = (SlaveNumber / 2) % 10

    endif

    return TensDigit + "_ (Collarbone)"

EndFunction



string Function GetOnesDigitTat()

    return "_" + (SlaveNumber % 10) + " (Collarbone)"

EndFunction



Function AddSlaveNumberTat()

    Actor slave = GetActorRef()

    SlaveTats.simple_add_tattoo(slave, "Slave Number", GetOnesDigitTat())

    SlaveTats.simple_add_tattoo(slave, "Slave Number", GetTensDigitTat())

EndFunction



Function RemoveSlaveNumberTat()

    Actor slave = GetActorRef()

    SlaveTats.simple_remove_tattoo(slave, "Slave Number", GetOnesDigitTat())

    SlaveTats.simple_remove_tattoo(slave, "Slave Number", GetTensDigitTat())

EndFunction



Function FreeSlave()

    Actor slave = GetActorRef()

    slave.GetActorBase().SetVoiceType(OriginalVoice)

    SetFactionsToFreeSlave()

    RemoveSlaveNumberTat()

    Clear()

    slave.EvaluatePackage()

EndFunction



Function ResetFactions()

    Actor slave = GetActorRef()

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsPosing)

    slave.RemoveFromFaction(ESOUtility.ESOwnerInScene)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsRestrained)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsRunningAway)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsFreeSlave)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsWaitHere)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsFollowing)

    slave.AddToFaction(ESOUtility.ESOwnerIsSlave)

EndFunction



Function ResetFactionsToFollowing()

    ResetFactions()

    Actor slave = GetActorRef()

    slave.AddToFaction(ESOUtility.ESOwnerIsFollowing)

EndFunction



Function ResetFactionsToWaitHere()

    ResetFactions()

    Actor slave = GetActorRef()

    slave.AddToFaction(ESOUtility.ESOwnerIsWaitHere)

EndFunction



Function SetFactionsToFreeSlave()

    Actor slave = GetActorRef()

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsPosing)

    slave.RemoveFromFaction(ESOUtility.ESOwnerInScene)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsRestrained)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsRunningAway)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsWaitHere)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsSlave)

    slave.RemoveFromFaction(ESOUtility.ESOwnerIsFollowing)

    slave.AddToFaction(ESOUtility.ESOwnerIsFreeSlave)

EndFunction



Function FollowMe()

    Actor slave = GetActorRef()

    ResetFactionsToFollowing()

    slave.EvaluatePackage()

EndFunction



Function WaitHere()

    Actor slave = GetActorRef()

    ResetFactionsToWaitHere()

    slave.EvaluatePackage()

EndFunction



; #### EVENTS ####

Event OnUpdate()

    Actor slave = GetActorRef()

    if (slave != None)

        BehaviourOnUpdate()

    endif

EndEvent



; #### UTILITIES ####

Function StartBehaviour()

EndFunction



Function BehaviourOnUpdate()

EndFunction



Function EndBehaviour()

EndFunction



; #### PROPERTIES ###

String _behaviour = ""

String Property behaviour

    String Function get()

        return _behaviour

    EndFunction



    Function set(String value)

        _behaviour = value

        EndBehaviour()

        GoToState(_behaviour)

        StartBehaviour()

    EndFunction

EndProperty



String _nextAnimation = ""

String Property nextAnimation

    String Function get()

        return _nextAnimation

    EndFunction



    Function set(String value)

        _nextAnimation = value

    EndFunction

EndProperty



ESOwnerUtility _ESOUtility = None

ESOwnerUtility Property ESOUtility

    ESOwnerUtility Function get()

        return _ESOUtility

    EndFunction



    Function set(ESOwnerUtility value)

        _ESOUtility = value

    EndFunction

EndProperty



Int SlaveNumber = 0

Light SlaveLight

VoiceType OriginalVoice

 

It's not a lot of code and it's not complicated code, but at this rate in a few months the ESOwnerSlave script will be thousands of lines long, and will be a nightmare to maintain.
 
Some this ideas this script uses are copied from [Paradise Halls - Home Sweet Home], and that helped me figure out a good starting point.
 
I'm going to experiment with some ideas and hopefully end up with a design that will be much easier to maintain.
 
[Two Easy Wins]
 
4 functions and two variables are only used for adding/removing the slave number tattoo. I need to pull that out into an external script.
4 functions are related to setting factions on the slave. This should also be moved into an external script.
 
That's a fast easy change to do right away.
 
[The Bigger Refactor]
 
I don't like how I'm currently handling actions/behaviors/states.
 
Right now I call some animation:
(GetOwningQuest() as ESOwnerDialog).SlaveUtility.SlaveAnimations.HoldTorch(akSpeaker, "ZazAPC007")
 
Then ESOwnerAnimations calls:
slave.HoldLight(animation, SlaveUtility.ESOwnerTorch)
 
And finally ESOwnerSlave:
Sets the next animation
Runs EndBehaviour() on the current animation
Starts the new animation with StartBehaviour()
 
It's a nice design, and I like how it works, but - hopefully - I can improve on it.
 
My concern is that over time I'll end up with a ton of StartBehaviour() and EndBehaviour() functions for many different states in ESOwnerSlave. ESOwnerSlave shouldn't know anything about specific animations/poses/scenes.
 
So I plan on reversing it.
 
I want to do something like this:
 
slave.NewBehavor(HoldTorch, "ZazAPC007")
 
Then slave.NewBehavor looks something like this:
 
Function NewBehavior(Behavior behavior, string startingAnimation, string newEndingAnimation)
    Actor slave = GetActorRef()
    if (currentBehavior != None)
        currentBehavior.End(slave, endingAnimation)
    endif

    currentBehavior = behavior
    currentBehavior.Start(slave, startingAnimation)
    endingAnimation = endingAnimation
EndFunction
 
This reversal doesn't look like much, but it's deceptively powerful.
 
ESOwnerSlave can have very complicated behaviors and animations -- without  knowing anything about them.
 
I may need to revisit this subject a couple times before I'm really happy with it, but I think I'm on the right track.
 
I need to play with it some and find out where the problems are.
 
I also need to learn about papyrus performance ... Are multiple scripts cheap even in larger numbers? I need a better understanding of when I'm getting a new copy of a script vs when I'm getting an existing copy of a script. What happens if I add a script to the mod and don't attach it to anything?
 
Hopefully I'll get a chance to dig in some more tomorrow.
 
 
 
Link to comment

I found the best way to change to a new package for an NPC is to add the NPC to some other alias that has a package running and then remove them from it.  This forces the NPC to re-evaluate his package.  There maybe better ways to do it but this has been working pretty well for me.  I just use one of the three package related aliases I have and hope one of them is available for temporary use.

 

 

; Forces an actor to re-evaluate his AI package by forcing him into an alias and then removing
; him, thereby changing his package stack. A dedicated alias should really be used for this
; but for now we will rely on one of our current aliases being available.
Function ReEvaluatePackage(Actor aActor)
   If (_aAliasApproachPlayer.ForceRefIfEmpty(aActor))
      _aAliasApproachPlayer.Clear()
   ElseIf (_aAliasMoveToLocation.ForceRefIfEmpty(aActor))
      _aAliasMoveToLocation.Clear()
   ElseIf (_aAliasMoveToObject.ForceRefIfEmpty(aActor))
      _aAliasMoveToObject.Clear()
   EndIf
   aActor.EvaluatePackage()
EndFunction

 

 

 

Regarding the scripts they can be quite complicated.

I am certainly no expert on this but I think the significant issues are:

1. Watch what run the scripts on.  Several scripts in a quest is not as bad as several scripts each on different NPCs since this will force the game to keep details of the NPCs around for longer than is needed.

2. Make sure your scripts end cleanly.  Scripts whose flow of control don't end timely can be difficult to upgrade.  Saving and loading games can cause multiple versions of such scripts to exist at the same time making things difficult.

 

Pretty much any function that is not within the script can cause a context switch allowing different threads of the same script to run.  My Devious Framework main script has some mutex functions (iMutexCreate (not sure why the i is there), MutexLock, and MutexRelease) to help protect data.

 

If a script is running on saving a game, the game will keep a copy of that script.  When the game loads it will continue execution of that copy until the thread exits the script.  This is in addition to idle scripts "instances" that are attached to various forms.

 

You can use a tool called a Save Game Script Cleaner to view the scripts of your mod.  There are a couple of similar tools out there.  Feel free to experiment to find the best one.

I'm not really sure what the difference is between "Scripts" and "Script Instances".  I would think the "Scripts" not being attached to a form wouldn't have any data; however, their data seems to be identical to the "Script Instances".

 

Happy modding,

legume.

Link to comment
[Refactor - Version 0.0.5]

1. Created Faction Utility and moved all faction related items into it.

2. Created global tattoo script, and moved all related functionality into it.

3. Added simple "Debug" quest/dialoge

4. Broke most links in SimpleCapture and SlaveLight when I opened them with the esm flag off on EvilSlaveOwner.. so annoying.

5. I added a very simple clone operation to the debug dialog. I want to play with that tomorrow and see what (if anything) I can do with it.

 

[Plans For Next Time]

1. Play with cloning, and see if it can create a new actor that just looks like the old one (no dialog options moved)

2. Refactor actions/behaviors/states (see my previous post)

3. Spend some time looking at https://github.com/DeviousFramework :)

 

@legume

 

I used the EvaluatePackage function, and it appeared to work correctly for the very limited playtesting I did.

 

Do you know if there is a problem with it I don't know about?

 

I just spent a few minutes browsing dfwDeviousFramework.psc - thanks for linking it.

 

I'll learn a lot browsing https://github.com/DeviousFramework :)

 

I'm headed to bed, It's almost 2am here.

Link to comment
@legume
 
I used the EvaluatePackage function, and it appeared to work correctly for the very limited playtesting I did.
 
Do you know if there is a problem with it I don't know about?

I can't specifically recall any problems but the API page lists one that I feel is a problem:

 

"If however you call EvaluatePackage for when conditions for a different package is met to travel to say, Windhelm, the previous package will continue to run for a random amount of time."

 

I've had a number of troubles with changing packages.  I suspect they are related to calling this function and having the packages not actually change but I could be mixing things up.

 

It might not be a bad idea to use EvaluatePackage() as is.  But keep this in mind if you see any NPCs not changing their packages.

 

Hope this helps,

legume.

Link to comment
[Refactor - Version 0.0.6]

1. Complete refactor of how I handle animations/behaviors.

2. Played with cloning, and several different cloning methods. I'm shelving the idea for now for two reasons. (1) I will take a great deal of time and effort to make work, and (2) I'm not 100% sure it's even possible.

3. Removed the slave posing sub mod.

 

Now that I have a proof of concept working well, and know that I can break things like this into sub mods, I don't want to separate base poses into a sub mod. Everything will need animation/poses. Posing is just better off as part of the core - I think...

 

I'm sure I'll add additional sub mods in the future. 

 

[Plans For Next Time]

1. Design Slave Personality framework

 

(Note: these are my notes from yesterday. I just didn't post them last night)
Link to comment
[slave Personality - Rough Notes]

I'm going to use a two part system for personality trait ranges.
 
First I have a 100 point range for like/dislike for normal people in normal circumstances. 
 
Exhibitionism 0 = I kick out the cat before changing clothes!
Exhibitionism 100 = I love going to nude beaches!
 
But.. just because you love going to a nudist beach, doesn't mean you want someone to force you to strip.
 
With spells that twist our slaves minds and training we can move our slaves up and down the scale. We can even push 3 stats past 100. The three stats you choose to push past 100 can be pushed all the way to 200.
 
Exhibitionism 200 = Will always strip. Take them outside in lethal cold, and they will strip anyway!
 
Because faction ranks can not go up to 200 (they are limited to -128 - +127), I'm shifting everything down 100.
Exhibitionism -100 = I kick out the cat before changing clothes!
Exhibitionism 0 =  I love going to nude beaches!
Exhibitionism 100 = Will always strip. Take them outside in lethal cold, and they will strip anyway!
 
Personality Traits: (-100 to 100)
Exhibitionism
Sadism
Masochism
Submission
Dominance
Bondage
Humiliation
 
Other Traits: (0 to 100)
Compassion - Linked 1/1 with cruelty.
Cruelty - Linked 1/1 with compassion.
 
Cruelty and Compassion are directly linked, and increasing one will decrease the other.
 
Someone with high cruelty would love to be given power over other slaves.. 

 
[stockholm - Rough Notes]

Trait: Stockholm (0 to 100)
 
As this climbs they start treating you as a confidant/lover. Take it to 100 and most things become consensual.
There will be a way to reset to 0.
 
Stockholm is increased by special actions.
Have a compassionate slave heal / feed other slaves in need.
Give a cruel slave another slave to play with.
Give a submissive slave orders. (tiny increase)
etc..

 
[slave Obedience - Rough Notes]

Obedience is calculated using several sub traits and Stockholm.
 
Obedience Sub Traits: (0 - 100)
Fear
Despair
Anger
Hope
 
Fear and Despair increase obedience.
Anger and Hope decrease obedience.
 
Obedience is: (Stockholm + Fear + Despair) - (Anger + Hope) + (randomized 50 point swing)
 
Obedience is recalculated every time you give your slave an order? (or something like that)
 
In order for the personality / obedience systems to really work, slaves must be able to say NO.
 
I need to figure out how to fit that into the system (Perhaps as part of the story line?).
 
For example, if you have a slave hogtied, and say it's time to strip - how can she say no?
 
I literally just had an awesome idea to fix this... Broken Slaves - read the next section for more information...

 
[broken Slaves - Rough Notes]

Special Trait: (0 - 100)
MindBroken - Slave collapses and ignores everything around her if this climbs to high. Time + Care required to cure. 
MindShattered - Can not be cured. Slave will collapse on the floor and ignore everything.
 
Pushing a slave to far will increase MindBroken. This is what lets slaves say "NO".
 
If your use force on a Broken slave or if you don't take care of her to pull her back, she will become MindShattered.
 
In gameplay this will result in:
Push a slave to far and you cant play with them unless you cure them.
Keep pushing them and you will never play with them again. 
 
You cant simply pick out a slave and then tell her to do whatever you want. You need to train her and work up to it. Do some rewarding. Do some punishing. Twist her mind until you can play as desired.
 
You also can't have one slave that will do everything you want without a lot of time/training/magic

 
[slave Relationships - Rough Notes]

I also want slaves to form relationships with each other.
 
Both platonic friendship and romantic lovers.
 
This is still very nebulous, but I'll let it churn in the back of my mind.

 
Obviously, much of this will change as I actually build these systems.
 
I want slaves to have very different personalities and make gameplay interesting.
 
I'm hoping that I can end up with a system that is straightforward enough to actually program, but will produce very complicated and interesting interactions in game.
 
I'd love feedback/ideas for doing this.

I think I have a good general framework here.

Translating these ideas into Creation Kit and Papyrus isn't going to be easy.... (Though I think I can get close enough)

 

[Plans For Next Time]

1. Add dialog options for many poses.
2. Add dialog options for holding a torch (that is held while posing)
3. Add MCM options
Link to comment

The complex behavior of a slave can be set by three parameters: fear, respect, love.

Fear (0-100)

0 - not at all afraid
Does not carry out any orders of the master.
He wants to escape.

100 is very afraid.
Fulfills any orders.
He wants to escape, but is afraid of punishment.

Fear increases from punishments and cruel acts, decreases from a good relationship.

Respect (0-100)
0 - considers the master a nonentity
Does not fulfill any orders.
He wants to escape.

100 - masters the master of the deity
He thirsts to serve.
He wants to be near the master.

Respect the owner of a slave achieves through accomplishing feats, achieving high ranks in factions and increasing skills. Respect is falling because of failures.

Love (0-100)

0 - hatred.
The desire to kill.
Sexual connection with masters is disgusting.

100 - love.
Desire to make a pleasant service.
Desire for sexual intercourse.

Love is enhanced by kindness, gifts, sex by agreement. Reduces punishment, violence, rape.

Thus, a variety of situations are possible.
For example, when a slave hates the master, but faithfully serves, because he is afraid of being punished, or considers it a great honor to serve a great warrior and magician. Or when the slave loves his master (and sex with him), but he does not listen at all, because he does not respect and not be afraid.

 

Link to comment
  • 3 months later...

I'm sure it's already clear, but this project is on hold for now (life went crazy for a few months, and now that I'm back I have an idea I want to do first)

 

The good news is that many of the ideas from here will be incorporated in the new mod.

Link to comment

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

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

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use