So basically what we want to do in this tutorial is delete the old connections between capturepoint and spawnpoints and create them from scratch. We do that because then we can add as many spawnpoints as we like.
We will also change the position of the flagpole.
So in the beginning we define the capturepoint for which we would like to change the spawnpoints (which are AlternativeSpawnEntityData’s btw).
CPA = {
GUID = Guid('5C3EEC89-4314-4714-8423-1D10A0270458'),
POS = LinearTransform(
Vec3(1, 0, 0),
Vec3(0, 1, 0),
Vec3(0, 0, 1),
Vec3(50.466816, 64.052544, 157.341797)),
USSPAWNS = { LinearTransform(
Vec3(-0.849120, 0.000000, -0.528200),
Vec3(0.0, 1.0, 0.0),
Vec3(0.528200, 0.000000, -0.849120),
Vec3(65.537018, 63.671684, 201.545914)),
LinearTransform(
Vec3(-0.810182, 0.000000, 0.586178),
Vec3(0.0, 1.0, 0.0),
Vec3(-0.586178, 0.000000, -0.810182),
Vec3(66.369141, 63.766407, 208.351563))
},
RUSPAWNS = { LinearTransform(
Vec3(0.906630, 0.000000, -0.421926),
Vec3(0.0, 1.0, 0.0),
Vec3(0.421926, 0.000000, 0.906630),
Vec3(21.334951, 63.745972, 104.221687)),
LinearTransform(
Vec3(0.789017, 0.000000, -0.614371),
Vec3(0.0, 1.0, 0.0),
Vec3(0.614371, 0.000000, 0.789017),
Vec3(6.633789, 65.470505, 113.493164))
}
}
We have a Guid, a position, 2 US spawns and 2 RU spawns.
To define the SpawnPoints you should use the SpawnPointHelper by @Janssent. He has also contributed at the MP_Lake mod where I took most of this from.
Now we have set up the config. What is missing is the event and the deleting and adding part.
Let’s beginn with the event when we change all this stuff. For that we use the shared event Level:RegisterEntityResources.
Events:Subscribe('Level:RegisterEntityResources', function(levelData)
-- change all stuff here
end)
About the guid: the guid is our capturepoint defined as a ReferenceObjectData.
For Métro Conquest Small it looks like this in webx:
You can also see that this is CapturePoint A if you look a bit closer:
I guess you know what to do, get all capturepoint guids you want to modify.
Then define additional to that the partitionGuid so we can load it:
local cqLogicPartitionGuid = Guid('F5DE48B8-29ED-4E73-B040-82637BE0E81C')
So your code should look like this:
CPA = {
-- GUID, POS, USSPAWNS, RUSPAWNS
}
CPB = {
-- GUID, POS, USSPAWNS, RUSPAWNS
}
-- etc.
local cqLogicPartitionGuid = Guid('F5DE48B8-29ED-4E73-B040-82637BE0E81C') -- your partition guid
Events:Subscribe('Level:RegisterEntityResources', function(levelData)
-- change all stuff here
end)
At this point everything clear?
Fine, now we need the SubWorldData and then we can do the magic. The SubWorldData stores all connections. That’s why it is necessary for us.
Do this within the Level:RegisterEntityResources event:
local subWorldData = ResourceManager:SearchForDataContainer("Levels/MP_Subway/Conquest_Small")
if subWorldData ~= nil then
subWorldData = SubWorldData(subWorldData)
subWorldData:MakeWritable()
end
BTW You can define the SpawnPoints now. If you use the SpawnPointHelper type something like this in console:
spawnpointhelper.load Levels/MP_Subway/Conquest_Small 5C3EEC89-4314-4714-8423-1D10A0270458 1
Of course with your level and your capturepoint Guid.
Like this:
And if you don’ t know how to use it just type spawnpointhelper.help
into console.
Let’s go on with the mod. Now we are ready to delete all existing connections and add new ones.
if subWorldData ~= nil then
subWorldData = SubWorldData(subWorldData)
subWorldData:MakeWritable()
local cpAObjectData = ReferenceObjectData(ResourceManager:FindInstanceByGuid(cqLogicPartitionGuid, CPA.GUID))
cpAObjectData:MakeWritable()
cpAObjectData.blueprintTransform = CPA.POS
ClearSpawnPoints(subWorldData, cpAObjectData)
CreateSpawnPoints(subWorldData, cpAObjectData, CPA.USSPAWNS, "USCP")
CreateSpawnPoints(subWorldData, cpAObjectData, CPA.RUSPAWNS, "RUCP")
end
I guess this part needs deeper explanation.
Here we already changed the position of the capture point with: cpAObjectData.blueprintTransform = CPA.POS
I already added ClearSpawnPoints and CreateSpawnPoints but we didn’t define these functions yet.
But this is what we will do now.
As I said before the SubWorldData stores all connections so now we loop through the linkConnections and erase everything that links from our capturepoint to a spawnpoint.
function ClearSpawnPoints(subWorldData, cpObjectData)
-- Since we are removing stuff, iterate through the connections in reverse order.
for i = #subWorldData.linkConnections, 1, -1 do
local connection = subWorldData.linkConnections[i]
if connection.target:Is("AlternateSpawnEntityData") then
if connection.source == cpObjectData then
subWorldData.linkConnections:erase(i)
end
end
end
end
This clears all spawn points of that capture point.
We check if the target is a spawnpoint (AlternateSpawnEntityData) and if the source is our capturepoint (cpObjectData ). If so, then we erase it.
Now we only need to add the new ones and we are done. For that we need some eventHashes:
local teamAndHash = {
["USCP"] = { 0, 1751730141 }, --TeamID, eventID/eventHash
["RUCP"] = { 0, 1879290430 },
["USHQ"] = { 1, -2001390482 },
["RUHQ"] = { 2, -2001390482 },
-- TDM/ SQDM/ Gunmaster
["DM1"] = {0, -1404628591},
["DM2"] = {0, -890967278},
-- SQDM
["DM3"] = {0, 465180179},
["DM4"] = {0, 1475647380}
}
We will only use USCP
and RUCP
but if you want to edit the base spawns too you will need USHQ
and RUHQ
.
Now we do the last part to add the connections:
function CreateSpawnPoints(subWorldData, cpObjectData, spawns, type)
for _, spawnTransform in pairs(spawns) do
local alternateSpawn = AlternateSpawnEntityData()
alternateSpawn.team = teamAndHash[type][1]
alternateSpawn.transform = spawnTransform
-- The sourceFieldId depends on what team the spawn belongs to. Base spawns have a different one as well.
local connection = LinkConnection()
connection.target = alternateSpawn
connection.source = cpObjectData
connection.sourceFieldId = teamAndHash[type][2]
subWorldData.linkConnections:add(connection)
end
end
You see we loop through the spawns and create an AlternateSpawnEntityData()
and a LinkConnection()
for all of them.
Remember we do:
CreateSpawnPoints(subWorldData, cpAObjectData, CPA.USSPAWNS, "USCP")
CreateSpawnPoints(subWorldData, cpAObjectData, CPA.RUSPAWNS, "RUCP")
So spawns
is a table with all our stored spawns as LinearTransforms and type
is either "USCP"
or "RUCP"
.
Both of them will define alternateSpawn.team = 0
but the connection.sourceFieldId
will be different.
Well and that’s it. I hope you could follow this. If you want you can also take a look at the MP_Lake mod for reference.
Note that we didnt change the capturepoint zone as we discussed that already in the How to adjust the redzones and capturepoint areas tutorial.