Jump to content
  • 0
havenphillip

Trying to make a health regen code...

Question

Can't figure out how to make it show rounded numbers. Is this a quick fix or am I way off? I'm guessing using Math:Round() but I don't know how to plug it in.

Here's what it looks like and the code I've got so far:

Round it off.png

Share this post


Link to post

24 answers to this question

Recommended Posts

  • 0

Use a timer system like seen in TriggerDelay.lua

Script.delay=1000--int "Delay"
Script.activatetime=0

Script.maxHealth = 100
Script.healthRate = 2 -- 2 hp per second..

function Script:Regen()
	self.activatetime = Time:GetCurrent()+self.delay
end

function AddHealth(health)
	self.health = health
end

function Script:UpdatePhysics()
	if self.activatetime>0 then
		if Time:GetCurrent()>self.activatetime then
			self.activatetime=0
			self:AddHealth(self.healthRate)
		end
	end
end

 

Share this post


Link to post
  • 0

Using Math:Round when drawing the text will round to the nearest whole number:

context:DrawText("Health: "..Math:Round(health).."/100",2,2)

To display to a specific decimal place:

context:DrawText(string.format("Health: %.3f/100",health),2,22)

where %.3f will show to the 3rd decimal place; %.2f would show to the 2nd decimal; %.1f would show to the 1st decimal... etc..

  • Like 1

Share this post


Link to post
  • 0
1 hour ago, havenphillip said:

Awesome. I'll try that. I like the trigger delay version but I couldn't' get it to work and I'm a noob at coding so I get easily confused...

You have a picture of Data with a beard.

I believe in you.

Share this post


Link to post
  • 0
15 hours ago, Josh said:

You have a picture of Data with a beard.

I believe in you.

Haha! Thanks. Chicks dig it. I have a lot of fun with Leadwerks and the community is really helpful. The appeal of it was that a noob like me can download it and make my own games and I'm finding that to be the case. I don't get stuck and just give up.

Gratuitous feedback: I hope you end up making that Boner 3D program. I'd buy it. I'm learning the coding but I also want a way to make models and rig/animate them and a lot of these programs (looking at you, Blender) are horribly tedious and confusing. Possibly a lot more Leadwerks projects would come to fruition if there were some kind of modeling/rigging/animating program that was easily accessible to somebody like me the way Leadwerks is with the coding aspect.

end rant
 

Share this post


Link to post
  • 0

I got the code working. Works well with the Math:Round() under the PostRender function but now I'm noticing the regen rate changes while I'm walking around. When I spawn in the first crawler attacks me and the health immediately jumps back. But as I walk around it is really slow. What would cause that? I'm using Time:GetCurrent() so maybe it has something to do with the frame rate or something?

Share this post


Link to post
  • 0
Quote

 now I'm noticing the regen rate changes while I'm walking around. When I spawn in the first crawler attacks me and the health immediately jumps back. But as I walk around it is really slow. What would cause that? I'm using Time:GetCurrent() so maybe it has something to do with the frame rate or something?

No, it has to do with the fact that Time:GetCurrent() returns the application time. So the longer the game runs the higher the Time:GetCurrent() value becomes, which inversely lowers the value added to health. You need to do what Reepblue suggested and only add a fixed amount of health after a certain delay has occurred if you want a fixed rate of health increase.

Share this post


Link to post
  • 0

You could either add the health in the UpdatePhysics function, which runs at a constant 60 FPS, or you could add a small amount in the UpdateWorld function each frame like this:

self.health = self.health + 0.001 * Time:GetSpeed()
if self.health > 1 then self.health = 1 end

 

Share this post


Link to post
  • 0

Cool I got this to work. So far so good:

function Script:UpdatePhysics()

    --Regenerate Health
    if     self.health < self.maxHealth and self.health > 0 then
           self.healthRegen = 0.01 * (Time:GetSpeed())
           self.health = self.health + self.healthRegen
    end
    
    if     self.health >= self.maxHealth then
          self.health = self.maxHealth  
    end

    if    self.health <= 0 then
          self.health = 0
    end

Share this post


Link to post
  • 0

If your code is in UpdatePhysics() then you actually should not multiply it by GetSpeed() since this function is called 60 times per second no matter what.

Share this post


Link to post
  • 0
11 minutes ago, Josh said:

If your code is in UpdatePhysics() then you actually should not multiply it by GetSpeed() since this function is called 60 times per second no matter what.

That's assuming the computer is fast enough to keep up or the scene isn't too heavy, right?  It's can't be 100% guaranteed, right?

Share this post


Link to post
  • 0
4 minutes ago, gamecreator said:

That's assuming the computer is fast enough to keep up or the scene isn't too heavy, right?  It's can't be 100% guaranteed, right?

Well, if the computer is too slow then it will perform the physics step twice, or more, depending on how much time has passed. But basically yeah it can always be assumed to be running at 60 hz.

  • Like 1

Share this post


Link to post
  • 0

Oops. Ok. Like this, then? The other thing now is how to turn it into a script.variable so I can adjust it in the side tab. I tried...


script.healthRegen = 0.005...
local t = self.healthRegen * (Time:GetSpeed())...


...but then my health stayed at 100 no matter what:
 

function Script:UpdateWorld()
    
    --Regenerate Health
    if   self.health < self.maxHealth and self.health > 0 then
        local healthRegen = 0.005 * (Time:GetSpeed())
        self.health = self.health + healthRegen
    end
    
    if  self.health >= self.maxHealth then
        self.health = self.maxHealth  
    end

    if  self.health <= 0 then
        self.health = 0
    end

 

Share this post


Link to post
  • 0

That's what makes sense to me, logically. But when I do it that way I take no damage at all. I have:

Script.healthRegen = 0.005 -- float "Health Regen Rate"

function Script:UpdateWorld()

    --Regenerate Health
      if     self.health < self.maxHealth and self.health > 0 then
             local regenRate = self.healthRegen * (Time:GetSpeed())
             self.health = self.health + regenRate
      end
    
      if     self.health >= self.maxHealth then
             self.health = self.maxHealth  
      end

      if  self.health <= 0 then
          self.health = 0
      end

I tried to get a picture of it. You can see I just got hit and no damage:
 

 

no damage.png

Share this post


Link to post
  • 0

Just a little note.

	if     self.health >= self.maxHealth then
             self.health = self.maxHealth  
      end
	if  self.health <= 0 then
          self.health = 0
 end
	

could be replaced with

self.health = Math:Clamp(self.health, 0, self.MaxHealth)

 

  • Like 1

Share this post


Link to post
  • 0
10 minutes ago, AggrorJorn said:

Can you post your entire script?

That's all it is. It's plugged into the FPSPlayer with the Status Bars from the Workshop. But here's what I have:

 

 

import "Scripts/Functions/ReleaseTableObjects.lua"

Script.health = 100        --int "Health"
Script.maxHealth = 100        --float "Max Health"
Script.healthRegen = 0.005 --float "Health Regen Rate"
Script.stamina = 1000    --float "Stamina"
Script.maxStamina = 1000 --float "Max Stamina"
Script.mouseSensitivity = 15     --float "Mouse sensitivity"
Script.camSmoothing =     2     --float "Cam smoothing"
Script.moveSpeed = 2.5         --float "Move Speed"
Script.speedMultiplier = 1.5     --float "Run Multiplier"
Script.strafeSpeed = 4         --float "Strafe Speed"
Script.playerHeight = 1.8    --float "Player Height"
Script.jumpForce = 8         --float "Jump Force"
Script.flashlighton = false --bool "Flashlight on"
Script.useDistance = 3
Script.alive=true
Script.eyeheight=1.4
Script.footstepwalkdelay = 500
Script.footsteprundelay = 300
Script.weaponfile=""--path "Weapon" "Prefab (*.pfb):pfb|Prefabs"
Script.input={}
Script.maxcarryweight=5
Script.throwforce = 500
Script.isairborne=false
Script.bloodindex=1
Script.teamid=1--choice "Team" "Neutral,Good,Bad"
Script.hurtoffset=Vec3(0)
Script.smoothedhurtoffset=Vec3(0)
Script.mouseDifference = Vec2(0,0)
Script.playerMovement = Vec3(0,0,0)
Script.tempJumpForce = 0
Script.IsClimbing = false
Script.climbingSpeed = 2 --float "Climbing Speed"

function Script:CycleWeapon(direction)
    local n,weapon
    local foundindex=false
    local prevweapon
    
    if direction==1 then
        for n,weapon in pairs(self.weapons) do
            if foundindex then
                self:SelectWeapon(n)
                return
            end
            if self.currentweaponindex==n then
                foundindex=true
            end
        end
        if foundindex then
            for n,weapon in pairs(self.weapons) do
                self:SelectWeapon(n)
                return
            end        
        end
    else
        for n,weapon in pairs(self.weapons) do
            if prevweapon then
                if self.currentweaponindex==n then
                    self:SelectWeapon(prevweapon)
                    return
                end
            end
            prevweapon=n
        end
        if prevweapon then
            self:SelectWeapon(prevweapon)        
        end        
    end
end

function Script:AddWeapon(weapon)
    if weapon.index==nil then
        weapon.index=1
    end
    
    if self.weapons[weapon.index]==nil then
        self.weapons[weapon.index]=weapon
        self.weapons[weapon.index].player = self
        self.weapons[weapon.index].entity:SetParent(self.weapontag)
        self.weapons[weapon.index].entity:SetPosition(self.weapons[weapon.index].offset)
        if self.weapons[weapon.index].rotation~=nil then
            self.weapons[weapon.index].entity:SetPosition(self.weapons[weapon.index].rotation)
        end
        self.weapons[weapon.index].entity:Hide()
        if weapon.index>self.currentweaponindex then self:SelectWeapon(weapon.index) end
        if self.sound.pickupweapon~=nil then self.sound.pickupweapon:Play() end
        return true
    end
    return false
end

function Script:SelectWeapon(index)
    if index~=self.currentweaponindex then
        if self.weapons[self.currentweaponindex]~=nil then
            self.weapons[self.currentweaponindex].entity:Hide()
        end
        self.currentweaponindex = index
        if self.weapons[self.currentweaponindex]~=nil then
            self.weapons[self.currentweaponindex].entity:Show()
        end
        self.weaponlowerangle=90
        self.suspendfire=false
        self.weapontag:SetRotation(self.weaponlowerangle,0,0)
    end
end

--This function will be called when an entity is loaded in a map.  Use this for intitial setup stuff.
function Script:Start()

    self.spawntime = Time:GetCurrent()
    self.count = 0

    self.weapons={}
    self.currentweaponindex=-1
    
    self.camRotation = self.entity:GetRotation(true)
    self.weaponlowerangle=0    

    self.image={}
    self.image.crosshair = Texture:Load("Materials/HUD/crosshair.tex")
    self.image.hand = Texture:Load("Materials/HUD/use.tex")
    
    self.image.blood={}
    self.image.blood[1]=Texture:Load("Materials/HUD/blood1.tex")
    self.image.blood[2]=Texture:Load("Materials/HUD/blood2.tex")
    self.image.blood[3]=Texture:Load("Materials/HUD/blood3.tex")
    self.image.blood[4]=Texture:Load("Materials/HUD/blood4.tex")
    
    --Load shared sounds
    self.sound={}--table to store sound in
    self.sound.flashlight=Sound:Load("Sound/Player/flashlight_02_on.wav")
    self.sound.damage={}
    self.sound.damage[1]=Sound:Load("Sound/Impact/body_punch_03.wav")
    self.sound.damage[2]=Sound:Load("Sound/Impact/body_punch_04.wav")
    self.sound.pickupweapon=Sound:Load("Sound/Player/pickupammo.wav")
    self.sound.footsteps={}
    self.sound.footsteps.concrete={}
    self.sound.footsteps.concrete.step={}
    --self.sound.footsteps.concrete.step[1] = Sound:Load("Sound/Footsteps/Concrete/step1.wav")
    --self.sound.footsteps.concrete.step[2] = Sound:Load("Sound/Footsteps/Concrete/step2.wav")
    --self.sound.footsteps.concrete.step[3] = Sound:Load("Sound/Footsteps/Concrete/step3.wav")
    --self.sound.footsteps.concrete.step[4] = Sound:Load("Sound/Footsteps/Concrete/step4.wav")
    --self.sound.footsteps.concrete.jump = Sound:Load("Sound/Footsteps/Concrete/jump.wav")
    
    self.bloodoverlay={}

    self.entity:SetPickMode(0)
    
    --Set the type for this object to player
    self.entity:SetKeyValue("type","player")
    
    local mass = self.entity:GetMass()
    if self.entity:GetMass()==0 then Debug:Error("Player mass should be greater than 0.") end

    --Create a camera
    self.camera = Camera:Create()
    self.camera:SetFOV(70)
    self.camera:SetRange(0.05,1000)
    self.camera:SetMultisampleMode((System:GetProperty("multisample","1")))
    
    --Set the camera's rotation to match the player
    self.camera:SetRotation(self.entity:GetRotation(true))
    
    --Set the camera position at eye height
    self.camera:SetPosition(self.entity:GetPosition(true)+Vec3(0,self.eyeheight,0))
    
    --Create listener
    self.listener = Listener:Create(self.camera)    

    --Add fog to camera
    self.camera:SetFogMode(true)
    self.camera:SetFogRange (0,40)
    self.camera:SetFogColor (0.9,0.9,0.9,0.08)
    self.camera:SetFogAngle (0, 180)
    self.camera:SetClearColor(0.721, 0.352, 0,1)
    
    --Create flashlight
    self.flashlight = SpotLight:Create()
    self.flashlight:SetParent(self.camera,false)
    self.flashlight:SetPosition(0.2,-0.1,0)
    self.flashlight:SetRotation(10,-3,0)
    self.flashlight:SetConeAngles(30,10)
    self.flashlight:SetShadowMode(Light.Dynamic+Light.Static)
    if self.flashlighton==false then
        self.flashlight:Hide()
    end
    
    --Load the default weapon, if one is set
    self.weapontag = Pivot:Create(self.camera)
    
    --Hitbox for bullets
    self.entity:SetCollisionType(Collision.Character)
    local hitbox = Model:Box(0.5,1.8,0.5)
    hitbox:SetPosition(self.entity:GetPosition())
    hitbox:Translate(0,0.9,-1)
    hitbox:SetParent(self.entity,true)    
    hitbox:SetCollisionType(Collision.Prop)
    hitbox:SetShadowMode(0)
    
    ---------------------------------------------------------------------------
    --We want the player model visible in the editor, but invisible in the game
    --We can achieve this by creating a material, setting the blend mode to make
    --it invisible, and applying it to the model.
    ---------------------------------------------------------------------------
    local material = Material:Create()
    material:SetBlendMode(5)--Blend.Invisible
    self.entity:SetMaterial(material)
    hitbox:SetMaterial(material)
    material:Release()
    self.entity:SetShadowMode(0)
    
    local window = Window:GetCurrent()
    local context = Context:GetCurrent()
    window:SetMousePosition(Math:Round(context:GetWidth()/2), Math:Round(context:GetHeight()/2))
    
    self.camera:SetRotation(self.camRotation)

    if self.weaponfile~="" then
        local prefab = Prefab:Load(self.weaponfile)
        if prefab~=nil then
            if prefab.script~=nil then
                self:AddWeapon(prefab.script)
            else
                prefab:Release()
            end
        end
    end
end

function Script:Release()
    self.listener:Release()
    self.flashlight:Release()
    if self.corpse~=nil then
        self.corpse:Release()
        self.corpse=nil
    end
    ReleaseTableObjects(self.sound)
    ReleaseTableObjects(self.image)
    local k,v
    for k,v in pairs(self.weapons) do
        v:Release()
    end
end

function Script:Collision(entity,position,normal,speed)
    if speed>20 then
        self:Hurt(5)
    end
end

function Script:Hurt(damage,distributorOfPain)
    if self.health>0 then
        self.sound.damage[math.random(#self.sound.damage)]:Play()
        self.health = self.health - damage
        self.hurtoffset = Vec3(math.random(-1,1),math.random(-1,1),0):Normalize()*30
        local blood = {}
        local n=1
        blood.texture=self.image.blood[math.random(1,4)]
        blood.intensity=1
        table.insert(self.bloodoverlay,blood)        
        if self.bloodindex>4 then self.bloodindex=1 end
        if self.health<=0 then
            self:Kill()
        end
    end
end

function Script:Kill()
    self.corpse = Pivot:Create()
    local shape = Shape:Load("Models/Characters/Generic/corpse.phy")--this shape is made from a low-poly CSG sphere, so it will roll around a bit but come to a stop quickly
    self.corpse:SetShape(shape)
    if shape~=nil then shape:Release() end
    self.flashlight:Hide()
    if self.weapons[self.currentweaponindex]~=nil then
        self.weapons[self.currentweaponindex]:Hide()
    end
    self.corpse:SetMass(5)
    self.corpse:SetMatrix(self.camera:GetMatrix())
    self.camera:SetParent(self.corpse)
    self.camera:SetPosition(0,0,0)
    self.camera:SetRotation(0,0,0)
    self.corpse:SetCollisionType(Collision.Prop)
    self.corpse:SetSweptCollisionMode(true)
    self.entity:SetCollisionType(0)
    self.corpse:SetFriction(10,10)
    local maxomega=5
    self.corpse:SetOmega(Vec3(math.random(-maxomega,maxomega),math.random(-maxomega,maxomega),math.random(-maxomega,maxomega)))
    local v = self.entity:GetVelocity()
    if v:Length()>1 then
        v=v:Normalize()
    end
    self.corpse:SetVelocity(Vec3(math.random(-1,1),math.random(-1,1),math.random(-1,1)))
    --self.entity:SetMass(0) -- Line deleted because game crash if you die
    self.entity:SetPhysicsMode(Entity.RigidBodyPhysics)
end

function Script:FindUsableEntity(entity)
    while entity~=nil do
        if entity.script then
            if type(entity.script.Use)=="function" then
                --If "enable" has not been set, it still won't be "false" so this will pass:
                if entity.script.enabled~=false then
                    return entity
                else
                    return nil
                end
            end
        end
        entity = entity:GetParent()
    end
    return nil
end

function Script:UpdateWorld()
    
    --Regenerate Health
    if     self.health < self.maxHealth and self.health > 0 then
        local regenRate = self.healthRegen * (Time:GetSpeed())
        self.health = self.health + regenRate
    end
    
    if     self.health >= self.maxHealth then
        self.health = self.maxHealth  
    end

    if  self.health <= 0 then
        self.health = 0
    end

        --Put this under post-render function: context:DrawText("Health: "..Math:Round(health).."/100",2,2)
    
    local currenttime = Time:GetCurrent()

    if self.lastweaponhittesttime==nil then self.lastweaponhittesttime=0 end
    if currenttime - self.lastweaponhittesttime>100 then
        self.lastweaponhittesttime=currenttime
        local pickinfo=PickInfo()
        local p1 = Transform:Point(0,0,0,self.camera,nil)
        local p2 = Transform:Point(0,0,0.6,self.camera,nil)
        local pickmode = self.entity:GetPickMode()    
        self.entity:SetPickMode(0)
        --if self.entity.world:Pick(p1,p2,pickinfo,0.25) then
        --    self.weaponlowered=true
        --else
        --    self.weaponlowered=false
        --end
        self.entity:SetPickMode(pickmode)
    end
    if self.weaponlowered then
        self.weaponlowerangle = self.weaponlowerangle + 4 * Time:GetSpeed()
    else
        self.weaponlowerangle = self.weaponlowerangle - 4 * Time:GetSpeed()
    end
    self.weaponlowerangle = math.max(0,math.min(self.weaponlowerangle,90))
    self.weapontag:SetRotation(self.weaponlowerangle,0,0)
    
    --Exit the function early if the player is dead
    if self.health<=0 then return end
    
    local window = Window:GetCurrent()
    local context=Context:GetCurrent()
    
    if window:KeyHit(Key.P) then
        self.camera:SetDebugPhysicsMode(true)
    end
    
    if self.isairborne==true then
        if self.entity:GetAirborne()==false then
            if self.weapons[self.currentweaponindex]~=nil then
                self.weapons[self.currentweaponindex]:BeginLand()
            end
        end
    end
    self.isairborne = self.entity:GetAirborne()
    
    --Mouse look
    self.currentMousePos = window:GetMousePosition()
    window:SetMousePosition(Math:Round(context:GetWidth()/2), Math:Round(context:GetHeight()/2))
    self.currentMousePos.x = Math:Round(self.currentMousePos.x)
    self.currentMousePos.y = Math:Round(self.currentMousePos.y)
    
    if self.mousezpos==nil then self.mousezpos=0 end
    if self.currentMousePos.z~=self.mousezpos then
        if self.weapons[self.currentweaponindex] then
            if self.weapons[self.currentweaponindex].currentaction==nil then
                for n=1,math.abs(self.currentMousePos.z-self.mousezpos) do
                    if self.currentMousePos.z>self.mousezpos then
                        self:CycleWeapon(-1)
                    else
                        self:CycleWeapon(1)
                    end
                end
                self.mousezpos=self.currentMousePos.z
            end
        else
            self.mousezpos=self.currentMousePos.z
        end
    end
    
    self.mouseDifference.x = Math:Curve(self.currentMousePos.x - Math:Round(context:GetWidth()/2),self.mouseDifference.x,3)
    self.mouseDifference.y = Math:Curve(self.currentMousePos.y - Math:Round(context:GetHeight()/2),self.mouseDifference.y,3)
    self.camRotation.x = Math:Clamp(self.camRotation.x + self.mouseDifference.y / self.mouseSensitivity,-90,90)
    self.camRotation.y = self.camRotation.y + (self.mouseDifference.x / self.mouseSensitivity)
    
    --Adjust the view shake
    self.hurtoffset.x = Math:Inc(0,self.hurtoffset.x,2*Time:GetSpeed())
    self.hurtoffset.y = Math:Inc(0,self.hurtoffset.y,2*Time:GetSpeed())
    self.smoothedhurtoffset.x = Math:Curve(self.hurtoffset.x,self.smoothedhurtoffset.x,3)
    self.smoothedhurtoffset.y = Math:Curve(self.hurtoffset.y,self.smoothedhurtoffset.y,3)
    
    --Set the camera angle
    self.camera:SetRotation(self.camRotation+self.smoothedhurtoffset)
    
    --Picking and usage
    local pickInfo = PickInfo()
    
    --Raycast Pick that is being send from the camera in to the world
    self.canUse = false
    
    local fire = false
    local currentime = Time:GetCurrent()
    if self.carryingEntity==nil then
        if self.weapons[self.currentweaponindex]~=nil then
            if self.weapons[self.currentweaponindex].automatic then
                if window:MouseDown(1) then
                    fire=true
                else
                    self.suspendfire=false
                end
            else
                if window:MouseHit(1) then
                    fire=true
                end
            end
        end
    end
    
    --Fire weapon
    if self.carryingEntity==nil then
        if fire then
            if self.suspendfire~=true then
                if self.weapons[self.currentweaponindex].clipammo==0 and self.weapons[self.currentweaponindex].automatic==true then
                    self.suspendfire=true
                end
                self.weapons[self.currentweaponindex]:Fire()
            end
        end
    end
    
    --Throw object if holding one
    if self.carryingEntity then
        if window:MouseHit(1) then
            local dir = Transform:Vector(0,0,self.throwforce,self.camera,nil)
            self.carryingEntity:AddForce(dir)
            self:DropEntityCarrying()
        end
    end
    
    if window:KeyHit(Key.R) then
        if self.weapons[self.currentweaponindex]~=nil then
            if type(self.weapons[self.currentweaponindex].CanReload)=="function" then
                if self.weapons[self.currentweaponindex]:CanReload() then
                    self.suspendfire=false
                    self.weapons[self.currentweaponindex]:Reload()
                end
            end
        end
    end
    
    if window:KeyHit(Key.E) then
        if self.carryingEntity then
            self:DropEntityCarrying()
        else
            local p0 = self.camera:GetPosition(true)
            local p1 = Transform:Point(0,0,self.useDistance,self.camera,nil)
            if self.entity.world:Pick(p0,p1, pickInfo, 0, true) then
                
                --Looks for any entity in the hierarchy that has a "Use" function
                local usableentity = self:FindUsableEntity(pickInfo.entity)
                
                if usableentity~=nil then
                    
                    --Use the object, whatever it may be
                    usableentity.script:Use(self)
                    
                else                    
                    if self.carryingEntity == nil then
                        mass = pickInfo.entity:GetMass()
                        
                        --Pick up object if it isn't too heavy
                        if mass>0 and mass<=self.maxcarryweight then
                            self.carryingEntity = pickInfo.entity
                            self.carryingobjectcollisiontype = self.carryingEntity:GetCollisionType()
                            self.carryingEntity:SetCollisionType(Collision.Debris)
                            self.carryrotation = Transform:Rotation(pickInfo.entity:GetQuaternion(true),nil,self.camera)
                            self.carryposition = Transform:Point(pickInfo.entity:GetPosition(true),nil,self.camera)
                        end
                    end
                end
            end
        end
    end
    
    --The icon that shows that an object can be picked up or can be interacted with
    if self.carryingEntity == nil then
        local p0 = self.camera:GetPosition(true)
        local p1 = Transform:Point(0,0,self.useDistance,self.camera,nil)
        if self.entity.world:Pick(p0,p1, pickInfo, 0, true) then
            if self:FindUsableEntity(pickInfo.entity)~=nil then
                self.canUse=true
            else
                local mass = pickInfo.entity:GetMass()
                if mass>0 and mass<=self.maxcarryweight then
                    self.canUse = true
                end
            end
        end
    end
end

function Script:DropEntityCarrying()
    self.carryingEntity:SetCollisionType(self.carryingobjectcollisiontype)
    self.carryingEntity = nil
end

--[[This function plays footstep sounds in regular intervals as the player walks
function Script:UpdateFootsteps()
    if self.lastfootsteptime==nil then self.lastfootsteptime=0 end
    if self.input[0]~=0 or self.input[1]~=0 then
        local speed = self.entity:GetVelocity():xz():Length()
        if self.entity:GetAirborne()==false then
            if (speed>self.moveSpeed*0.5) then
                local t = Time:GetCurrent()
                local repeatdelay = self.footstepwalkdelay
                if speed>self.moveSpeed * (1+(self.speedMultiplier-1)*0.5) then repeatdelay = self.footsteprundelay end
                if t-self.lastfootsteptime>repeatdelay then
                    self.lastfootsteptime = t
                    local index = math.random(1,4)
                    self.sound.footsteps.concrete.step[index]:Play()
                end
            end
        end
    end
end]]

 

--This function will be called once per physics update
function Script:UpdatePhysics()
        
    --Exit the function early if the player is dead
    if self.health <= 0 then return end
    
    local window = Window:GetCurrent()
    
    --Fade out the screen blood
    if self.bloodintensity~=nil then
        if self.bloodintensity>0 then
            self.bloodintensity = self.bloodintensity-0.01
            self.bloodintensity = math.max(0,self.bloodintensity)
        end
    end
    
    --Update the footstep sounds when walking
    --self:UpdateFootsteps()

    --Toggle the flash light on and off
    if window:KeyHit(Key.F) then
        self.sound.flashlight:Play()
        if self.flashlight:Hidden() then
            self.flashlight:Show()
            self.flashlighton = true
        else
            self.flashlight:Hide()
            self.flashlighton = false
        end
    end

    --Apply forces to make the carried object move the way we want
    if self.carryingEntity then
        local currentpos = self.carryingEntity:GetPosition(true)
        
        local pos = Transform:Point(self.carryposition,self.camera,nil)
        local rot = Transform:Rotation(self.carryrotation,self.camera,nil)
        
        local maxdiff = 0.5
        local diff = pos:DistanceToPoint(currentpos)
        
        --Drop the carryinItem when the distance between camera and item exceed the pickdistance
        if diff>1.5 then
            self:DropEntityCarrying()
        else
            if diff>maxdiff then
                pos = currentpos + (pos-currentpos):Normalize()*maxdiff
                diff = maxdiff
            end            
            self.carryingEntity:PhysicsSetPosition(pos.x,pos.y,pos.z,0.25)
            self.carryingEntity:PhysicsSetRotation(rot,0.5)
        end
    end
    
    --Player Movement
    local movex=0
    local movez=0
    self.input[0]=0
    self.input[1]=0
    if window:KeyDown(Key.W) then self.input[1]=self.input[1]+1 end
    if window:KeyDown(Key.S) then self.input[1]=self.input[1]-1 end
    if window:KeyDown(Key.D) then self.input[0]=self.input[0]+1 end
    if window:KeyDown(Key.A) then self.input[0]=self.input[0]-1 end
    
    local playerMovement = Vec3(0)
    if self.isClimbing then
        playerMovement.y = self.input[1] * self.climbingSpeed
        playerMovement.z = self.input[1] * self.climbingSpeed

        self.entity:Move(0,playerMovement.y,playerMovement.z/10)
    else

        playerMovement.x = self.input[0] * self.moveSpeed
        playerMovement.z = self.input[1] * self.moveSpeed
        
        --This prevents "speed hack" strafing due to lazy programming
        if self.input[0]~=0 and self.input[1]~=0 then
            playerMovement = playerMovement * 0.70710678
        end

        --if self.entity:GetAirborne() then
        --    playerMovement = playerMovement * 0.2
        --end
        
        --Check for running with shift and when not carrying anything
        if self.carryingEntity == nil and window:KeyDown(Key.Shift) then
            if self.stamina > 0 then
                self.abletorun = true
            else
                self.abletorun = false
            end
        end
        
        if self.notrunning then
            if self.stamina <= 99 then
                if self.stamina == 0 then
                    if window:KeyDown(Key.Shift) then
                    self.stamina = self.stamina -1
                    end
                end
            end
        end
        
        if self.stamina < self.maxStamina then
            self.stamina = self.stamina +1
        end
        
        if self.stamina == self.maxStamina then
            self.stamina = self.stamina +0
        end
        
        if self.abletorun and window:KeyDown(Key.Shift) and window:KeyDown(Key.W) then
            playerMovement.z = playerMovement.z  * self.speedMultiplier
            self.running=true
        else
            self.running=false
            self.notrunning=true
        end
        
        if self.running then
            self.stamina = self.stamina - (2%Time:GetCurrent())
        end
        
        -- Check for jumping
        local jump = 0
        if window:KeyHit(Key.Space) and self:IsAirborne() == 0 then
            jump = self.jumpForce
            
            --self.sound.footsteps.concrete.jump:Play()

            if self.weapons[self.currentweaponindex]~=nil then
                self.weapons[self.currentweaponindex]:BeginJump()
            end

            --Give the player an extra boost when jumping
            playerMovement = playerMovement * 1.6
        end
        -- Check for crouching
        --if App.window:KeyHit(Key.ControlKey) then
        --    crouched = not crouched
        --end
    
        --With smoothing
        --Position camera at correct height and playerPosition
        self.entity:SetInput(self.camRotation.y, playerMovement.z, playerMovement.x, jump , false, 1.0, 0.5, true)
    end

    local playerPos = self.entity:GetPosition()
    local newCameraPos = self.camera:GetPosition()
    --local playerTempHeight = ((self:IsCrouched() == 1) and crouchHeight or playerHeight)
    newCameraPos = Vec3(playerPos.x, newCameraPos.y ,playerPos.z)
    
    if newCameraPos.y<playerPos.y + self.eyeheight then
        newCameraPos.y = Math:Curve(playerPos.y + self.eyeheight, newCameraPos.y, self.camSmoothing)
    else
        newCameraPos.y = playerPos.y + self.eyeheight
    end
    
    self.camera:SetPosition(newCameraPos)
end


--Return whether the player is airborne
function Script:IsAirborne()
    return self.entity:GetAirborne() and 1 or 0
end

function Script:PostRender(context)

    context:SetBlendMode(Blend.Alpha)
    context:SetColor(1,1,1,1)

    --[[this is if you want to see your ammo on screen
    if self.weapons[self.currentweaponindex]~=nil then
    context:DrawText("Ammo: "..self.weapons[self.currentweaponindex].clipammo.."/"..self.weapons[self.currentweaponindex].ammo,context:GetWidth()-100,context:GetHeight()-100)
    end]]
    -----------------------------------------------------------------------
    --Draw the blood overlay on the screen to indicate damage
    local k,v
    for k,v in pairs(self.bloodoverlay) do
        if v.intensity>0 then
            context:SetColor(1,1,1,v.intensity*0.5)
            context:DrawImage(v.texture,0,0,context:GetWidth(),context:GetHeight())
            if self.health>0 then
                v.intensity = v.intensity-0.02 * Time:GetSpeed()
            end
        else
            self.bloodoverlay[k]=nil
        end
    end
    context:SetColor(1,1,1,1)
    
    if self.health>0 then
        if self.canUse==true and self.carryingEntity == nil then
            local pickUpX = math.floor((context:GetWidth() - self.image.hand:GetWidth()))/2
            local pickUpY = math.floor((context:GetHeight() - self.image.hand:GetHeight()))/2
            context:SetBlendMode(Blend.Alpha)
            context:DrawImage(self.image.hand, pickUpX, pickUpY)    
        else
            if self.carryingEntity==nil then
                if self.weapons[self.currentweaponindex]~=nil then
                    if self.image.crosshair then
                        local crossHairX = math.floor((context:GetWidth() - self.image.crosshair:GetWidth()))/2
                        local crossHairY = math.floor((context:GetHeight() - self.image.crosshair:GetHeight()))/2
                        context:SetBlendMode(Blend.Alpha)
                        context:DrawImage(self.image.crosshair, crossHairX, crossHairY)
                    end
                end
            end
        end
    end
    
    context:SetBlendMode(1)
    context:SetColor(0,0,0,0.5)
    local indent=8
    local w = 180
    local h = 40
end

--Return whether the player is crouching
function Script:IsAlive()
    return self.alive and 1 or 0
end

--TakeDamage
function Script:TakeDamage(damage)

    --Decrease health
    self.health = self.health - damage;

    --Call OnHit output
    self:OnHit()

    --If health lower or equal to zero, the player is dead
    if self.health == 0 then
        self.alive = false
        --Call the OnDead output
        self:OnDead()
        
    end
end

--Increase health
function Script:ReceiveHealth(healthPoints)--in
    --Increase health
    self.health = self.health + healthPoints;

    --Health can not be more then maximum health
    if self.health > self.maxHealth then
        self.health = self.maxHealth
    end

    --Call Health received output
    self.component:CallOutputs("HealthReceived")
end

--stamina bar
function Script:StaminaBar(staminaPoints)
    if self.running then
        self.stamina = self.stamina - 1
    end
    
    if self.stamina > self.maxStamina then
        self.stamina = self.maxStamina
    end
end

--when health is zero or lower, an output call is made
function Script:OnDead()--out
    --Extra check to make sure that the player is no longer alive
    if not(self:IsAlive()) then
        self.component:CallOutputs("Ondead")
    end
end

--when the player gets damaged we call this output
function Script:OnHit()--out
    self.component:CallOutputs("OnHit")
end

function Script:GetInventory()
    return self.entity:FindChild("PlayerInventory").script
end

Share this post


Link to post
  • 0
12 minutes ago, Roland said:

Just a little note.

 


	if     self.health >= self.maxHealth then
             self.health = self.maxHealth  
      end
	if  self.health <= 0 then
          self.health = 0
 end
	

 

could be replaced with


self.health = Math:Clamp(self.health, 0, self.MaxHealth)

 

 

Nice! That worked. I was wondering what clamp meant.

Share this post


Link to post
  • 0

Ok I figured out if I do it like this it works:
local healthRegen = 0.001 * (Time:GetSpeed()) * self.healthRegen

 

So here's everything I added to the FPSPlayer to get health regen. Thanks, ya'll:

Script.healthRegen = 10 --float "Health Regen Rate"

function Script:UpdateWorld()
    
    --Regenerate Health
    if     self.health < self.maxHealth and self.health > 0 then
           local healthRegen = 0.001 * (Time:GetSpeed()) * self.healthRegen
           self.health = self.health + healthRegen
    end
    
    self.health = Math:Clamp(self.health, 0, self.maxHealth)

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...