Unity引擎类游戏MOD制作通用教程,一个非游戏软件行业的软件系统架构师的经验谈,跟水友们分享经验,2019年春节前的献礼!!!
本帖最后由 liyun_1981 于 2019-2-3 16:08 编辑前言:
如题,本人是一个非游戏软件行业的软件开发人员,基于个人对计算机游戏的强烈兴趣,在空闲时间时常会研究下当前各种主流的游戏引擎,以便于使得制作游戏MOD成为可能!在春节前夕,打算整一个Unity引擎类游戏MOD的通用教程,分享给各位水友!:lol
正题:
本教程计划分为五个部分分别讲述,从第二楼起,每楼阐述一个部分。
第一部分:MOD制作前必备的工具软件;
第二部分:DLL文件的反编译与重编译;
第三部分:IL文件的修改;
第四部分:IL汇编语言相关;
第五部分:对MOD制作的一些展望。
最后,水友们觉得写得不错的都给俺评个分点个赞,谢谢!!!:lol
午茶心情 发表于 2019-4-12 17:38
大佬请问一下,使用40级上限那个补丁之后,新建角色和角色升级的时候,种族的名字和天赋的名字都不显示了, ...
在“游戏设置”界面把字体调到最小就行,这个是游戏的UI的框框不能自动跟随字体动态调整的问题。
午茶心情 发表于 2019-4-15 21:40
大佬游戏更新到1.3.2,40级上限那个mod是不是不能用了
是的,游戏每次更新都必须同步更新这个补丁。
第一部分:MOD制作前必备的工具软件
1、Visual Studio 2017(C++、C#语言类开发IDE);
2、dotPeek(个人认为该软件是最好的.NET框架反编译工具,网址:https://www.jetbrains.com/decompiler/?fromMenu);
3、UtralEdit或者EditPlus(二者选其一即可,个人认为这两个文本编辑软件是最好的)。
对上述工具的作用简要说明下:
dotPeek主要用来将游戏目录下的XXXX_Data\Managed目录下的游戏业务逻辑类库文件Assembly-CSharp.dll反编译成VS2017的.NET项目;Visual Studio 2017主要用来查看将Assembly-CSharp.dll反编译后得到的源代码,有助于理解游戏的业务逻辑;UtralEdit或者EditPlus主要用来修改将Assembly-CSharp.dll反编译后得到的Assembly-CSharp.il文件。
本帖最后由 liyun_1981 于 2019-5-31 11:38 编辑
第二部分:DLL文件的反编译与重编译
1、打开dotPeek后,先打开文件Assembly-CSharp.dll再导出VS项目,如下图:
导出成功后即可到导出目录双击*.sln文件打开VS2017查看源代码了;
2、在任意硬盘分区新建3个目录,例如:E:\Decompile,E:\Decompile\DLL,E:\Decompile\DLL-ildasm,将文件Assembly-CSharp.dll复制到E:\Decompile\DLL目录;
3、打开“VS 2017的开发人员命令提示符 ”,输入命令:
cd /d "E:\Decompile\DLL"
ildasm Assembly-CSharp.dll /output:..\DLL-ildasm\Assembly-CSharp.il
此时在E:\Decompile\DLL-ildasm目录会生成Assembly-CSharp.res和Assembly-CSharp.il两个文件,我们只关心文件Assembly-CSharp.il,该文件就是反编译文件Assembly-CSharp.dll后得到的il中间语言文件,后续的MOD制作都是基于该文件的;
4、使用UtralEdit或者EditPlus修改完文件Assembly-CSharp.il后,再输入命令:
cd /d "E:\Decompile\DLL-ildasm"
ilasm /dll /resource:Assembly-CSharp.res Assembly-CSharp.il /output:Assembly-CSharp.dll
此时在E:\Decompile\DLL-ildasm目录会生成文件Assembly-CSharp.dll,该文件就是重编译文件Assembly-CSharp.il后得到的新的类库文件;
5、将步骤4得到的新类库文件Assembly-CSharp.dll复制到游戏目录下的XXXX_Data\Managed目录即完成了MOD制作,此时可以运行游戏查看效果了。
本帖最后由 liyun_1981 于 2019-2-22 16:39 编辑
第三部分:IL文件的修改
这部分内容是MOD制作的核心,对观看的水友有一定的要求,需要能读懂C#语言和IL汇编语言;考虑到不懂这两种语言的水友,我尽可能简明的举例说明下怎么修改。
下面我以角色负重值修改(100倍负重)为例具体说明下操作过程:
1、双击*.sln文件打开VS2017,在左侧的解决方案资源管理器窗口定位到C#源文件EncumbranceHelper.cs并双击图标,此时在右侧源代码编辑窗口搜索GetHeavy定位到获得角色负重值上限的方法,记住最后一行return语句表示的代码含义,如下图:
2、使用UtralEdit或者EditPlus打开文件Assembly-CSharp.il,搜索关键字// end of method EncumbranceHelper::GetHeavy定位到GetHeavy方法结尾处,往上回溯查看GetHeavy方法的IL代码,将标签IL_007a到标签IL_007f包含的内容替换为以下5行IL代码: IL_007a:call float64 System.Math::Round(float64)
IL_007b:conv.i4
IL_007c:ldc.i4.s 100
IL_007d:mul
IL_007f:conv.i4
如下图:
3、保存文件Assembly-CSharp.il,并按照第二部分的操作重编译为文件Assembly-CSharp.dll,至此角色负重值修改(100倍负重)已全部完成;
4、使用dotPeek打开重编译后的文件Assembly-CSharp.dll,并双击打开EncumbranceHelper类的源代码文件EncumbranceHelper.cs,搜索GetHeavy定位到方法,可以看到该方法最后的return语句已经变成了return (int) Math.Round(Math.Truncate(100.0 * a / num + 0.5) * num) * 100;,说明方才已经正确的将角色负重上限修改为100倍了,如下图:
下面为方便水友们自己修改,提供我自制的《开拓者:拥王者》40级上限修改补丁的所有修改的相关IL代码片段如下:*开头的行表示需要替换,+开头的行表示需要新增,右边是查询需要被修改的IL代码片段的关键字
角色等级上限及经验值修改
*} // end of method LevelUpController::CanLevelUp
IL_0034:ldloc.0
IL_0035:ldc.i4.s 40
IL_0036:blt IL_0039
IL_0037:ldc.i4.0
IL_0038:ret
IL_0039:ldloc.0
IL_003a:ldc.i4.s 20
IL_003b:bge IL_004e
IL_003c:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_003d:callvirt instance class Kingmaker.Blueprints.Root.BlueprintRoot Kingmaker.Game::get_BlueprintRoot()
IL_003e:ldfld class Kingmaker.Blueprints.Root.ProgressionRoot Kingmaker.Blueprints.Root.BlueprintRoot::Progression
IL_003f:ldfld class Kingmaker.Blueprints.Classes.BlueprintStatProgression Kingmaker.Blueprints.Root.ProgressionRoot::XPTable
IL_0040:ldloc.0
IL_0041:ldc.i4.1
IL_0042:add
IL_0043:callvirt instance int32 Kingmaker.Blueprints.Classes.BlueprintStatProgression::GetBonus(int32)
IL_0044:ldc.i4.2
IL_0045:div
IL_0046:stloc.1
IL_0047:ldloc.1
IL_0048:ldarg.0
IL_0049:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_004a:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_Experience()
IL_004b:ble IL_006e
IL_004c:ldc.i4.0
IL_004d:ret
IL_004e:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_004f:callvirt instance class Kingmaker.Blueprints.Root.BlueprintRoot Kingmaker.Game::get_BlueprintRoot()
IL_0050:ldfld class Kingmaker.Blueprints.Root.ProgressionRoot Kingmaker.Blueprints.Root.BlueprintRoot::Progression
IL_0051:ldfld class Kingmaker.Blueprints.Classes.BlueprintStatProgression Kingmaker.Blueprints.Root.ProgressionRoot::XPTable
IL_0052:ldc.i4.s 20
IL_0053:callvirt instance int32 Kingmaker.Blueprints.Classes.BlueprintStatProgression::GetBonus(int32)
IL_0054:ldc.i4.2
IL_0055:div
IL_0056:ldloc.0
IL_0057:ldc.i4.s 19
IL_0058:sub
IL_0059:ldc.i4 90000
IL_005a:mul
IL_005b:add
IL_005c:stloc.1
IL_005d:ldloc.1
IL_005e:ldarg.0
IL_005f:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_0060:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_Experience()
IL_0061:ble IL_006e
IL_006c:ldc.i4.0
*} // end of method UnitProgressionData::AddClassLevel
IL_0061:ldloc.0
IL_0062:ldloc.0
IL_0063:ldlen
IL_0064:conv.i4
IL_0065:ldc.i4.1
IL_0066:sub
IL_0067:ldarg.0
IL_0068:call instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_0069:call int32 System.Math::Min(int32,
int32)
IL_006a:ldelem.i4
IL_006b:ldc.i4.2
IL_006c:div
IL_006d:stloc.1
IL_006e:ldarg.0
IL_006f:call instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_0070:ldc.i4.s 20
IL_0071:ble IL_007b
IL_0072:ldloc.1
IL_0073:ldarg.0
IL_0074:call instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_0075:ldc.i4.s 20
IL_0076:sub
IL_0077:ldc.i4 90000
IL_0078:mul
IL_0079:add
IL_007a:stloc.1
IL_007b:ldarg.0
IL_007c:ldarg.0
IL_007d:call instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_Experience()
IL_007e:ldloc.1
IL_007f:call int32 System.Math::Max(int32,
int32)
IL_0081:call instance void Kingmaker.UnitLogic.UnitProgressionData::set_Experience(int32)
*} // end of method CharSLevel::FillData
IL_00bd:br IL_0100
IL_00c2:ldarg.0
IL_00c3:ldfld class ['Assembly-CSharp-firstpass']TMPro.TextMeshProUGUI Kingmaker.UI.ServiceWindow.CharacterScreen.CharSLevel::Level
IL_00c8:ldloc.0
IL_00c9:ldfld class Kingmaker.Localization.LocalizedString Kingmaker.Blueprints.Root.Strings.UITextCharSheet::LEVEL
IL_00ce:call string Kingmaker.Localization.LocalizedString::op_Implicit(class Kingmaker.Localization.LocalizedString)
IL_00d3:ldstr " "
IL_00d8:ldarg.1
IL_00d9:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_00de:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_00e3:box System.Int32
IL_00e8:call string System.String::Concat(object,
object,
object)
IL_00ed:callvirt instance void ['Assembly-CSharp-firstpass']TMPro.TMP_Text::set_text(string)
IL_00f2:ldarg.0
IL_00f3:ldfld class UnityEngine.UI.Image Kingmaker.UI.ServiceWindow.CharacterScreen.CharSLevel::NegativeLevel
IL_00f8:callvirt instance class UnityEngine.GameObject UnityEngine.Component::get_gameObject()
IL_00fd:ldc.i4.0
IL_00fe:callvirt instance void UnityEngine.GameObject::SetActive(bool)
IL_0100:ldarg.1
IL_0101:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_0102:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_0103:ldc.i4.s20
IL_0104:bge IL_0141
IL_0105:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_0106:callvirt instance class Kingmaker.Blueprints.Root.BlueprintRoot Kingmaker.Game::get_BlueprintRoot()
IL_0107:ldfld class Kingmaker.Blueprints.Root.ProgressionRoot Kingmaker.Blueprints.Root.BlueprintRoot::Progression
IL_0108:ldfld class Kingmaker.Blueprints.Classes.BlueprintStatProgression Kingmaker.Blueprints.Root.ProgressionRoot::XPTable
IL_0109:ldfld int32[] Kingmaker.Blueprints.Classes.BlueprintStatProgression::Bonuses
IL_010a:ldarg.1
IL_010b:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_010c:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_010d:ldc.i4.1
IL_010e:add
IL_010f:ldelem.i4
IL_0110:ldc.i4.2
IL_0111:div
IL_011c:stloc.3
IL_011d:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_011e:callvirt instance class Kingmaker.Blueprints.Root.BlueprintRoot Kingmaker.Game::get_BlueprintRoot()
IL_011f:ldfld class Kingmaker.Blueprints.Root.ProgressionRoot Kingmaker.Blueprints.Root.BlueprintRoot::Progression
IL_0120:ldfld class Kingmaker.Blueprints.Classes.BlueprintStatProgression Kingmaker.Blueprints.Root.ProgressionRoot::XPTable
IL_0121:ldfld int32[] Kingmaker.Blueprints.Classes.BlueprintStatProgression::Bonuses
IL_0122:ldarg.1
IL_0123:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_0124:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_0125:ldelem.i4
IL_0126:ldc.i4.2
IL_0127:div
IL_0128:stloc.s V_4
IL_0140:br IL_0174
IL_0141:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_0142:callvirt instance class Kingmaker.Blueprints.Root.BlueprintRoot Kingmaker.Game::get_BlueprintRoot()
IL_0143:ldfld class Kingmaker.Blueprints.Root.ProgressionRoot Kingmaker.Blueprints.Root.BlueprintRoot::Progression
IL_0144:ldfld class Kingmaker.Blueprints.Classes.BlueprintStatProgression Kingmaker.Blueprints.Root.ProgressionRoot::XPTable
IL_0145:ldfld int32[] Kingmaker.Blueprints.Classes.BlueprintStatProgression::Bonuses
IL_0146:ldc.i4.s20
IL_0147:ldelem.i4
IL_0148:ldc.i4.2
IL_0149:div
IL_014a:ldarg.1
IL_014b:ldfld class Kingmaker.UnitLogic.UnitProgressionData Kingmaker.UnitLogic.UnitDescriptor::Progression
IL_014c:callvirt instance int32 Kingmaker.UnitLogic.UnitProgressionData::get_CharacterLevel()
IL_014d:ldc.i4.s19
IL_014e:sub
IL_014f:ldc.i490000
IL_0150:mul
IL_0151:add
IL_0152:stloc.3
IL_0153:ldloc.3
IL_0154:ldc.i490000
IL_0155:sub
IL_0172:stloc.s V_4
职业等级上限及升级能力点数修改
*} // end of method BlueprintCharacterClass::MeetsPrerequisites
IL_001a:ldc.i4.s 40
IL_001c:blt IL_0023
IL_0021:ldc.i4.0
IL_0022:ret
IL_0023:ldarg.0
IL_0024:ldfld bool Kingmaker.Blueprints.Classes.BlueprintCharacterClass::PrestigeClass
IL_0029:brfalse IL_0038
IL_002e:ldloc.0
IL_002f:ldc.i4.s 40
*} // end of method ProgressionData::GetLevelEntry
IL_0000:ldarg.1
IL_0001:ldc.i4.s 20
IL_0002:rem
IL_0003:starg.s level
IL_0004:ldarg.1
IL_0005:brtrue.s IL_0008
IL_0006:ldc.i4.s 20
IL_0007:starg.s level
IL_0008:newobj instance void Kingmaker.UnitLogic.ProgressionData/'<GetLevelEntry>c__AnonStorey0'::.ctor()
IL_0009:stloc.0
IL_000a:ldloc.0
IL_000b:ldarg.1
IL_000c:stfld int32 Kingmaker.UnitLogic.ProgressionData/'<GetLevelEntry>c__AnonStorey0'::level
IL_000d:ldarg.0
角色属性点获得修改(每两级获得1点属性点)
*} // end of method LevelUpState::.ctor
IL_00c8:ldc.i4.2
角色升级生命值修改(每级获得生命点数为:角色生命骰+2+体质加点)
*// end of method ApplyClassMechanics::ApplyHitPoints
IL_00d4:ldc.i4.1
角色负重值修改(100倍负重)
*} // end of method EncumbranceHelper::GetHeavy
IL_007a:call float64 System.Math::Round(float64)
IL_007b:conv.i4
IL_007c:ldc.i4.s 100
IL_007d:mul
IL_007f:conv.i4
角色移动速度修改(移动1.5倍速,战斗1.25倍速)
*} // end of method TimeController::Tick
IL_0063:beq IL_0068
IL_0064:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_0065:callvirt instance valuetype Kingmaker.GameModes.GameModeType Kingmaker.Game::get_CurrentMode()
IL_0066:ldc.i4.7
IL_0067:bne.un IL_00aa
IL_0068:call class Kingmaker.Game Kingmaker.Game::get_Instance()
IL_0069:callvirt instance class Kingmaker.Player Kingmaker.Game::get_Player()
IL_006a:callvirt instance bool Kingmaker.Player::get_IsInCombat()
IL_006b:brtrue IL_0073
IL_006c:ldarg.0
IL_006d:ldarg.0
IL_006e:call instance float32 Kingmaker.Controllers.TimeController::get_DeltaTime()
IL_006f:ldc.r4 1.5
IL_0070:mul
IL_0071:call instance void Kingmaker.Controllers.TimeController::set_DeltaTime(float32)
IL_0072:br IL_0079
IL_0073:ldarg.0
IL_0074:ldarg.0
IL_0075:call instance float32 Kingmaker.Controllers.TimeController::get_DeltaTime()
IL_0076:ldc.r4 1.25
IL_0077:mul
IL_0078:call instance void Kingmaker.Controllers.TimeController::set_DeltaTime(float32)
IL_0079:ldarg.0
IL_007a:ldarg.0
IL_007b:call instance float32 Kingmaker.Controllers.TimeController::get_DeltaTime()
IL_007f:call instance void Kingmaker.Controllers.TimeController::set_GameDeltaTime(float32)
角色大地图移动速度修改(VisualSpeedBase越大移动越快,MechanicsSpeedBase越大游戏时间流逝越慢)
*} // end of method GlobalMapRoot::.ctor
IL_0000:ldarg.0
IL_0001:ldc.r4 0.02
IL_0006:stfld float32 Kingmaker.Blueprints.Root.GlobalMapRoot::VisualSpeedBase
IL_000b:ldarg.0
IL_000c:ldc.r4 12.
IL_0011:stfld float32 Kingmaker.Blueprints.Root.GlobalMapRoot::MechanicsSpeedBase
视野缩放范围修改
*} // end of method CameraZoom::TickZoom
IL_0088:ldc.r4 30
IL_008f:ldc.r4 5
新增隐藏UI开关快捷键 Ctrl + Alt + H
*} // end of method KeyboardAccess::RegisterBuiltinBindings
IL_04d1:ldarg.0
IL_04d2:ldstr "RapidBugReportWindowOpen"
IL_04d3:ldc.i4.s 98
IL_04d4:ldloc.0
IL_04d5:ldc.i4.1
IL_04d6:ldc.i4.1
IL_04d7:ldc.i4.1
IL_04d8:ldc.i4.0
IL_04d9:ldc.i4.0
IL_04da:call instance void Kingmaker.UI.KeyboardAccess::RegisterBinding(string,
valuetype UnityEngine.KeyCode,
class System.Collections.Generic.IEnumerable`1<valuetype Kingmaker.GameModes.GameModeType>,
bool,
bool,
bool,
bool,
valuetype Kingmaker.UI.KeyboardAccess/ModificationSide)
IL_04db:ldarg.0
IL_04dc:ldstr "HideUI"
IL_04dd:ldc.i4.s 104
IL_04de:ldloc.0
IL_04df:ldc.i4.1
IL_04e0:ldc.i4.1
IL_04e1:ldc.i4.0
IL_04e2:ldc.i4.0
IL_04e3:ldc.i4.0
IL_04e4:call instance void Kingmaker.UI.KeyboardAccess::RegisterBinding(string,
valuetype UnityEngine.KeyCode,
class System.Collections.Generic.IEnumerable`1<valuetype Kingmaker.GameModes.GameModeType>,
bool,
bool,
bool,
bool,
valuetype Kingmaker.UI.KeyboardAccess/ModificationSide)
IL_04e5:ldarg.0
IL_04e6:call void Kingmaker.PubSubSystem.EventBus::Subscribe(object)
IL_04ea:ret
+.field public class Kingmaker.GameStatistic Statistic
.field public class UnityEngine.GameObject GameObject
+} // end of method Game::.cctor
.method private hidebysig instance void
'<Initialize>m__13'() cil managed
{
.custom instance void System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// 代码大小 19 (0x13)
.maxstack8
IL_0000:ldarg.0
IL_0001:ldfld class UnityEngine.GameObject Kingmaker.Game::GameObject
IL_0002:brtrue IL_000a
IL_0003:ldarg.0
IL_0004:ldarg.0
IL_0005:ldfld class Kingmaker.UI.UIAccess Kingmaker.Game::UI
IL_0006:callvirt instance class Kingmaker.Assets.UI.MainCanvas Kingmaker.UI.UIAccess::get_MainCanvas()
IL_0007:callvirt instance class UnityEngine.CanvasGroup Kingmaker.Assets.UI.MainCanvas::get_CanvasGroup()
IL_0008:callvirt instance class UnityEngine.GameObject UnityEngine.Component::get_gameObject()
IL_0009:stfld class UnityEngine.GameObject Kingmaker.Game::GameObject
IL_000a:ldarg.0
IL_000b:ldfld class UnityEngine.GameObject Kingmaker.Game::GameObject
IL_000c:ldarg.0
IL_000d:ldfld class UnityEngine.GameObject Kingmaker.Game::GameObject
IL_000e:callvirt instance bool UnityEngine.GameObject::get_activeSelf()
IL_000f:ldc.i4.0
IL_0010:ceq
IL_0011:callvirt instance void UnityEngine.GameObject::SetActive(bool)
IL_0012:ret
} // end of method Game::'<Initialize>m__13'
*} // end of method Game::Initialize
IL_0037:ldarg.0
IL_0038:ldfld class Kingmaker.UI.KeyboardAccess Kingmaker.Game::Keyboard
IL_0039:call void Kingmaker.Utility.Screenshot::Initialize(class Kingmaker.UI.KeyboardAccess)
IL_003a:ldarg.0
IL_003b:ldfld class AuraSupport Kingmaker.Game::AuraSupport
IL_003c:callvirt instance void AuraSupport::Initialize()
IL_003d:ldarg.0
IL_003e:ldfld class Kingmaker.UI.KeyboardAccess Kingmaker.Game::Keyboard
IL_003f:ldstr "HideUI"
IL_0040:ldarg.0
IL_0041:ldftn instance void Kingmaker.Game::'<Initialize>m__13'()
IL_0042:newobj instance void System.Action::.ctor(object,
native int)
IL_0048:callvirt instance void Kingmaker.UI.KeyboardAccess::Bind(string,
class System.Action)
修改施法造成的友军伤害减半
*} // end of method AbilityAcceptBurnOnCast::OnCast
IL_0019:ldfld int32 Kingmaker.UnitLogic.Class.Kineticist.AbilityAcceptBurnOnCast::BurnValue
IL_001a:ldc.i4.2
IL_001b:div
IL_001e:ldarg.1
*} // end of method KineticistAbilityBurnCost::GetTotal
IL_0095:brfalse IL_009c
IL_009a:ldc.i4.1
IL_009b:br IL_009d
IL_009c:ldc.i4.0
IL_009d:mul
IL_009e:add
IL_009f:ldc.i4.2
IL_00a0:div
IL_00a3:ret
本帖最后由 liyun_1981 于 2019-2-8 18:08 编辑
第四部分:IL语言相关
IL汇编语言是什么?简单来说,IL是微软.NET平台上衍生出的一门中间语言,.NET平台上的各种高级语言(如C#,VB,F#)的编译器会将各自的代码转化为IL;详细介绍推荐给有C#编程基础的水友看下这两篇文章:https://blog.csdn.net/dodream/article/details/4726421和http://www.cnblogs.com/xiaoxiang ... /08/08/2130768.html。
本人为了修改IL文件时能方便的查询IL指令,自制了一个IL语言帮助命令,可查询和配置管理IL指令和IL语句的帮助信息;该命令使用说明:
1、解压缩game.7z(有需要的水友请到我这个帖子下载:http://bbs.3dmgame.com/thread-5745545-1-1.html)到任意目录,例如:D:\tools;
2、运行命令提示符,输入cd /d d:\tools\game\bin,再输入 il -h 会显示详细的命令行参数帮助信息:
参数说明:
il [-i|-s]
-i 只显示IL指令的帮助信息。
-s 只显示IL语句的帮助信息。
name IL指令或语句的名称。
单条命令:
il
il -i
il -s
il -i name
il -s name
示例:
il
显示所有IL指令和IL语句的帮助信息。
il -i
显示所有IL指令的帮助信息。
il -s
显示所有IL语句的帮助信息。
il -i ldc.i4
显示IL指令名称为ldc.i4的帮助信息。
il -s instance
显示IL语句名称为instance的帮助信息。
3、第1次运行il命令后,程序会在game\bin目录生成配置文件il.xml,该文件格式如下:
<IL>
<Instructions>
<Helper>
<name>add</name>
<desc>将两个值相加并将结果推送到计算堆栈上。</desc>
<example>
// V_0 += 1
IL_0001:ldloc.0
IL_0002:ldc.i4.1
IL_0003:add
IL_0004:stloc.0
</example>
</Helper>
</Instructions>
<Statements>
<Helper>
<name>class</name>
<desc></desc>
<example></example>
</Helper>
</Statements>
</IL>
其中,Instructions表示IL指令的帮助信息,Statements表示IL语句的帮助信息;每个Helper节点表示一个帮助信息对象,Helper节点包含3个子节点;name表示IL指令或IL语句名称,desc表示IL指令或IL语句的具体描述,example表示IL指令或IL语句的示例代码;直接输入il可以显示所有IL指令和IL语句的帮助信息;该配置文件水友们可以修改或新增内容以丰富IL指令和IL语句的帮助信息。
本帖最后由 liyun_1981 于 2019-2-22 16:43 编辑
第五部分:对MOD制作的一些展望
根据本人对Unity引擎和IL语言的研究心得,目前觉得将来实现以下两个工具提高MOD制作效率是有可能的:
1、使用C#整一个Unity引擎类游戏通用的控制台插件dll,可以在任何Unity引擎类游戏中打开控制台,这样就可以正确的调用所有针对具体的游戏实现了的控制台命令;
2、使用Java扩展下file命令,使其能根据指定的IL替换代码片段自动替换文件Assembly-CSharp.il。
最后,提前祝水友们猪年发大财!:lol
2019年2月22日已实现了第二个展望:使用Java扩展下file命令,使其能根据指定的IL替换代码片段自动替换文件Assembly-CSharp.il,感兴趣的水友请见我今天发的帖子:自制IL汇编语言源文件内容自动替换工具,继年前的帖子“Unity引擎类游戏MOD制作通用教程。。。”后新年第一弹!!!
强力支持~希望好MOD越来越多。 楼主对游戏是真爱 楼主牛逼 感谢分享!~ 66666666666666666666666666666
66666666666666666666666666666 liyun_1981 发表于 2019-2-2 23:02
第二部分:DLL文件的反编译与重编译
第二部分第4条第二个ildasm少了个d
liyun_1981 发表于 2019-2-2 23:02
第三部分:IL文件的修改
大神,我很好奇你是怎么得知需要修改的目标代码的查询关键字的?望指点
bin4633 发表于 2019-3-13 01:51
大神,我很好奇你是怎么得知需要修改的目标代码的查询关键字的?望指点
...
这种时候一般都是根据方法名类名去猜测的,在看看代码的具体逻辑,得出结论并不难,难的是汇编看着太费劲了
大佬打包成dll时候错了ilasm /dll /resource:Assembly-CSharp.res Assembly-CSharp.il /output:Assembly-CSharp.dll 这一步报错了,fail to write output file, error code=0x80070005:Q 楼主你不仅把移动速度改成1.5了吧,整个游戏时间被你加快了1.5倍 大佬请问一下,使用40级上限那个补丁之后,新建角色和角色升级的时候,种族的名字和天赋的名字都不显示了, liyun_1981 发表于 2019-4-12 17:42
在“游戏设置”界面把字体调到最小就行,这个是游戏的UI的框框不能自动跟随字体动态调整的问题。
...
谢大佬,去试一试
大佬游戏更新到1.3.2,40级上限那个mod是不是不能用了 那就等大佬更新mod了{:3_113:} 楼主牛逼!!!!!!!!!!!! 厉害!!!!!!!!!!!! 谢大佬。。不过升两级拿属性的代码被改了。。还是那里是要加一行啊 大佬牛逼啊,必须支持 liyun_1981 发表于 2019-2-2 23:02
第三部分:IL文件的修改
LZ求问魔战士的法术战斗(SpellCombat)怎么改成神术/双手/双持武器可用?
借地问一下,40级mod里秘术师10级之后不提升神术施法者等级了啊 真干货,感谢楼主分享
页:
[1]
2