Tower Targeting ALWAYS going for `mega fein`

I have a module script that handles the targeting of all towers in my game, it is pretty simple:

Summary
function tower.findTarget(Tower, range, mode)
	local bestTarget = nil
	local bestWaypoint = nil
	local bestDist = nil
	local bestHealth = nil
	
	for i, mob in ipairs(workspace.MobRealm:GetChildren()) do
		if mob.Humanoid.Health > 0 then
			local distToMob = (mob.HumanoidRootPart.Position - Tower.PrimaryPart.Position).Magnitude
			local distToWaypoint = (mob.HumanoidRootPart.Position - workspace.Board.Player1.PlayerPath.Waypoints[mob.MovingTo.Value].Position).Magnitude
			
			if distToMob <= range then
				print(bestTarget, mode)
				if mode == "Near" then
					bestTarget = mob
				elseif mode == "First" then
					if not bestWaypoint or mob.MovingTo.Value >= bestWaypoint then
						if bestWaypoint then
							bestDist = nil
						end
						bestWaypoint = mob.MovingTo.Value
						
						if not bestDist or distToWaypoint < bestDist then
							print(mob, bestDist, distToWaypoint)
							bestDist = distToWaypoint
							bestTarget = mob
						end
					end
				elseif mode == "Last" then
					if not bestWaypoint or mob.MovingTo.Value <= bestWaypoint then
						if bestWaypoint then
							bestDist = nil
						end
						bestWaypoint = mob.MovingTo.Value

						if not bestDist or distToWaypoint > bestDist then
							bestDist = distToWaypoint
							bestTarget = mob
						end
					end
				elseif mode == "Strong" then
					if not bestHealth or mob.Humanoid.Health > bestHealth then
						bestHealth = mob.Humanoid.Health
						bestTarget = mob
					end
				elseif mode == "Weak" then
					if not bestHealth or mob.Humanoid.Health < bestHealth then
						bestHealth = mob.Humanoid.Health
						bestTarget = mob
					end
				end
			end
		end
		return bestTarget
	end
		
end
targetingEvent.OnInvoke = tower.findTarget

This is called from the tower, the target is found, then the tower continues with its animation, effects and damage.

However, no matter what mode the tower is in, it ALWAYS attacks the mega fein target when it is on the board and I can’t seem to figure out why this is happening.

https://gyazo.com/39f8a17859dacb0d60b8c2157eed52c5

image
image

3 Likes

did you change the mode cus that is the only thing I can think of

3 Likes

can you show us where you’re calling the function so we can have a clue what you’re passing through?

as above stated, maybe the mode isn’t changing

2 Likes

Sure here is the script that handles one of my towers, they all function the same with the targeting:

Summary
local events = game:WaitForChild("ReplicatedStorage"):WaitForChild("Events")
local targetingEvent = events:WaitForChild("TargetingEvent")

local function FindBestTarget()
	local target = targetingEvent:Invoke(script.Parent, config.Range.Value, config:WaitForChild("TargetMode").Value)
	return target
end

while true do
	local target = FindBestTarget()
	if target then
	
		local windClone = wind:Clone()
		windClone.Parent = workspace
		windClone.PrimaryPart.CFrame = script.Parent.Proj.CFrame
		
		local windParts = windClone:GetChildren()

		local newPosition = target.HumanoidRootPart.Position

		for i, part in ipairs(windParts) do
			if part:IsA("BasePart") then
				local tween = TweenService:Create(part, info, {Position = newPosition})
				tween:Play()
			end
		end
		
		if target then
			target.Humanoid:TakeDamage(calcDamage.Value)
		end
		
		game:GetService("Debris"):AddItem(windClone, .3)

		if math.random(1, 100) <= calcInsta.Value then
			target.Humanoid:TakeDamage(target.Humanoid.MaxHealth)
		end
	end
	task.wait(calcSpeed.Value)
end

Basically the only thing that matters is the top where the target is determined based on the tower range and targeting mode. This function is called every time the tower fires.

But no, I can actually cycle through the modes and regardless of what mode that tower is in, it will always attack the mega fein

Is the TargetMode’s Default Mode set to First?

1 Like

Yeah every tower is set to First by default:

local mode = Instance.new("StringValue")
mode.Name = "TargetMode"
mode.Value = "First"
mode.Parent = newTower.Config

This happens whenever the tower is placed into the game

Hey uhm, I’ve found the error in your code, I know where you have been getting the code so I check the tutorial again

if bestWaypoint then
	bestDist = nil
end

Theses lines of code are not needed, remove that with the “Last” and “First” targetting. He fixed that in the next episode

1 Like

Could it be where youre returning the best target? shouldnt that be returned outside of the for loop? looks like its returning the first thing it sees

2 Likes

I went ahead and removed that and am still having the same issue happen
https://gyazo.com/6d75acd9f7ed00665198036db780cdcf

I moved return bestTarget out of the loop and now it seems halfway fixed

https://gyazo.com/7d73b5e34fadf6f7304714a11fccf0c3

The tower now alternates between the front target and mega fein

image

EDIT:

I believe this is happening because it is targeting the mob nearest any waypoint and not the furthest waypoint, but am not sure why this isn’t being tracked with if not bestWaypoint or mob.MovingTo.Value >= bestWaypoint then

It might have to do with the increased height of the mega zombies. More height will almost surely effect the distance from the tower to the unit. You’ll want to use the position of the feet of the enemy rather than their humanoid root part.

local trueMobPos = mob.HumanoidRoot.Position - Vector3.new(0,(mob.HumanoidRoot.Size.Y/2) + mob["Left Leg"].Size.Y,0) 

local distToMob = (trueMobPos - Tower.PrimaryPart.Position).Magnitude
local distToWaypoint = (trueMobPos - workspace.Board.Player1.PlayerPath.Waypoints[mob.MovingTo.Value].Position).Magnitude
1 Like

I’m sorry to have to bump this but I figured out the issue, I’m just not sure how to fix it:


^ The last line is the bestTarget

What’s happening is the script is setting the MegaFein’s distToWaypoint as bestDist because it is first in the loop.

It will then go to the next target, which has a higher MovingToValue (bestWaypoint) that the MegaFein, but is further from its Waypoint than the MegaFein is from its Waypoint. Which leaves the bestDist set to the MegaFein.

I need to update the bestDist to whichever target has the bestWaypoint and is closest to that waypoint, but I don’t know how to code that.

Current script, issue takes place at if not bestDist or distToWaypoint < bestDist then:

            elseif mode == "First" then
				if not bestWaypoint or mob.MovingTo.Value >= bestWaypoint then
					bestWaypoint = mob.MovingTo.Value
					
					if mob.MovingTo.Value == bestWaypoint then
						print("Mob and MovingTo: ", mob, mob.MovingTo.Value, "Dist and Best: ", distToWaypoint, bestDist)
						
						if not bestDist or distToWaypoint < bestDist then
							bestDist = distToWaypoint
							print("dist check: ", mob)
							if distToWaypoint == bestDist and mob.MovingTo.Value == bestWaypoint then
								print("This should be it", mob, "MovingTo: ", mob.MovingTo.Value, "BestWaypoint: ", bestWaypoint)
								bestTarget = mob
							end
						end
					end

				end
			elseif mode == "Last" then

I might be misreading this, but it looks like the code doesn’t do anything if the new enemy in the loop has a higher bestWaypoint value than the current one.

		elseif mode == "First" then
			if not bestWaypoint or mob.MovingTo.Value >= bestWaypoint then
				bestWaypoint = mob.MovingTo.Value
				if mob.MovingTo.Value == bestWaypoint then
					print("Mob and MovingTo: ", mob, mob.MovingTo.Value, "Dist and Best: ", distToWaypoint, bestDist)
					
					if not bestDist or distToWaypoint < bestDist then
						bestDist = distToWaypoint
						print("dist check: ", mob)
						if distToWaypoint == bestDist and mob.MovingTo.Value == bestWaypoint then
							print("This should be it", mob, "MovingTo: ", mob.MovingTo.Value, "BestWaypoint: ", bestWaypoint)
							bestTarget = mob
						end
					end
				else --//If the bestwaypoint is higher, then there is no need to check waypoint distance.
					bestTarget = mob
				end
			end
		elseif mode == "Last" then

It actually gets checked right under mode == "First with mob.MovingTo.Value >= bestWaypoint

I just don’t know how to change the bestDist whenever a new target has a higher bestWaypoint than the target that initially set bestDist

if not bestDist or distToWaypoint < bestDist then > this doesn’t work because the bestDist is set low with the first target; bestDist needs updated before this point.

I solved this by creating a new variable checking for which waypoint bestDist what set from, and then updating bestDist if bestWaypoint is higher than that variable.

			elseif mode == "First" then
				if not bestWaypoint or mob.MovingTo.Value >= bestWaypoint then
					bestWaypoint = mob.MovingTo.Value
					if mob.MovingTo.Value == bestWaypoint then
						if not bestDist or distToWaypoint < bestDist or mob.MovingTo.Value > waypointValue then
							bestDist = distToWaypoint
							waypointValue = mob.MovingTo.Value	-- the variable that checks highest waypoint when checking bestDist
							
							if distToWaypoint == bestDist and mob.MovingTo.Value == bestWaypoint then
								bestTarget = mob
							end
							
						end
					end
				end
			elseif mode == "Last" then

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.