Friday, June 22, 2012

Tutorial: Creating A Skill

Object: To create a new skill using Papyrus scritps

Difficulty: Very complicated and difficult

Time Needed: A great deal. If you are an unexperienced modder, it will take you even longer. For experienced modders, while actually writing the scripts might not take much time, designing the system, implementing it, and perfecting it until it plays well can still take a long time.

An extended version of this tutorial, along with a fully-functional example woodcutting skill mod are available on the Skyrim Nexus for free.

Things you will need:



  • Creation Kit.
  • A plan for how the skill will work mathematically
  • Scripting and general Skyrim modding experience

Note: You cannot create a new skill that uses the vanilla interface without editing most of the base code of the game. This tutorial explains a workaround tactic for create a system of scripts that let you track the how much the player does a certain item so that you can add perks, quests, or other features that depend on the player reaching a certain level in that skill. This tutorial is not going to follow the normal format (a list of buttons that you need to click and actions that you need to do). Rather, it is going to explain the concept of the skill workaround, and how to design/implement it. The actual implementation and the specific equations will be left to you to develop. In this tutorial, we will be using a Woodcutting skill as an example.

Setting up the XP: You first need to plan out the math of your skill. How you gain XP, how much XP you need to level, whether each level requires more XP, what higher levels give you, etc. These decisions will decide how the skill actually works mathematically and are extremely subject to change. I can't tell you how many times I have tweaked and changed my Unarmed leveling system in Way of the Monk. Once you being testing the skill you will inevitably find ways in which it can be improved or tweaked. What sounds good  in theory may not play well in the real game.

The first thing that you need to determine is the XP system. Even though Skyrim tries to take away the numbers as much as possible so that the game feels more immersive, it does actually use XP. Every time you use one of the skills (by casting a spell, hitting an enemy with a weapon, creating a potion, etc.) your XP is raised by a certain amount. Once it hits a cap, the skill level is then increased and the amount of XP needed to reach the next level is raised. You can study the XP system in Skyrim on the UESP wiki. I would highly recomend that you study the vanilla skills to gain a grasp of how they work. In the Woodcutting skill that I will be using as an example I used the following Papyrus Code:
if WoodcuttingXP.GetValue() >= 100
    WoodcuttingLevel.SetValue()WoodcuttingLevel.GetValue() + 1)
    WoodcuttingXP.SetValue(WoodcuttingXP - 100)
endif
Each time you activate the Woodcutting block, your XP will be raised. In the above code, the IF statement determines that when your XP reaches 100, your skill level is raised by one and your XP is reset.

If you want to have the amount of XP required to level increased every time, then you can do one of two things. 1) Instead of increasing the XP by a set amount every time the Woodcutting Block is activated, you should use a variable that can be decreased every time you level. So, say the variable starts out at a value of 10 and you must use the Woodcutting block 10 times to reach level 2. You should add to the above code a line that decreases that variable from 10 to (for instance) 8. Next time, it will take 12.5 (rounded to 13) uses of the Woodcutting Block to raise your level to 3. You can continue that process as long as you want to make it harder to level each time. Keep in mind, though, that if you simply subtract from the variable each time then the variable will eventually hit 0 and the level will never increase. So I would advise you to either write an IF statement to make sure that it never hits 0, or make sure that it hits 0 at just the right time if you want to have a level cap.

2) The other possibility is to have the amount of XP required to level set as a variable and increase it each time you gain a level. So, say at level 1 you gain 10 XP each time you use the Woodcutting Block and must acquire 100 XP to reach level 2. You can write the code so that when you hit level 2, the amount required to level is raised to (for example) 130. That way, it will take 13 uses of the Woodcutting Block to reach Level 3.

So, which of those methods should you use? It's really up to you. The second method is much more natural and runs much smoother than the first. But the first one makes it easier to modify the speed at which you raise your level with perks/abilities, and can be set up so that it stops level progression after a while.

Rewards: A skill is useless without rewards. You can give the player as fancy of an XP system as you want, but if it doesn't change the gameplay for them, then there is no point in downloading your mod. The vanilla game uses a perk system and a scaling system to reward the player for using a skill. The manner of your rewards depends entirely upon the skill that you are creating. For a Woodcutting Skill, the player might expect to be able to get a perk that increases the amount of firewood that they get each time they use the Woodcutting Block. Another good reward might be the ability to create items with your wood (arrows, bows, Forsworn items, etc.). Decide what type of reward you would like to give to the player.

Perks are the standard method of rewarding the player for raising their level. They are also an incredibly versatile way of giving bonuses to the player. I won't discuss perks in detail, since that's another discussion for another time. I will add, though, that one of the conditions that you can add to perks and their effects is the GetGlobalValue condition. This condition is extremely useful when using a skill system based upon Global Variables. If (for example), you want to specify that a Perk Entry only works when your Woodcutting Level is over 10, you can choose the S GetGlobalValue(WoodcuttingLevel) >= 10 condition information. This condition can also be used on Magic Effects in Spells.

Perk points are a good way of giving the player a choice in how they level. There is a reason why the game developers of Skyrim gave the player the choice of choosing their perks, rather than making the perk rewards mandatory like in Oblivion. It adds replay value and makes the player feel more invested in their character. If you're going to give the player that option, you will most likely end up having to create more perks so that they have some to choose from. While that means more work, it also means a more enjoyable playing experience.

The other type of reward that I mentioned was scaling. Scaling is when your ability to use the skill is improved as your level is increased. In the case of weapons, it means that your damage is increases when your level in that type of weapon is raised. The best way to set this up is to use an equation or perk that includes the skill level divided by a certain amount (e.g. effectiveness = 1 + Level*.01). You can also increase the effectiveness by a finite amount each time you level.

Example, using the equation:

        WoodcuttingEffectiveness.SetValue(1 + (WoodcuttingLevel.GetValue()*0.01))

OR by increasing it by a finite amount:

      WoodcuttingEffectiveness.SetValueInt(WoodCuttingEffectiveness.GetVaueInt() + 1)
This can be done with perks or by code in the leveling script. In the case of the example Woodcutting skill, the player can gain perks that increase the amount of wood that you gain each time you chop at the Chopping Block.



Another standard way of rewarding the player for raising their level is with new abilities or spells. New powers can be hard to make if you are trying to create a new type of effect that suits your skill, but they are a great way of making the player feel like they have accomplished something.

The other standard way of rewarding the player is with items. If you are a 3d artist, know someone who is, or have the permission of a mod author to use their models, you can add new items to reward the player with. Otherwise, you can add new enchantments or allow the crafting of vanilla items that you previously could not craft. Now, to fit the rest of the game, you probably don't want to simply add the item to their inventory once they reach a certain skill level. That breaks immersion and seems totally unnatural or special. It is best to either have a quest or a leveled list to give the item to the player. You can either make a quest for them to find it that you can only start once your skill reaches a certain level, or you can create a leveled list that has a chance to give you the item determined by a global variable. You can learn more about using globals in leveled lists by reading the "Chance None" entry on the wiki page, or by studying the Golden Touch perk in the Creation Kit.

The Coding Process: Now that you have finished the planning process, you need to actually write the code.

First, you need to find an Event that will run the code. This can actually be more challenging than it sounds. In my Way of the Monk mod, the Unarmed leveling script actually used the OnEffectStart Event because it was implemented as a script on a Magic Effect. Why? Because it was the only way to make sure that the script ran when the player successfully hit the enemy. Finding the right event can be tricky, and will likely take some testing. The Event that you use is totally dependent upon the nature of your skill, and it will probably take a lot of testing and inventive designing to find the right one.

For the Woodcutting example skill, finding the event was a bit difficult. I tried creating a unique script that ran on the OnActivate Event, but that ended up only running it whenever the player pressed 'e', rather than each time that they chopped wood. It would also run whenever NPCs used the Chop Block. So, instead, I edited the woodchoppingscript (not the vanilla script for the process) and added in my calculations as a function that ran when the played chopped a piece of wood.


        if WoodCuttingLevel.GetValueInt() <= 3
                WoodcuttingXP.SetValueInt(WoodcuttingXP.GetValueInt() + 1)
                if WoodcuttingXP.GetValueInt() >= 10
                        WoodcuttingLevel.SetValueInt(WoodcuttingLevel.GetValueInt() + 1)               
                        WoodcuttingXP.SetValueInt(WoodcuttingXP.GetValueInt() - 10)        
                        Debug.Notification("Your Woodcutting level has been raised to " + WoodcuttingLevel.GetValueInt())
                        PerkPointsAvailable.SetValueInt(PerkPointsAvailable.GetValueInt() + 1)
                        PerkPointsEarned.SetValueInt(PerkPointsSpent.GetValueInt() + PerkPointsAvailable.GetValueInt())
                endif
        endif

 After this, I created some perks, created a power to let you choose your perks and check your stats, and some notifications to let the player know that they are leveling as they use the Chop Block.

After you have found the Event to use, and have implemented the code, you need to test your mod. Creating the code is the easy part. Refining it takes time. I would highly suggest finding a group of modders to beta-test your skill once you have finished it. A system that seems to work well in the code and in your own testing might not work as pleasantly when others are using it.

Testing: After you have finished your planning, your coding, and your implementation, you must test your mod. I would highly suggest gathering a group of beta testers. You can do this by uploading your mod as a BETA version online. Let players know that what they are downloading is still in beta-mode, and give them an invitation to report any bugs or areas which could be improved.


Example: If you want to see an example of this tutorial in action, then feel free to download the Woodcutting Skill mod. You can also download an extended tutorial for creating a skill in PDF format.

2 comments:

  1. Nice! Thank you, it's very useful! I have one more question - I have encountered the fact that some players can open a duplicate of Oghma Infinium. Do you have any ideas how to do that?

    ReplyDelete
    Replies
    1. I would suppose it would be possible to simply duplicate the item itself in the CK?

      Delete

Comments are moderated to prevent bot spamming