dvdvideo1234 / TrackAssemblyTool

A Garry's mod tool for assembing a prop-segmented track
GNU Affero General Public License v3.0
21 stars 2 forks source link

Track piece ghost gets stuck and stays visible after switching from weapon to different tool #58

Closed SligWolf closed 2 months ago

SligWolf commented 2 months ago

The ghost entity gets stuck when deploying a different tool while having a non-toolgun equiped. It only unstucks itself when the Track Assembly Tool is redeployed. When the ghost is stuck, it stays visible and could even interfere with saves and dupes. It happens in singleplayer and multiplayer.

Do the following to reproduce the error:

  1. Equip the Track Assembly Tool and choose a random track piece.
  2. Switch to a weapon or physgun.
  3. Choose a different tool from the Q-Menu. Tool gets deployed.
  4. The previos ghost appear again and is stuck until Track Assembly Tool is redeployed.

This seems to be a similar issue to https://github.com/dvdvideo1234/TrackAssemblyTool/issues/50.

The expected behavior would be that the ghost disappears whenever the Track Assembly Tool is not deployed.

Here a video that shows the error: https://github.com/dvdvideo1234/TrackAssemblyTool/assets/17761396/a7a4d73d-a088-48be-949d-b26b538ce63b

GMod Version: 2024.03.21 (main branch)

dvdvideo1234 commented 2 months ago

Probably ClearGhosts has to be called when switching the tool mode from TA to anthing

dvdvideo1234 commented 2 months ago

This action must have TA-only filter but it does not

  asmlib.SetAction("DRAW_GHOSTS", -- Must have the same parameters as the hook
    function() local sLog = "*DRAW_GHOSTS"
      local oPly, actSwep, actTool = asmlib.GetHookInfo()
      if(not asmlib.IsPlayer(oPly)) then
        asmlib.LogInstance("Hook mismatch",sLog); return nil end
      local model = actTool:GetModel()
      local ghcnt = actTool:GetGhostsDepth()
      local atGho = asmlib.GetOpVar("ARRAY_GHOST")
      if(asmlib.IsModel(model)) then
        if(not (asmlib.HasGhosts() and ghcnt == atGho.Size and atGho.Slot == model)) then
          if(not asmlib.NewGhosts(ghcnt, model)) then
            asmlib.LogInstance("Ghosting fail",sLog); return nil end
          actTool:ElevateGhost(atGho[1], oPly) -- Elevate the properly created ghost
        end; actTool:UpdateGhost(oPly) -- Update ghosts stack for the local player
      end
    end) -- Read client configuration

It is hooked to the Think routine that's why the ghosts drawing get re triggered I think. I must test this. Thanks for the report ;)

Grocel commented 2 months ago

I noticed that when the tool gun is redeployed from the Q-Menu the previous tool (e.g. the Track Assembly Tool) is active for a short period of time (like for a single frame or something) before switching to the actually selected tool without calling TOOL:Holster() for the previous tool.

This might be a GMod bug. I think to fix the bug the tool should only "Think" if it is actually actively selected and only after TOOL:Deploy() has been called, I think this should be reported to Rubat.

dvdvideo1234 commented 2 months ago

This thing just executes the hook again for whatever reason, you are right @Grocel

DG  Player [1][[Sk$Bh]Trick or treat KID!]  Weapon [81][gmod_tool]  gmod_tool   table: 0xe4eb49a2   trackassembly
-- Picking the crowbar ends here
]
]
]
]
-- Picking another tool starts here
DG  Player [1][[Sk$Bh]Trick or treat KID!]  Weapon [81][gmod_tool]  gmod_tool   table: 0xe4eb49a2   trackassembly
dvdvideo1234 commented 2 months ago

The easiest fix I think will be to clear the ghosts when the player is invalid TOOL:Deploy() and TOOL:Holster() to control a player flag so that the hook will know how to ghost. However I agree with you @Grocel because this was not the expected behavior for me too:

function TOOL:Holster()
  if(CLIENT) then return end
  local user = self:GetOwner()
  if(not asmlib.IsPlayer(user)) then return end
  local sKey = (gsToolPrefL.."ghost")
  user:SetNWBool(sKey, false)
  netStart(gsLibName.."SendDeleteGhosts")
  netSend(user)
end

function TOOL:Deploy()
  if(CLIENT) then return end
  local user = self:GetOwner()
  if(not asmlib.IsPlayer(user)) then return end
  local sKey = (gsToolPrefL.."ghost")
  user:SetNWBool(sKey, true)
end

The result is quite OK and will work for @SligWolf so he can workout his stuff ;) I will create and upload the new branch to the WS

DG1 Player [1][[Sk$Bh]Trick or treat KID!]  true    Weapon [81][gmod_tool]  table: 0xe4eb49a2
DG2 Player [1][[Sk$Bh]Trick or treat KID!]  Weapon [81][gmod_tool]  gmod_tool   table: 0xe4eb49a2   trackassembly
DG1 Player [1][[Sk$Bh]Trick or treat KID!]  false   Weapon [81][gmod_tool]  table: 0xe4eb49a2
DG2 Player [1][[Sk$Bh]Trick or treat KID!]  Weapon [81][gmod_tool]  gmod_tool   table: 0xe4eb49a2   trackassembly
dvdvideo1234 commented 2 months ago

Hey, guys, I've uploaded the fix to the WS. God speed. I think we should tell Rubat though. I will write to him about this

dvdvideo1234 commented 2 months ago

Depending on the answer from the Gmod devs I will merge this branch to the POA branch

Grocel commented 2 months ago

Nice that you got to it that fast. The Adv Duplicator 1 has the same issue too, so you are not alone with this. https://github.com/wiremod/advduplicator/issues/91