《終極動員令:重製版》MOD製作圖文教程
《終極動員令:重製版》是對終極動員令的高清重置,當然一些製作MOD的方法可以繼承,不過一些老版的工具代碼無法使用了,下邊就給大家帶來“bbitt”分享的終極動員令重製版MOD製作圖文教程,大家可以來看一看。
終極動員令重製版MOD製作圖文教程
我們先準備一些東西:
1.有一定儲備的知識:具備一定的計算機編程語言知識,MOD的製作不只是隨便修改一下代碼就OK的。
2.Microsoft Visual Studio:要下載2017版本,2019版與官方提供的開源存在一定衝突。我在附件裡會提供下載安裝用的程序。
3.批量UTF8查找工具:我附件會提供一個,你們若是有更好的請自行準備。
4.《終極動員令》MOD開發用的開源代碼:正版遊戲安裝目錄中會有提供。
現在開始教程:
一、下載安裝 Microsoft Visual Studio 2017版,選擇 使用C++桌面開發 其他用不到,就不要裝了。
右邊的安裝詳細信息裡的建議都選上。裡面有你對應系統的一些補丁、編程語言包之類的。
然後右下角點 安裝 ,我因為已經裝好了所以是“關閉”。
注意:將你的系統設置為支持UTF8編碼,如果不設置的話 Microsoft Visual Studio 會將源碼程序中編碼編譯成其他編碼,生成MOD的時候會報錯。
Win10設置方法:
1、首先在開始菜單單擊滑鼠右鍵,點擊 運行 ;
2、輸入control回車打開控制面板>時鐘和區域>區域>管理>更該系統區域設置>勾選"Beta 版: 使用 Unicode UTF-8 提供全球語言支持" 。
二、我們找到遊戲安裝目錄中的 SOURCECODE 目錄(正版有,盜版有沒有不知道),將其拷貝出來(存哪你自己決定,別問我)。這個目錄就是官方提供的開源代碼程序。
用 Microsoft Visual Studio 打開你拷貝出去的目錄中的 CnCRemastered.sln 文件(文件→打開→項目/解決方案),右邊的解決方案資源管理器就會如圖中所示加載完畢。
裡麵包含兩個項目,分別對應的是《紅色警戒》和《終極動員令》,請根據自己的目標來修改。我這裡就以《終極動員令》中修改一個部門“jeep”車為例。點開 TiberianDawn 項目,
我們可以看到很多的文件,哪個文件才是我們要找的目標呢?
接下來我們就需要用到 批量UTF8查找工具 了,我附件有提供,如果你們有其他工具請注意,一定要使用支持UTF8的工具。MOD修改時需要用到遊戲中的一些要素,我們就通過查找這些要素來定位要找的文件。
這裡因為打算要修改的是遊戲裡部門的屬性,我們已知的要素包含名字“jeep”和購買價格“COST”兩個字元串,我們就搜索這兩組字元串來找文件。
以我提供的修改器為例:
目錄選擇拷貝出去的目錄中 tiberiandawn 目錄,原字元串名改為 JEEP ,不區分大小寫,選中 僅查找不替換 ,新字元串名留空,點執行會生成一個文本文檔,不要關閉。
將原字元串名改為 COST(購買價格),點執行又會生成一個文本文檔。我們現在對比兩份文檔,可以看到這兩種字元串在同一個文件中出現了:UDATA.CPP
窗口切換到Microsoft Visual Studio ,找到之前打開的TiberianDawn 項目下 Source Files 目錄中的 UDATA.CPP 文件並雙擊打開。按 Ctrl+F 彈出搜索框 輸入 jeep 回車,就
找到了我們要搜索的字元段。
我們看下下邊的內容:
//符號左邊邊是源代碼,右邊是對該段代碼的描述。
// Jeep (hummer)
static UnitTypeClass const UnitJeep(
UNIT_JEEP,
TXT_JEEP, // NAME: Text name of this unit type. 這個部門類型的名字
"JEEP", // NAME: Text name of this unit type. 這個部門類型的名字(和上一個有什麽區別不知道,沒做測試)
ANIM_FRAG1, // EXPLOSION: Type of explosion when destroyed. 摧毀時的爆炸類型
2, // Build level. 建造、製造等級
STRUCTF_NONE, // Building prerequisite. 建造、製造先決條件
true, // Can this be a goodie surprise from a crate? 這個是否能從“板條箱”中得到(遊戲裡拾取箱子)
true, // Is a leader type? 是否是領航類型
false, // Only has eight facings? 是否只有8個朝向?(應該是車輛朝的方向:上、下、左、右、左上、右上、左下、右下)
false, // Always use the given name for the vehicle? 始終使用車輛的給定名稱?
false, // Is this a typical transport vehicle? 這是典型的運輸工具嗎?
false, // Can it be crushed by a heavy vehicle? 能被重型車壓碎嗎?
false, // Can this unit squash infantry? 這個部門能壓製步兵嗎?
false, // Does this unit harvest Tiberium? 這個部門能運送泰伯利亞礦石嗎?
false, // Is invisible to radar? 這個部門在雷達上隱形嗎?
true, // Is selectable by player? 這個部門能否被玩家選中?
true, // Can it be a target for attack or move? 是否是可以被移動或攻擊的目標
false, // Is it insignificant (won't be announced)? 是否無關緊要
false, // Is it immune to normal combat damage? 對正常戰鬥傷害免疫嗎?
true, // Is it equipped with a combat turret? 它裝備了戰鬥炮塔嗎?
false, // Fires multiple shots in quick succession? 快速射擊是否連續射出多發子彈?
true, // Can it be repaired in a repair facility? 它能在修理廠修理嗎?
true, // Can the player construct or order this unit? player可以建造或命令這個單元嗎?
true, // Is there a crew inside? 裡面有人嗎?(有人的話擊毀後可以掉出小兵)
false, // Does it have a rotating radar dish? 它有旋轉的雷達天線嗎?
false, // Is there an associated firing animation? 是否存在關聯的射擊動畫?
false, // Must the turret be in a locked down position while moving? 移動時炮塔是否鎖定不動?
true, // Does it lay tracks while moving? 它在移動時會留下痕跡嗎?
false, // Is this a gigundo-rotund-enormous unit? 是一個 gigundo-圓形-巨大 單元嗎?(不懂)
false, // Is the unit's art as "chunky" cardinal facing only? (不懂)
false, // Is the unit capable of cloaking? 這個部門能隱形嗎?
false, // Does the unit have a constant animation? 該單元是否具有常量動畫?
-1, // AMMO: Number of shots it has (default). 彈藥量 -1是無限
150, // STRENGTH: Strength (in damage points). 裝甲強度(俗稱血量)
2, // SIGHTRANGE: Range of sighting. 視線範圍
1, // COST: Cost to build (Credits). 價格(我這裡改成1是因為測試MOD用)
5, // SCENARIO: Starting availability scenario. 可用性開始場景(不明白用法)
80,41, // RISK/RWRD: Risk/reward rating values. 風險與回報評級值(不太懂用法)
HOUSEF_MULTI1|
HOUSEF_MULTI2|
HOUSEF_MULTI3|
HOUSEF_MULTI4|
HOUSEF_MULTI5|
HOUSEF_MULTI6|
HOUSEF_JP|
HOUSEF_GOOD, // OWNABLE: Ownable by house (bit field).
WEAPON_M60MG,WEAPON_NONE, 第一武器 ,第二武器
ARMOR_ALUMINUM, // ARMOR: Armor type 裝甲類型 ALUMINUM 是鋁
SPEED_WHEEL, // MOVE: Locomotion type. 移動類型 WHEEL輪式
MPH_MEDIUM_FAST, // SPEED: Miles per hour. 速度(英裡每小時) 格式不太懂,這個應該是個變量可以參考其他部門
10, // ROT: Rate of turn (degrees per tick). 炮塔轉動速度
0, // Turret center offset along body centerline. 炮塔中心沿著身體中心線偏移(使用方法不明)
MISSION_HUNT // ORDERS: Default order to give new unit. 訂單:給予新部門的默認訂單。(用法不明)
);
根據自己的目的進行修改代碼。(我這裡只是修改了價格為1)
三、當你把所有要修改的修改完成後我們接下來生成MOD文件
滑鼠右鍵點擊 Microsoft Visual Studio 的窗口中右邊解決方案資源管理器中 TiberianDawn 項目,彈出菜單後選擇 生成
生成時會在下邊的輸出窗口有各種提示,如果有錯誤會提示哪裡有錯誤,請根據提示修正問題。如果正常生成完成就會提示 生成: 成功 xx 個,失敗 0 個,最新 0 個,跳過 0 個
這裡重說一下,如果你之前沒有將系統修改為支持UTF8編碼,就會提示:
warning C4819: 該文件包含不能在當前代碼頁(936)中表示的字元。請將該文件保存為 Unicode 格式以防止數據丟失
生成成功後我們到源代碼目錄中的 bin 目錄下的 Win32 目錄中有4個文件,其中我們要用到的只有 TiberianDawn.dll 和 TiberianDawn.pdb 兩個文件。
MOD文件已經準備好了,現在建立一個目錄 bbitt - TD Only (名字你自己決定,這裡就以我準備的測試用MOD舉例)。在bbitt - TD Only 目錄下新建一個 DATA 目錄。
將之前準備好的 TiberianDawn.dll 和 TiberianDawn.pdb 兩個文件複製進去。
然後回到 bbitt - TD Only 目錄下新建一個文本文檔,內容為:
{
"name": "bbitt - TD Only", MOD名字 bbitt - TD Only ,我怕識別不了就和目錄名字相同
"description": "Changes Hummer cost = 1", MOD簡介 Changes Hummer cost = 1 改變hummer的價額為1
"author": "bbitt", 作者
"load_order": 1, 加載順序
"version_low": 0, 版本低
"version_high": 1, 版本高,與版本低之間貌似一個設為1,另一個必須設為0
"game_type": "TD" 遊戲類型:泰伯利亞黎明
}
內容填好後將其重命名為 ccmod.json 注意擴展名,可不是 ccmod.json.txt 。
這樣MOD目錄就OK了。我們現在需要的就是將其放在遊戲專門的MODS目錄中。具體位置是在 文檔>CnCRemastered>Mods>Tiberian_Dawn 目錄中。
好了我們測試一下,看看我們的MOD是否能加載,是否有效果。進入遊戲、選項、模組,OK,我們的MOD已經刷新出來了。選中然後點確定,會重啟遊戲。
重啟後模組就加載好了,測試一下,完美!
首先對上邊關於部門的代碼段中關於可購買的陣營做一個補充 HOUSEF_GOOD, // OWNABLE: Ownable by house (bit field).
這段代碼代表的是可購買的陣營 HOUSEF_GOOD 是GDI HOUSEF_BAD 是NOD ,如果設置成 HOUSEF_GOOD|(回車換行)HOUSEF_BAD, 就是兩個陣營都能選。
四、上邊給大家講到了UDATA.CPP 中對於遊戲中部門的修改。通過之前提到的對比方式我們可以在以下幾個文件中查到並修改相關的一些數據。
AADATA.CPP 裡面存放的是飛行部門的數據
BDATA.CPP 裡面存放的是建築物的數據
BBDATA.CPP 裡面可以找到子彈相關數據(修改武器屬性可以用到)
CONST.CPP 裡面存放的是常量數據,我們可以在裡面找到武器屬性、彈頭傷害等相關的數據
DEFINE.H 裡面是一些定義 比如武器有哪些、彈頭有哪些,因為沒深層次研究所以不知道是否在這裡增加武器。因為就算光在這裡增加武器,沒修改其他相關代碼也沒用。
飛行部門和建築物的修改,我就不做過多介紹了,仔細看好 // 符號右邊的相關注釋,實在不知道怎麽改對比一下同類其他部門或建築物的代碼,一般不會有什麽大問題。
我們接下來講一下CONST.CPP 中武器傷害的修改。
首先我們先通過之前查找部門相關代碼中找到關於 第一武器和第二武器的代碼。然後在 CONST.CPP 中查找你相關的武器代碼,例如 WEAPON_M60MG (jeep的M60機槍)
可以看到以下的代碼:
***************************************************************************
** 這些是各種武器及其特點
**
** 子彈類型 傷害,再次發射間隔,範圍, 聲音,動畫 //右邊的是武器代碼
*/
WeaponTypeClass const Weapons[WEAPON_COUNT] = {
{BULLET_SNIPER, 125, 40, 0x0580, VOC_SNIPER, ANIM_NONE}, // WEAPON_RIFLE
{BULLET_SPREADFIRE, 25, 50, 0x0400, VOC_MINI, ANIM_GUN_N}, // WEAPON_CHAIN_GUN
{BULLET_BULLET, 1, 7, 0x01C0, VOC_RIFLE, ANIM_NONE}, // WEAPON_PISTOL
{BULLET_BULLET, 15, 20, 0x0200, VOC_MGUN2, ANIM_NONE}, // WEAPON_M16
{BULLET_TOW, 30, 60, 0x0400, VOC_BAZOOKA,ANIM_NONE}, // WEAPON_DRAGON
{BULLET_FLAME, 35, 50, 0x0200, VOC_FLAMER1,ANIM_FLAME_N}, // WEAPON_FLAMETHROWER
{BULLET_FLAME, 50, 50, 0x0200, VOC_FLAMER1,ANIM_FLAME_N}, // WEAPON_FLAME_TONGUE
{BULLET_CHEMSPRAY, 80, 70, 0x0200, VOC_FLAMER1,ANIM_CHEM_N}, // WEAPON_CHEMSPRAY
{BULLET_GRENADE, 50, 60, 0x0340, VOC_TOSS, ANIM_NONE}, // WEAPON_GRENADE
{BULLET_APDS, 25, 60, 0x0400, VOC_TANK2, ANIM_MUZZLE_FLASH}, // WEAPON_75MM
{BULLET_APDS, 30, 50, 0x04C0, VOC_TANK3, ANIM_MUZZLE_FLASH}, // WEAPON_105MM
{BULLET_APDS, 40, 80, 0x04C0, VOC_TANK4, ANIM_MUZZLE_FLASH}, // WEAPON_120MM
{BULLET_APDS, 40, 60, 0x0600, VOC_TANK4, ANIM_MUZZLE_FLASH}, // WEAPON_TURRET_GUN
{BULLET_SSM, 75, 80, 0x0500, VOC_ROCKET1,ANIM_NONE}, // WEAPON_MAMMOTH_TUSK
{BULLET_SSM2, 75, 80, 0x0600, VOC_ROCKET1,ANIM_NONE}, // WEAPON_MLRS
{BULLET_HE, 150, 65, 0x0600, VOC_TANK1, ANIM_MUZZLE_FLASH}, // WEAPON_155MM
{BULLET_BULLET, 15, 30, 0x0400, VOC_MGUN11, ANIM_GUN_N}, // WEAPON_M60MG
{BULLET_SSM, 60, 35, 0x0780, VOC_ROCKET2,ANIM_NONE}, // WEAPON_TOMAHAWK
{BULLET_SSM, 60, 40, 0x0680, VOC_ROCKET2,ANIM_NONE}, // WEAPON_TOW_TWO
{BULLET_NAPALM, 100, 20, 0x0480, VOC_NONE, ANIM_NONE}, // WEAPON_NAPALM
{BULLET_LASER, 200, 90, 0x0780, VOC_LASER, ANIM_NONE}, // WEAPON_OBELISK_LASER
{BULLET_SAM, 50, 50, 0x0780, VOC_ROCKET2,ANIM_NONE}, // WEAPON_NIKE
{BULLET_HONEST_JOHN, 100, 200, 0x0A00, VOC_ROCKET1,ANIM_NONE}, // WEAPON_HONEST_JOHN
{BULLET_HEADBUTT, 100, 30, 0x0180, VOC_DINOATK1,ANIM_NONE}, // WEAPON_STEG
{BULLET_TREXBITE, 155, 30, 0x0180, VOC_DINOATK1,ANIM_NONE}, // WEAPON_TREX
#ifdef PETROGLYPH_EXAMPLE_MOD
{BULLET_NUKE_LOB, 150, 130, 0x0B00, VOC_NUKE_LOB, ANIM_MUZZLE_FLASH}, // WEAPON_NUKE_LOB
#endif //PETROGLYPH_EXAMPLE_MOD
從上邊代碼可以看出M60機槍的默認屬性
使用的子彈類型是BULLET_BULLET(普通子彈),傷害值——15,射擊間隔(暫定為15=1秒)2秒,射擊距離為0x0400(怎麽計算不知道),聲音為VOC_MGUN11,射擊動畫 ANIM_GUN_N
這段代碼結合其他武器代碼,我們可以修改傷害值不用說,比如把射擊距離改的和155MM艦炮一樣0x0600,子彈類型改成 BULLET_HE(高爆)或者 BULLET_NUKE_LOB (核彈)。
我們接下來看一下子彈的相關數據,以高爆彈 BULLET_HE為例,我們從BBDATA.CPP 裡查到代碼如下:
tatic BulletTypeClass const Class120mm(
BULLET_HE,
"120mm", // NAME: Text name of this unit type. 部門名稱
true, // Flies over tall walls? 是否飛躍建築物
false, // Homes in on target? 房屋是否列為目標
true, // Projectile arcs to the target? 向目標發射弧線彈道嗎
false, // Is this a dropping bomb-like object? 這是否是一個炸彈
false, // Is this projectile invisible? 這個投射物不可見嗎?
false, // Will it blow up even if it gets just NEAR to target? 接近目標,會爆炸嗎?
false, // Does it have flickering flame animation? 是否有閃爍的火焰動畫
false, // Can it run out of fuel? 是否會耗光燃料
true, // Is there no visual difference between projectile facings? 拋射面之間是否沒有視覺差異
true, // Is projectile inherently inaccurate? 拋射本身就不準確嗎?
false, // Translucent colors are used? 使用半透明的顏色
false, // Good against aircraft? 是否對飛機有好處
0, // ARMING: Time to arm projectile after launch. 發射後準備發射的時間
0, // RANGE: Inherent override range factor. 固有覆蓋範圍因子
MPH_MEDIUM_FAST, // SPEED: Miles per hour.
0, // ROT: Rate of turn (degrees per tick). 旋轉速度
WARHEAD_HE, // WARHEAD: If fires weapon, warhead type 子彈的彈頭類型
ANIM_ART_EXP1 // Explosion to use upon impact. 子彈爆炸的動畫
);。
子彈的彈頭相關數據還在 CONST.CPP 中,就在武器代碼的下方:
/***************************************************************************
** 這些是各種彈頭。
**
** 擴散系數, 是否摧毀牆壁,是否摧毀建築, 是否摧毀泰礦, {裝甲防禦表} ///裝甲防禦表代表不同的裝甲在該種彈頭的攻擊下受到的不同的傷害比例
** -vs- {無裝甲, 木頭, 鋁質, 鋼鐵, 混凝土}
*/
WarheadTypeClass const Warheads[WARHEAD_COUNT] = {
{ 2,false,false,false,{0x100, 0x80, 0x90, 0x40, 0x40}}, // WARHEAD_SA Small arms -- good against infantry.
{ 6,true,true,true,{0xE0, 0xC0, 0x90, 0x40, 0x100}}, // WARHEAD_HE High explosive -- good against buildings & infantry.
{ 6,true,true,false,{0x40, 0xC0, 0xC0, 0x100, 0x80}}, // WARHEAD_AP Armor piercing -- good against armor.
{ 8,false,true,true,{0xE0, 0x100, 0xB0, 0x40, 0x80}}, // WARHEAD_FIRE Incendiary -- Good against flammables.
{ 4,false,false,false,{0x100, 0x100, 0x100, 0x100, 0x100}},// WARHEAD_LASER Light Amplification of Stimulated Emission by Radiation.
{ 7,true,true,true,{0x100, 0x100, 0xC0, 0xC0, 0xC0}}, // WARHEAD_PB Particle beam (neutron beam).
{ 4,false,false,false,{0x100, 0x20, 0x20, 0x10, 0x10}}, // WARHEAD_FIST Punching in hand-to-hand combat.
{ 4,false,false,false,{0x100, 0x20, 0x20, 0x10, 0x10}}, // WARHEAD_FOOT Kicking in hand-to-hand combat.
{ 4,false,false,false,{0x100, 0x08, 0x08, 0x08, 0x08}}, // WARHEAD_HOLLOW_POINT Sniper bullet type.
{255,false,false,false,{0x100, 0x01, 0x01, 0x01, 0x01}}, // WARHEAD_SPORE
{ 1, true,true,false,{0x100, 0xC0, 0x80, 0x20, 0x08}}, // WARHEAD_HEADBUTT
{ 1, true,true,false,{0x100, 0xC0, 0x80, 0x20, 0x08}}, // WARHEAD_FEEDME
};
對比一下各種彈頭對於不同類型傷害,可以看出,WARHEAD_HE 彈頭,對於無裝甲目標的時候的傷害是最高的 0xE0 。只要不超過這個值你可以根據需要自己設置。
五,超級武器冷卻間隔的設置
STEAM創意工廠已經有人放出了修改了冷卻時間的MOD,這裡就給大家講一下搜索以及修改的原理
我們首先要知道兩個要素:1 超級武器裡的核武 NUKE ;2 時間 TIME ,其次要知道 TIME 這個要素肯定有很多地方會用到,相對的 NUKE 則會用到的地方少一些。
在 Microsoft Visual Studio 打開的源代碼中按 CTRL+SHIFT+F 彈出搜索框,查找內容一欄輸入 NUKE ,查找範圍選擇 當前項目 ,然後點 查找全部,會在下方出現 查找結果 。
我們從查找結果列表中可以看到列出的各個文件中包含 NUKE 這個代碼的所有文件和相對應的代碼語句。滑鼠點擊列表中的任意一項就會打開對應的文件以及定位到對應的語句。
通過查找列表可以看到 SOURCECODE\TIBERIANDAWN\DEFINES.H(320):#define NUKE_GONE_TIME 14*TICKS_PER_MINUTE 這一項中兩個要查找的要素都包含。
點擊該項打開文件,我們可以看到以下代碼段:
/**********************************************************************
** These defines control the rate of ion cannon and airstrike recharging.
*/
#define NUKE_GONE_TIME 14*TICKS_PER_MINUTE //核武冷卻時間
#define ION_CANNON_GONE_TIME 10*TICKS_PER_MINUTE //離子加農炮冷卻時間
#define AIR_CANNON_GONE_TIME 8*TICKS_PER_MINUTE //空中打擊冷卻時間
#define OBELISK_ANIMATION_RATE 15
這就是超級武器的冷卻時間。但是 TICKS_PER_MINUTE 是什麽意思呢?用上邊講到的方法,我們查找 TICKS_PER_MINUTE ,在 ABSTRACT.CPP 文件中可以找到以下代碼段:
/****************************************************************************
** Timer constants. These are used when setting the countdown timer.
** Note that this is based upon a timer that ticks every 60th of a second.
*/
#define TICKS_PER_SECOND 15
#define TICKS_PER_MINUTE (TICKS_PER_SECOND * 60)
#define TIMER_SECOND 60
#define TIMER_MINUTE (TIMER_SECOND*60)
這個是整個源代碼中對於一些時間變量的定義。比如你查到的時間變量是 14*TICKS_PER_MINUTE ,這個是多久?通過這個定義就知道了,是14分鐘。如果查到的是 14*TIMER_SECOND,就是14秒。
了解了時間變量 TICKS_PER_MINUTE 的含義,我們回到之前的超級武器冷卻時間的代碼段,就明白了該怎麽設置了吧。3*TICKS_PER_SECOND ? 1*TICKS_PER_MINUTE?一切都隨你所願。如果想
徹底無冷卻就改成 0*TICKS_PER_MINUTE 即可。
附件鏈接:https://pan.baidu.com/s/1O9OE6PWy4OM9unHSSizJjQ
提取碼:cx1j