Einlander
-
Posts
778 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Posts posted by Einlander
-
-
Is there a reason to not simply convert all strings to wstring to allow utf8 in the fonts that allow them? Or have a global font settings that will take the restrictions off for those who know the risks? Maybe you might gain some customers using logogram based writing systems.
-
The editor use to be in Meters ( multiples of 10), but Josh changed it to be powers of 2 (256, 512, 1024). I still rather it was in multiples of 10. 256cm has no room for jumping indoors, so I have to make all my interiors 384cm, which is not as pretty in the editor.
-
Yeah just checked your script, and we do the same things.
-
Reepblue we seem to have the same idea all the time! I also have a lua based laser beam script for leadwerks. Though I suspect yours will handle materials better than mine can.
These are the notes to the script:
Notes: If you want your beam to be see through, the material need to be see through. My Recomendation is to set the material to alpha and to set the last diffuse box to 128 Since we are streching a quad (thats what a sprite is in Leadwerks) your material will be unrecognizable
Script in spoiler.
--[[
Title: Laser Beam
Author: Einlander
Version: .01
Start Date: 1-22-2016
Description: Draws a laser beam between 2 pivots
Notes: If you want your beam to be see through, the material need to be see through.
My Recomendation is to set the material to alpha and to set the last diffuse box to 128
Since we are streching a quad (thats what a sprite is in Leadwerks) your material will be unrecognizable
--]]
Script.enabled = true --bool "Enabled"
Script.EndPoint = nil --entity "End Point:"
Script.BeamMaterialFile = "" --path "Beam Material:" "Material File (*.mat):mat|Material"
Script.BeamHeight = .2 --float "Beam Height cm:"
Script.PhysicsUpdate = true --bool "Update in Physics:"
function Script:Start()
self.BeamHeight = self.BeamHeight / 10
-- Check End Point
Debug:Assert(self.EndPoint ~= nil , "End point missing. Was an entity added?")
-- Load the Material
self.BeamMaterial = Material:Load(self.BeamMaterialFile)
Debug:Assert(self.BeamMaterial ~= nil , "Error loading the material.")
self.BeamMaterial = tolua.cast(self.BeamMaterial:Copy(),"Material") -- force a copy of the asset because we will need to modify it.
self.BeamMaterial:SetSortMode(true) -- force zsorting (It will be used in a sprite,)
-- Create sprite
self.LaserBeam = Sprite:Create()
self.LaserBeam:SetSize(self.BeamHeight,.1)
self.LaserBeam:SetPickMode(0)
self.LaserBeam:SetMaterial(self.BeamMaterial) -- assign material
self.LaserBeam:SetShadowMode(2)
self.LaserBeam:Show()
--draw Initial Beam
if self.enabled then
self:DebugRay(self.entity:GetPosition(true), self.EndPoint:GetPosition(true), self.LaserBeam)
end
self.OldStartPosition = self.entity:GetPosition(true)
self.OldEndPosition = self.EndPoint:GetPosition(true)
end
-- Draws the Beam
function Script:DebugRay(startpos_as_vec3, endpos_as_vec3, spriteEntity_as_sprite)
local startpos = startpos_as_vec3
local endpos = endpos_as_vec3
local spriteEntity = spriteEntity_as_sprite
local midpoint = ((startpos + endpos) / 2)
local raydistance = math.sqrt((endpos.x - startpos.x)^2 + (endpos.y - startpos.y)^2 + (endpos.z - startpos.z)^2)
spriteEntity:SetPosition(midpoint,true)
local allignvector = startpos - endpos
spriteEntity:SetViewMode(6)
spriteEntity:AlignToVector(allignvector:Normalize(),2)
spriteEntity:SetSize(self.BeamHeight, raydistance)
end
function Script:UpdateWorld()
--check if the positions moved
if (self.PhysicsUpdate == false) and self.enabled then
if ((self.OldStartPosition == self.entity:GetPosition(true)) ~= (self.OldEndPosition == self.EndPoint:GetPosition(true))) then -- Only update if moved
self:DebugRay(self.entity:GetPosition(true), self.EndPoint:GetPosition(true), self.LaserBeam)
self.OldStartPosition = self.entity:GetPosition(true)
self.OldEndPosition = self.EndPoint:GetPosition(true)
end
end
end
function Script:UpdatePhysics() -- update in physics to save some processing cycles
--check if the positions moved
if (self.PhysicsUpdate == true) and self.enabled then
if ((self.OldStartPosition == self.entity:GetPosition(true)) ~= (self.OldEndPosition == self.EndPoint:GetPosition(true))) then -- Only update if moved
self:DebugRay(self.entity:GetPosition(true), self.EndPoint:GetPosition(true), self.LaserBeam)
self.OldStartPosition = self.entity:GetPosition(true)
self.OldEndPosition = self.EndPoint:GetPosition(true)
end
end
end
function Script:Enable()--in
if self.enabled==false then
self.enabled=true
self.component:CallOutputs("_Enabled")
end
end
function Script:Disable()--in
if self.enabled then
self.enabled=false
self.component:CallOutputs("_Disabled")
end
end
--This function will be called when the entity is deleted.
function Script:Detach()
self.BeamMaterial:Release()
self.LaserBeam:Release()
end
- 1
-
Currently to expose settings to the editor users have to use the format:
Script.variable = value --Type "Label"
I propose a breaking change to the way editor properties function.
First the syntax/method would need to change.
Script would become a table:
Script = {}
All entries would be become named variables holding tables:
Script = {
--variable = {value, "type as string","label as string"}
ground_height = {100, "uinteger","Ground Height" },
jump_height = {4,"uinteger", "Jump Height"},
player_name = {"","string", "Player Name"}
}
What this would mean is the editor would need to actually load the script itself, which brings a few drawbacks.
1. the entire script would need to be able to load without any errors.
2. if the script fails there is a chance that the properties will fail to load.
3. if the script property section is malformed or wrong it will not show up.
or just grab it from the debug info (i would assume it's rather hard)
A solution for this would be:
1. To hold a copy of the properties in memory/cache and restore them when the properties returns.
2. add a small reset button to reset the value to default. (since the editor will always be remembering the last value).
If this is implemented there is an additional benefit:
function Script:test1()
return {"Good","Neutral","Bad"}
end
Script = {
--variable = {value, "type as string","label as string"}
ground_height = {100, "uinteger","Ground Height" },
jump_height = {4,"uinteger", "Jump Height"},
player_name = {"","string", "Player Name"},
dynamic_list = {self:test1() ,"choice","Team"}
}
You can now dynamically populate lists!!
1 draw back is you would either need to forward declare functions or put the functions above the script declaration.
Even if this is not implemented, it could be useful if editor plugins are ever added.
- 1
-
ThStill supported some things may have changed over time though.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms728460(v=vs.85).aspx
-
I've had this issue too. With 3 monitors twitch based gaming can become a pain. This code forcibly puts the mouse back in the windows active area. http://www.leadwerks.com/werkspace/topic/10211-trapping-the-mouse-to-the-current-window/
The only issue is, as already mentioned in this thread, that if you move the mouse fast enough you can click outside the window. Leadwerks will as usual keep polling for input.
The code is from when Leadwerks use to have an app.lua instead of main.lua.
-
After this last update on 1-6-17 the drag/rotate/shear arrows do not show up in the perspective view
-
I'm also on Multiple monitors.
-
When I start Leadwerks and open the script editor, the title area is off the screen:
- 1
-
You can raycast from the front and top of the character controller to the ground. And another ray from the bottom faceing front. If while crouched the bottom raycast hits something with an angle greater than 45, and the top ray has a correct step height, move the player up by step height + 1cm. The controller should take care of the rest.
-
Read the all the comments on this blog: http://www.leadwerks.com/werkspace/blog/120/entry-1575-einlanders-halloween-devlog/#commentsStart
-
I also have a trigger script. It is a comprehensive clone of the unity functions. It keeps track of every entity that enters, stays, and leaves a trigger. It also provides 3 functions that other scripts can use to interact with the trigger. It gives you the option of triggering on props, characters, and projectiles
--[[
Title: Enhanced Collision Trigger
By: Einlander
Version: 1.0 First public release
Function: Per-Entity collision trigger. With an additional OnTriggerExit output. Made to mimic unity3d collision handler
Details: Some times you need to have a trigger that will not only know that it is triggered, but know how many entities triggered it, and when any given trigger has left it's trigger area.
Extras: Provides 3 new trigger functions for other scripts to use.
Notes:
-- on collision
a collision has happened
Check if the entity is on the entity collision list
If not, it is placed on the entity list
call OnEnter
If it is on the entity list
call OnStay
-- check during physics -because it's certian to be run, but not as often as update world
check to see if collision happened last run
No collision has happened last time because collision flag is still off
remove from entity list
OnTriggerExit
Collsion happened
set the entity collision flag to false
wake up the entity so the trigger will continue detecting it.
]]--
Script.enabled = true --bool "Enable"
Script.debugtext = false -- bool "Debug Text"
Script.spoofcollision = false --bool "Spoof Trigger"
Script.triggerProps = true --bool "Trigger Props"
Script.triggerCharacters = true --bool "Trigger Characters"
Script.triggerProjectiles = true --bool "Trigger Projectiles"
function Script:Start()
if self.spoofcollision then
-- [spoof collision trigger] dont know if this would actually work
Collision.EnhancedCollisionTrigger = Collision.Trigger --Masqurade as the original trigger collision
else
Collision.EnhancedCollisionTrigger = Time:GetCurrent() -- hopefully no collisions here
end
-- make sure the trigger interacts with most things
-- should be selectable
if self.triggerProps then
Collision:SetResponse(Collision.EnhancedCollisionTrigger, Collision.Prop, Collision.Trigger)
end
if self.triggerCharacters then
Collision:SetResponse(Collision.EnhancedCollisionTrigger, Collision.Character, Collision.Trigger)
end
if self.triggerProjectiles then
Collision:SetResponse(Collision.EnhancedCollisionTrigger, Collision.Projectile, Collision.Trigger)
end
self.entity:SetCollisionType(Collision.EnhancedCollisionTrigger)
self.entitydb = {}
end
function Script:Enable()--in
if self.enabled==false then
self.enabled=true
--self.component:CallOutputs("Enable")
end
end
function Script:Disable()--in
if self.enabled then
self.enabled=false
--self.component:CallOutputs("Disable")
end
end
function Script:OnTriggerEnter(entity)
end
function Script:OnTriggerStay(entity)
end
function Script:OnTriggerExit(entity)
end
function Script:UpdatePhysics()
if self.enabled then
-- check to see if entity is still inside the trigger
for key, value in pairs (self.entitydb) do
if self.entitydb[key].hadcollision == false then -- check if the entity had a collision from the last check
-- on exit
self.component:CallOutputs("OnTriggerExit")
self:OnTriggerExit(self.entitydb[key].entity)
if self.entitydb[key].script then
if type(elf.entitydb[key].script.OnTriggerExit)=="function" then -- Check to see if entity has a script with the right function in it, then call it.
self.entitydb[key].script:OnTriggerExit(self.entity)
end
end
table.remove(self.entitydb, key) -- got to remove it, or else we will end up indexing nil values
else
self.entitydb[key].hadcollision = false -- set it to false because if it is still in the trigger it will get activated again
self.entitydb[key].entity:AddForce(0,0,0) -- wake up the entit's physics. This is a work around because by default, physics objects go to sleep and the trigger can no longer see them. doesnt actually move entity
end
end
end
end
function Script:Collision(entity, position, normal, speed)
if self.enabled == true then
-- check if entity is in the list
local entitymatch = false
for key, value in pairs (self.entitydb) do
if self.entitydb[key].entity == entity then -- found it in the list
self.entitydb[key].hadcollision = true
entitymatch = true
self.component:CallOutputs("OnTriggerStay")
self:OnTriggerStay(entity)
if entity.script then
if type(entity.script.OnTriggerStay)=="function" then -- Check to see if entity has a script with the right function in it, then call it.
entity.script:OnTriggerStay(self.entity)
end
end
end
end
if entitymatch == false then -- add new object to the list
local newEntity = {}
newEntity.entity = entity
newEntity.hadcollision = true
table.insert(self.entitydb, newEntity)
entitymatch = true
self.component:CallOutputs("OnTriggerEnter")
self:OnTriggerEnter(entity)
if entity.script then
if type(entity.script.OnTriggerEnter)=="function" then -- Check to see if entity has a script with the right function in it, then call it.
entity.script:OnTriggerEnter(self.entity)
end
end
end
end
end
--This function will be called when the entity is deleted.
function Script:Detach()
ReleaseTableObjects(self.entitydb)
end
function Script:PostRender(context)
if self.enabled then
if self.debugtext then
context:SetBlendMode(1)
context:SetColor(1,1,1)
context:DrawText("Total Contained Entities: " .. #self.entitydb,0,36)
end
end
end
Entities interacting with the trigger can use:
function Script:OnTriggerEnter(entity)
end
function Script:OnTriggerStay(entity)
end
function Script:OnTriggerExit(entity)
end
- 2
-
you can use luajit ffi, if you have to. http://www.leadwerks.com/werkspace/blog/120/entry-1182-luajit-awesome-luajit-enet-loaded/
the code there is super old, so just take it as inspiration because it's so bad.
This are some repos that deal with curl in lua.
https://github.com/Playermet/CurLua
https://gist.github.com/LPGhatguy/09d3955207ab35d96e97
These will not work in the sandbox and thus not in the game player.
As you probably know. You need to have the proper curl lib for the os installed in the same directory as the exe.
-
See the comments on this blog http://www.leadwerks.com/werkspace/blog/120/entry-1575-einlanders-halloween-devlog/
-
In my game my approach will be similar to the way Left 4 dead did it.
on page 29 to 36.
http://www.valvesoftware.com/publications/2009/ai_systems_of_l4d_mike_booth.pdf
Raycast periodically above the player to find ceilings and paths..
-
Make a material with the 'transparent.shader'
Then use this code:
function Script:Start() if not DEBUG then local material = Material:Create() material:SetBlendMode(5)--Blend.Invisible self.entity:SetMaterial(material) material:Release() end end
This will make whatever the object is invisible at runtime (F6), but visible when debugging (f5) or in the editor.
-
I have done something similar. I had a script that registered players to a playermanager.
The player manager is added to a pivot
function Script:Start()
--= self.entity.script:overwatch_registerplayer(playerEntity)
--[[ REQUIRE A CERTIAN OVERWATCH VERSION AND ABOVE. OVERWATCH VERSION SHOULD ALSO STATE HOW FAR BACK IT STAYS COMPATIBLE ]]
-- Would prefer that the manager finds the entities itself, but thats not a very easy task without ahead of time preperations before this script is even loaded
-- so we have the players self register
-- Register it's existance
if overwatch ~= nil then
if overwatch.playermanager == nil then
overwatch.playermanager = {}
overwatch.playermanager.players = {}
overwatch.playermanager.enabled = true
overwatch.playermanager.entity = self.entity
overwatch.playermanager.instances = 0
end
else
Debug:Error("Overwatch System Not Loaded")
end
overwatch.playermanager.instances = overwatch.playermanager.instances + 1 -- i thought it would be intresting to know how many times an overwatch unit is placed in the map
-- If the same script that saet the entity first is not the same one doing the test, we have too many entities
if overwatch.playermanager.entity ~= self.entity then
Debug:Error("Multiple inscances of Overwatch Player Manager: " .. tostring(overwatch.playermanager.instances) .. " instances")
-- it wont even get past 2
end
end
function Script:overwatch_registerplayer (playerEntity) -- Adds player to the list of forces to be acted apon
local i
for i =0, #overwatch.playermanager.players, 1 do
if overwatch.playermanager.players == playerEntity then
return false -- its already in it
end
end
table.insert(overwatch.playermanager.players,playerEntity)
return true
end
function Script:overwatch_unRegisterplayer (playerEntity) -- Remove player from the list of forces to be acted apon
local i
for i =0, #overwatch.playermanager.players, 1 do
if overwatch.playermanager.players == playerEntity then
table.remove(overwatch.playermanager.players,i)
return true
end
end
return false -- its already removed/never added
end
function overwatch_registerplayer (playerEntity) -- global function: points to local function
overwatch.playermanager.entity.script:overwatch_registerplayer(playerEntity)
end
function overwatch_unRegisterplayer (playerEntity) -- global function: points to local function
overwatch.playermanager.entity.script:overwatch_unRegisterplayer(playerEntity)
end
--[[
function Script:UpdateWorld()
end
--]]
--[[
function Script:UpdatePhysics()
end
--]]
--[[
function Script:Collision(entity, position, normal, speed)
end
--]]
--[[
function Script:Draw()
end
--]]
--[[
function Script:DrawEach(camera)
end
--]]
--This function will be called after the world is rendered, before the screen is refreshed.
--Use this to perform any 2D drawing you want the entity to display.
function Script:PostRender(context)
context:SetBlendMode(Blend.Alpha)
context:SetColor(1,1,1,1)
context:DrawText("PlayerManager Player Count:" .. tostring(#overwatch.playermanager.players),2,200)
context:SetBlendMode(1)
context:SetColor(0,0,0,0.5)
end
--[[
--This function will be called when the entity is deleted.
function Script:Detach()
end
--]]
--[[
--This function will be called when the last instance of this script is deleted.
function Script:Cleanup()
end
--]]
And in the Fps player script we register it.
function Script:Start() overwatch_registerplayer(self.entity) end
I basically created a global function that pointed to a local function.
If I wanted I could have the player manager poll in the Script:UpdateWorld() and do things to the players. That was the goal, but I never had enough time to do what I envisioned and dropped the project.
Edit--
This is the base system that everything loads into. Also added into a pivot
if overwatch == nil then -- Create the base table that all Overwatch systems use. overwatch = {} end
it loads a global table for all the other modules to find.
-
How much more expensive is this shader renderwise?
-
**Operating system or device - Leadwerks Version:**
- Windows 7 Pro x64
- Leadwerks 4.2 Beta BuildID:1479910
**Issue description** (what happened, and what was expected):
- -Issue:
- Models added to the terrain vegetation layer do not show up in game. The same model used for vegitation will reflect if manually dragged into the world.
[*]-What was expected
- Models to show reflection in the water.
- Models added to the terrain vegetation layer do not show up in game. The same model used for vegitation will reflect if manually dragged into the world.
**Steps to reproduce:**
- Create scene.
- Add terrain
- Add skybox
- Add models to vegetation layer
- Run Game
**Link to minimal example project**
- No project just an images:
-
**EDIT**
So It seems that the game defaults to a medium water quality instead of high. :/
- Windows 7 Pro x64
-
I have a program that I wrote that edits the leadwerks obj export to be more editable in 3d editors. I will make it look more presentable and release it one day.
- 2
-
Honestly, the bigger question there is should we have single scripts that are 494+ lines long? We should not. If it gets that big it's a great time to try and refactor things out to other scripts (make a system). Now, when I have files this big if I'm prototyping things out, it's always in the back of my mind to refactor out to it's own system/class as it'll improve the readability a ton. It's pretty rare that any sub-system would need to be that big. Just to give an alternative view.
Great if you are using c++ but the lua export version doesn't support linking to external files.
-
Ehhh rather not. I like to have my steam account divorced from my online presence. I have people actually trying to do real harm to my game servers and steam group users.
-
This is what I found when I was programming something. it also has resources and sources I used linked
function Script:LookAt(start,target) --http://www.leadwerks.com/werkspace/topic/10191-short-example-of-mathatan2/page__hl__lookat --http://stackoverflow.com/questions/1251828/calculate-rotations-to-look-at-a-3d-point --http://leadwerks.wikidot.com/wiki:face-entity --// Calculate angle from point A towards point B local tv = (target - start) local tRoty = Math:ATan2(tv.x, tv.z) --local tRotx = if tv.z >= 0 then tRotx = -Math:ATan2(tv.y* Math:Cos(tRoty), tv.z) else tRotx = Math:ATan2(tv.y* Math:Cos(tRoty), -tv.z) end tRotz = Math:ATan2( Math:Cos(tRotx), Math:Sin(tRotx) * Math:Sin(tRoty) ) return Vec3(tRotx,tRoty,tRotz-90) end
Leadwerks Obj Fixer
in Programming
Posted
Ever made a level in csg and exported it to obj? Well you probably found out that you end up with one massive mess of polygons. This tool fixes that. It will take a leadwerks exported mesh and fix it to something that is easier to handle.
What it does:
Separates all the objects into mesh groups.
What it doesn't do:
Anything with textures or uvmaps. Leadwerks doesn't export any of them
It was written in vb.net so it should run in wine if your on linux.
leadwerks obj fixer.zip