Skip to content

Commit 896f017

Browse files
InfernioSharlikran
authored andcommitted
Enderal Support
- bash/game/enderal has been created and fully updated. - Added icons and created a customized taglist based on the Skyrim one. If the LOOT team makes one for Enderal, we should switch to using that, but for now, we'll stick with this one. - Enabled all Skyrim features for Enderal. - Created an EnderalEdit launcher. - Added NSIS installer support for Enderal.
1 parent 87ed32f commit 896f017

27 files changed

Lines changed: 15903 additions & 13 deletions

Mopy/Bash Patches/Enderal/taglist.yaml

Lines changed: 14623 additions & 0 deletions
Large diffs are not rendered by default.

Mopy/bash/basher/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@
394394
'fo4View.iKnowWhatImDoing':False,
395395
'fo3View.iKnowWhatImDoing':False,
396396
'fnvView.iKnowWhatImDoing':False,
397+
'enderalView.iKnowWhatImDoing':False,
397398
#--BOSS:
398399
'BOSS.ClearLockTimes':True,
399400
'BOSS.AlwaysUpdate':True,

Mopy/bash/basher/links.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ def _init_tool_buttons(): # tooldirs must have been initialized
113113
imageList(u'tools/tes4edit%s.png'),
114114
_(u"Launch TES5Edit"),
115115
uid=u'TES5Edit'))
116+
BashStatusBar.buttons.append( #EnderalEdit
117+
App_Tes4View((bass.tooldirs['EnderalEditPath'], u'-Enderal -edit'),
118+
imageList(u'tools/tes4edit%s.png'),
119+
_(u"Launch EnderalEdit"),
120+
uid=u'EnderalEdit'))
116121
BashStatusBar.buttons.append( #SSEEdit
117122
App_Tes4View((bass.tooldirs['SSEEditPath'], u'-SSE -edit'),
118123
imageList(u'tools/tes4edit%s.png'),
@@ -493,7 +498,7 @@ def InitModLinks():
493498
exportMenu.links.append(CBash_Mod_CellBlockInfo_Export())
494499
exportMenu.links.append(Mod_EditorIds_Export())
495500
## exportMenu.links.append(Mod_ItemData_Export())
496-
if bush.game.fsName == u'Skyrim':
501+
if bush.game.fsName in (u'Enderal', u'Skyrim'):
497502
exportMenu.links.append(Mod_FullNames_Export())
498503
exportMenu.links.append(Mod_Prices_Export())
499504
exportMenu.links.append(Mod_Stats_Export())
@@ -528,7 +533,7 @@ def InitModLinks():
528533
importMenu = MenuLink(_(u"Import"))
529534
importMenu.links.append(Mod_EditorIds_Import())
530535
## importMenu.links.append(Mod_ItemData_Import())
531-
if bush.game.fsName == u'Skyrim':
536+
if bush.game.fsName in (u'Enderal', u'Skyrim'):
532537
importMenu.links.append(Mod_FullNames_Import())
533538
importMenu.links.append(Mod_Prices_Import())
534539
importMenu.links.append(Mod_Stats_Import())

Mopy/bash/bosh/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,8 @@ def mod_bsas(self, bsa_infos=None):
703703
"""Return bsas from bsaInfos, that match plugin's name."""
704704
pattern = re.escape(self._modname)
705705
# games other than skyrim accept more general bsa names
706-
if bush.game.fsName != u'Skyrim': pattern += u'.*'
706+
if bush.game.fsName not in (u'Enderal', u'Skyrim'):
707+
pattern += u'.*'
707708
reg = re.compile(pattern, re.I | re.U)
708709
# bsaInfos must be updated and contain all existing bsas
709710
if bsa_infos is None: bsa_infos = bsaInfos
@@ -2980,6 +2981,7 @@ def pathlist(*args): return [x.join(*args) for x in pf]
29802981
tooldirs['Tes4FilesPath'] = dirs['app'].join(u'Tools', u'TES4Files.exe')
29812982
tooldirs['Tes4EditPath'] = dirs['app'].join(u'TES4Edit.exe')
29822983
tooldirs['Tes5EditPath'] = dirs['app'].join(u'TES5Edit.exe')
2984+
tooldirs['EnderalEditPath'] = dirs['app'].join(u'EnderalEdit.exe')
29832985
tooldirs['SSEEditPath'] = dirs['app'].join(u'SSEEdit.exe')
29842986
tooldirs['Fo4EditPath'] = dirs['app'].join(u'FO4Edit.exe')
29852987
tooldirs['Fo3EditPath'] = dirs['app'].join(u'FO3Edit.exe')

Mopy/bash/bosh/bsa_files.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ def get_bsa_type(game_fsName):
648648
""":rtype: type"""
649649
if game_fsName == u'Oblivion':
650650
return OblivionBsa
651-
elif game_fsName in {u'Skyrim', u'Fallout3', u'FalloutNV'}:
651+
elif game_fsName in {u'Enderal', u'Fallout3', u'FalloutNV', u'Skyrim'}:
652652
return SkyrimBsa
653653
elif game_fsName == u'Skyrim Special Edition':
654654
return SkyrimSeBsa

Mopy/bash/bosh/cosaves.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,7 @@ def get_cosave_type(game_fsName):
15751575
if game_fsName == u'Oblivion':
15761576
xSECosave._pluggy_signature = 0x2330
15771577
_xSEHeader.savefile_tag = u'OBSE'
1578-
elif game_fsName == u'Skyrim':
1578+
elif game_fsName in (u'Enderal', u'Skyrim'):
15791579
xSECosave._xse_signature = 0x0
15801580
_xSEHeader.savefile_tag = u'SKSE'
15811581
elif game_fsName == u'Skyrim Special Edition':

Mopy/bash/bosh/mods_metadata.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ def getLootApiGameType(fsName):
321321
return None
322322
if fsName == 'Oblivion':
323323
return loot_api.GameType.tes4
324-
elif fsName == 'Skyrim':
324+
# TODO See if LOOT adds a new GameType for Enderal
325+
elif fsName in ('Enderal', 'Skyrim'):
325326
return loot_api.GameType.tes5
326327
elif fsName == 'Skyrim Special Edition':
327328
return loot_api.GameType.tes5se

Mopy/bash/bosh/save_headers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ def get_save_header_type(game_fsName):
474474
""":rtype: type"""
475475
if game_fsName == u'Oblivion':
476476
return OblivionSaveHeader
477-
elif game_fsName in {u'Skyrim', u'Skyrim Special Edition'}:
477+
elif game_fsName in {u'Enderal', u'Skyrim', u'Skyrim Special Edition'}:
478478
return SkyrimSaveHeader
479479
elif game_fsName == u'Fallout4':
480480
return Fallout4SaveHeader

Mopy/bash/game/enderal/__init__.py

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# GPL License and Copyright Notice ============================================
4+
# This file is part of Wrye Bash.
5+
#
6+
# Wrye Bash is free software; you can redistribute it and/or
7+
# modify it under the terms of the GNU General Public License
8+
# as published by the Free Software Foundation; either version 2
9+
# of the License, or (at your option) any later version.
10+
#
11+
# Wrye Bash is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU General Public License
17+
# along with Wrye Bash; if not, write to the Free Software Foundation,
18+
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+
#
20+
# Wrye Bash copyright (C) 2005-2009 Wrye, 2010-2019 Wrye Bash Team
21+
# https://github.com/wrye-bash
22+
#
23+
# =============================================================================
24+
25+
"""This modules defines static data for use by bush, when Enderal is set as the
26+
active game."""
27+
28+
from .constants import *
29+
from .default_tweaks import default_tweaks
30+
from ..skyrim import SkyrimGameInfo
31+
from ... import brec
32+
from ...brec import MreGlob
33+
34+
class EnderalGameInfo(SkyrimGameInfo):
35+
displayName = u'Enderal'
36+
fsName = u'Enderal'
37+
altName = u'Wrye Smash'
38+
defaultIniFile = u'enderal_default.ini'
39+
# Set to this because TESV.exe also exists for Enderal
40+
game_detect_file = [u'Enderal Launcher.exe']
41+
iniFiles = [u'Enderal.ini', u'EnderalPrefs.ini']
42+
regInstallKeys = (
43+
u'SureAI\\Enderal',
44+
u'Install_Path'
45+
)
46+
saveProfilesKey = (u'General', u'SLocalSavePath', u'..\\Enderal\\Saves\\')
47+
48+
nexusUrl = u'https://www.nexusmods.com/enderal/'
49+
nexusName = u'Enderal Nexus'
50+
nexusKey = u'bash.installers.openEnderalNexus.continue'
51+
52+
vanilla_string_bsas = {
53+
u'skyrim.esm': [u'Skyrim - Interface.bsa'],
54+
u'update.esm': [u'Skyrim - Interface.bsa'],
55+
u'enderal - forgotten stories.esm': [u'Skyrim - Interface.bsa'],
56+
}
57+
SkipBAINRefresh = {u'enderaledit backups', u'enderaledit cache'}
58+
needs_empty_dirs = True
59+
60+
raceNames = {
61+
0x13741 : _(u'Half Kilénian'),
62+
0x13742 : _(u'Half Aeterna'),
63+
0x13743 : _(u'Half Aeterna'),
64+
0x13746 : _(u'Half Arazealean'),
65+
0x13748 : _(u'Half Qyranian'),
66+
}
67+
raceShortNames = {
68+
0x13741 : u'Kil',
69+
0x13742 : u'Aet',
70+
0x13743 : u'Aet',
71+
0x13746 : u'Ara',
72+
0x13748 : u'Qyr',
73+
}
74+
# TODO Not updated yet
75+
raceHairMale = {
76+
0x13741 : 0x90475, #--Kil
77+
0x13742 : 0x64214, #--Aet
78+
0x13743 : 0x7b792, #--Aet
79+
0x13746 : 0x1da82, #--Ara
80+
0x13748 : 0x64215, #--Qyr
81+
}
82+
raceHairFemale = {
83+
0x13741 : 0x1da83, #--Kil
84+
0x13742 : 0x1da83, #--Aet
85+
0x13743 : 0x690c2, #--Aet
86+
0x13746 : 0x1da83, #--Ara
87+
0x13748 : 0x64210, #--Qyr
88+
}
89+
90+
@classmethod
91+
def init(cls):
92+
# Copy-pasted from Skyrim, otherwise it crashes - shouldn't
93+
# classmethods be inherited?
94+
from .records import MreCell, MreWrld, MreFact, MreAchr, MreDial, \
95+
MreInfo, MreCams, MreWthr, MreDual, MreMato, MreVtyp, MreMatt, \
96+
MreLvsp, MreEnch, MreProj, MreDlbr, MreRfct, MreMisc, MreActi, \
97+
MreEqup, MreCpth, MreDoor, MreAnio, MreHazd, MreIdlm, MreEczn, \
98+
MreIdle, MreLtex, MreQust, MreMstt, MreNpc, MreFlst, MreIpds, \
99+
MreGmst, MreRevb, MreClmt, MreDebr, MreSmbn, MreLvli, MreSpel, \
100+
MreKywd, MreLvln, MreAact, MreSlgm, MreRegn, MreFurn, MreGras, \
101+
MreAstp, MreWoop, MreMovt, MreCobj, MreShou, MreSmen, MreColl, \
102+
MreArto, MreAddn, MreSopm, MreCsty, MreAppa, MreArma, MreArmo, \
103+
MreKeym, MreTxst, MreHdpt, MreHeader, MreAlch, MreBook, MreSpgd, \
104+
MreSndr, MreImgs, MreScrl, MreMust, MreFstp, MreFsts, MreMgef, \
105+
MreLgtm, MreMusc, MreClas, MreLctn, MreTact, MreBptd, MreDobj, \
106+
MreLscr, MreDlvw, MreTree, MreWatr, MreFlor, MreEyes, MreWeap, \
107+
MreIngr, MreClfm, MreMesg, MreLigh, MreExpl, MreLcrt, MreStat, \
108+
MreAmmo, MreSmqn, MreImad, MreSoun, MreAvif, MreCont, MreIpct, \
109+
MreAspc, MreRela, MreEfsh, MreSnct, MreOtft
110+
# ---------------------------------------------------------------------
111+
# Unused records, they have empty GRUP in skyrim.esm-------------------
112+
# CLDC HAIR PWAT RGDL SCOL SCPT
113+
# ---------------------------------------------------------------------
114+
# These Are normally not mergeable but added to brec.MreRecord.type_class
115+
#
116+
# MreCell,
117+
# ---------------------------------------------------------------------
118+
# These have undefined FormIDs Do not merge them
119+
#
120+
# MreNavi, MreNavm,
121+
# ---------------------------------------------------------------------
122+
# These need syntax revision but can be merged once that is corrected
123+
#
124+
# MreAchr, MreDial, MreLctn, MreInfo, MreFact, MrePerk,
125+
# ---------------------------------------------------------------------
126+
cls.mergeClasses = (# MreAchr, MreDial, MreInfo, MreFact,
127+
MreAact, MreActi, MreAddn, MreAlch, MreAmmo, MreAnio, MreAppa,
128+
MreArma, MreArmo, MreArto, MreAspc, MreAstp, MreAvif, MreBook,
129+
MreBptd, MreCams, MreClas, MreClfm, MreClmt, MreCobj, MreColl,
130+
MreCont, MreCpth, MreCsty, MreDebr, MreDlbr, MreDlvw, MreDobj,
131+
MreDoor, MreDual, MreEczn, MreEfsh, MreEnch, MreEqup, MreExpl,
132+
MreEyes, MreFlor, MreFlst, MreFstp, MreFsts, MreFurn, MreGlob,
133+
MreGmst, MreGras, MreHazd, MreHdpt, MreIdle, MreIdlm, MreImad,
134+
MreImgs, MreIngr, MreIpct, MreIpds, MreKeym, MreKywd, MreLcrt,
135+
MreLctn, MreLgtm, MreLigh, MreLscr, MreLtex, MreLvli, MreLvln,
136+
MreLvsp, MreMato, MreMatt, MreMesg, MreMgef, MreMisc, MreMovt,
137+
MreMstt, MreMusc, MreMust, MreNpc, MreOtft, MreProj, MreRegn,
138+
MreRela, MreRevb, MreRfct, MreScrl, MreShou, MreSlgm, MreSmbn,
139+
MreSmen, MreSmqn, MreSnct, MreSndr, MreSopm, MreSoun, MreSpel,
140+
MreSpgd, MreStat, MreTact, MreTree, MreTxst, MreVtyp, MreWatr,
141+
MreWeap, MreWoop, MreWthr,
142+
####### for debug
143+
MreQust,)
144+
145+
# MreScpt is Oblivion/FO3/FNV Only
146+
# MreMgef, has not been verified to be used here for Skyrim
147+
148+
# Setting RecordHeader class variables --------------------------------
149+
brec.RecordHeader.topTypes = ['GMST', 'KYWD', 'LCRT', 'AACT', 'TXST',
150+
'GLOB', 'CLAS', 'FACT', 'HDPT', 'HAIR', 'EYES', 'RACE', 'SOUN',
151+
'ASPC', 'MGEF', 'SCPT', 'LTEX', 'ENCH', 'SPEL', 'SCRL', 'ACTI',
152+
'TACT', 'ARMO', 'BOOK', 'CONT', 'DOOR', 'INGR', 'LIGH', 'MISC',
153+
'APPA', 'STAT', 'SCOL', 'MSTT', 'PWAT', 'GRAS', 'TREE', 'CLDC',
154+
'FLOR', 'FURN', 'WEAP', 'AMMO', 'NPC_', 'LVLN', 'KEYM', 'ALCH',
155+
'IDLM', 'COBJ', 'PROJ', 'HAZD', 'SLGM', 'LVLI', 'WTHR', 'CLMT',
156+
'SPGD', 'RFCT', 'REGN', 'NAVI', 'CELL', 'WRLD', 'DIAL', 'QUST',
157+
'IDLE', 'PACK', 'CSTY', 'LSCR', 'LVSP', 'ANIO', 'WATR', 'EFSH',
158+
'EXPL', 'DEBR', 'IMGS', 'IMAD', 'FLST', 'PERK', 'BPTD', 'ADDN',
159+
'AVIF', 'CAMS', 'CPTH', 'VTYP', 'MATT', 'IPCT', 'IPDS', 'ARMA',
160+
'ECZN', 'LCTN', 'MESG', 'RGDL', 'DOBJ', 'LGTM', 'MUSC', 'FSTP',
161+
'FSTS', 'SMBN', 'SMQN', 'SMEN', 'DLBR', 'MUST', 'DLVW', 'WOOP',
162+
'SHOU', 'EQUP', 'RELA', 'SCEN', 'ASTP', 'OTFT', 'ARTO', 'MATO',
163+
'MOVT', 'SNDR', 'DUAL', 'SNCT', 'SOPM', 'COLL', 'CLFM', 'REVB']
164+
#-> this needs updating for Skyrim
165+
brec.RecordHeader.recordTypes = set(
166+
brec.RecordHeader.topTypes + ['GRUP', 'TES4', 'REFR', 'ACHR',
167+
'ACRE', 'LAND', 'INFO', 'NAVM',
168+
'PHZD', 'PGRE'])
169+
brec.RecordHeader.plugin_form_version = 43
170+
brec.MreRecord.type_class = dict((x.classType,x) for x in (
171+
MreAchr, MreDial, MreInfo, MreAact, MreActi, MreAddn, MreAlch,
172+
MreAmmo, MreAnio, MreAppa, MreArma, MreArmo, MreArto, MreAspc,
173+
MreAstp, MreAvif, MreBook, MreBptd, MreCams, MreClas, MreClfm,
174+
MreClmt, MreCobj, MreColl, MreCont, MreCpth, MreCsty, MreDebr,
175+
MreDlbr, MreDlvw, MreDobj, MreDoor, MreDual, MreEczn, MreEfsh,
176+
MreEnch, MreEqup, MreExpl, MreEyes, MreFact, MreFlor, MreFlst,
177+
MreFstp, MreFsts, MreFurn, MreGlob, MreGmst, MreGras, MreHazd,
178+
MreHdpt, MreIdle, MreIdlm, MreImad, MreImgs, MreIngr, MreIpct,
179+
MreIpds, MreKeym, MreKywd, MreLcrt, MreLctn, MreLgtm, MreLigh,
180+
MreLscr, MreLtex, MreLvli, MreLvln, MreLvsp, MreMato, MreMatt,
181+
MreMesg, MreMgef, MreMisc, MreMovt, MreMstt, MreMusc, MreMust,
182+
MreNpc, MreOtft, MreProj, MreRegn, MreRela, MreRevb, MreRfct,
183+
MreScrl, MreShou, MreSlgm, MreSmbn, MreSmen, MreSmqn, MreSnct,
184+
MreSndr, MreSopm, MreSoun, MreSpel, MreSpgd, MreStat, MreTact,
185+
MreTree, MreTxst, MreVtyp, MreWatr, MreWeap, MreWoop, MreWthr,
186+
MreCell, MreWrld, # MreNavm, MreNavi
187+
####### for debug
188+
MreQust, MreHeader,
189+
))
190+
brec.MreRecord.simpleTypes = (
191+
set(brec.MreRecord.type_class) - {'TES4', 'ACHR', 'CELL', 'DIAL',
192+
'INFO', 'WRLD', })
193+
194+
GAME_TYPE = EnderalGameInfo

0 commit comments

Comments
 (0)