Jump to content

[Solved] I need help with physics/knockback thing


Recommended Posts

Hello, I need help with this physics/knockback thing I'm trying to get to work, if anyone can help that'd be SO great :D!!!!

So, here are the codes so far...

Spoiler

local function oncollide(inst, other)    
    if (inst:IsValid() and Vector3(inst.Physics:GetVelocity()):LengthSq() > .1) or
        (other ~= nil and other:IsValid() and Vector3(other.Physics:GetVelocity()):LengthSq() > .1) then
        inst.AnimState:PlayAnimation("hit")
        inst.AnimState:PushAnimation("idle", true)
        --inst.SoundEmitter:PlaySound("dontstarve/common/balloon_bounce")
    end
end

local master_postinit = function(inst)
	inst.Physics:SetCollisionCallback(oncollide)
	inst.Physics:SetFriction(.3)
	inst.Physics:SetDamping(0)
	inst.Physics:SetRestitution(1)
end

So, I took this code straight out of balloon.lua... I'm trying to make my character take knockback when attacked, but problem is I don't know what to do with this code... Right now the way it is my character can be pushed by things walking into him just like a balloon, but that's it :(..

 

I saw the Ancient Fuelweaver's shield pushes back players that attack it, which is similar to what I want. So I looked through "stalker_shield.lua" & found these codes, but they're so complicated I don't know how to use them at all :(...

Spoiler


local REPEL_RADIUS = 3
local REPEL_RADIUS_SQ = REPEL_RADIUS * REPEL_RADIUS

local function UpdateRepel(inst, x, z, creatures)
    for i = #creatures, 1, -1 do
        local v = creatures[i]
        if not (v.inst:IsValid() and v.inst.entity:IsVisible()) then
            table.remove(creatures, i)
        elseif v.speed == nil then
            local distsq = v.inst:GetDistanceSqToPoint(x, 0, z)
            if distsq < REPEL_RADIUS_SQ then
                if distsq > 0 then
                    v.inst:ForceFacePoint(x, 0, z)
                end
                local k = .5 * distsq / REPEL_RADIUS_SQ - 1
                v.speed = 25 * k
                v.dspeed = 2
                v.inst.Physics:SetMotorVelOverride(v.speed, 0, 0)
            end
        else
            v.speed = v.speed + v.dspeed
            if v.speed < 0 then
                local x1, y1, z1 = v.inst.Transform:GetWorldPosition()
                if x1 ~= x or z1 ~= z then
                    v.inst:ForceFacePoint(x, 0, z)
                end
                v.dspeed = v.dspeed + .25
                v.inst.Physics:SetMotorVelOverride(v.speed, 0, 0)
            else
                v.inst.Physics:ClearMotorVelOverride()
                v.inst.Physics:Stop()
                table.remove(creatures, i)
            end
        end
    end
end

local function TimeoutRepel(inst, creatures, task)
    task:Cancel()

    for i, v in ipairs(creatures) do
        if v.speed ~= nil then
            v.inst.Physics:ClearMotorVelOverride()
            v.inst.Physics:Stop()
        end
    end
end

local function StartRepel(inst)
    local x, y, z = inst.Transform:GetWorldPosition()
    local creatures = {}
    for i, v in ipairs(TheSim:FindEntities(x, y, z, REPEL_RADIUS, { "locomotor" }, { "fossil", "shadow", "playerghost", "INLIMBO" })) do
        if v:IsValid() and v.entity:IsVisible() and not (v.components.health ~= nil and v.components.health:IsDead()) then
            if v:HasTag("player") then
                v:PushEvent("repelled", { repeller = inst, radius = REPEL_RADIUS })
            elseif v.components.combat ~= nil then
                v.components.combat:GetAttacked(inst, 10)
                if v.Physics ~= nil then
                    table.insert(creatures, { inst = v })
                end
            end
        end
    end

    if #creatures > 0 then
        inst:DoTaskInTime(10 * FRAMES, TimeoutRepel, creatures,
            inst:DoPeriodicTask(0, UpdateRepel, nil, x, z, creatures)
        )
    end
end

I spent a long time trying to do this knockback thing myself, but I'm just too stupid... & I really need this knockback thing.. My only choice was to ask for help, hopefully someone can understand this complicated stuff & help me :)!

Thanks for reading my problem! Have a wonderful day/night :D!!

Edited by SuperDavid
Link to comment
Share on other sites

I know a little bit about the game physics, its a little strange though.

Balloon physics are different than player physics, since balloon physics have less friction and damping. Normal players were never really designed to be thrown around a lot, since the motor they use to move completely negates friction and the damping prevents them from really rising or falling on the Y axis at all. You can change them, but it might have some unintended side effects in game.

Aside from all that, here is a basic formula for launching. where x y and z determine the direction and strength of the launch.

inst.Physics:SetVel(x, y, z) 

If the character's Damping is 1 or the character is moving, they probably won't go anywhere.

You could probably throw this onto an onhit event listener, but getting the angle between the player and the enemy would be a factor too.

Link to comment
Share on other sites

Thanks a lot for your help Pickleplayer :D!!

So, with your help this is the code I have now in mychar.lua

Spoiler

local function oncollide(inst, other)    
    if (inst:IsValid() and Vector3(inst.Physics:GetVelocity()):LengthSq() > .1) or
        (other ~= nil and other:IsValid() and Vector3(other.Physics:GetVelocity()):LengthSq() > .1) then
    end
end

local master_postinit = function(inst)
	inst.Physics:SetCollisionCallback(oncollide)
	inst.Physics:SetFriction(.3)
	inst.Physics:SetDamping(0)
	inst.Physics:SetRestitution(1)

	inst:ListenForEvent("attacked", function(inst, data)
	inst:DoTaskInTime(.25, function() inst.Physics:SetVel(5, 5, 5) end)
	end)
end

 

& I'm so close now! Do you maybe also know how I can do this like you said

32 minutes ago, pickleplayer said:

but getting the angle between the player and the enemy would be a factor too.

if you don't know how then that's okay :)..

Also, since you know about the DST physics a bit can you if you know maybe tell me what does these do?

inst.Physics:SetFriction(.3)
inst.Physics:SetDamping(0)
inst.Physics:SetRestitution(1)

I'm guessing friction is how much the entity can be pushed back or something? But the other things I don't know. And thanks so, so much for your help man :D!!!

Link to comment
Share on other sites

Yea, it's been a little while, but I'm pretty sure I remember them all. Friction affects the character's resistance to the ground. Like if other objects run into you, you might slide around more. Normally it would also make you slide a bit when stopping, but I think the motor just stops you instantly anyways.

Damping is... it's weird and hard to explain. Kinda like air resistance I guess. At 0 you just experience normal gravity, and at 1 you barely move up or down at all (if for some reason you weren't already on the ground)

Restitution is like bounciness. At 1, you will bounce around on surfaces that you hit hard enough, and at 0 you wont. There are in-betweens with decimals too. But most of these physics attributes don't come into play much in-game, except for stuff like the balloons or inventory drop physics.

The only reason I know a lot about this is because the mod I'm working on is... not a typical don't starve mod, and all the characters use completely different physics.

 

And as for the directional bounce; heres something I threw together real quick from stuff in projectile.lua that you can put into your onhit listener. I haven't tested it out, so I'm not sure if it even works, but it might give you an idea.

local facing_angle = data.attacker.Transform:GetRotation() * DEGREES --I forget if attacker is passed into the attacked event data
inst:DoTaskInTime(.25, function() inst.Physics:SetVel(math.cos(facing_angle)*5, 5, math.sin(facing_angle)*5) end)

 

Link to comment
Share on other sites

Wow, thanks so, so much for this great information :D!!!

@pickleplayer I have a new problem now if you maybe can help me, that would be so great! I'm so close to being done :D!!

So, this new problem is if my character gets knockbacked, but if you don't move & just stand still 90% of the time won't get knockbacked anymore until you walk around for a couple seconds, like in these picture

Spoiler

ezgif.com-optimize.gif

ezgif.com-optimize.gif

& I don't know why it happens... Here's all my current code right now!

Spoiler

local function oncollide(inst, other)    
    if (inst:IsValid() and Vector3(inst.Physics:GetVelocity()):LengthSq() > .1) or
        (other ~= nil and other:IsValid() and Vector3(other.Physics:GetVelocity()):LengthSq() > .1) then
    end
end


inst.Physics:SetCollisionCallback(oncollide)
inst.Physics:SetFriction(.3)
inst.Physics:SetDamping(0)
inst.Physics:SetRestitution(1)

inst:ListenForEvent("attacked", function(inst, data)
	if inst.components.playercontroller ~= nil then
		inst.components.playercontroller:Enable(false)
		inst:DoTaskInTime(.75, function() inst.components.playercontroller:Enable(true) end)
	end
	
	if not inst.Physics:IsActive() then
		inst.Physics:Start()
		inst.components.locomotor:Start()
	end
	
	local facing_angle = data.attacker.Transform:GetRotation() * DEGREES
	inst:DoTaskInTime(.25, function() inst.Physics:SetVel(math.cos(facing_angle)*9, 6, math.sin(facing_angle)*-8) end)
end)

 

 

8 hours ago, pickleplayer said:

The only reason I know a lot about this is because the mod I'm working on is... not a typical don't starve mod, and all the characters use completely different physics.

I can't wait till your mod's finished, sounds like it's going to be very cool! And thanks so, so, so much for your help, man! Your help is really makes me happy, thanks so much for everything :D!!!!!!!

Edited by SuperDavid
Link to comment
Share on other sites

Oh yea, I remember this bug. So it turns out that if you stand still for 3 seconds, physics just kind of... turns off. I never actually figured out how to disable this. Instead, I just turn the motor on and off real quick before every time I launch something. I'm pretty sure this is what I used

inst.components.locomotor:RunForward()
inst.Physics:SetMotorVel(0,0,0)

if you put this right before the code that launches them, that should refresh the physics before it launches.

 

Link to comment
Share on other sites

Thank you very, very much for  your help Pickleplayer :wilson_laugh:!!

If I can just ask a few more things if you don't mind! Would I put the codes below inside the event when my character gets hit or somewhere else?

3 hours ago, pickleplayer said:

inst.components.locomotor:RunForward()

inst.Physics:SetMotorVel(0,0,0)

Right now it's like.

Spoiler

inst:ListenForEvent("attacked", function(inst, data)
local attacker = data.attacker

inst.components.locomotor:RunForward()
inst.Physics:SetMotorVel(0,0,0)

	if inst.components.playercontroller ~= nil then
		inst.components.playercontroller:Enable(false)
		inst:DoTaskInTime(.75, function() inst.components.playercontroller:Enable(true) end)
	end
	
	if not inst.Physics:IsActive() then
		inst.Physics:Start()
		inst.components.locomotor:Start()
	end
	
	local facing_angle = attacker.Transform:GetRotation() * DEGREES
	inst:DoTaskInTime(.25, function() inst.Physics:SetVel(math.cos(facing_angle)*9, 3, math.sin(facing_angle)*-8) end) -- 2nd = height, 1st = distance?, 
end)

 

 

Also, with these values of a balloon-

local function oncollide(inst, other)    
    if (inst:IsValid() and Vector3(inst.Physics:GetVelocity()):LengthSq() > .1) or
        (other ~= nil and other:IsValid() and Vector3(other.Physics:GetVelocity()):LengthSq() > .1) then
    end
end

inst.Physics:SetCollisionCallback(oncollide)
inst.Physics:SetFriction(.3)
inst.Physics:SetDamping(0)
inst.Physics:SetRestitution(1)

-my character's extremely easy to be pushed around which's weird.. Do you maybe know how to make it more like normal players when being pushed? I tried increasing damping to 1, but then he wouldn't take any knockback :(..

 

17 hours ago, pickleplayer said:

Friction affects the character's resistance to the ground. Like if other objects run into you, you might slide around more. Normally it would also make you slide a bit when stopping, but I think the motor just stops you instantly anyways.

This interests me because I have an ice character which I'd like to slide around a little bit after stop moving, is there a way to stop the motor from stopping you or do something then the character takes friction even when moving? Sorry, this probably very complicated question..

 

And thanks very much, I really couldn't have done this without you at all :D!!!

Link to comment
Share on other sites

It would go right before the actual launch code, so inside the 0.25 second dotaskintime. But I thought it would still work even in the place that it is now, does it not work?

And being easy to push around is one of those side effects I mentioned of having physics settings similar to the balloon. Thats from the friction, though. You'll want to leave the damping at 0. Increasing the friction should make it less easy to get pushed around. 

3 hours ago, SuperDavid said:

This interests me because I have an ice character which I'd like to slide around a little bit after stop moving, is there a way to stop the motor from stopping you or do something then the character takes friction even when moving? Sorry, this probably very complicated question..

Yea, you'd likely need to mess around with locomotor.lua to get them to slide around. That's what I was able to do. But that probably wouldn't be a realistically usable solution for a normal mod like yours, since that would likely make everyone else slide around too.

Link to comment
Share on other sites

28 minutes ago, pickleplayer said:

It would go right before the actual launch code, so inside the 0.25 second dotaskintime. But I thought it would still work even in the place that it is now, does it not work?

No, it works I just wanted to make sure it's in the right place :)!

 

So, for the side effect of being pushed around I had a idea that in the function oncollide

if I do something like this-

Spoiler

local function oncollide(inst, other)    
    if (inst:IsValid() and Vector3(inst.Physics:GetVelocity()):LengthSq() > .1) or
        (other ~= nil and other:IsValid() and Vector3(other.Physics:GetVelocity()):LengthSq() > .1) then
    end
	
	if other:HasTag("player") then
		inst.Physics:SetFriction(10)
	end
end

-my char when being pushed by a player will become harder to push, the only problem is the higher the friction of an entity is they become slower.. So, maybe you know how I can disable these code?

Spoiler

inst.Physics:SetFriction(1)
inst.Physics:SetDamping(0)
inst.Physics:SetRestitution(1)

So when my char collides with a player he turns hard to push, but when hit by something I renable it for knockback!

 

26 minutes ago, pickleplayer said:

Yea, you'd likely need to mess around with locomotor.lua to get them to slide around. That's what I was able to do. But that probably wouldn't be a realistically usable solution for a normal mod like yours, since that would likely make everyone else slide around too.

My mod is far from normal ;), so if you want maybe you can show me how? If you don't want or it's too hard then I guess that's okay.. :)

 

And man I really want to thank you for being so patient with me, dude :D! Really thanks so, so, so, so, so, so, so, so, so, VERY much :D:D!!!!!!!!!!!!!

Link to comment
Share on other sites

Oh, he becomes slower? That's weird, I thought motors ignored friction. Also I didn't think friction went any higher than 1. maybe having 10 as the friction is giving them super friction that the motor can't handle. Generally, all of those physics values are supposed to be between 0 and 1, and the normal player friction is 1. Just leaving their friction at 1 at all times might be good enough.

My locomotor is pretty chopped up, so you might need to look into that one yourself though.

And yea, you're welcome c:

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...