Gameplay Bugs & Feedback MEGATHREAD

Ahhhh patience is a virtue. I am looking good forward to playing the game with a lot more people. I dislike ai overall, though it has been fun playing expert ai games looking trying to help the developers. They are very receptive and responsive. It is a good feeling to know that much care and attention is being given to the series.

2 Likes

They aren’t gonna fix anything.

oh really?

I would have a look at this

3 Likes

http://memesvault.com/wp-content/uploads/Facepalm-Meme-Picard-14.jpg

2 Likes

Seems like the game still ignore captured Frigates in the first mission. In the original only the first one disappeared as it was an required objective but in the remaster all of them are gone if you capture them all at once.

2 Likes

There are some bugs in the crates code.

  1. Firstly, the ping ID needs to be stored in an global array, not a single local variable, since there can be multiple crates at one time (one for each player). It should be like this in the SelectivlyPlaceCrate and CheckCratesRule functions:

    CRATES_PingIDs[playerIndex + 1]

instead of just:

ping_c

If you don’t do this, then when the oldest crates start expiring, the newest crate will always be deleted from the map instead.

  1. Also in the SelectivlyPlaceCrate function, you use the Subtitle_Message_Handler function to display a message and play a sound when a crate is spawned. However, this function checks for the local player, but there is no guarantee that every player will be iterated through (the loop can be exited early), so not all players will see this message or hear this sound most likely.

  2. Next, in GetBestCrateLocation at line at line 130 of crates.lua, cratePosition is sometimes {0,0,0} which causes divide by zero errors later in the code, and prevents the crate from spawning at all. (Though there is no error in the log.)

So I turned the crate position into a random unit vector when this happens by inserting the following code:

-- if the crate position hasn't moved from the map origin, create a random unit vector that acts as the new crate position
if ((cratePosition[1] + cratePosition[2] + cratePosition[3]) == 0) then
	local theta = srandom(crate_seed, 360)
	local phi = srandom(crate_seed, 180)
	cratePosition =
	{
		cos(theta) * sin(phi),
		cos(phi),
		sin(theta) * sin(phi),
	}
end

Thanks for reading!

[edit]

Numbered the problems 1, 2 and 3.

I have never in all the games I have played, ever seen more than one crate on the map at a time. This is from HW1 all the way to present so I don’t think the code for multiples was ever used. That or the errors you describe prevent more than one from showing.

You can find the original version of the crates scripts here:

http://forums.relicnews.com/showthread.php?22748-NOW-AVAILABLE-HW-Classic-Gameplay-in-HW2

-------------------------------------------------------------------------------
-- Called when we need to actually spawn a crate
function SelectivlyPlaceCrate()
    --find a sobgroup to spawn sob in
    local playerIndex = 0
    local playerCount = Universe_PlayerCount();
    while (playerIndex < playerCount) do
        if (SobGroup_Empty("CrateSpawnGroup"..playerIndex) == 1) then
            local x,y,z = GetBestCrateLocation()
            print("Spawning crate at ("..x..","..y..","..z..")")
            Volume_AddSphere("CrateDetectVolume"..playerIndex, {x,y,z}, CRATES_PlayerNearRadius)
            SobGroup_SpawnNewShipInSobGroup(0, "Meg_Crate", "Crate", "CrateSpawnGroup"..playerIndex, "CrateDetectVolume"..playerIndex)
            crateNumberCrates = crateNumberCrates + 1
            crateSpawnTime[playerIndex] = Universe_GameTime()
            print("Added a crate to slot "..playerIndex..".  There are now "..crateNumberCrates.." in universe")
            return
        end
        playerIndex = playerIndex + 1
    end
    print("No empty crate spawn groups...not spawning")
end

You can see in the above code that a crate is (supposed to be) spawned for every playerIndex. Also, look specifically at the text “There are now “…crateNumberCrates…” in universe”. That means more than one crate.

But again, just because the code has settings for a crate per player doesn’t mean the code was ever active.

Have you looked at the code?

Okay, I checked the different games and mods.

Homeworld 1 Classic

  • spawn times are very long
  • you never see more than one crate at a time AFAIK

Homeworld 2 Classic

  • does not have crates code

Homeworld Classic mod for Homeworld 2 Classic

  • has code for multiple crates
  • but the spawn time equals the despawn time, so you never see more than one crate at a time

Homeworld RM

  • has code for multiple crates
  • but the spawn time equals the despawn time, so you never see more than one crate at a time

Homeworld Classic Enhanced mod for Homeworld 2 Classic and Homeworld RM

  • has code for multiple crates
  • spawn time is adjustable, so you can potentially see multiple crates depending on the setting

So it’s not a bug I guess. Though fixing it wouldn’t hurt either. :shrug:

1 Like
  1. Bug in “tur_ionarrayfrigate.ship” at line 136. Fighterhw1 should be Fighter_hw1.

  2. Also, “der_lifeboat” crashes the game.

  3. Not sure if the “-freeMouse” command-line flag works any more. It would be great if it did!

1 Like

so found found a bug on the patch preview, tried to dock my damaged strike craft, (mainly light corvettes) refused to dock while the ms and carrier are moving. they just line up outside until the ships stop moving then proceed to dock.

1 Like

The file “data\ship\tai_mothership\tai_mothership.lua” has a bug that causes the game to crash when not using one of GearBox’s game rules.

function Update_Tai_Mothership(CustomGroup, playerIndex, shipID)	
	SobGroup_CreateIfNotExist("tai_mothership"..playerIndex)
	SobGroup_Clear("tai_mothership"..playerIndex)
	SobGroup_SobGroupAdd("tai_mothership"..playerIndex, CustomGroup)
	--preventing to have 2 research ship
	if SobGroup_IsBuilding("tai_mothership"..playerIndex, "tai_researchship") == 1 then
		SobGroup_RestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship")
	else
		SobGroup_UnRestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship")
	end
	for i = 1,5,1 do
		if SobGroup_IsBuilding("tai_mothership"..playerIndex, "tai_researchship_"..i) == 1 then
			SobGroup_RestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship_"..i)
		else
			SobGroup_UnRestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship_"..i)
		end
	end
end

needs to be changed to

function Update_Tai_Mothership(CustomGroup, playerIndex, shipID)	
	SobGroup_CreateIfNotExist("tai_mothership"..playerIndex)
	SobGroup_Clear("tai_mothership"..playerIndex)
	SobGroup_SobGroupAdd("tai_mothership"..playerIndex, CustomGroup)
	SobGroup_CreateIfNotExist("tai_carrier"..playerIndex)
	--preventing to have 2 research ship
	if SobGroup_IsBuilding("tai_mothership"..playerIndex, "tai_researchship") == 1 then
		SobGroup_RestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship")
	else
		SobGroup_UnRestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship")
	end
	for i = 1,5,1 do
		if SobGroup_IsBuilding("tai_mothership"..playerIndex, "tai_researchship_"..i) == 1 then
			SobGroup_RestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship_"..i)
		else
			SobGroup_UnRestrictBuildOption("tai_carrier"..playerIndex, "tai_researchship_"..i)
		end
	end
end

This is because there’s no guarantee there will be a carrier, in which case there might not be a carrier sobgroup, and the game will crash when loading this ship.

[edit]

The same problem exists with “data\ship\kus_mothership\kus_mothership.lua”.

I would create a singular bug thread for issues under Homeworld Multiplayer. I think the devs wanted us to do that, so they can see them more easily and not lost in a huge thread.

  1. In “data\ship\kus_dronefrigate\kus_dronefrigate.lua” the game is indexing a table called drone_attacking using a variable called k. The problem is that k starts at 0 and goes to 13, but Lua tables are indexed starting with 1 not 0, and thus k should go from 1 to 14.

    What I did was create a new variable:

     local kIndex = k + 1
    

    and used that for the table indices instead.

  2. Further, all the drone frigates should not be sharing the same drone_attacking table. Otherwise one ship will override the others, and things get confusing. Instead, each ship needs its own place to store this data. What I did was this:

     drone_attacking["kus_drone" .. tostring(shipID)] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
    

    You have to make sure to create this sobgroup when each ship is built, and delete it when the ship dies.

  3. Next, the sobgroup name for each drone in “data\ship\kus_dronefrigate\kus_dronefrigate.lua” needs to be changed from this:

     "kus_drone" .. tostring(shipID) .. tostring(k)
    

    to this:

     "kus_drone_" .. tostring(shipID) .. "_" .. tostring(k)
    

    Since the shipID and the value for k are both numbers, there will be confusion when the combined number is the same for two different ships. So you have to separate the numbers with a text character such as the underscore.

  4. In “data\ship\kus_drone0\kus_drone0.lua” there needs to be an additional line:

     SobGroup_CreateIfNotExist("temp")
    

    This is because there’s no guarantee that this sobgroup has been created already in a custom game rule. If it has not already been created, then the game will crash when loading this ship.

Here’s my final version of this script:

    drone_attacking = {}
    
    function Start_DroneFrigate(CustomGroup, playerIndex, shipID) 
    	SobGroup_SetSpeed(CustomGroup, 0.9)
    	local r = random(1, 6)
    	FX_StartEvent(CustomGroup, "dronelaunch_sfx" .. r)
    end
    
    function Do_DroneFrigate(CustomGroup, playerIndex, shipID)  	
    	SobGroup_CreateIfNotExist("dronefrigate_temp")
    	SobGroup_CreateIfNotExist("dronefrigate_temp1")
    	SobGroup_CreateIfNotExist("dronefrigate_temp2")				
    	SobGroup_Clear("dronefrigate_temp2")		
    	SobGroup_GetSobGroupBeingCapturedGroup(CustomGroup, "dronefrigate_temp2")		
    	for k = 0, 13, 1 do
    		local sobname = "kus_drone_" .. tostring(shipID) .. "_" .. tostring(k)
    		SobGroup_CreateIfNotExist(sobname)		
    		SobGroup_Clear("dronefrigate_temp")
    		SobGroup_Clear("dronefrigate_temp1")
    		SobGroup_GetSobGroupDockedWithGroup(CustomGroup, "dronefrigate_temp")
    		SobGroup_FillShipsByType("dronefrigate_temp1", "dronefrigate_temp", "kus_drone"..k)
    		SobGroup_SobGroupAdd(sobname, "dronefrigate_temp1")
    		if SobGroup_Count(sobname) == 0 and
    		SobGroup_IsDoingAbility(CustomGroup, AB_Hyperspace) == 0 and				
    		SobGroup_IsDoingAbility(CustomGroup, AB_HyperspaceViaGate) == 0 and
    		SobGroup_AreAllInRealSpace(CustomGroup) == 1 and
    		SobGroup_IsDoingAbility(CustomGroup, AB_Dock) == 0 and				
    		SobGroup_IsDoingAbility(CustomGroup, AB_Retire) == 0 and
    		SobGroup_Count("dronefrigate_temp2") == 0 then
    			local CreateGroup = SobGroup_CreateShip(CustomGroup, "kus_drone"..k)
    			SobGroup_SobGroupAdd(sobname, CreateGroup)
    			if k == 0 or k == 4 or k == 8 or k == 12 then
    				FX_StartEvent(CustomGroup, "dronelaunch1")
    			elseif k == 1 or k == 5 or k == 9 or k == 13 then
    				FX_StartEvent(CustomGroup, "dronelaunch2")
    			elseif k == 2 or k == 6 or k == 10 then	
    				FX_StartEvent(CustomGroup, "dronelaunch3")
    			elseif k == 3 or k == 7 or k == 11 then	
    				FX_StartEvent(CustomGroup, "dronelaunch4")
    			end
    			break
    		else
    			--SobGroup_SwitchOwner(sobname, playerIndex)
    			if SobGroup_IsDockedSobGroup(sobname, CustomGroup) == 1 and
    			SobGroup_IsDoingAbility(CustomGroup, AB_Hyperspace) == 0 and
    			SobGroup_IsDoingAbility(CustomGroup, AB_HyperspaceViaGate) == 0 and
    			SobGroup_AreAllInRealSpace(CustomGroup) == 1 and
    			SobGroup_IsDoingAbility(CustomGroup, AB_Dock) == 0 and				
    			SobGroup_IsDoingAbility(CustomGroup, AB_Retire) == 0 and
    			SobGroup_Count("dronefrigate_temp2") == 0 then
    				SobGroup_Launch(sobname, CustomGroup)
    				if k == 0 or k == 4 or k == 8 or k == 12 then
    					FX_StartEvent(CustomGroup, "dronelaunch1")
    				elseif k == 1 or k == 5 or k == 9 or k == 13 then
    					FX_StartEvent(CustomGroup, "dronelaunch2")
    				elseif k == 2 or k == 6 or k == 10 then	
    					FX_StartEvent(CustomGroup, "dronelaunch3")
    				elseif k == 3 or k == 7 or k == 11 then	
    					FX_StartEvent(CustomGroup, "dronelaunch4")
    				end
    				break
    			end				
    		end			
    	end		
    end
    
    function Finish_DroneFrigate(CustomGroup, playerIndex, shipID)	
    	SobGroup_SetSpeed(CustomGroup, 1)
    	local r = random(1,6)
    	FX_StartEvent(CustomGroup, "droneretract_sfx"..r)
    	for k = 0, 13, 1 do
    		local sobname = "kus_drone_" .. tostring(shipID) .. "_" .. tostring(k)
    		if SobGroup_Empty(sobname) == 0 then
    			SobGroup_AbilityActivate(sobname, AB_Targeting, 0)
    			SobGroup_AbilityActivate(sobname, AB_Attack, 0)
    			SobGroup_DockSobGroupAndStayDocked(sobname, CustomGroup)
    		end	
    	end	
    end
    
    -----------------------------------------------------------------------------------
    
    function Create_DroneFrigate(CustomGroup, playerIndex, shipID)
    	SobGroup_SetSwitchOwnerFlag(CustomGroup, 0)
    	SobGroup_CreateIfNotExist("dronefrigate_temp")
    	SobGroup_CreateIfNotExist("dronefrigate_temp1")
    	SobGroup_CreateIfNotExist("dronefrigate_temp2")
    	local shipname = "kus_drone_" .. tostring(shipID)
    	drone_attacking[shipname] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
    	for k = 0, 13, 1 do
    		local sobname = shipname .. "_" .. tostring(k)
    		SobGroup_CreateIfNotExist(sobname)		
    	end
    end
    
    function Update_DroneFrigate(CustomGroup, playerIndex, shipID)
    	SobGroup_CreateIfNotExist("dronefrigate_temp2")
    	SobGroup_Clear("dronefrigate_temp2")	
    	SobGroup_GetSobGroupBeingCapturedGroup(CustomGroup, "dronefrigate_temp2")
    	if Player_GetLevelOfDifficulty(playerIndex) > 0 then
    		local playerIndex_ai = 0		
    		local enemyships = 0
    		while playerIndex_ai < Universe_PlayerCount() do
    			if Player_IsAlive(playerIndex_ai) == 1 then								
    				local distance = 4000
    				if SobGroup_FillProximitySobGroup("dronefrigate_temp1", "Player_Ships"..playerIndex_ai, CustomGroup, distance) == 1 then									
    					if AreAllied(playerIndex, playerIndex_ai) == 0 then						
    						enemyships = 1
    					end					
    				end				
    			end
    			playerIndex_ai = playerIndex_ai + 1
    		end
    		if enemyships > 0 then
    			if SobGroup_IsDoingAbility(CustomGroup, AB_Custom) == 0 then
    				SobGroup_CustomCommand(CustomGroup)
    			end
    		end
    	end
    	local shipname = "kus_drone_" .. tostring(shipID)
    	for k = 0, 13, 1 do
    		local sobname = shipname .. "_" .. tostring(k)
    		if SobGroup_Empty(sobname) == 0 then
    			if SobGroup_IsDockedSobGroup(sobname, CustomGroup) == 0 and
    			SobGroup_IsDoingAbility(sobname, AB_Parade) == 0 and
    			SobGroup_IsDoingAbility(sobname, AB_Dock) == 0 then
    				SobGroup_ParadeSobGroup(sobname, CustomGroup, 0)
    			end
    			if SobGroup_GetDistanceToSobGroup(sobname, CustomGroup) > 950 then
    				SobGroup_TakeDamage(sobname, 1)
    			elseif SobGroup_GetDistanceToSobGroup(sobname, CustomGroup) > 275 then
    				SobGroup_AbilityActivate(sobname, AB_Targeting, 0)
    				SobGroup_AbilityActivate(sobname, AB_Attack, 0)
    			else
    				SobGroup_AbilityActivate(sobname, AB_Targeting, 1)
    				SobGroup_AbilityActivate(sobname, AB_Attack, 1)
    				SobGroup_GuardSobGroup (sobname, CustomGroup) 
    			end			
    			if SobGroup_IsDoingAbility(CustomGroup, AB_Hyperspace) == 1 or
    			SobGroup_IsDoingAbility(CustomGroup, AB_HyperspaceViaGate) == 1 or
    			SobGroup_AreAllInRealSpace(CustomGroup) == 0 or
    			SobGroup_IsDoingAbility(CustomGroup, AB_Dock) == 1 or			
    			SobGroup_IsDoingAbility(CustomGroup, AB_Retire) == 1 or
    			SobGroup_Count("dronefrigate_temp2") > 0 or
    			SobGroup_OwnedBy(sobname) ~= playerIndex then					
    				SobGroup_TakeDamage(sobname, 1)
    				--SobGroup_DockSobGroupInstant(sobname, CustomGroup)
    			end
    			local kIndex = k + 1
    			local kDrone = drone_attacking[shipname][kIndex]
    			if SobGroup_IsDoingAbility(CustomGroup, AB_Attack) == 1 then
    				if (kDrone == -1) or (kDrone == DefensiveROE) then
    					SobGroup_SetROE(sobname, OffensiveROE) 
    					drone_attacking[shipname][kIndex] = OffensiveROE
    				end
    			else
    				if (kDrone == -1) or (kDrone == OffensiveROE) then
    					SobGroup_SetROE(sobname, DefensiveROE) 
    					drone_attacking[shipname][kIndex] = DefensiveROE
    				end
    			end
    		end
    	end
    end
    
    function Destroy_DroneFrigate(CustomGroup, playerIndex, shipID)	
    	local shipname = "kus_drone_" .. tostring(shipID)
    	for k = 0, 13, 1 do
    		local sobname = shipname .. "_" .. tostring(k)
    		if SobGroup_Empty(sobname) == 0 then
    			SobGroup_TakeDamage(sobname, 1)
    		end
    	end
    	drone_attacking[shipname] = nil
    end
    
    function SobGroup_GetDistanceToSobGroup(sg_Group1, sg_Group2)
    	if SobGroup_Empty(sg_Group1) == 0 and SobGroup_Empty(sg_Group2) == 0 then
    		local t_position1 = SobGroup_GetPosition(sg_Group1)
    		local t_position2 = SobGroup_GetPosition(sg_Group2)
    		local li_distance = floor(sqrt((t_position1[1] - t_position2[1])*(t_position1[1] - t_position2[1]) + (t_position1[2] - t_position2[2])*(t_position1[2] - t_position2[2]) + (t_position1[3] - t_position2[3])*(t_position1[3] - t_position2[3])))
    		return li_distance
    	else
    		return 0
    	end
    end

The drone frigate is definitely a lot more lethal after these changes.

1 Like

Does GearBox have something like BugZilla where we can also make our bug reports?

1 Like
  1. lua tables can have a 0 index, but it must be explicitely used during the declaration, which is not the case here, so you’re totally right.
    For example, drone_attacking[shipname] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } could have been replaced by drone_attacking[shipname] = { [0]=-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }

  2. I wonder. Each ship have perhaps its own scope, and so each drone_attacking{} would be local in an hardcoded way.

Great work nonetheless :slight_smile:

2 Likes

No, they just want us to use the forums, but i think they want us to create threads for each bug.

1 Like

There are several functions. If the variables are local then how will functions 2, 3 and 4 know what values they take in function 1?

1 Like