Center-Facing Starting Fleets Query [SOLVED]!

When creating maps programmatically and using ringAdd for player positioning: Does anyone know of a method for positioning starting fleets so that they face the center of the map?

I have seen rotation = “toCenter”, used in various maps within various mods, but alone it doesn’t seem to affect my starting fleets. Searching my rather large collection of mods I have found no code that enables a toCenter value so I am presuming, but have not noted via observation that the game simply does not recognize that value and defaults to a rotation of 180°.

Once again, I am humbly grateful for any help.

Thom.

I take it from the lack of response that no one knows the answer or have these forums been, for the most part, abandoned?

I’m assuming you need to use 4 coordinates. 3 to triangulate position and a 4th to determine lateral rotation. I don’t know about “toCenter” command.

I’m presuming ringAdd is a custom function that’s probably from Mikali. While I haven’t tested this out, you could try editing line ~112 of the file /scripts/MapFunctions.lua

original

elseif (objType == "StartPoint") then
  objName = "StartPos" .. iStartPoints
  -- addPoint(<sPointName>, <tPosition>, <tRotation>)
  addPoint(objName, vaddV(tCoo, tPar[4]), tPar[5])
  iStartPoints = iStartPoints + 1

edited

elseif (objType == "StartPoint") then
  objName = "StartPos" .. iStartPoints
  -- addPoint(<sPointName>, <tPosition>, <tRotation>)
  -- addPoint(objName, vaddV(tCoo, tPar[4]), tPar[5])

  local pos = vaddV(tCoo, tPar[4])
  local x,z = (-pos[1]+tPos[1]),(-pos[3]+tPos[3])
  addPoint(objName, pos, {tPar[5][1],(180-atan2(x,-z)),tPar[5][3]})

  iStartPoints = iStartPoints + 1

if it works correctly, it should have the starting fleets point towards the center of the ring

@shadowwinterknig Thank you!

Strangely enough and quite unfortunately, my version of MapFunctions.lua (mapFunctions_v1.52.lua - - Created: 10/07/04 by Mikail, Last updated: 04/08/08) has no lines that I recognize as kin to what you have suggested… as exhibited:

function ringAdd(tPos, tDst, tPar, tRot)
	local tCoo = {}
	local X, Y, Z = 0, 0, 0
	local fAx1, fAx2, fThk, fHgh, tArc, iMod = tPar[1], tPar[2], tPar[3], tPar[4], tPar[5], tPar[6]
	local minArc, maxArc = tArc[1], tArc[2]
	for i, tTab in tDst do
		local u, w, h, arc = 0, 0, 0, 0
		local iNum = tTab[1]
		for j = 1, iNum do
			-- if set to random mode w/ even width
			if (iMod == 2) then
				u = random3(minArc, maxArc)
				X = cos(u) * fAx2 - random3(fThk)
				Y = random3(fHgh) - fHgh / 2
				Z = sin(u) * fAx1 - random3(fThk)
			-- if set to random mode w/ gradual width
			elseif (iMod == 1) then
				u = random3(minArc, maxArc)
				X = cos(u) * (fAx2 - random3(fThk))
				Y = random3(fHgh) - fHgh / 2
				Z = sin(u) * sqrt((fAx2 - random3(fThk))^2 - fAx2^2 + fAx1^2)
			-- if set to non-random mode
			elseif (iMod == 0) then
				u = minArc + arc
				X = cos(u) * (fAx2 + fThk / -2 + w)
				Y = fHgh / -2 + h
				Z = sin(u) * (fAx1 + fThk / -2 + w)
				arc = arc + (maxArc - minArc) / iNum
				w = w + fThk / iNum
				h = h + fHgh / iNum
			end
			tCoo = {X, Y, Z,}
			appendShape(tPos, i, tTab, j, tCoo, tRot)
		end
	end
end

That said, perhaps I am missing something because of my unfamiliarity with the code? I am still searching for what I may have overlooked.

Any suggestions?

I just noticed that there is a reference to appendShape within the ringAdd code.

appendShape includes:

	elseif (tPar[2] == "StartPoint") then
		local name = "StartPos" .. iStartPointsCount
		addPoint(name, vaddV(tCoo, tPar[4]), tPar[5])
		iStartPointsCount = iStartPointsCount + 1			

I am not sure how to I might modify your suggestion to fit this.

EDIT: I found another seemingly newer version of Mikali’s mapFunctions in Simplex 4.6 in which appendShape instead has the following script:

	elseif (objType == "StartPoint") then
		local name = "StartPos" .. iStartPoints
		--addPoint(<sPointName>, <tPosition>, <tRotation>)
		addPoint(name, vaddV(tCoo, tPar[4]), tPar[5])
		iStartPoints = iStartPoints + 1

Although this is closer to what you modified, how might I reconcile the two?

appendShape is the one your after.

Using the code you provided,

	elseif (tPar[2] == "StartPoint") then
		local name = "StartPos" .. iStartPointsCount
		addPoint(name, vaddV(tCoo, tPar[4]), tPar[5])
		iStartPointsCount = iStartPointsCount + 1			

You could try changing it to

	elseif (tPar[2] == "StartPoint") then
		local name = "StartPos" .. iStartPointsCount
		--addPoint(name, vaddV(tCoo, tPar[4]), tPar[5])

		local pos = vaddV(tCoo, tPar[4])
		local x,z = (-pos[1]+tPos[1]),(-pos[3]+tPos[3])
		addPoint(name, pos, {tPar[5][1],(180-atan2(x,-z)),tPar[5][3]})

		iStartPointsCount = iStartPointsCount + 1

I’ve been at my computer for a bit, so I’ve been looking through MapFunctions.lua
Oddly enough, the version I’m looking at says it’s (Version: 1.23.5 – Created: 2004/10/07 – Updated: 2021/06/03 ) :person_shrugging:

GitHub - mjhorvath/Mikali-Map-Collection-for-HWRM: Multiplayer maps for the real-time strategy video game, Homeworld Remastered.

The change I’ve been making will cause any map to have the starting fleets all focus towards the center of the ring/map, regardless of if they where added by ringAdd or not. I might try later to modify the ringAdd function, rather then the appendShape function to orientate the starting fleets

My initial testing of your changes (swapping out the original code) resulted in no change; startingfleet maintained a 180° orientation.

When I awaken (It is 4:45 AM local time) I will replace my entire mapfunctions.lua for the one you so kindly referred me to above and then swap out the same code.

Although it should make no difference whatsoever I am using HW2, not HWRM.

Edit: My fault for being a bit hasty. Just noticed you said your using the classic version. Changes below are for the remastered version. When I get on my computer again, I’ll work on getting the classic version of MapFunctions working with the orientation.

Attached is a modified copy of the mapfunctions.lua file and a ring test map.
(there are also other files from a stripped down version of mikalis mod that are required for the ring test map)

Main changes is the ability to have the starting fleet

  • Maintain the 180° orientation (Or what is set in the distribution table)
  • Face the center of the map
  • Face the center of the ring

How to do this is a change in the distribution table.
{{2, "StartPoint", "StartPos", {0,0,0,}, {0,0,0,},},}

By changing the StartPos to either centerWorld or centerRing will change how the starting fleet orientates itself. *(Note: These are case sensative)

The last {0,0,0,} is the orientation of the starting fleet if not centering. Only the second value should be changed (Haven’t tested this, but that is how the code is written)

local StartDist1 = {{2, "StartPoint", "centerWorld", {0,0,0,}, {0,0,0,},},}
local StartDist2 = {{2, "StartPoint", "centerRing",  {0,0,0,}, {0,0,0,},},}
local StartDist3 = {{2, "StartPoint", "StartPos",    {0,0,0,}, {0,0,0,},},}

The included map ringTest is for 6 players.

  • Players 1 & 2 will face the center of the map.
  • Players 3 & 4 will both face the center of the ring.
  • Players 5 & 6 will both face the direction set in the distribution table.

Attached should be a working version of MapFunctions.lua and the RingTest level for Homeworld 2 Classic

Same as my previous post, there are 3 possible orientations. Default , centerRing and centerWorld

Changes to the MapFunctions.lua file was

including

function appendShape(tPos, i, tPar, j, tCoo, tRot)
	tCoo = vaddV(vrotate(tCoo, tRot), tPos)
	local objNum = tPar[1]     --< This Line
	local objType = tPar[2]
	local objName = tPar[3]    --< This Line

replacing

	elseif (objType == "StartPoint") then
		local name = "StartPos" .. iStartPoints
		--addPoint(<sPointName>, <tPosition>, <tRotation>)
		addPoint(name, vaddV(tCoo, tPar[4]), tPar[5])
		iStartPoints = iStartPoints + 1

with

	elseif (objType == "StartPoint") then
		local pos = vaddV(tCoo, tPar[4])
		local rot = tPar[5]

		if objName == "centerRing"  then rot[2] = 180 - atan2((-pos[1]+tPos[1]),-(-pos[3]+tPos[3])) end
		if objName == "centerWorld" then rot[2] = 180 - atan2(-pos[1],pos[3]) end

		objName = "StartPos" .. iStartPoints
		addPoint(objName, pos, rot)
		iStartPoints = iStartPoints + 1

The MapFunctions.lua I used for this is from
Mikali-Map-Collection-for-HW2C/MapFunctions.lua at master · mjhorvath/Mikali-Map-Collection-for-HW2C · GitHub

3 Likes

I keep playing with this, but I still do not understand how to change the following example from one of my maps to work correctly with your modified mapFunctions.lua

ringAdd({0, 0, 0,}, startRing, random(750000, 850000)*ThisMultiplier, random(750000, 850000)*ThisMultiplier, random(40000, 80000)*ThisMultiplier,  0, 0, 360, 0, 0, 1)

The reference that I have used previously is as follows:

REFERENCE: function ringAdd(tPosition, tDistribution, fAxis1, fAxis2, fThickness, fHeight, fArc1, fArc2, fTilt, fRotate, iMode)

  • tPosition: the ring’s center coordinates.
  • tDistribution: the distribution table used to populate the ring.
  • fAxis1: the length of axis 1.
  • fAxis2: the length of axis 2.
  • fThickness: the distance from the outer radius to the inner radius (varies according to iMode).
  • fHeight: the height of the ring, relative to the plane.
  • fArc1: the ring begins at this point along its circumference (degrees).
  • fArc2: the ring ends at this point along its circumference (degrees).
  • fTilt: the entire ring is rotated around the Z axis by this amount (degrees).
  • fRotate: the entire ring is rotated around the Y axis by this amount (degrees).
  • iMode: if 0, then non-random mode. If 1, then random mode w/ gradual width. If 2, then random mode w/ even width.

Prior to the ringAdd call, you should have a distribution table looking something like
local startRing= {{2, "StartPoint", "StartPos", {0,0,0,}, {0,0,0,},},}
Its this table where you will need to change "StartPos" to "centerWorld"

tDistribution: the distribution table used to populate the ring.

The ringAdd should not need changing.

My distribution table (prior to any modification) is currently:

local startRing = { StartPos = {class = “Point”, name = “StartPos”, rotation = {0, 0, 0,}, number = 6,}, }

EDIT:
I just tried the 6p_RingTest.level and received the same “Fleet Defeated” error as I do on my own map.

Your distribution table is far different to what i was expecting to see. Are you able to upload the level and mapfunctions files, along with any other required files so i can test it?

I will upload all of the files that I use… in their entirety to Dropbox in the morning. Both my wife and I have Covid so I am rather slow right now.

I do deeply appreciate your help.

Wishing you both a speedy recovery.

1 Like

@VaultHunter101
Thank you. It is nice to belong to a community with good manners.

@shadowwinterknig
Leveldata.zip
You may need to comment certain scripts/objects out.
EDIT: If you need (or are curious about) anything not included, just ask and I will upload.

Hopefully this works, made some changes in map_functions_toys.lua and modified my ringtest map to work with it.

Edit: I found one error I made in this, if downloading the below map_functions_toys.lua, a change will need to be made. I’ll note it further down this post.

Changes
After line 18 in map_functions_toys.lua I added. Edit: Have slightly modified the code below to include a fix.

	local rot = {0,0,0}

	if iCount.rotation then -- this line is the ''fix''
		if iCount.rotation == "centerRing" then
			rot[2] = 180 - atan2((-tCoordinates[1]+tPosition[1]),-(-tCoordinates[3]+tPosition[3]))
		elseif iCount.rotation == "centerWorld" then
			rot[2] = 180 - atan2(-tCoordinates[1],tCoordinates[3])
		else
			rot = iCount.rotation
		end
	end  -- end fix

Then a couple of lines below I changed
addPoint("StartPos" .. startNum, tCoordinates, {0, 0, 0,})
to
addPoint("StartPos" .. startNum, tCoordinates, rot)
and
addPoint(iCount.name .. (i - 1), tCoordinates, {0, 0, 0,})
to
addPoint(iCount.name .. (i - 1), tCoordinates, rot)

and lastly changed
addSquadron(iCount.name .. (i - 1), iCount.type, tCoordinates, iCount.player, iCount.rotation, 0, 0)
to
addSquadron(iCount.name .. (i - 1), iCount.type, tCoordinates, iCount.player, rot, 0, 0)

Effect
So, these changes should allow a starting fleet to be orientated either manually, center to the ring or center to the world. To do this, change the rotation variable in the distribution table to either a xyz table ({0,0,0}) or the string “centerRing” or “centerWorld”

    local StartDist1 = { StartPos ={ class = "Point", name = "StartPos", rotation = "centerWorld", number = 2,},}
    local StartDist2 = { StartPos ={ class = "Point", name = "StartPos", rotation = "centerRing", number = 2,},}
    local StartDist3 = { StartPos ={ class = "Point", name = "StartPos", rotation = {0,0,0,}, number = 2,},}
2 Likes

Thank you for all of your work @shadowwinterknig. I may have to put testing this off a day for personal reasons.

EDIT:
@shadowwinterknig This system works perfectly. The centerWorld, centerRing and x,y,z rotation system are incredibly useful in so many situations. I am not aware of any such solution for center-facing StartingFleets

Unless you wish to add something to this topic, perhaps I should add [Solved] to the Topic header or rename it to “Center-Facing StartingFleets Solution”. Or, you may wish to write (or ask someone to write) a clear tutorial regarding this. Let me know what you think.

Once again, I am profoundly grateful for the extensive time and effort that you volunteered here in this pursuit. Thank you.

Thom.

2 Likes