Getting Started with BF4 WR Modding
Author
DesertShadowDate Published
Prerequisites:
- EA App (For BF4 verification)
- Battlefield 4
- Warsaw Revamped Account
1.) Open EA App and login.
This is for when WR-Launcher asks for first-time verification.
2.) Download and Install the Warsaw Revamped Launcher.
Login to https://warsaw.gg/ and download the launcher. Microsoft Smartscreen will block WR-Launcher. Click more more info
and run anyway
. In WR-Launcher click Sign In and use your Warsaw Revamped account to login thru the browser. Go back your Warsaw Launcher follow the instructions for verifying BF4.
3.) Configuring your server
Click on the Server Icon. Create a new Template.
In the template overview enable Official WR Experience Mod
and Enable Workspace
Now click on the Start button to run your server.
Go to the server browser.
Click on the Play button for your Server.
Click on Soldier in the new dropdown.
Should be able to join your own server.
Go to your Documents/Warsaw Revamped/Servers/YourTemplateName/Admin
folder.
Create any missing files:
Engine.txt
A few engine tweaks, like no preround, more TBA.
1Game.DisablePreRound 12Server.OutgoingHighFrequency 60
Startup.txt
This controls your server name in the listing, the RCON admin server. More TBA.
1admin.password "YOUR_PASSWORD_HERE"2vars.serverName "YOUR_SEVER_NAME_HERE"3vars.serverType "unranked"
Maplist.txt
The first entry here controls first map you load into. All mapcodes/gamemodes TBA.
1MP_Playground TutorialMP 12MP_Siege ConquestLarge0 13MP_Naval ConquestLarge0 24MP_Journey SquadDeathMatch0 25MP_Prison SquadDeathMatch0 26MP_Prison ConquestSmall0 27MP_Journey ConquestSmall0 28MP_Prison ConquestLarge0 29MP_Journey ConquestLarge0 210XP6_CMP ConquestLarge0 211MP_Naval ConquestLarge0 212MP_Naval SquadDeathMatch0 213XP0_Firestorm ConquestLarge0 214MP_Journey TeamDeathMatch0 215MP_Prison TeamDeathMatch0 216XP2_002 ConquestLarge0 217MP_Flooded TeamDeathMatch0 218MP_Siege ConquestSmall0 219MP_Prison GunMaster0 220MP_Siege SquadDeathMatch0 221MP_Abandoned Domination0 222MP_Flooded ConquestLarge0 223MP_Siege TeamDeathMatch0 2
4.) IDE setup
Download and install VSCode from
Open VSCode and press CTRL + Shift + X
to open extensions menu.
Type luau and click the one by JohnnyMoganz. Install this extension.
Inside of ..Documents/Warsaw Revamped/Mods
(Create Mods folder if it doesn't exist yet)
Create the folder wr_official
Inside of wr_official
create the folder .vscode
Inside of .vscode
create the file settings.json
Paste in the following to the file:
1{2 "luau-lsp.completion.autocompleteEnd": true,3 "luau-lsp.completion.imports.requireStyle": "alwaysRelative",4 "luau-lsp.require.directoryAliases": {5 ".": "C:\\Users\\YOUR_USER_HERE\\Documents\\Warsaw Revamped\\Package Cache"6 },7 "luau-lsp.require.mode": "relativeToFile",8 "luau-lsp.types.definitionFiles": [9 "C:\\Users\\YOUR_USER_HERE\\Documents\\Warsaw Revamped\\Mod Toolkit\\API Definitions\\wr-core.d.luau",10 "C:\\Users\\YOUR_USER_HERE\\Documents\\Warsaw Revamped\\Mod Toolkit\\API Definitions\\wr-gen.d.luau",11 "C:\\Users\\YOUR_USER_HERE\\Documents\\Warsaw Revamped\\Mod Toolkit\\API Definitions\\wr-managers.d.luau"12 ],13 "luau-lsp.platform.type": "standard",14 "luau-lsp.inlayHints.functionReturnTypes": true,15 "luau-lsp.inlayHints.parameterNames": "all",16 "luau-lsp.inlayHints.parameterTypes": true,17 "luau-lsp.inlayHints.variableTypes": true18}
In your .vscode/settings.json
, update YOUR_USER_HERE with the username of your computer.
Double click on YOUR_USER_HERE and press CTRL + H
to activate Find and Replace.
In lower box type your Windows User Name. Press CTRL + ALT + ENTER
to replace all.
5.) Version control setup (OPTIONAL)
If you don't want version control, skip to section 6.
Instructions if you are okay with Github:
Create a Github Account at https://github.com
Download and install Github Desktop from https://desktop.github.com/download/
Complete the 2 minute tutorial to get the basics.
In Github Desktop, click on add existing repository and navigate to your wr_official folder.
It might prompt you to make a new repository, just follow the instructions.
6.) Modding Overview (file structure etc)
Each mod requires 3 files.
wr-config.toml
this file tells WR info about your mod
preinit.luau
this is the first file which executes. It has some niche use cases, such as setting up an reporting handler
init.luau
this is the entry point for your mod logic. Everything starts from here.
Pre-init phase is before a map has been loaded, essentially on startup. You can modify static datacontainers that don't change here, but some stuff will be restricted here because it's not initialized yet.
Init phase only exists while a map is loaded. Scripts are always reloaded between rounds.
To visualize it, you'll have pre-init -> map load -> init -> map load -> init -> map load -> init
7.) Creating and running a mod
Go to your Documents/Warsaw Revamped/Package Cache
and extract the partitions zip folder. Rename the extracted folder to just partitions
. Leave the zip on in there.
Go to the website
If Powback's EBX site is not loading anything for you (folder with no name), **clear your session / localstorage for the site** and refresh.
At the top left switch from Venice to Warsaw and hit refresh (f5).
Double Click on the warsaw folder
Click on Gameplay folder dropdown
Click on Weapons folder dropdown
Click on AK12 folder dropdown
Click on AK12.json file
In the middle section you will now see a SoldierWeaponBlueprint
This is where you can get the Partition
and Instance
GUIDs.
If an instance GUID is full of Zero's like this: 0000-0000-0000-0005
it is **invalid** and you must pick something higher up and drill down to whatever datacontainer you are trying to change.
Don't worry about copying them, the example code has everything already.
Inside of Documents/Warsaw Revamped/Mods/wr_official
Create the file wr-config.toml
with content:
1[script]2name = "wr_official"3version = "0.1.0"4author_ids = ["yourName"]5description = "yourDescription"6repository = "https://anyTextButShouldBeLinkToYourRepository"7tags = ["official", "wr"]89[dependencies]10partitions = "0.1.0"
Create the file preinit.luau
with content:
1--!strict23local partitions = require("./partitions")45print("PreInitializing of Mod")67return nil
Create the file init.luau
with content:
1--!strict23require("Weapons/AK12")45return nil
Create a folder called Weapons
.
Inside of Weapons
, create a file called AK12.luau
1--!strict2local partitions = require("./partitions")34local AK12 = {}56print("Hello World!")78local AK12SoldierWeaponBlueprint = {9 partitionGuid = Guid("AE353FA9-58C8-41F0-B6FF-2E65C28D2D4A"),10 instanceGuid = Guid("286A045F-C526-4339-A0F5-5FA5FB681D20")11}1213function AK12:OnWeaponBlueprintLoad(p_SoldierWeaponBlueprint: SoldierWeaponBlueprint)14 print("***** Found AK12 Blueprint!!!")15 local s_SoldierWeaponData = p_SoldierWeaponBlueprint.object :: SoldierWeaponData16 local s_WeaponFiringData = s_SoldierWeaponData.weaponFiring17 local s_FiringFunctionData = s_WeaponFiringData.primaryFire18 local s_Shot = s_FiringFunctionData.shot19 s_Shot.initialSpeed.z = 5020end2122partitions.onInstanceLoad(23 AK12SoldierWeaponBlueprint.partitionGuid,24 AK12SoldierWeaponBlueprint.instanceGuid,25 AK12,26 AK12.OnWeaponBlueprintLoad27)2829return nil
For the function parameter we are annotating the p_SoldierWeaponBlueprint
with type SoldierWeaponBlueprint
(you can see the type in the EBX page).
After the print statement we are casting the p_SoldierWeaponBlueprint.object
to SoldierWeaponData
(you can see the type in the EBX page).
This allows us to see the fields in vscode, and it warns you when accessing a field that doesn't exist.
You should see Hello World!
in the server log.
You will not see Found AK12 Blueprint!!!
until you equip an AK12.
In BF4 things are only loaded when they are needed.
This also means if you switch from AK12 to something else, and nobody else has AK12, the changes are destroyed.
When you switch back from something else, to the AK12, you will see Found AK12 Blueprint!!!
again and again.
This heavily complicates modding, because you have to make sure the things you are using are all loaded, and will continue to be loaded.
Sidenote: The prefixes before variable names are optional. I just have them to keep track of parameters and variables defined inside of functions.
8.) Example of modding not working.
Make the contents of Weapons/AK12.luau
:
1--!strict23local partitions = require("./partitions")45local AK12 = {}67local AK12SoldierWeaponBlueprint = {8 partitionGuid = Guid("AE353FA9-58C8-41F0-B6FF-2E65C28D2D4A"),9 instanceGuid = Guid("286A045F-C526-4339-A0F5-5FA5FB681D20")10}1112local SmawProjectile = {13 partitionGuid = Guid("168F529B-17F6-11E0-8CD8-85483A75A7C5"),14 instanceGuid = Guid("90BAEBC0-C9E6-CB0B-7531-110499218677")15}1617function AK12:OnEverythingLoaded(p_SoldierWeaponBlueprint: SoldierWeaponBlueprint, p_SmawProjectileBlueprint: ProjectileBlueprint)18 print("Making AK12 fire SMAW projectiles")19 local s_SoldierWeaponData = p_SoldierWeaponBlueprint.object :: SoldierWeaponData20 local s_WeaponFiringData = s_SoldierWeaponData.weaponFiring21 local s_FiringFunctionData = s_WeaponFiringData.primaryFire2223 local s_Shot = s_FiringFunctionData.shot24 s_Shot.projectile = p_SmawProjectileBlueprint25 s_Shot.projectileData = p_SmawProjectileBlueprint.object :: MissileEntityData26end2728partitions.onAllInstancesLoaded(AK12, AK12.OnEverythingLoaded,29 {30 partition = AK12SoldierWeaponBlueprint.partitionGuid,31 instance = AK12SoldierWeaponBlueprint.instanceGuid32 },33 {34 partition = SmawProjectile.partitionGuid,35 instance = SmawProjectile.instanceGuid36 }37)3839return nil
With this code we are attempting to take the SMAW's projectile and put it onto the AK12.
You have to spawn with AK12. Redeploy. Spawn with SMAW. Redeploy. Spawn with AK12 again and shoot quickly.
AK12 will shoot SMAW rockets for a second or two until the SMAW is cleaned up from map (because nobody has smaw).
Then your client will crash. :D:D:D:D
This problem is being worked on atm.
9.) How and where to deploy/distribute mods?
TBA. There will be a modding platfrom eventually. For now just your stuff onto github and share it in the discord.
10.) How to find and use other people's mods?
Check the WR discord for mod announcements
11.) How to join someone running a custom mod?
Host and whover joins must have the same exact mod in their Mods folder, with workspace enabled and Official WR enabled. We are working on a better solution.
12.) Resources
Lua compiler online. You can run whatever lua code to learn lua.
Powback's EBX viewer. An essential tool for BF3/BF4 modders.
Flashhit's EBX Dump. Can search EBX locally with this.
Sample WR_Mod. An easy drag+drop to start modding without manually making above files.
WR_Mods. Some example mods.
13.) Useful Extensions
StyLua by JohnnyMoganz. Formatter for lua/luau files.