damage is dealt based whether the player hits the body or the head (aka, headshot and bodyshot damage)
but some enemies (like the one seen in the video), have gore elements that are NOT called “Head” or limb names like “Torso”
to get around this, i decided to use :FindFirstAncestor() and IsDescendantOf(), but for some reason it just doesn’t work?
function DealDamage(result: RaycastResult, character: Model, humanoid: Humanoid, bodyshotDamage: number, headshotDamage: number)
if players:GetPlayerFromCharacter(character) then return end
if not humanoid then return end
local damageDealt = nil
if result.Instance == character.Head or result.Instance:FindFirstAncestor("Head") or result.Instance:IsDescendantOf("Head") then
humanoid:TakeDamage(headshotDamage)
damageDealt = headshotDamage
elseif result.Instance ~= character.Head then
for _,bodyPart in validLimbs do
if result.Instance:IsDescendantOf(bodyPart) or result.Instance:FindFirstAncestor(bodyPart) then
humanoid:TakeDamage(bodyshotDamage)
damageDealt = bodyshotDamage
break
end
end
end
return damageDealt
end
visual presentation:
oh and here are the hierarchies of the limbs that i’ve hit:
the print statements only run if i don’t shoot the gore elements, what…?
(and the second print statement will print true if it’s the head of course)
not sure why that happens?
-- Tables;
local validLimbs = {
"Left Arm",
"Right Arm",
"Left Leg",
"Right Leg",
"Torso"
}
-- Functions;
function DealDamage(result: RaycastResult, character: Model, humanoid: Humanoid, bodyshotDamage: number, headshotDamage: number)
if players:GetPlayerFromCharacter(character) then return end
if not humanoid then return end
local damageDealt = nil
if result.Instance == character.Head or result.Instance:FindFirstAncestor("Head") or result.Instance:IsDescendantOf("Head") then
humanoid:TakeDamage(headshotDamage)
damageDealt = headshotDamage
elseif result.Instance ~= character.Head then
for _,bodyPart in validLimbs do
if result.Instance:IsDescendantOf(bodyPart) or result.Instance:FindFirstAncestor(bodyPart) then
humanoid:TakeDamage(bodyshotDamage)
damageDealt = bodyshotDamage
break
end
end
end
print(result.Instance)
print(result.Instance == character.Head)
return damageDealt
end
try replace:
if result.Instance:IsDescendantOf(bodyPart) or result.Instance:FindFirstAncestor(bodyPart) then
WITH
if result.Instance:IsDescendantOf(character[bodyPart]) or result.Instance:FindFirstAncestor(bodyPart) then
IsDescendantOf takes an Instance parameter, whereas FindFirstAncestor takes in a string parameter. So to make the bodypart an instance, we just index character with it.
:FindFirstAncestor and :IsDescendantOf are functionally the same, with the only difference being the arguments. :FindFirstAncestor requires the argument to be a string, while :IsDescendantOf takes the argument as an Instance. You’ve got some of these mixed up.
So your issue is, those print statements only run if you DON’T shoot the gore elements. Do the gore elements have CanQuery = true? and show me the raycasting section of the code please
function Raycasting(origin: Part, player: Player, hitPos: Mouse, weapon: Tool)
local HEADSHOT_DAMAGE = gunInfo[weapon.Name]["HEADSHOT_DAMAGE"]
local BODYSHOT_DAMAGE = gunInfo[weapon.Name]["BULLET_DAMAGE"]
-- Raycast parameters.
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {player.Character}
raycastParams.IgnoreWater = true
local direction = (hitPos - origin.Position).Unit
local displacement = direction * gunInfo[weapon.Name]["MAX_DISTANCE"]
local result = workspace:Raycast(
origin.Position,
displacement,
raycastParams
)
local endPos = nil
-- Did the raycast hit something?
if result then
endPos = result.Position
local character: Model = result.Instance.Parent
local humanoid: Humanoid = character:FindFirstChildOfClass("Humanoid")
local damageDealt: number = DealDamage(result, character, humanoid, BODYSHOT_DAMAGE, HEADSHOT_DAMAGE)
if damageDealt == nil then return end
damageIndicatorEvent:FireClient(player, damageDealt, humanoid)
else
endPos = origin.Position + displacement
end
end
If the gore part is a child of Head. then the character would be result.Instance.Parent.Parent, therefore the humanoid would be nil, not running the function at all
Try:
local humanoid: Humanoid = result.Instance.Parent:FindFirstChildOfClass(“Humanoid”) or result.Instance.Parent.Parent:FindFirstChildOfClass(“Humanoid”)
locla character: Model = humanoid and humanoid.Parent
(note, result.Instance.Parent.Parent can be nil so make sure to check for this too)
function Raycasting(origin: Part, player: Player, hitPos: Mouse, weapon: Tool)
local HEADSHOT_DAMAGE = gunInfo[weapon.Name]["HEADSHOT_DAMAGE"]
local BODYSHOT_DAMAGE = gunInfo[weapon.Name]["BULLET_DAMAGE"]
-- Raycast parameters.
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {player.Character}
raycastParams.IgnoreWater = true
local direction = (hitPos - origin.Position).Unit
local displacement = direction * gunInfo[weapon.Name]["MAX_DISTANCE"]
local result = workspace:Raycast(
origin.Position,
displacement,
raycastParams
)
local endPos = nil
-- Did the raycast hit something?
if result then
endPos = result.Position
local humanoid: Humanoid = result.Instance.Parent:FindFirstChildOfClass("Humanoid")
local character: Model = humanoid and humanoid.Parent
if result.Instance.Parent.Parent == nil then return end
local damageDealt: number = DealDamage(result, character, humanoid, BODYSHOT_DAMAGE, HEADSHOT_DAMAGE)
if damageDealt == nil then return end
damageIndicatorEvent:FireClient(player, damageDealt, humanoid)
else
endPos = origin.Position + displacement
end
end
local humanoid: Humanoid = result.Instance.Parent:FindFirstChildOfClass(“Humanoid”) or result.Instance.Parent.Parent:FindFirstChildOfClass(“Humanoid”)
locla character: Model = humanoid and humanoid.Parent