Author Topic: Highlight or hotkey individual turret  (Read 7500 times)

0 Members and 1 Guest are viewing this topic.

Offline Lepanto

  • 210
  • Believes in Truth
    • Skype
Re: Highlight or hotkey individual turret
No dice, sorry. Got the following errors:

Code: [Select]
LUA ERROR: [string "turretHotkey-sct.tbm - On Gameplay Start"]:166: 'then' expected near 'do'

------------------------------------------------------------------
ADE Debug:
------------------------------------------------------------------
Name: (null)
Name of: (null)
Function type: (null)
Defined on: 0
Upvalues: 0

Source: (null)
Short source:
Current line: 0
- Function line: 0
------------------------------------------------------------------


------------------------------------------------------------------

stack traceback:
------------------------------------------------------------------

------------------------------------------------------------------

Code: [Select]
turretHotkey-sct.tbm(line 272):
Error: Missing required token: [#End]. Found [$State: GS_STATE_GAME_PLAY] instead.

ntdll.dll! ZwWaitForSingleObject + 12 bytes
KERNELBASE.dll! WaitForSingleObject + 18 bytes
fs2_open_3_7_2_RC5.exe! <no symbol>
fs2_open_3_7_2_RC5.exe! <no symbol>
"We have now reached the point where every goon with a grievance, every bitter bigot, merely has to place the prefix, 'I know this is not politically correct, but...' in front of the usual string of insults in order to be not just safe from criticism, but actually a card, a lad, even a hero. Conversely, to talk about poverty and inequality, to draw attention to the reality that discrimination and injustice are still facts of life, is to commit the sin of political correctness. Anti-PC has become the latest cover for creeps. It is a godsend for every curmudgeon and crank, from fascists to the merely smug."
Finian O'Toole, The Irish Times, 5 May 1994

Blue Planet: The Battle Captains: Missions starring the Admirals of BP: WiH
Frontlines 2334+2335: T-V War campaign
GVB Ammit: Vasudan strike bomber
Player-Controlled Capship Modding Tutorial

 

Offline AdmiralRalwood

  • 211
  • The Cthulhu programmer himself!
    • Skype
    • Steam
    • Twitter
Re: Highlight or hotkey individual turret
Same problem, different line.

Code: [Select]
#Conditional Hooks

$Application: FS2_Open
$On Gameplay Start:
[
turretHotkeys = {}
turretHotkeys.key = "F9"
turretHotkeys.enabled = false

-- Subsystem indicator settings
turretHotkeys.indicator = {}
turretHotkeys.indicator.color = {
    r = 255,
    g = 255,
    b = 255,
    a = 200
}

turretHotkeys.subsystems = {}
turretHotkeys.lastIndex = {1, 0}

function turretHotkeys:keyPressed(key)
    if (self:isEnabled() and key == self.key) then
        local tblIndex, subsysIndex = self:getNextIndex()

        if (tblIndex ~= false) then
            -- This is ugly code, don't look at it or it won't work
            local subsys = self.subsystems[tblIndex].ship[self.subsystems[tblIndex][subsysIndex]]

            if (subsys:isValid()) then
                hv.Player.Target = self.subsystems[tblIndex].ship
                hv.Player.TargetSubsystem = subsys
            end

            self.lastIndex = { tblIndex, subsysIndex }
        end
    end
end

function turretHotkeys:checkIndexes(tblIndex, subsysIndex)
    if (tblIndex > 0 and tblIndex <= #self.subsystems) then
        if (subsysIndex > 0 and subsysIndex <= #self.subsystems[tblIndex]) then
            return tblIndex, subsysIndex
        else
            return tblIndex, math.max(1, math.min(subsysIndex, #self.subsystems[tblIndex]))
        end
    else
        -- If we're here it means that we've got an invalid index...
        return math.max(1, math.min(tblIndex, #self.subsystems)), math.max(1, math.min(1, #self.subsystems[tblIndex]))
    end
end

function turretHotkeys:getNextIndex()
    local tblIndex = self.lastIndex[1]

    local tbl = self.subsystems[tblIndex]

    if (tbl == nil) then
        if (tblIndex == 1) then
            return false
        else
            return self:checkIndexes(1, 1)
        end
    end

    local subsystemIndex = self.lastIndex[2] + 1

    if (subsystemIndex > #tbl) then
        subsystemIndex = 1
        tblIndex = tblIndex + 1

        tbl = self.subsystems[tblIndex]
    end

    if (tblIndex > #self.subsystems) then
        tblIndex = 1

        if (tblIndex > #self.subsystems) then
            return self:checkIndexes(tblIndex, 1)
        end
    end

    return self:checkIndexes(tblIndex, subsystemIndex)
end

function turretHotkeys:onFrame()
    if (self:isEnabled()) then
        self:checkShips()

        if (hu.HUDDrawn) then
            self:drawSubsystems()
        end
    end
end

function turretHotkeys:checkShips()
    local index = 1
    local done = false

    while (not done) do
        done = true
        for i = index, #self.subsystems do
            if (i ~= #self.subsystems) then
                done = false
            end
            if (not self.subsystems[i].ship:isValid() ) then
                table.remove(self.subsystems, i)
                index = i
                break
            end
        end
    end
end

function turretHotkeys:drawSubsystems()
    local target = hv.Player.Target
    local subsysName = hv.Player.TargetSubsystem:getModelName()

    for i = 1, #self.subsystems do
        local tbl = self.subsystems[i]
        for j = 1, #tbl do
            local current = tbl.ship[tbl[j]]
            if current.HitpointsLeft > 0 and (tbl.ship ~= target or current:getModelName() ~= subsysName) then
                self:drawSubsystem(current)
            end
        end
    end
end

function turretHotkeys:drawSubsystem(subsys)
    local indicator = self.indicator

    gr.setColor(indicator.color.r, indicator.color.g, indicator.color.b, indicator.color.a)

    gr.drawSubsystemTargetingBrackets(subsys)
end

function turretHotkeys:addShip(ship)
    table.insert(self.subsystems, {
        name = ship.Name,
        ship = ship
    })
end

function turretHotkeys:isValidIndex(index)
    return self.subsystems[index] ~= nil and self.subsystems[index].ship:isValid()
end

function turretHotkeys:addSubsystem(index, name)
    local tbl = self.subsystems[index]

    if (not tbl.ship[name]:isValid()) then
        ba.warning(string.format("Unknown subsystem %q on ship %q of class %q.", name, tbl.ship.name, tbl.ship.class))
        return false
    end

    table.insert(tbl, name)

    return true
end

function turretHotkeys:removeSubsystem(index, name)
    local tbl = self.subsystems[index]

    local newIndex = 1
    local done = false

    while (not done) do
        done = true
        for i = newIndex, #tbl do
            if (i ~= #tbl) then
                done = false
            end
            if (tbl[i] == name) then
                table.remove(tbl, i)
                newIndex = i
                break
            end
        end
    end
end

function turretHotkeys:isEnabled()
    return self.enabled and hv.Player:getBreedName() == "Ship"
end

function thkEnable(bool)
    if (bool == nil) then
        bool = true
    end

    if (type(bool) ~= "boolean") then
        ba.warning("Invalid argument type for thkKey. Need a boolean or no argument, got " .. type(bool) .. ".")
        return
    end

    turretHotkeys.enabled = bool
end

function thkKey(key)
    if (type(key) ~= "string") then
        ba.warning("Invalid argument type for thkKey. Need a string, got " .. type(key) .. ".")
        return
    end

    turretHotkeys.key = key
end

function thkShip(...)
    local names = { ... }

    for i = 1, #names do
        if (type(names[i]) ~= "string") then
            ba.warning("Invalid argument type for thkShip. Need a string, got " .. type(names[i]) .. ".")
            return
        end

        local ship = mn.Ships[names[i]]

        if (not ship:isValid()) then
            ba.warning("No ship with name \"" .. names[i] .. "\" could be found in the current mission.")
            return
        end

        turretHotkeys:addShip(ship)
    end
end

function thkAdd(index, name)
    if (type(index) ~= "number") then
        ba.warning("Invalid first argument type for thkAdd. Need a string, got " .. type(index) .. ".")
        return
    end

    if (type(name) ~= "string") then
        ba.warning("Invalid second argument type for thkAdd. Need a string, got " .. type(name) .. ".")
        return
    end

    if (not turretHotkeys:isValidIndex(index)) then
        ba.warning("Invalid ship index \"" .. tostring(index) .. "\"!")
        return
    end

    turretHotkeys:addSubsystem(index, name)
end

function thkRemove(index, name)
    if (type(index) ~= "number") then
        ba.warning("Invalid first argument type for thkRemove. Need a string, got " .. type(index) .. ".")
        return
    end

    if (type(name) ~= "string") then
        ba.warning("Invalid second argument type for thkRemove. Need a string, got " .. type(name) .. ".")
        return
    end

    if (not turretHotkeys:isValidIndex(index)) then
        ba.warning("Invalid ship index \"" .. tostring(index) .. "\"!")
        return
    end

    turretHotkeys:removeSubsystem(index, name)
end

function thkClear()
    turretHotkeys.subsystems = {}
end
]

$State: GS_STATE_GAME_PLAY
$On Key Pressed:
[
turretHotkeys:keyPressed(hv.Key)
]

$State: GS_STATE_GAME_PLAY
$On Frame:
[
turretHotkeys:onFrame()
]

#End
Ph'nglui mglw'nafh Codethulhu GitHub wgah'nagl fhtagn.

schrödinbug (noun) - a bug that manifests itself in running software after a programmer notices that the code should never have worked in the first place.

When you gaze long into BMPMAN, BMPMAN also gazes into you.

"I am one of the best FREDders on Earth" -General Battuta

<Aesaar> literary criticism is vladimir putin

<MageKing17> "There's probably a reason the code is the way it is" is a very dangerous line of thought. :P
<MageKing17> Because the "reason" often turns out to be "nobody noticed it was wrong".
(the very next day)
<MageKing17> this ****ing code did it to me again
<MageKing17> "That doesn't really make sense to me, but I'll assume it was being done for a reason."
<MageKing17> **** ME
<MageKing17> THE REASON IS PEOPLE ARE STUPID
<MageKing17> ESPECIALLY ME

<MageKing17> God damn, I do not understand how this is breaking.
<MageKing17> Everything points to "this should work fine", and yet it's clearly not working.
<MjnMixael> 2 hours later... "God damn, how did this ever work at all?!"
(...)
<MageKing17> so
<MageKing17> more than two hours
<MageKing17> but once again we have reached the inevitable conclusion
<MageKing17> How did this code ever work in the first place!?

<@The_E> Welcome to OpenGL, where standards compliance is optional, and error reporting inconsistent

<MageKing17> It was all working perfectly until I actually tried it on an actual mission.

<IronWorks> I am useful for FSO stuff again. This is a red-letter day!
* z64555 erases "Thursday" and rewrites it in red ink

<MageKing17> TIL the entire homing code is held up by shoestrings and duct tape, basically.

 

Offline Lepanto

  • 210
  • Believes in Truth
    • Skype
Re: Highlight or hotkey individual turret
Tried that version. CTD when I try to F9-select the second ship's weapons after it jumps in. Works just fine on the debug build, weirdly enough.
"We have now reached the point where every goon with a grievance, every bitter bigot, merely has to place the prefix, 'I know this is not politically correct, but...' in front of the usual string of insults in order to be not just safe from criticism, but actually a card, a lad, even a hero. Conversely, to talk about poverty and inequality, to draw attention to the reality that discrimination and injustice are still facts of life, is to commit the sin of political correctness. Anti-PC has become the latest cover for creeps. It is a godsend for every curmudgeon and crank, from fascists to the merely smug."
Finian O'Toole, The Irish Times, 5 May 1994

Blue Planet: The Battle Captains: Missions starring the Admirals of BP: WiH
Frontlines 2334+2335: T-V War campaign
GVB Ammit: Vasudan strike bomber
Player-Controlled Capship Modding Tutorial

 

Offline Axem

  • Administrator
  • 211
Re: Highlight or hotkey individual turret
Just as a heads up, I made a new version that should hopefully be a bit more robust and user friendly.

Turret Hotkey Script v2

Please note that this is not a drop in replacement! You will need to alter your syntax a bit, but it should make things more readable.

The way to call it is now (with script-eval-block so you have room for all of this!):
TurretHotkey:Add('ship name','subobject name,'label','hotkey')
Where ship name is the ship's name, subobject name is what you refer to it in the subsystems part of the table or PCS2, label is an optional text label you can give it (like Beam Cannon, Weakpoint etc) and hotkey is F5 though F12. If hotkey isn't entered, it'll use F9.

You can remove a turret from the list with:
TurretHotkey:Rem('ship name','subobject name')
If you don't put the subobject name it will clear everything tied to the ship.

See the pic below for some real power user stuff.



And there are a a few new features. Like I said before, you can specify labels for giving the player more clarity, and also it'll show the health of any subsystem while the list is active, and... AND! When you destroy subsystems that are on a hotkey list, it will jump to the next one in line for easy disarming!

Let me know if this crashes for you!

(Also if you use this right away, the text drawing will be a little goofy until the new nightly goes out tomorrow)

 

Offline Lepanto

  • 210
  • Believes in Truth
    • Skype
Re: Highlight or hotkey individual turret
Thanks a ton, Mr. Make Everyone Else Feel Inferior! :p

I'll give it a try tomorrow, then.
"We have now reached the point where every goon with a grievance, every bitter bigot, merely has to place the prefix, 'I know this is not politically correct, but...' in front of the usual string of insults in order to be not just safe from criticism, but actually a card, a lad, even a hero. Conversely, to talk about poverty and inequality, to draw attention to the reality that discrimination and injustice are still facts of life, is to commit the sin of political correctness. Anti-PC has become the latest cover for creeps. It is a godsend for every curmudgeon and crank, from fascists to the merely smug."
Finian O'Toole, The Irish Times, 5 May 1994

Blue Planet: The Battle Captains: Missions starring the Admirals of BP: WiH
Frontlines 2334+2335: T-V War campaign
GVB Ammit: Vasudan strike bomber
Player-Controlled Capship Modding Tutorial

 

Offline Lepanto

  • 210
  • Believes in Truth
    • Skype
Re: Highlight or hotkey individual turret
Sorry, but it's giving me grief again. Believe I tested it on 2 separate missions.

The first set of TurretHotkey:Add-ed turrets shows up on SEXP call, with damage percentages and everything. But for some reason, when targeting a certain set of 3 turrets I can't target the 3rd turret using F9 (when I destroy the other 2 turrets in the group, it does switch target to turret 3 as intended, though.)

No errors from the script when the first set of ships with tagged turrets warps out, or when the second ship/group jumps in. But when I try to F9-target the turrets on the second ship/group of ships, it immediately CTDs.

Would you please do this lowly LUA-illiterate peasant (and the Inferno project) a favor? Please kindly find out why the script gets so cranky when having to load two separate sets of turrets on two separate ships/groups of ships?

[attachment deleted by nobody]
"We have now reached the point where every goon with a grievance, every bitter bigot, merely has to place the prefix, 'I know this is not politically correct, but...' in front of the usual string of insults in order to be not just safe from criticism, but actually a card, a lad, even a hero. Conversely, to talk about poverty and inequality, to draw attention to the reality that discrimination and injustice are still facts of life, is to commit the sin of political correctness. Anti-PC has become the latest cover for creeps. It is a godsend for every curmudgeon and crank, from fascists to the merely smug."
Finian O'Toole, The Irish Times, 5 May 1994

Blue Planet: The Battle Captains: Missions starring the Admirals of BP: WiH
Frontlines 2334+2335: T-V War campaign
GVB Ammit: Vasudan strike bomber
Player-Controlled Capship Modding Tutorial

 

Offline Axem

  • Administrator
  • 211
Re: Highlight or hotkey individual turret
Can you make me a retail usable mission to try that out on? And which ship from the debug log is it that it's not cycling correctly on.

 

Offline procdrone

  • Formerly TheHound
  • 29
  • Balance breaker! Thats me!
    • Steam
Re: Highlight or hotkey individual turret
Sorry, but it's giving me grief again. Believe I tested it on 2 separate missions.

The first set of TurretHotkey:Add-ed turrets shows up on SEXP call, with damage percentages and everything. But for some reason, when targeting a certain set of 3 turrets I can't target the 3rd turret using F9 (when I destroy the other 2 turrets in the group, it does switch target to turret 3 as intended, though.)

No errors from the script when the first set of ships with tagged turrets warps out, or when the second ship/group jumps in. But when I try to F9-target the turrets on the second ship/group of ships, it immediately CTDs.

Would you please do this lowly LUA-illiterate peasant (and the Inferno project) a favor? Please kindly find out why the script gets so cranky when having to load two separate sets of turrets on two separate ships/groups of ships?

Do you remember to delete the turret from the script when the ship/turret is destroyed? Otherwise, it might just bug the hell out of it. Had many issues with that in the past as well. Script also had issues when the ship you are setting up is not on the mission from the start, but arriving at some point.
--Did it! It's RELEASED! VeniceMirror Thread--

 

Offline Axem

  • Administrator
  • 211
Re: Highlight or hotkey individual turret
My new script has a "auto-prune" function that will get rid the hotkey list of departed and destroyed ships. But that's not to say it might not be tripping on something I didn't take in account.

 

Offline procdrone

  • Formerly TheHound
  • 29
  • Balance breaker! Thats me!
    • Steam
Re: Highlight or hotkey individual turret
I was not using your version 2 so dunno
--Did it! It's RELEASED! VeniceMirror Thread--

 

Offline Lepanto

  • 210
  • Believes in Truth
    • Skype
Re: Highlight or hotkey individual turret
2 bugs CONFIRMED, when only using hotkey script + MediaVPs 2014.

-When you try to F9-target a second group of tagged ships' turrets after the first group of tagged ships has departed, immediate CTD.

-When some of the tagged turrets are destroyed, the F9 key no longer works to switch between the remaining turrets.

Here is a provided test mod, containing Axem's turret hotkey script and a single mission (in the techroom.)

[attachment deleted by nobody]
"We have now reached the point where every goon with a grievance, every bitter bigot, merely has to place the prefix, 'I know this is not politically correct, but...' in front of the usual string of insults in order to be not just safe from criticism, but actually a card, a lad, even a hero. Conversely, to talk about poverty and inequality, to draw attention to the reality that discrimination and injustice are still facts of life, is to commit the sin of political correctness. Anti-PC has become the latest cover for creeps. It is a godsend for every curmudgeon and crank, from fascists to the merely smug."
Finian O'Toole, The Irish Times, 5 May 1994

Blue Planet: The Battle Captains: Missions starring the Admirals of BP: WiH
Frontlines 2334+2335: T-V War campaign
GVB Ammit: Vasudan strike bomber
Player-Controlled Capship Modding Tutorial

 

Offline Axem

  • Administrator
  • 211
Re: Highlight or hotkey individual turret
Great! I will take a look at this tomorrow.

 

Offline Lepanto

  • 210
  • Believes in Truth
    • Skype
Re: Highlight or hotkey individual turret
Wow that was fast thanks.
"We have now reached the point where every goon with a grievance, every bitter bigot, merely has to place the prefix, 'I know this is not politically correct, but...' in front of the usual string of insults in order to be not just safe from criticism, but actually a card, a lad, even a hero. Conversely, to talk about poverty and inequality, to draw attention to the reality that discrimination and injustice are still facts of life, is to commit the sin of political correctness. Anti-PC has become the latest cover for creeps. It is a godsend for every curmudgeon and crank, from fascists to the merely smug."
Finian O'Toole, The Irish Times, 5 May 1994

Blue Planet: The Battle Captains: Missions starring the Admirals of BP: WiH
Frontlines 2334+2335: T-V War campaign
GVB Ammit: Vasudan strike bomber
Player-Controlled Capship Modding Tutorial

 

Offline Axem

  • Administrator
  • 211
Re: Highlight or hotkey individual turret
Okay, I can reproduce the issue, and I am working on it!

  

Offline AdmiralRalwood

  • 211
  • The Cthulhu programmer himself!
    • Skype
    • Steam
    • Twitter
Re: Highlight or hotkey individual turret
Happy, uh, 2nd of July?

I was working with Battuta to fix up the bugs with the turret hotkey script and figured I should post it here, too, so here you go:
Code: [Select]
#Conditional Hooks

$Application: FS2_Open
$On Gameplay Start:
[
turretHotkeys = {}
turretHotkeys.key = "F9"
turretHotkeys.enabled = false

-- Subsystem indicator settings
turretHotkeys.indicator = {}
turretHotkeys.indicator.color = {
    r = 255,
    g = 255,
    b = 255,
    a = 200
}

turretHotkeys.subsystems = {}
turretHotkeys.lastIndex = {1, 0}

function turretHotkeys:keyPressed(key)
    if (self:isEnabled() and key == self.key) then
        local done = false
        local startindex = nil
        local startsubsys = nil
        while (not done) do
            local tblIndex, subsysIndex = self:getNextIndex()
            if (startindex == nil) then
                startindex = tblIndex
                startsubsys = subsysIndex
            else
                if (startindex == tblIndex and startsubsys == subsysIndex) then
                    done = true
                    break
                end
            end

            if (tblIndex ~= false) then
                -- This is ugly code, don't look at it or it won't work
                local tbl = self.subsystems[tblIndex]
                if (tbl ~= nil and tbl[subsysIndex] ~= nil) then
                    local subsys = tbl.ship[tbl[subsysIndex]]

                    if (subsys:isValid() and subsys.HitpointsLeft > 0) then
                        hv.Player.Target = self.subsystems[tblIndex].ship
                        hv.Player.TargetSubsystem = subsys
                        done = true
                    end

                    self.lastIndex = { tblIndex, subsysIndex }
                end
            else
                done = true
            end
        end
    end
end

function turretHotkeys:checkIndexes(tblIndex, subsysIndex)
    if (tblIndex > 0 and tblIndex <= #self.subsystems) then
        if (subsysIndex > 0 and subsysIndex <= #self.subsystems[tblIndex]) then
            return tblIndex, subsysIndex
        else
            return tblIndex, math.max(1, math.min(subsysIndex, #self.subsystems[tblIndex]))
        end
    else
        -- If we're here it means that we've got an invalid index...
        return math.max(1, math.min(tblIndex, #self.subsystems)), math.max(1, math.min(1, #self.subsystems[tblIndex]))
    end
end

function turretHotkeys:getNextIndex()
    local tblIndex = self.lastIndex[1]

    local tbl = self.subsystems[tblIndex]

    if (tbl == nil) then
        if (tblIndex == 1) then
            return false
        else
            return self:checkIndexes(1, 1)
        end
    end

    local subsystemIndex = self.lastIndex[2] + 1

    if (subsystemIndex > #tbl) then
        subsystemIndex = 1
        tblIndex = tblIndex + 1

        tbl = self.subsystems[tblIndex]
    end

    if (tblIndex > #self.subsystems) then
        tblIndex = 1

        if (tblIndex > #self.subsystems) then
            return self:checkIndexes(tblIndex, 1)
        end
    end

    return self:checkIndexes(tblIndex, subsystemIndex)
end

function turretHotkeys:onFrame()
    if (self:isEnabled()) then
        self:checkShips()

        if (hu.HUDDrawn) then
            self:drawSubsystems()
        end
    end
end

function turretHotkeys:checkShips()
    local i = 1

    while (i <= #self.subsystems) do
        if (self.subsystems[i].ship:isValid() and self.subsystems[i].ship.HitpointsLeft > 0 and self.subsystems[i].ship:getBreedName() == "Ship") then
            i = i + 1
        else
            table.remove(self.subsystems, i)
        end
    end
end

function turretHotkeys:drawSubsystems()
    local target = hv.Player.Target
    local subsysName = hv.Player.TargetSubsystem:getModelName()

    for i = 1, #self.subsystems do
        local tbl = self.subsystems[i]
        for j = 1, #tbl do
            local current = tbl.ship[tbl[j]]
            if current.HitpointsLeft > 0 and (tbl.ship ~= target or current:getModelName() ~= subsysName) then
                self:drawSubsystem(current)
            end
        end
    end
end

function turretHotkeys:drawSubsystem(subsys)
    local indicator = self.indicator

    gr.setColor(indicator.color.r, indicator.color.g, indicator.color.b, indicator.color.a)

    gr.drawSubsystemTargetingBrackets(subsys)
end

function turretHotkeys:addShip(ship)
    table.insert(self.subsystems, {
        name = ship.Name,
        ship = ship
    })
end

function turretHotkeys:isValidIndex(index)
    return self.subsystems[index] ~= nil and self.subsystems[index].ship:isValid()
end

function turretHotkeys:addSubsystem(index, name)
    local tbl = self.subsystems[index]

    if (not tbl.ship[name]:isValid()) then
        ba.warning(string.format("Unknown subsystem %q on ship %q of class %q.", name, tbl.ship.name, tbl.ship.class))
        return false
    end

    table.insert(tbl, name)

    return true
end

function turretHotkeys:removeSubsystem(index, name)
    local tbl = self.subsystems[index]

    local newIndex = 1
    local done = false

    while (not done) do
        done = true
        for i = newIndex, #tbl do
            if (i ~= #tbl) then
                done = false
            end
            if (tbl[i] == name) then
                table.remove(tbl, i)
                newIndex = i
                break
            end
        end
    end
end

function turretHotkeys:isEnabled()
    return self.enabled and hv.Player:getBreedName() == "Ship"
end

function thkEnable(bool)
    if (bool == nil) then
        bool = true
    end

    if (type(bool) ~= "boolean") then
        ba.warning("Invalid argument type for thkKey. Need a boolean or no argument, got " .. type(bool) .. ".")
        return
    end

    turretHotkeys.enabled = bool
end

function thkKey(key)
    if (type(key) ~= "string") then
        ba.warning("Invalid argument type for thkKey. Need a string, got " .. type(key) .. ".")
        return
    end

    turretHotkeys.key = key
end

function thkShip(...)
    local names = { ... }

    for i = 1, #names do
        if (type(names[i]) ~= "string") then
            ba.warning("Invalid argument type for thkShip. Need a string, got " .. type(names[i]) .. ".")
            return
        end

        local ship = mn.Ships[names[i]]

        if (not ship:isValid()) then
            ba.warning("No ship with name \"" .. names[i] .. "\" could be found in the current mission.")
            return
        end

        turretHotkeys:addShip(ship)
    end
end

function thkAdd(index, name)
    if (type(index) ~= "number") then
        ba.warning("Invalid first argument type for thkAdd. Need a string, got " .. type(index) .. ".")
        return
    end

    if (type(name) ~= "string") then
        ba.warning("Invalid second argument type for thkAdd. Need a string, got " .. type(name) .. ".")
        return
    end

    if (not turretHotkeys:isValidIndex(index)) then
        ba.warning("Invalid ship index \"" .. tostring(index) .. "\"!")
        return
    end

    turretHotkeys:addSubsystem(index, name)
end

function thkRemove(index, name)
    if (type(index) ~= "number") then
        ba.warning("Invalid first argument type for thkRemove. Need a string, got " .. type(index) .. ".")
        return
    end

    if (type(name) ~= "string") then
        ba.warning("Invalid second argument type for thkRemove. Need a string, got " .. type(name) .. ".")
        return
    end

    if (not turretHotkeys:isValidIndex(index)) then
        ba.warning("Invalid ship index \"" .. tostring(index) .. "\"!")
        return
    end

    turretHotkeys:removeSubsystem(index, name)
end

function thkClear()
    turretHotkeys.subsystems = {}
end
]

$State: GS_STATE_GAME_PLAY
$On Key Pressed:
[
turretHotkeys:keyPressed(hv.Key)
]

$State: GS_STATE_GAME_PLAY
$On Frame:
[
turretHotkeys:onFrame()
]

#End
No real new features, but plenty of bugfixes, and the hotkey will now skip over destroyed subsystems, plus destroyed/departed ships be automatically pruned.

EDIT: Updated again; pruned ships are now marked as inactive but left in the table, so indices won't rearrange themselves mid-mission without thkClear() getting called. In addition, thkAdd() and thkRemove() now accept a ship name for an index so you don't actually have to keep track of what order ships were added to the script (helpful if a ship is only added conditionally). Use script-eval-block to execute longer pieces of Lua from SEXPs.
Code: [Select]
#Conditional Hooks

$Application: FS2_Open
$On Gameplay Start:
[
turretHotkeys = {}
turretHotkeys.key = "F9"
turretHotkeys.enabled = false

-- Subsystem indicator settings
turretHotkeys.indicator = {}
turretHotkeys.indicator.color = {
    r = 255,
    g = 255,
    b = 255,
    a = 200
}

turretHotkeys.subsystems = {}
turretHotkeys.lastIndex = {1, 0}

function turretHotkeys:keyPressed(key)
    if (self:isEnabled() and key == self.key) then
        local done = false
        local startindex = nil
        local startsubsys = nil
        while (not done) do
            local tblIndex, subsysIndex = self:getNextIndex()
            if (startindex == nil) then
                startindex = tblIndex
                startsubsys = subsysIndex
            else
                if (startindex == tblIndex and startsubsys == subsysIndex) then
                    done = true
                    break
                end
            end

            if (tblIndex ~= false) then
                -- This is ugly code, don't look at it or it won't work
                local tbl = self.subsystems[tblIndex]
                if (tbl ~= nil and tbl.active and tbl[subsysIndex] ~= nil) then
                    local subsys = tbl.ship[tbl[subsysIndex]]

                    if (subsys:isValid() and subsys.HitpointsLeft > 0) then
                        hv.Player.Target = self.subsystems[tblIndex].ship
                        hv.Player.TargetSubsystem = subsys
                        done = true
                    end
                end
                self.lastIndex = { tblIndex, subsysIndex }
            else
                done = true
            end
        end
    end
end

function turretHotkeys:checkIndexes(tblIndex, subsysIndex)
    if (tblIndex > 0 and tblIndex <= #self.subsystems) then
        if (subsysIndex > 0 and subsysIndex <= #self.subsystems[tblIndex]) then
            return tblIndex, subsysIndex
        else
            return tblIndex, math.max(1, math.min(subsysIndex, #self.subsystems[tblIndex]))
        end
    else
        -- If we're here it means that we've got an invalid index...
        return math.max(1, math.min(tblIndex, #self.subsystems)), math.max(1, math.min(1, #self.subsystems[tblIndex]))
    end
end

function turretHotkeys:getNextIndex()
    local tblIndex = self.lastIndex[1]

    local tbl = self.subsystems[tblIndex]

    if (tbl == nil) then
        if (tblIndex == 1) then
            return false
        else
            return self:checkIndexes(1, 1)
        end
    end

    local subsystemIndex = self.lastIndex[2] + 1

    if (subsystemIndex > #tbl) then
        subsystemIndex = 1
        tblIndex = tblIndex + 1

        tbl = self.subsystems[tblIndex]
    end

    if (tblIndex > #self.subsystems) then
        tblIndex = 1

        if (tblIndex > #self.subsystems) then
            return self:checkIndexes(tblIndex, 1)
        end
    end

    return self:checkIndexes(tblIndex, subsystemIndex)
end

function turretHotkeys:onFrame()
    if (self:isEnabled()) then
        self:checkShips()

        if (hu.HUDDrawn) then
            self:drawSubsystems()
        end
    end
end

function turretHotkeys:checkShips()
    for i = 1, #self.subsystems do
    if (self.subsystems[i].active) then
        if (not (self.subsystems[i].ship:isValid() and self.subsystems[i].ship.HitpointsLeft > 0 and self.subsystems[i].ship:getBreedName() == "Ship")) then
            self.subsystems[i].active = false
        end
    end
    end
end

function turretHotkeys:drawSubsystems()
    local target = hv.Player.Target
    local subsysName = hv.Player.TargetSubsystem:getModelName()

    for i = 1, #self.subsystems do
        local tbl = self.subsystems[i]
        if (tbl.active) then
        for j = 1, #tbl do
            local current = tbl.ship[tbl[j]]
            if current.HitpointsLeft > 0 and (tbl.ship ~= target or current:getModelName() ~= subsysName) then
                self:drawSubsystem(current)
            end
        end
    end
    end
end

function turretHotkeys:drawSubsystem(subsys)
    local indicator = self.indicator

    gr.setColor(indicator.color.r, indicator.color.g, indicator.color.b, indicator.color.a)

    gr.drawSubsystemTargetingBrackets(subsys)
end

function turretHotkeys:addShip(ship)
    table.insert(self.subsystems, {
        name = ship.Name,
        ship = ship,
        active = true
    })
end

function turretHotkeys:isValidIndex(index)
    return self.subsystems[index] ~= nil and self.subsystems[index].ship:isValid()
end

function turretHotkeys:addSubsystem(index, name)
    local tbl = self.subsystems[index]

    if (not tbl.ship[name]:isValid()) then
        ba.warning(string.format("Unknown subsystem %q on ship %q of class %q.", name, tbl.ship.name, tbl.ship.class))
        return false
    end

    table.insert(tbl, name)

    return true
end

function turretHotkeys:removeSubsystem(index, name)
    local tbl = self.subsystems[index]

    local newIndex = 1
    local done = false

    while (not done) do
        done = true
        for i = newIndex, #tbl do
            if (i ~= #tbl) then
                done = false
            end
            if (tbl[i] == name) then
                table.remove(tbl, i)
                newIndex = i
                break
            end
        end
    end
end

function turretHotkeys:isEnabled()
    return self.enabled and hv.Player:getBreedName() == "Ship"
end

function turretHotkeys:findIndex(name)
for i = 1, #self.subsystems do
if (self.subsystems[i].name == name) then
return i
end
end
return nil
end

function thkEnable(bool)
    if (bool == nil) then
        bool = true
    end

    if (type(bool) ~= "boolean") then
        ba.warning("Invalid argument type for thkEnable. Need a boolean or no argument, got " .. type(bool) .. ".")
        return
    end

    turretHotkeys.enabled = bool
end

function thkKey(key)
    if (type(key) ~= "string") then
        ba.warning("Invalid argument type for thkKey. Need a string, got " .. type(key) .. ".")
        return
    end

    turretHotkeys.key = key
end

function thkShip(...)
    local names = { ... }

    for i = 1, #names do
        if (type(names[i]) ~= "string") then
            ba.warning("Invalid argument type for thkShip. Need a string, got " .. type(names[i]) .. ".")
            return
        end

        local ship = mn.Ships[names[i]]

        if (not ship:isValid()) then
            ba.warning("No ship with name \"" .. names[i] .. "\" could be found in the current mission.")
            return
        end

        turretHotkeys:addShip(ship)
    end
end

function thkAdd(index, name)
    if (type(index) ~= "number") then
    if (type(index) == "string") then
    local temp = turretHotkeys:findIndex(index)
    if (index == nil) then
    ba.warning("Ship name \"" .. index .. "\" not found in list of registered ship names.")
    return
    end
    index = temp
    else
        ba.warning("Invalid first argument (index) type for thkAdd. Need a number or string, got " .. type(index) .. ".")
        return
    end
    end

    if (type(name) ~= "string") then
        ba.warning("Invalid second argument (subsys name) type for thkAdd. Need a string, got " .. type(name) .. ".")
        return
    end

    if (not turretHotkeys:isValidIndex(index)) then
        ba.warning("Invalid ship index \"" .. tostring(index) .. "\"!")
        return
    end

    turretHotkeys:addSubsystem(index, name)
end

function thkRemove(index, name)
    if (type(index) ~= "number") then
    if (type(index) == "string") then
    local temp = turretHotkeys:findIndex(index)
    if (temp == nil) then
    ba.warning("Ship name \"" .. index .. "\" not found in list of registered ship names.")
    return
    end
    index = temp
    else
        ba.warning("Invalid first argument (index) type for thkRemove. Need a number or string, got " .. type(index) .. ".")
        return
    end
    end

    if (type(name) ~= "string") then
        ba.warning("Invalid second argument (subsys name) type for thkRemove. Need a string, got " .. type(name) .. ".")
        return
    end

    if (not turretHotkeys:isValidIndex(index)) then
        ba.warning("Invalid ship index \"" .. tostring(index) .. "\"!")
        return
    end

    turretHotkeys:removeSubsystem(index, name)
end

function thkClear()
    turretHotkeys.subsystems = {}
end
]

$State: GS_STATE_GAME_PLAY
$On Key Pressed:
[
turretHotkeys:keyPressed(hv.Key)
]

$State: GS_STATE_GAME_PLAY
$On Frame:
[
turretHotkeys:onFrame()
]

#End

EDIT2: Couple more bugfixes in the previous version of the script.
« Last Edit: July 03, 2018, 10:10:53 am by AdmiralRalwood »
Ph'nglui mglw'nafh Codethulhu GitHub wgah'nagl fhtagn.

schrödinbug (noun) - a bug that manifests itself in running software after a programmer notices that the code should never have worked in the first place.

When you gaze long into BMPMAN, BMPMAN also gazes into you.

"I am one of the best FREDders on Earth" -General Battuta

<Aesaar> literary criticism is vladimir putin

<MageKing17> "There's probably a reason the code is the way it is" is a very dangerous line of thought. :P
<MageKing17> Because the "reason" often turns out to be "nobody noticed it was wrong".
(the very next day)
<MageKing17> this ****ing code did it to me again
<MageKing17> "That doesn't really make sense to me, but I'll assume it was being done for a reason."
<MageKing17> **** ME
<MageKing17> THE REASON IS PEOPLE ARE STUPID
<MageKing17> ESPECIALLY ME

<MageKing17> God damn, I do not understand how this is breaking.
<MageKing17> Everything points to "this should work fine", and yet it's clearly not working.
<MjnMixael> 2 hours later... "God damn, how did this ever work at all?!"
(...)
<MageKing17> so
<MageKing17> more than two hours
<MageKing17> but once again we have reached the inevitable conclusion
<MageKing17> How did this code ever work in the first place!?

<@The_E> Welcome to OpenGL, where standards compliance is optional, and error reporting inconsistent

<MageKing17> It was all working perfectly until I actually tried it on an actual mission.

<IronWorks> I am useful for FSO stuff again. This is a red-letter day!
* z64555 erases "Thursday" and rewrites it in red ink

<MageKing17> TIL the entire homing code is held up by shoestrings and duct tape, basically.