I just can’t wrap my head around for loops, here’s what I’ve done for auto-repair in STC but I am unable to get the thing to loop through the proximity group and pick the worst off ship
Can someone please tell me where my for loop went wrong?
function AutoRepair(CustomGroup, playerIndex, shipID)
if SOB_tShips[shipID].iRepairShip == 1 then
print(">> REPAIR >> | repair ship "..shipID.." of player "..playerIndex.." recognised")
if SOB_tShips[shipID].iRepairingShipID == 0 then
local nearbyShips = "nearbyShips"
SobGroup_Create(nearbyShips)
SobGroup_Clear(nearbyShips)
Player_FillProximitySobGroup(nearbyShips, playerIndex, CustomGroup, 6000)
local nearbyShipCount = 0
local mostDamagedShipID = 0
local mostDamagePercentage = 1
if SobGroup_Count(nearbyShips) >= 0 then
nearbyShipCount = SobGroup_Count(nearbyShips)
end
print(">> REPAIR >> | There is no ship currently assigned to repairship "..shipID.." of player "..playerIndex.." with "..nearbyShipCount.." ships nearby")
for i = 1, nearbyShipCount do
if SobGroup_HealthPercentage(nearbyShips[i]) < mostDamagePercentage then
mostDamagePercentage = SobGroup_HealthPercentage(nearbyShips[i])
mostDamagedShipID = GetShipId(nearbyShips[i])
end
end
print(">> REPAIR >> | the most damaged ship near repairship "..shipID.." of player "..playerIndex.." is ship "..mostDamagedShipID)
SOB_tShips[shipID].iRepairingShipID = mostDamagedShipID
SobGroup_RepairSobGroup(CustomGroup, SOB_tShips[mostDamagedShipID].sob)
else
if SobGroup_HealthPercentage(SOB_tShips[iRepairingShipID].sob) == 1 then
print(">> REPAIR >> | ship "..SOB_tShips[shipID].iRepairingShipID.." is now fully repaired")
SOB_tShips[shipID].iRepairingShipID = 0
end
end
end
end
I’m hoping to get this working before Thursday night AEST so I can include it in this month’s upload
I don’t believe you can use nearbyShips as a table. It’s a string (well, SobGroup name).
Instead, you will need to put each ship in nearbyShips into it’s own sobgroup and test that. There are a few ways of doing this, but my personal choice for this is
--
local shipCount = SobGroup_Count(nearbyShips)
local shipIndex = 0
if (shipCount > 0) then
while (shipIndex < shipCount) do
SobGroup_FillShipsByIndexRange("checkShip", nearbyShips, shipIndex, 1) -- This is important as it selects only a certain amount of ships from another sobgroup.
shipIndex = shipIndex + 1
if (SobGroup_Count("checkShip") > 0) then shipIndex = shipIndex +(SobGroup_Count("checkShip")- 1) end --Sometimes there are 0 ships, sometimes theres more (eg, Hiigaran Interceptors)
if (SobGroup_HealthPercentage("checkShip") < mostDamagePercentage) then
mostDamagePercentage = SobGroup_HealthPercentage("checkShip")
mostDamagedShipID = GetShipId("checkShip")
end
end
end
Also, SobGroup_HealthPercentage(SOB_tShips[iRepairingShipID].sob) may not work unless iRepairingShipID is set else where, guessing it should be SOB_tShips[SOB_tShips[shipID].iRepairingShipID].sob
Next, if the ship set in SOB_tShips[SOB_tShips[shipID].iRepairingShipID].sob is destroyed or moves away or something other the being fully repaired, the ship calling the AutoRepair function won’t move on to repair another ship.
Lastly, I may be wrong in this, but shouldn’t playerIndex be the first argument for Player_FillProximitySobGroup ?
[Edit]
Forgot to say,
SobGroup_FillShipsByIndexRange may be a v2.1 function
Test ships to see if there health is greater then 0. Dead ships still doing their death animations will still appear in sobgroups. (A v2.1 function for this is SobGroup_FilterExclude(nearybyShips, nearbyShips, "Health", 0) [’Health’ may be wrong, at the moment I don’t have access to a strings dump of the v2.1 exe)
From what I’ve learnt with bug 666, if a ship is just inside the proximity range for 1 player and just outside for another player, there is the possibility for a desync. A possible fix for this is to use a second Proximity at a slightly closer distance (say 5900) that only selects ships from the first proximity group.
The ship can’t really “move away” as the repairer will follow it, even after the repair is completed. This whole exercise is about compensating for that and sending it onto other ships in need. You can’t give more than one target for repair too unfortunately, which would make this all much simpler
I will need to check for health > 0 though, you’re right! I’ll see about that SobGroup_FilterExclude function and the appropriate strings for it
STARSHIP >> | Player 0 has built fed_TNG_flagship with an ID of 368
STARSHIP >> | Player 0 has built fed_TNG_repairship with an ID of 384
REPAIR >> | repair ship 384 of player 0 recognised
LOOP 1 CHECK >> | most damaged shipID is 3186101028 with 0 health value
REPAIR >> | repairship with ID 384 is repairing ship with ID 3186101028
parameter: attempt to index a nil value
stack traceback:
1: function AutoRepair' at line 58 [string ""] 2: functionUpdate_STC_Starship’ at line 27 [string “”]
GetShipId() doesn’t return the same ID as the shipID in the custom code
//EDIT
It also appears to only operate by class… I’m going to need another approach
STARSHIP >> | Player 0 has built fed_TNG_sovereign with an ID of 1680 with a second ID of 2022555814
STARSHIP >> | Player 0 has built fed_TNG_sovereign with an ID of 1696 with a second ID of 2022555814
STARSHIP >> | Player 0 has built fed_TNG_sovereign with an ID of 1712 with a second ID of 2022555814
//EDIT
In fact, I’d go so far to say as that ID is useless, even checking for it in the master table per ship gives different results
function AutoRepair(CustomGroup, playerIndex, shipID)
local repairGroup = "iRepairShip"..shipID
local nearbyShips = "nearbyShips"
SobGroup_CreateIfNotExist(repairGroup)
if (SOB_tShips[shipID].iRepairShip == 0) then
if (SobGroup_Empty(repairGroup)== 0) then
SobGroup_Clear(repairGroup)
end
end
if (SOB_tShips[shipID].iRepairShip == 1) then
local sobEmpty = SobGroup_Empty(repairGroup)
print(">> REPAIR >> | repair ship "..shipID.." of player "..playerIndex.." recognised")
if (sobEmpty == 0) then
local shipHealth = SobGroup_HealthPercentage(repairGroup)
if (shipHealth >= 1) then
print(">> REPAIR >> | ship being repaired by "..shipID.." has completed")
SobGroup_Clear(repairGroup)
sobEmpty = 1
end
if (shipHealth <= 0) then
print(">> REPAIR >> | ship being repaired by "..shipID.." has died")
SobGroup_Clear(repairGroup)
sobEmpty = 1
end
end
if (sobEmpty == 1) then
SobGroup_CreateIfNotExist(nearbyShips)
SobGroup_Clear(nearbyShips)
Player_FillProximitySobGroup(nearbyShips, playerIndex, CustomGroup, 6000)
SobGroup_FillProximitySobGroup(nearbyShips, nearbyShips, CustomGroup, 5900)
local nearbyCount = SobGroup_Count(nearbyShips)
local nearbyIndex = 0
local mostDamagePercentage = 1
print(">> REPAIR >> | There is no ship currently assigned to repairship "..shipID.." of player "..playerIndex.." with "..nearbyCount.." ships nearby")
while (nearbyIndex < nearbyCount) do
SobGroup_CreateIfNotExist(nearbyShips.."Check")
SobGroup_FillShipsByIndexRange(nearbyShips.."Check", nearbyShips, nearbyIndex, 1)
nearbyIndex = nearbyIndex + 1
if (SobGroup_Count(nearbyShips.."Check") > 0) then
nearbyIndex = nearbyIndex + (SobGroup_Count(nearbyShips.."Check")- 1)
end
local shipHealth = SobGroup_HealthPercentage(nearbyShips.."Check")
if (shipHealth > 0 and shipHealth < mostDamagePercentage) then
mostDamagePercentage = shipHealth
SobGroup_Clear(repairGroup)
SobGroup_SobGroupAdd(repairGroup, nearbyShips.."Check")
end
end
if (mostDamagePercentage < 1) then
print(">> REPAIR >> | the most damaged ship near repairship "..shipID.." of player "..playerIndex.." is ship of type "..SobGroup_GetShipType(repairGroup).." with health of "..mostDamagePercentage)
SobGroup_RepairSobGroup(CustomGroup, repairGroup)
end
end
end
end
Instead of storing the ship id, this instead stores the repair target in a sobgroup using the repair ships id.
I needed to add the repair command in and I also need to fine-tune it a bit (ships to repair were abandoned for some reason…) but I think it’s mostly there. Thank you
I’ve update the above function to add the repair command.
I’m unsure why it would abandon the repair targets unless the repair command is in an incorrect position.
There are some issues i have encounted before that a sobgroup may not be updated till next frame, but it only occurs with certain sobgroup functions (Unable to remember what functions they where, but one of them might be SobGroup_Empty, if that is correct, then try replacing them SobGroup_Count.)
[Edit]
I should also state that, as I am unsure how you use SOB_tShips[shipID].iRepairShip, when that value is set to 0, the stored repair group is cleared.
I think the ships are being abandoned once repaired instead of the group just being updated and the command reissued when there’s another ship in need and the original target is fully repaired. The instant the ship is repaired it’s no longer targeted for repair
if (shipHealth >= 1) then
print(">> REPAIR >> | ship being repaired by "..shipID.." has completed")
SobGroup_Clear(repairGroup)
sobEmpty = 1
end
The iRepairShip thing is simply this:
if (SobGroup_CanDoAbility(CustomGroup, AB_Repair) == 1) then
tShip.iRepairShip = 1
end
I can probably abandon this methodology and just check it on the fly since nothing else in the main ship table is useable
//EDIT
I figured it out! The repairship is targeting itself, and it gets stuck on that
Here’s the final, fully functional, code with my minor tweaks
function AutoRepair(CustomGroup, playerIndex, shipID)
if (SobGroup_CanDoAbility(CustomGroup, AB_Repair) == 1) and (Universe_GameTime() > 10) then
local repairGroup = "iRepairShip"..shipID
local nearbyShips = "nearbyShips"
SobGroup_CreateIfNotExist(repairGroup)
local sobEmpty = SobGroup_Empty(repairGroup)
-- print(">> REPAIR >> | repair ship "..shipID.." of player "..playerIndex.." recognised")
if (sobEmpty == 0) then
local shipHealth = SobGroup_HealthPercentage(repairGroup)
if (shipHealth >= 1) then
-- print(">> REPAIR >> | ship being repaired by "..shipID.." has completed")
SobGroup_Clear(repairGroup)
sobEmpty = 1
end
if (shipHealth <= 0) then
-- print(">> REPAIR >> | ship being repaired by "..shipID.." has died")
SobGroup_Clear(repairGroup)
sobEmpty = 1
end
end
if (sobEmpty == 1) then
SobGroup_CreateIfNotExist(nearbyShips)
SobGroup_Clear(nearbyShips)
Player_FillProximitySobGroup(nearbyShips, playerIndex, CustomGroup, 8000)
SobGroup_FillProximitySobGroup(nearbyShips, nearbyShips, CustomGroup, 7900)
SobGroup_FillSubstract(nearbyShips, nearbyShips, CustomGroup)
local nearbyCount = SobGroup_Count(nearbyShips)
local nearbyIndex = 0
local mostDamagePercentage = 1
-- print(">> REPAIR >> | There is no ship currently assigned to repairship "..shipID.." of player "..playerIndex.." with "..nearbyCount.." ships nearby")
while (nearbyIndex < nearbyCount) do
SobGroup_CreateIfNotExist(nearbyShips.."Check")
SobGroup_FillShipsByIndexRange(nearbyShips.."Check", nearbyShips, nearbyIndex, 1)
nearbyIndex = nearbyIndex + 1
if (SobGroup_Count(nearbyShips.."Check") > 0) then
nearbyIndex = nearbyIndex + (SobGroup_Count(nearbyShips.."Check")- 1)
end
local shipHealth = SobGroup_HealthPercentage(nearbyShips.."Check")
if (shipHealth > 0 and shipHealth < mostDamagePercentage) then
mostDamagePercentage = shipHealth
SobGroup_Clear(repairGroup)
SobGroup_SobGroupAdd(repairGroup, nearbyShips.."Check")
end
end
if (mostDamagePercentage < 1) then
-- print(">> REPAIR >> | the most damaged ship near repairship "..shipID.." of player "..playerIndex.." is ship of type "..SobGroup_GetShipType(repairGroup))
SobGroup_RepairSobGroup(CustomGroup, repairGroup)
end
end
end
end
As long as the unit starts repairing a target when using the command SobGroup_RepairSobGroup, it should work regardless. If not, then you will just need to replace that command with 1 that does.
If you were to replace SobGroup_RepairSobGroup with SobGroup_Attack, then the unit will attack the ship with the least amount of health that’s within 5900(m?) of the unit.
Both latching repair and repair beams are managed with SobGroup_RepairSobGroup, it just doesn’t seem to like working with more than one ship in the target group