nick.ace Posted May 21, 2015 Share Posted May 21, 2015 One problem I found is that there is no way to change the crouch height which creates a big problem when you want the character to go into small spaces such as vents. A command such as SetCrouchHeight(float height) would be ideal. Quote Link to comment Share on other sites More sharing options...
gamecreator Posted May 21, 2015 Share Posted May 21, 2015 There's a documented GetCrouched command but no SetCrouched. I wonder if this is also a navigation limitation but I'd check for an undocumented SetCrouched, just in case. 1 Quote Link to comment Share on other sites More sharing options...
nick.ace Posted May 21, 2015 Author Share Posted May 21, 2015 Actually, I just tested it out. Paths that the controller can go through while crouched are not created in the navmesh, so this shouldn't have an effect with navigation. Quote Link to comment Share on other sites More sharing options...
reepblue Posted May 21, 2015 Share Posted May 21, 2015 I got a crouch-able player working, What it does is if the user lets go of ctrl, a picker test is made to see if the player can stand up. Here is the entire code with unfinished features: import "Scripts/Functions/ReleaseTableObjects.lua" --[[ Purpose: A FPS Player that walks, jumps, crouch, and can use and pickup stuff. This is ment to be a alternative version than the one shipped with the SDK. Keywords: #Camera #Movement #Water #KeyInput #Flashlight #Use #Pickup #Health #Respawn #Death #Life #Damage #Hurt #Kill #Weapons ]]-- Script.input={} -- Life Script.health = 100 --float "Starting Health" Script.savedhealth=nil Script.maxHealth = 100 Script.alive=true Script.bregenghealth=false --bool "Regen. Health" Script.RegenTimer = 0 Script.RegenWaitTimer = 0 -- Camera Script.camSmoothing = 4 Script.mouseSensitivity = 15 Script.mouseDifference = Vec2(0,0) Script.eyeheight=1.30 -- Movement Script.moveSpeed = 5.0 Script.footstepwalkdelay = 500 Script.footsteprundelay = 300 Script.jumpForce = 8 Script.supressmovement = false --bool "Freeze Player" Script.allowcrouching = false -- bool "Allow Crouching" Script.canuncrouch = false Script.falldamage=true --bool "Fall Damage" Script.falldamagekills=true --bool "Fall Can Kill" Script.FallTimer= 0 -- Water Script.UnderWater= false -- Respawn Script.RectangleAlpha = 0 Script.RespawnPoint=nil --entity "Respawn Point" Script.RespawnPointPosition=Vec3(0,0,0) Script.RespawnPointRotation=Vec3(0,0,0) Script.RespawnTimer = 0 Script.RespawnDelay = 1.0 --float "Respawn Time" -- Use Script.useDistance = 2 Script.maxcarryweight=80 Script.throwforce = 500 --float "Throw Force" -- Weapon Script.weaponfile=""--path "Starting Weapon" "Prefab (*.pfb):pfb|Prefabs" --Script.weaponfile="Prefabs/Gameplay/VecGun.pfb" -- Flashlight Script.useflashlight = false --bool "Flashlight" Script.flashlighton= false -- Crosshair + HUD Script.supresscrosshair=false --bool "Hide Crosshair" Script.supresshud=false --bool "Hide Health" function Script:Start() --Set the type for this object to player self.entity:SetKeyValue("type","player") -- If we are not a pivot, then make the editor model invisible. if (self.entity:GetClass() ~= Object.PivotClass) then --1 System:Print("Player is not a pivot. Making entity invisible.") material = Material:Create() material:SetBlendMode(5)--Blend.Invisible self.entity:SetMaterial(material) material:Release() end self.savedhealth = self.health -- Draw HUD/Crosshair self.image={} self.image.crosshair = Texture:Load("Materials/HUD/crosshair.tex") self.hudfont = Font:Load("Fonts/Arial.ttf",36) -- Sounds self.sound={}--table to store sound in -- Flashlight (Only if enabled.) if self.useflashlight then --self.sound.flashlight=Sound:Load("Sound/Player/flashlight_02_on.wav") self.sound.flashlight=Sound:Load("Sound/Player/body_punch_03.wav") end -- Damage self.sound.damage={} self.sound.damage[1]=Sound:Load("Sound/Player/body_punch_03.wav") self.sound.damage[2]=Sound:Load("Sound/Player/body_punch_04.wav") self.sound.damage.fall=Sound:Load("Sound/Player/damage_fall_01.wav") self.playfellsound= false self.sound.damage.dead=Sound:Load("Sound/Player/death.wav") self.playdeathsound = false -- Footsteps self.sound.footsteps={} self.sound.footsteps[1] = Sound:Load("Sound/Player/Footsteps/concrete1.wav") self.sound.footsteps[2] = Sound:Load("Sound/Player/Footsteps/concrete2.wav") self.sound.footsteps[3] = Sound:Load("Sound/Player/Footsteps/concrete3.wav") self.sound.footsteps[4] = Sound:Load("Sound/Player/Footsteps/concrete4.wav") -- Jump and Land self.sound.footsteps.jump = Sound:Load("Sound/Player/Footsteps/concrete2.wav") self.sound.footsteps.land = Sound:Load("Sound/Player/Footsteps/concrete4.wav") -- Use self.sound.pickup=Sound:Load("Sound/Player/pickup.wav") self.sound.usedeny=Sound:Load("Sound/Player/use_deny.wav") -- Water --self.sound.underwater=Sound:Load("Sound/Player/underwater.wav") --self.playUnderWatersound= false -- Ignore pickers from picking us! self.entity:SetPickMode(0) -- Physics self.entity:SetCollisionType(Collision.Character) self.entity:SetPhysicsMode(Entity.CharacterPhysics) self.entity:SetGravityMode(true) self.crouched=false self.entity:SetMass(10) if self.entity:GetMass()==0 then Debug:Error("Player mass should be greater than 0.") end -- Create a camera local window = Window:GetCurrent() local context = Context:GetCurrent() self.camera = Camera:Create() self.camera:SetFOV(74) self.camera:SetRange(0.05,1000) self.camera:SetMultisampleMode((System:GetProperty("multisample","1"))) -- Set the camera's rotation to match the player self.camRotation = self.entity:GetRotation(true) 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)) -- Tie the mouse position to the camera's rotation window:SetMousePosition(Math:Round(context:GetWidth()/2), Math:Round(context:GetHeight()/2)) self.camera:SetRotation(self.camRotation) --Create listener self.listener = Listener:Create(self.camera) --#Flashlight if self.useflashlight then 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(25,15) self.flashlight:SetShadowMode(Light.Dynamic+Light.Static) if self.flashlighton==false then self.flashlight:Hide() end end -- Weapons self.weapons={} self.currentweaponindex=-1 self.weaponlowerangle=0 self.weapontag = Pivot:Create(self.camera) self:LoadWeapon() end --This function will be called once per world update function Script:UpdateWorld() self:UpdateCamera() self:UpdateOverlay() if self.bregenghealth then self:RegenHealth() end self:UpdateUse() self:Weapon() self:ListenForKeys() -- If our health is 0, then we are dead. if self.health <= 0 then self:Kill() -- If we have a respawn point vaild, repspawn the player after a second or so. self.RespawnTimer = self.RespawnTimer + (Time:GetSpeed() /100) if self.RespawnTimer > self.RespawnDelay then self:Respawn() end end end --This function will be called once per physics update function Script:UpdatePhysics() if not self.supressmovement then self:UpdateMovement() end self:UpdatePickupObject() end -- #KeyInput function Script:ListenForKeys() local window = Window:GetCurrent() -- If we are in devmode, Show the camera physics models. if System:GetProperty("dev","0")=="1" then if window:KeyHit(Key.P) then physics = not physics self.camera:SetDebugPhysicsMode(physics) end end --Exit the function early if the player is dead if self:IsAlive() <= 0 then return end self:FireWeapon(window) 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 --Toggle the #Flashlight if self.useflashlight then if window:KeyHit(Key.F) then self.sound.flashlight:Play() if self.flashlight:Hidden() then self.flashlight:Show() else self.flashlight:Hide() end end end --Throw object if holding one if self.throwforce > 0 then 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 end -- Check for crouching if window:KeyDown(Key.ControlKey) and self.allowcrouching then self.crouched = true else if self.crouched then self:CanUnCrouch() if self.canuncrouch then self.crouched = false end end end end -- #Camera -- Update the camera with mouse look. function Script:UpdateCamera() local window = Window:GetCurrent() local context=Context:GetCurrent() --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) 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) self.camera:SetRotation(self.camRotation) ------------------------------------------- --With smoothing local playerPos = self.entity:GetPosition() local newCameraPos = self.camera:GetPosition() newCameraPos = Vec3(playerPos.x, newCameraPos.y ,playerPos.z) self.crouchedheight = 1.5 if self.crouched==true then if newCameraPos.y<playerPos.y + self.crouchedheight then newCameraPos.y = Math:Curve(playerPos.y + self.crouchedheight, newCameraPos.y, self.camSmoothing) else newCameraPos.y = playerPos.y + self.crouchedheight end elseif 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 if self:IsAlive() >= 1 and not self.crouched then self.camera:SetPosition(newCameraPos) else deathCameraPos = Vec3(playerPos.x, newCameraPos.y-0.25,playerPos.z) self.camera:SetPosition(deathCameraPos) end --[[ --Not done! local world = World:GetCurrent() local waterenabled= world:GetWaterMode() local height= world:GetWaterHeight() if waterenabled then if (self.camera:GetPosition().y < height) then self.UnderWater = true else self.UnderWater = false end end ]]-- end -- Test crouching. If we are undersomething, don't get up. function Script:CanUnCrouch() local pickInfo = PickInfo() local p0 = self.entity:GetPosition() local p1 = Transform:Point(0,1.6,0,self.entity,nil) --if self.entity.world:Pick(p0,p1, pickInfo, 0, true, 3 ) then if self.entity.world:Pick(p0,p1, pickInfo, 0, true, Collision.Prop ) then --System:Print("NO") self.canuncrouch = false else --System:Print("YES") self.canuncrouch = true end end -- Change the camera's rotation function Script:SetCameraRotation(rot) self.camRotation = rot end -- #Movement -- Update movement function Script:UpdateMovement() --Exit the function early if the player is dead if self:IsAlive() <= 0 then return end local window = Window:GetCurrent() --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) playerMovement.x = self.input[0] * self.moveSpeed playerMovement.z = self.input[1] * self.moveSpeed if self.crouched then playerMovement.x = self.input[0] * self.moveSpeed / 2 playerMovement.z = self.input[1] * self.moveSpeed /2 else playerMovement.x = self.input[0] * self.moveSpeed playerMovement.z = self.input[1] * self.moveSpeed --Update the footstep sounds when walking self:UpdateFootsteps() end --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 -- Check for jumping local jump = 0 if window:KeyHit(Key.Space) and not self.crouched then -- If we are not under the water, jump normally. if not self.UnderWater and self:IsAirborne() == 0 then jump = self.jumpForce self.sound.footsteps.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 else -- self.entity:AddForce(0,5,0) end end --Position camera at correct height and playerPosition self.entity:SetInput(self.camRotation.y, playerMovement.z, playerMovement.x, jump , self.crouched, 1.0, 0.5, true) if self.isairborne==true then if self.entity:GetAirborne()==false then if self.weapons[self.currentweaponindex]~=nil then self.weapons[self.currentweaponindex]:BeginLand() end --System:Print("Landed! Fell for " ..self.FallTimer) if self.FallTimer > 1 then -- 0.1001 self.sound.footsteps.land:Play() end self.FallTimer = 0 if not self.UnderWater then --self.camera:EmitSound(self.sound.footsteps.jump,50,1,1,false) end end --System:Print("InAir") self.FallTimer = self.FallTimer + (Time:GetSpeed() /10) end self.isairborne = self.entity:GetAirborne() -- #Water -- Handle under water movement --[[ local world = World:GetCurrent() local waterenabled= world:GetWaterMode() if waterenabled then self:UnderWaterMovement() end --]] end --[[ -- #Water (Not Done) function Script:UnderWaterMovement() if self.UnderWater then self.entity:SetGravityMode(false) if not self.playUnderWatersound then --self.sound.underwater:Play() self.playUnderWatersound = true end else self.entity:SetGravityMode(true) self.playUnderWatersound = false end end --]] -- Don't allow any walking movement function Script:FreezePlayer()--in self.supressmovement = true end function Script:UnFreezePlayer()--in self.supressmovement = false end --Return whether the player is airborne function Script:IsAirborne() return self.entity:GetAirborne() and 1 or 0 end --Return whether the player is crouching function Script:IsCrouched() return self.crouched and 1 or 0 end --Return whether the player is underwater function Script:IsUnderWater() return self.UnderWater and 1 or 0 end --This function plays footstep sounds in regular intervals as the player walks function Script:UpdateFootsteps() if self.UnderWater then return end 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[index]:Play() end end end end end -- #Use + #Pickup function Script:UpdateUse() --Exit the function early if the player is dead if self:IsAlive() <= 0 then return end local window = Window:GetCurrent() local context=Context:GetCurrent() local pickInfo = PickInfo() --Raycast Pick that is being send from the camera in to the world self.canUse = false 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, 3 ) then if self.entity.world:Pick(p0,p1, pickInfo, 0, true, Collision.Prop ) 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 not self.iscarryingEntity and self.carryingEntity == nil then mass = pickInfo.entity:GetMass() if mass>0 and mass<=self.maxcarryweight then self.carryingEntity = pickInfo.entity self.iscarryingEntity = true self.carryingobjectcollisiontype = self.carryingEntity:GetCollisionType() self.carryingEntity:SetCollisionType(Collision.PickedUpProp) self.sound.pickup:Play() self.carryrotation = Transform:Rotation(pickInfo.entity:GetQuaternion(true),nil,self.camera) self.carryposition = Transform:Point(pickInfo.entity:GetPosition(true),nil,self.camera) end end -- If it's just basic geometry, play the deny sound. local infocollisiontype = pickInfo.entity:GetCollisionType() local infoscript = pickInfo.entity.script if infocollisiontype==Collision.Scene and infoscript == nil then self.sound.usedeny:Play() end end else self.sound.usedeny:Play() --self.entity:EmitSound(self.sound.usedeny, 45 / 100, 0.5, 1, false) end end end if self.carryingEntity == nil then local p0 = self.camera:GetPosition(true) local p1 = Transform:Point(0,0,self.useDistance,self.camera,nil) -- Fixed pickinfo hitting triggers! -reep --if self.entity.world:Pick(p0,p1, pickInfo, 0, true, 3 ) then if self.entity.world:Pick(p0,p1, pickInfo, 0, true, Collision.Prop ) then local collisiontype = pickInfo.entity:GetCollisionType() if (collisiontype==Collision.Prop or collisiontype==Collision.Character or 10) then if self:FindUsableEntity(pickInfo.entity)~=nil then self.canUse=true else local mass = pickInfo.entity:GetMass() -- Has to be atleast 1kg -reep if mass>1 and mass<=self.maxcarryweight then self.canUse = true end end end end end end -- Update the Pickuped item function Script:UpdatePickupObject() 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 end function Script:DropEntityCarrying() self.carryingEntity:SetCollisionType(self.carryingobjectcollisiontype) self.iscarryingEntity = false self.carryingEntity = nil end -- Find a useable entitiy 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 or entity.script.canuse~=false then return entity else self.sound.usedeny:Play() --self.entity:EmitSound(self.sound.usedeny, 45 / 100, 0.5, 1, false) return nil end end end entity = entity:GetParent() end -- If we've got nothing, play the deny use sound. --self.sound.usedeny:Play() return nil end -- #UI -- Toggle some of the drawing function Script:SupressCrosshair()--in self.supresscrosshair = true end function Script:UnSupressCrosshair()--in self.supresscrosshair = false end function Script:SupressHUD()--in self.supresshud = true end function Script:UnSupressHUD()--in self.supresshud = false end function Script:PostRender(context) -- Open the context context:SetBlendMode(Blend.Alpha) context:SetColor(1,1,1,0.8) -- If we are alive, draw our crosshair if self:IsAlive() >= 1 and not self.iscarryingEntity then -- Don't draw if the image is missing or we are hiding it. if self.image.crosshair and not self.supresscrosshair then local crossHairX = math.floor((context:GetWidth() - self.image.crosshair:GetWidth()))/2 local crossHairY = math.floor((context:GetHeight() - self.image.crosshair:GetHeight()))/2 context:DrawImage(self.image.crosshair, crossHairX, crossHairY) end end --- DRAW ALL OTHER UI ELEMENTS YOU WISH TO BE UNDER THE OVERLAY BEFORE THIS LINE -- -- Draw a rectangle for damage indication local x = System:GetProperty("screenwidth","1024") local y = System:GetProperty("screenheight","768") if not self.alive then self.RectangleAlpha = 0.35 end context:SetColor(1,0,0,self.RectangleAlpha) context:DrawRect(0,0,x,y) context:SetColor(1,1,1,1) --- DRAW ALL OTHER UI ELEMENTS YOU WISH TO BE OVER THE OVERLAY AFTER THIS LINE -- -- If we are alive, draw our health on screen if self:IsAlive() >= 1 and not self.supresshud then -- Draw the background context:SetColor(0,0,0,0.5) -- Color of Background --context:DrawRect(8,670,140,50) local RectX = 140 local RectY = 50 context:DrawRect(8, context:GetHeight() - RectY - 8, RectX, RectY) -- Now the actual display of the numbers. -- Change color depending on the health. if self.health >= 100 or self.health > 50 then context:SetColor(0,1,0,1) -- Green else if self.health <= 50 then context:SetColor(1,1,0,1) -- Yellow end if self.health < 20 then context:SetColor(1,0,0,1) -- Red end end context:SetFont(self.hudfont) --context:DrawText("+",14,684) context:DrawText("+",14, context:GetHeight() - 46) --context:DrawText(self.health,60,678) context:DrawText(self.health,60,context:GetHeight() - 50) end context:SetColor(1,1,1,1) context:SetBlendMode(1) end -- #Health -- #Respawn -- #Death -- #Life -- #Damage -- #Hurt -- #Kill --Return whether the player is Alive function Script:IsAlive() return self.alive and 1 or 0 end -- Fall and Physics Damage function Script:Collision(entity,position,normal,speed) if speed >= 20 and self.FallTimer >= 5.0 then if self.falldamagekills then self:Kill() else self:TakeDamage(1) if not self.playfellsound then self.camera:EmitSound(self.sound.damage.fall,5,1,1,false) self.playfellsound = true end end else if not self.falldamage then return end if speed > 18 then self:TakeDamage(1) --local index = math.random(1,4) --self.sound.damage.fall[index]:Play() if not self.playfellsound then self.camera:EmitSound(self.sound.damage.fall,5,1,1,false) self.playfellsound = true end else self.playfellsound = false end end --System:Print(speed) end --Increase health function Script:GiveHealth(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("GiveHealth") end function Script:RegenHealth() --Exit the function early if the player is dead if self:IsAlive() <= 0 then return end if self.health >= self.maxHealth then return end self.RegenTimer = self.RegenTimer + (Time:GetSpeed() /100) self.RegenWaitTimer = self.RegenWaitTimer + (Time:GetSpeed() /100) if self.RegenWaitTimer > 0.5 then if self.RegenTimer > 0.01 then --Increase health self.health = self.health + 1; --Health can not be more then maximum health if self.health > self.maxHealth then self.health = self.maxHealth end self.RegenTimer=0 end end end --TakeDamage function Script:TakeDamage(damage) if self.health>0 then --Decrease health self.health = self.health - damage; --Stop Timer self.RegenTimer=0 self.RegenWaitTimer=0 self.component:CallOutputs("OnTakeDamage") -- Add redness to the overlay! if (self.RectangleAlpha < 0.35) then self.RectangleAlpha=self.RectangleAlpha+0.10 self.sound.damage[math.random(#self.sound.damage)]:Play() end end end -- Life, Death, and Getting Hurt... function Script:UpdateOverlay() if self.savedhealth ~= self.health then if (self.RectangleAlpha ~= 0) then self.RectangleAlpha=self.RectangleAlpha-.08*Time:GetSpeed()/10 --use getspeed to be fps independant. end if self.RectangleAlpha <= 0 then self.savedhealth = self.health end end end -- Same as TakeDamage. function Script:Hurt(damage,distributorOfPain) self:TakeDamage(damage) end function Script:Kill()--in if self:IsAlive() then self.health = 0 self.alive = false self.entity:SetCollisionType(Collision.Prop) self.entity:SetPhysicsMode(Entity.RigidBodyPhysics) self.entity:SetGravityMode(false) self.component:CallOutputs("Kill") if self.iscarryingEntity then self:DropEntityCarrying() end if self.useflashlight then self.flashlight:Hide() end if not self.playdeathsound then self.sound.damage.dead:Play() self.playdeathsound = true end end end -- Respawn if we have a vaild respawn point. -- You can also make it reload a save file in this function instead of this. function Script:Respawn() if self.RespawnPoint ~= nil then -- Set the health back to 100, and we are no longer dead. self.health = 100 self.savedhealth = self.health self.alive = true -- Teleport to the respawn point. local pos = self.RespawnPoint:GetPosition() local rot = self.RespawnPoint:GetRotation() self.RespawnPointPosition = pos self.RespawnPointRotation = rot self.entity:SetPosition(self.RespawnPointPosition) self.camRotation = self.RespawnPointRotation -- Reset other values. self.entity:SetCollisionType(Collision.Character) self.entity:SetPhysicsMode(Entity.CharacterPhysics) self.entity:SetGravityMode(true) self.RectangleAlpha = 0 self.RespawnTimer = 0 self.playdeathsound = false self.crouched = false end end function Script:SetNewRespawnPoint(entity)--in self.RespawnPoint = entity end -- #Weapons function Script:LoadWeapon() 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: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:Weapon() 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) 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) end function Script:FireWeapon(window) -- Listen for Mouse clicks local fire = false local fire2 = 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 if window:MouseDown(2) then fire2=true else self.suspendfire=false end else if window:MouseHit(1) then fire=true end if window:MouseHit(2) then fire2=true end end end end --Fire weapon if self.carryingEntity==nil then -- Primary 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(1) end end -- Secondary if fire2 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(2) end end end end 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: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 function Script:Release() -- Release Listener self.listener:Release() -- Release #Flashlight if we have one. if self.useflashlight then self.flashlight:Release() end -- Release Tables ReleaseTableObjects(self.sound) ReleaseTableObjects(self.image) -- Release weapons local k,v for k,v in pairs(self.weapons) do v:Release() end -- Release Fonts self.hudfont:Release() end Hopes this helps. Quote Cyclone - Ultra Game System - Component Preprocessor - Tex2TGA - Darkness Awaits Template (Leadwerks) If you like my work, consider supporting me on Patreon! Link to comment Share on other sites More sharing options...
nick.ace Posted May 21, 2015 Author Share Posted May 21, 2015 Thanks, I have it working, but I would like control over the crouch height (so you can go through shorter spaces or even crawl). Currently, the character controller doesn't allow that. Quote Link to comment Share on other sites More sharing options...
reepblue Posted May 21, 2015 Share Posted May 21, 2015 Thanks, I have it working, but I would like control over the crouch height (so you can go through shorter spaces or even crawl). Currently, the character controller doesn't allow that. Alright, I would look at this a bit and see if there are any adjustments you can do to get what you want. I'm sure changing the value of self.crouchedheight would do the trick. Quote Cyclone - Ultra Game System - Component Preprocessor - Tex2TGA - Darkness Awaits Template (Leadwerks) If you like my work, consider supporting me on Patreon! Link to comment Share on other sites More sharing options...
nick.ace Posted May 21, 2015 Author Share Posted May 21, 2015 That would only change the camera height. The problem is that when you put the controller into crouched mode, the controller actually gets shorter (the physics mesh or whatever it is built of). So that means that you can't go under regions where the ceiling is too low. My problem is that I want to be able to control the height of the controller so that I can go under shorter regions. The default crouch height is like someone kneeling, which makes it impossible to have a character go through vents and stuff like that without massively changing the level's physics. 1 Quote Link to comment Share on other sites More sharing options...
Einlander Posted May 22, 2015 Share Posted May 22, 2015 There are a few things about the character controller and the navmesh I would love to control. 1. Is the controller height. I would love to add a standing/crouching/prone ability to my game. And 2. The navmesh minimum height. If the headspace for a map is too low a nav mesh is not created. I would like to add airducts or walls the ai need to crawl under. It's somewhat trivial to do obstical avoidance, if a raycast hits object, jump over, if nav mesh area head height blocked but crouch height is not, crouch. Other than having the ability to change nav mesh properties, you could solve this by scaling all models by 2. 1 Quote Link to comment Share on other sites More sharing options...
nick.ace Posted May 22, 2015 Author Share Posted May 22, 2015 The problem is that the character controller stays the same radius and then navmeshes get inaccurate (so AI could bust their way through cracks, etc., although you could work around this by enabling and disabling physics, but it's kind of a hassle). These would be nice options (I get why Josh removed them, but it would be nice for users to have them): http://www.leadwerks.com/werkspace/page/Documentation/le2/_/command-reference/controllers/createcontroller-r101 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.