Jump to content

The Proper, efficient way to add a perk to ALL NPCs?


Recommended Posts

Hello.
I am making an enhanced version of Balanced Magic.

In the mod, the spell magnitude is scaled to the skill level. The higher the skill level, the higher the spell magnitude. This is done by a perk that's given to the Player NPC (00000007).

However, I'd like all NPCs to benefit from the perk. How would I do this without adding the perk to every NPC in the CK? Which would make the mod incompatible with any other plugins that edit NPCs.

Is there a sort of "master" actor object that I can add the perk to, which would make every humanoid NPC have the perk?

Or, could I make a script of some sort, that would be run from MCM, which would add the perk to every NPC? Would that work with generated NPCs?

 

Edit: The perk that I want to add to NPCs is already added to the Player character. It's not a perk just for NPCs, if that makes a difference.

Any help would be appreciated, cheers.

Edited by mdesanta777
Link to comment
Share on other sites

One relatively "easy" way to do this is convert the perk into a constant effect, and then add it to the NPC races. You can do this by making a blank constant-self applied magic effect, and set the "Perk to Apply" to the perk you want to apply. You then add the magic effect to a constant effect spell, that is set as an "Ability" instead of a spell. Finally, add this ability to all of the playable races under the Specials part, on the General Data tab, of each race.

Link to comment
Share on other sites

One relatively "easy" way to do this is convert the perk into a constant effect, and then add it to the NPC races. You can do this by making a blank constant-self applied magic effect, and set the "Perk to Apply" to the perk you want to apply. You then add the magic effect to a constant effect spell, that is set as an "Ability" instead of a spell. Finally, add this ability to all of the playable races under the Specials part, on the General Data tab, of each race.

That is relatively easy and seems less prone to script errors, bugs and less engine-intensive than the Cloak spell method.

 

I will try and report back, thank you.

Edited by mdesanta777
Link to comment
Share on other sites

It didn't work. I check for conflicts in Tes5Edit and fixed them, so there should be no problems on that front.

In-game, I used hasperk to check on NPCs, they don't have the perk.

Then, I used addspell to make sure that the NPC has the spell. Then I checked the perk. Still no perk.

Is any of this wrong?
KwILmz.png

cTltHy.png

GcDZ1D.png

Link to comment
Share on other sites

This all looks right. Maybe you need to resurrect or spawn in new NPCs for the spell to be applied. I do know that if they do have the spell, they do have the perk. In some of my mods I've used this technique for some intricate effects, which required a condition function to check if the npc had the perk.

Link to comment
Share on other sites

Update: when I add this spell via console to myself, I have the perk. When I add this spell via console to a NPC, they don't have the perk :sad:

I tried giving the NPC the spell, killing then resurrecting them. No perk.

I also tried spawning in an stormcloak soldier NPC. No perk.


Spell is applied to all Nord NPCs. I know this because when I tried to console add the spell to Nords, it says it cannot be added. So they already have the spell.
The non-Nord NPCs don't have the spell, and I can console add it to them.
The Race-Ability link is working fine.

 

Either way, an NPC having the spell, still doesn't have the perk.

I added the spell to my player character, I received the perk.

 

 

Update2:

I also tried with an empty perk.

Still the exact same thing. Spell gives perk to me, doesn't give perk to NPCs.

Edited by mdesanta777
Link to comment
Share on other sites

There's confusion here. The suggestion to use a magic effect was to replace the perk not to apply it. You can not add perks dynamically to NPCs in game. If what you are trying to do actually requires a perk (and I think it does) then your only option is to edit the NPCs directly. To get around that problem and allow for compatibility the major perk overhaul mods use a patcher program. Since NPCs generally use different versions of the spells than the player you might also be able to directly modify their spells to approximate the effect you want.

Link to comment
Share on other sites

I made a very simple patcher with SkyProc starter, following this tutorial.

http://www.uesp.net/wiki/Tes5Mod:SkyProc/Getting_Started

However, when I run the patcher, it gives me the " Record lengths were off." error, and the perk is not applied in-game.

Here's the error in the debug file

 

...

...

...

[7213] [GRUP] [NPC_ | 01328ASkyrim.esm | IngeSixFingers]
[7214] [GRUP] [NPC_ | 01335ESkyrim.esm | Grelod]
[7215] [GRUP] [NPC_ | 013360Skyrim.esm | Hafjorg]
[7216] [GRUP] [NPC_ | 013372Skyrim.esm | Nura]
[7217] [GRUP] [NPC_ | 0133BFSkyrim.esm | Vigdis]
[7218] [GRUP] [NPC_ | 013614Skyrim.esm | Frida]
[7219] [GRUP] [NPC_ | 013B9CSkyrim.esm | FraliaGrayMane]
[7220] [GRUP] [NPC_ | 013BB3Skyrim.esm | BergritteBattleBorn]
[7221] [GRUP] [NPC_ | 013BB6Skyrim.esm | Tilma]
[7222] [GRUP] [NPC_ | 013BC0Skyrim.esm | LillithMaidenLoom]
[7223] [GRUP] [NPC_ | 014124Skyrim.esm | Helgird]
[7224] [GRUP] [NPC_ | 035533Skyrim.esm | Hilde]
[7225] [GRUP] [NPC_ | 0DDF86Skyrim.esm | dunPOIWitchAnise]
[7226] [GRUP] [NPC_ | 013391Skyrim.esm | Daighre]
[7227] [GRUP] [NPC_ | 0133BESkyrim.esm | UrzogaGraShugurz]
[7228] [GRUP] [NPC_ | 01347CSkyrim.esm | Gerdur]
[7229] [GRUP] [NPC_ | 013612Skyrim.esm | Beitild]
[7230] [GRUP] [NPC_ | 013B6ESkyrim.esm | LashGraDushnikh]
[7231] [GRUP] [NPC_ | 013B7ASkyrim.esm | Murbul]
[7232] [GRUP] [NPC_ | 013B7BSkyrim.esm | Arob]
[7233] [GRUP] [NPC_ | 013B7CSkyrim.esm | Gharol]
[7234] [GRUP] [NPC_ | 013B7DSkyrim.esm | Shel]
[7235] [GRUP] [NPC_ | 019953Skyrim.esm | Sharamph]
[7236] [GRUP] [NPC_ | 019955Skyrim.esm | Bagrak]
[7237] [GRUP] [NPC_ | 019957Skyrim.esm | Shuftharz]
[7238] [GRUP] [NPC_ | 0BFB55Skyrim.esm | VigilantCarcette]
[7239] [GRUP] [NPC_ | 0C78C0Skyrim.esm | Dulug]
[7240] [GRUP] [NPC_ | 0C78CASkyrim.esm | Gul]
[7241] [GRUP] [NPC_ | 01336BSkyrim.esm | Mjoll]
[7242] [GRUP] [NPC_ | 013478Skyrim.esm | Delphine]
[7243] [GRUP] [NPC_ | 013666Skyrim.esm | Annekke]
[7244] [GRUP] [NPC_ | 019959Skyrim.esm | Borgakh]
[7245] [GRUP] [NPC_ | 019E1ASkyrim.esm | Ugor]
[7246] [GRUP] [NPC_ | 01A696Skyrim.esm | AelaTheHuntress]
[7247] [GRUP] [NPC_ | 01A6D7Skyrim.esm | Ria]
[7248] [GRUP] [NPC_ | 01A6D9Skyrim.esm | NjadaStonearm]
[7249] [GRUP] [NPC_ | 048C2FSkyrim.esm | dunDarklightIllia]
[7250] [GRUP] [NPC_ | 0918E2Skyrim.esm | Uthgerd]
[7251] [GRUP] [NPC_ | 0A2C8ESkyrim.esm | HousecarlWhiterun]
[7252] [GRUP] [NPC_ | 0A2C8FSkyrim.esm | HousecarlSolitude]
[7253] [GRUP] [NPC_ | 0A2C91Skyrim.esm | HousecarlRiften]
[7254] [GRUP] [NPC_ | 002B6CDawnguard.esm | DLC1Serana]
[7255] [GRUP] [NPC_ | 01541BDawnguard.esm | DLC1Ingjard]
[7256] [GRUP] [NPC_ | 005215HearthFires.esm | BYOHHousecarlFalkreath]
[7257] [GRUP] [NPC_ | 017934Dragonborn.esm | DLC2Frea]
[7258] [GRUP] [NPC_ | 015CFESkyrim.esm | DBInitiate2]
[7259] [GRUP] [NPC_ | 01411DSkyrim.esm | Adelaisa]
[7260] [GRUP] [NPC_ | 01990FSkyrim.esm | Eola]
[7261] [GRUP] [NPC_ | 01C196Skyrim.esm | BrelynaMaryon]
[7262] [GRUP] [NPC_ | 028AD0Skyrim.esm | DA01Aranea]
[7263] [GRUP] [NPC_ | 0B9982Skyrim.esm | HirelingJenassa]
[7264] [GRUP] [NPC_ | 01541CDawnguard.esm | DLC1Beleval]
[7265] [Record Lengths] Major Record: NPC_ | is wrong. ({3025115->0x2E28DB})
[7266] [Record Lengths] NOT Validated.
[7267] [Record Length Check] Record lengths were off.
[7268] [EXCEPTION] skyproc.exceptions.BadRecord: Record lengths are off.
at skyproc.Mod.export(Mod.java:770)
at skyproc.Mod.export(Mod.java:638)
at skyproc.Mod.export(Mod.java:615)
at skyproc.gui.SUMGUI$ProcessingThread.run(SUMGUI.java:952)
at java.lang.Thread.run(Unknown Source)
[7269] [DEBUG] Closing Debug File. Time was: 252233

 


I check the last object 01541CDawnguard.esm | DLC1Beleval in Tes5Edit. It is overwritten by a mod's file, but there are no conflicts. Many previous files in the debug lists are overwritten by mods too, so I don't think there's an issue there.


Here's the code for the modified Skyproc Starter project, the only lines I added are in red.

 

 


package skyprocstarter;
import java.awt.Color;
import java.awt.Font;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import lev.gui.LSaveFile;
import skyproc.*;
import skyproc.gui.SPMainMenuPanel;
import skyproc.gui.SUM;
import skyproc.gui.SUMGUI;
import skyprocstarter.YourSaveFile.Settings;
/**
*
* @author Your Name Here
*/
public class SkyProcStarter implements SUM {
/*
* The important functions to change are:
* - getStandardMenu(), where you set up the GUI
* - runChangesToPatch(), where you put all the processing code and add records to the output patch.
*/
/*
* The types of records you want your patcher to import. Change this to
* customize the import to what you need.
*/
GRUP_TYPE[] importRequests = new GRUP_TYPE[]{
GRUP_TYPE.NPC_
};
public static String myPatchName = "BME Perk Patch";
public static String authorName = "mdesanta777";
public static String version = "1.0";
public static String welcomeText = "Give every NPC is BME perks.";
public static String descriptionToShowInSUM = "Give every NPC is BME perks.";
public static Color headerColor = new Color(66, 181, 184); // Teal
public static Color settingsColor = new Color(72, 179, 58); // Green
public static Font settingsFont = new Font("Serif", Font.BOLD, 15);
public static SkyProcSave save = new YourSaveFile();
// Do not write the bulk of your program here
// Instead, write your patch changes in the "runChangesToPatch" function
// at the bottom
public static void main(String[] args) {
try {
SPGlobal.createGlobalLog();
SUMGUI.open(new SkyProcStarter(), args);
} catch (Exception e) {
// If a major error happens, print it everywhere and display a message box.
System.err.println(e.toString());
SPGlobal.logException(e);
JOptionPane.showMessageDialog(null, "There was an exception thrown during program execution: '" + e + "' Check the debug logs or contact the author.");
SPGlobal.closeDebug();
}
}
@Override
public String getName() {
return myPatchName;
}
// This function labels any record types that you "multiply".
// For example, if you took all the armors in a mod list and made 3 copies,
// you would put ARMO here.
// This is to help monitor/prevent issues where multiple SkyProc patchers
// multiply the same record type to yeild a huge number of records.
@Override
public GRUP_TYPE[] dangerousRecordReport() {
// None
return new GRUP_TYPE[0];
}
@Override
public GRUP_TYPE[] importRequests() {
return importRequests;
}
@Override
public boolean importAtStart() {
return false;
}
@Override
public boolean hasStandardMenu() {
return true;
}
// This is where you add panels to the main menu.
// First create custom panel classes (as shown by YourFirstSettingsPanel),
// Then add them here.
@Override
public SPMainMenuPanel getStandardMenu() {
SPMainMenuPanel settingsMenu = new SPMainMenuPanel(getHeaderColor());
settingsMenu.setWelcomePanel(new WelcomePanel(settingsMenu));
settingsMenu.addMenu(new OtherSettingsPanel(settingsMenu), false, save, Settings.OTHER_SETTINGS);
return settingsMenu;
}
// Usually false unless you want to make your own GUI
@Override
public boolean hasCustomMenu() {
return false;
}
@Override
public JFrame openCustomMenu() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean hasLogo() {
return false;
}
@Override
public URL getLogo() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean hasSave() {
return true;
}
@Override
public LSaveFile getSave() {
return save;
}
@Override
public String getVersion() {
return version;
}
@Override
public ModListing getListing() {
return new ModListing(getName(), false);
}
@Override
public Mod getExportPatch() {
Mod out = new Mod(getListing());
out.setAuthor(authorName);
return out;
}
@Override
public Color getHeaderColor() {
return headerColor;
}
// Add any custom checks to determine if a patch is needed.
// On Automatic Variants, this function would check if any new packages were
// added or removed.
@Override
public boolean needsPatching() {
return false;
}
// This function runs when the program opens to "set things up"
// It runs right after the save file is loaded, and before the GUI is displayed
@Override
public void onStart() throws Exception {
}
// This function runs right as the program is about to close.
@Override
public void onExit(boolean patchWasGenerated) throws Exception {
}
// Add any mods that you REQUIRE to be present in order to patch.
@Override
public ArrayList<ModListing> requiredMods() {
return new ArrayList<>(0);
}
@Override
public String description() {
return descriptionToShowInSUM;
}
// This is where you should write the bulk of your code.
// Write the changes you would like to make to the patch,
// but DO NOT export it. Exporting is handled internally.
@Override
public void runChangesToPatch() throws Exception {
Mod patch = SPGlobal.getGlobalPatch();
Mod merger = new Mod(getName() + "Merger", false);
merger.addAsOverrides(SPGlobal.getDB());
FormID scalerID = new FormID("0012C4", "Balanced_Magic.esp");
FormID costoffsetID = new FormID("0063BA", "Balanced_Magic.esp");
for (NPC_ n : merger.getNPCs()) {
n.addPerk(scalerID,1);
n.addPerk(costoffsetID,1);
patch.addRecord(n);
}
}
}



If anyone who knows how to make Skyproc patchers could tell me what's wrong, that'd be great. The tutorial is outdated, and there are some parts that I had to figure out myself.


Update: no matter how many mods I disable it just keeps getting stuck at 71%, giving the same error, just stopping at a new NPC, which makes me realize that all the NPCs have been processed correctly (the last NPCs are the ones that I have mods for), and it's the step that comes afterwards (Validating length) that's the issue.


Update2: it seems that if I block the cleaned Dawnguard.esm, the patcher works fine. I don't know why that is, and what it means.

Edited by mdesanta777
Link to comment
Share on other sites

Update3:

Solved.

Updated Skyproc version.

 

Every link on that tutorial page is outdated and causes problems.

These up-to-date modder's resources should really be more prominently linked in big, shiny letters on a sticky somewhere, instead of hiding in some obscure corner of the Internet. :sad:

Edited by mdesanta777
Link to comment
Share on other sites

  • Recently Browsing   0 members

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