Jump to content

Rick

Members
  • Posts

    7,936
  • Joined

  • Last visited

Everything posted by Rick

  1. 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.
  2. @gamecreator Note that I did this in lua but a similar thing could be done if needed in C++. I reuse this idea for 1 time animations and continuous animations. For continuous if you specify a special frame callback it'll get called every frame and then you can do the work in there. All the work is done in AnimationManager.lua Below is the entire code for that: --[[ This script provides a programming interface to easily manage animation transitions. Just call the SetAnimationSequence() function from any other script and the entity's animation will be automatically blended from the previous sequence. It's okay to call this repeatedly with the same sequence. A new sequence will only be added in the animation stack when it is different from the previous sequence. ]]-- if AnimationManager~=nil then return end AnimationManager={} function AnimationManager:Create(entity) if entity==nil then Debug:Error("Entity cannot be nil.") end local animationmanager = {} animationmanager.entity = entity animationmanager.animations={} animationmanager.frameoffset = math.random(0,1000) local k,v for k,v in pairs(AnimationManager) do animationmanager[k] = v end return animationmanager end function AnimationManager:SetAnimationSequence(sequence, speed, blendtime, mode, endHookScript, endHook, specialFrameHook, specialFrame, endFrame) --Handle default parameters if speed==nil then speed=1.0 end if blendtime==nil then blendtime=500 end if mode==nil then mode=0 end --Check for redundant animation descriptor if mode==0 then if #self.animations>0 then if self.animations[#self.animations].sequence==sequence then if self.animations[#self.animations].speed==speed then --No change to blend time, so don't alter this? self.animations[#self.animations].blendtime=blendtime return end end end end --Create new animation descriptor and add to animation stack local animation={} animation.blendstart=Time:GetCurrent() animation.blendfinish=animation.blendstart+blendtime animation.sequence=sequence animation.speed=speed animation.mode=mode animation.starttime=animation.blendstart animation.endHookScript=endHookScript animation.endHook=endHook animation.endOfSequenceReached=false animation.endFrame = endFrame animation.specialFrameHook = specialFrameHook animation.specialFrame = specialFrame --Add a random offset to looped animations so they're not all identical --if mode==0 then -- animation.frameoffset = math.random(0,(self.entity:GetAnimationLength(sequence))) --end table.insert(self.animations,animation) end function AnimationManager:ClearAnimations() self.animations = {} end --[[ function Script:GetFrame(seq) local i,animation currenttime=Time:GetCurrent() for i,animation in ipairs(self.animations) do if animation.sequence == seq then return (currenttime-animation.blendstart) * animation.speed end end return -1 end ]]-- function AnimationManager:Update() local i,animation,blend,frame,n,completedanimation local doanimation=false local currenttime=Time:GetCurrent() local maxanim=-1 for i,animation in ipairs(self.animations) do --Lock the matrix before the first sequence is applied if doanimation==false then doanimation=true self.entity:LockMatrix() end --Calculate blend value blend = (currenttime-animation.blendstart)/(animation.blendfinish-animation.blendstart) blend = math.min(1.0,blend) if animation.mode==0 then frame = currenttime * animation.speed + self.frameoffset--animation.frameoffset local length = self.entity:GetAnimationLength(animation.sequence,true) if animation.specialFrameHook ~= nil then animation.specialFrameHook(animation.endHookScript, animation.sequence, frame, length) end else frame = (currenttime-animation.blendstart) * animation.speed local length = self.entity:GetAnimationLength(animation.sequence,true) -- trigger when special frame is hit if animation.specialFrame ~= nil then if frame > animation.specialFrame then animation.specialFrameHook(animation.endHookScript, animation.sequence) animation.specialFrame = nil end end --If a certain frame was specified, call the hook early and remove it --[[ if animation.endFrame~=nil then if frame>animation.endFrame then animation.endHook(animation.endHookScript, animation.sequence) animation.endFrame=nil animation.endHook=nil animation.endHookScript=nil end end ]] if frame>=length-1 then frame=length-1 maxanim = i+1--clears all animations up to this one, and then this one if (not animation.endOfSequenceReached) then animation.endOfSequenceReached=true if animation.endHookScript then if animation.endHook then animation.endHook(animation.endHookScript, animation.sequence) end end end end end --Apply the animation self.entity:SetAnimationFrame(frame, blend, animation.sequence, true) --If this animation is blended in 100%, all previous looping animation sequences can be dropped if blend>=1.0 then maxanim = math.max(maxanim,i) end end --Unlock entity matrix if any animations were applied if doanimation==true then self.entity:UnlockMatrix() end --Clear blended out animation - moved this out of the loop to prevent jittering if maxanim>-1 then local index=1 for n,completedanimation in ipairs(self.animations) do if n<maxanim then if completedanimation.mode==0 or completedanimation.endOfSequenceReached==true then table.remove(self.animations,index) else index=index+1 end else break end end end end function AnimationManager:GetAnimationStackSize() return #self.animations end Usage is: self.animMgr:SetAnimationSequence("Chop1", 0.04, 250, 1, self, self.EndAction, self.SpecialFrame, 14) function Script:SpecialFrame(seq) -- look into: I don't think I need to call the Use() of the current object each time if seq == "Chop1" then local sound = Math:Round(math.random(1, 4)) self.sounds.chop[sound]:Play() self.currentObject.script:Use(self.equippedItem) end end For walking, if anyone cares, I use the same AnimationManager.lua above but this is the callback that gets called each frame of the animation. Inside I check the frames (8 and 19 in this case which are the frames where the feet are hitting the ground) and toggle a left/right. This will sync up the footsteps sound. function Script:OnAnimationFrame(seq, frame, length) if seq == "Walk" then if math.floor(frame % length) == 8 and self.leftFoot == false then local sound = Math:Round(math.random(1, 5)) self.sounds.walk[sound]:Play() self.leftFoot = true end if math.floor(frame % length) == 19 and self.rightFoot == false then local sound = Math:Round(math.random(1, 5)) self.sounds.walk[sound]:Play() self.rightFoot = true end -- reset if math.floor(frame % length) == 0 then self.leftFoot = false self.rightFoot = false end end end[/code]
  3. If it's a FPS then camera pick out the center of the screen. If it's like a top down then world pick from the gun outward.
  4. Personally I'd just use raycasting (Pick) at the time of firing to see if it collided with anything.
  5. The 3rd way is to set a hook function for your animations. Allow the function to be called at any special frames you wish. Then setup this function to be called at the frames that best match when the feet are on the ground. Then inside this function play your footstep sound. This adjusts automatically with your animation speed too!
  6. I'm pretty sure his game is a multiplayer game, and I'm pretty sure loading a character model with the unique flag causes a pause in the game while it's happening in real-time. So as you're moving around and players are coming into your zone you'd have to load their characters which would cause an unwanted pause in the game all the time. Ideally the game would load 1 instance of each type of character (human, drawf, etc) and then just create instances (instant in game) and then swap textures that are also already loaded at startup. This is why things get tricky in LE. Without the ability to load assets on another thread and move them to the main thread we have to handle the pauses of loading in different ways.
  7. When you load a model you have options for asset flags and those values are: http://www.leadwerks.com/werkspace/page/api-reference/_/asset/ You can search this forum for these but I think unmanaged means unique materials per model? I could be wrong but we asked for this a long time ago. The issue is that this only works when loading the models in code. If you place them in the editor you don't have this option. That being said, why put the invisible mat on the tree in your first example? I would think just hiding the tree model would be a better option in that case. When you get into your characters and skins, I think you'd be better off searching the forums for the atlas shader that exists (shadmar made it). This allows you to make a really big texture that has subtextures on it. So you could have a 4096x4096 and it could have a 4x4 grid of subtextures (giving you 16 variations) that are 1024x1024. Only 16 you may say, but that was just an example and doing what you want (like most MMO's do) is a complicated thing and requires a lot of art setup really. Note that materials are per surface. So your characters could have a surface for the head, shoulders, chest, legs, hands, feet and you could programatically set which subtexture in the atlast each would get and each would be able to use a separate texture atlas. If you make the textures 512x512 and maybe use a bigger overall texture atlas you can get more variations. You could also swap entire models out for chest, head, etc and "stitch" them together at run-time to give even more variations. Don't ask me how to stitch them together but I hear this is a common thing in MMO's as well. Another option is to have all model variations in the model itself and then in code you just hide all the other surfaces that you don't want. One of the modelers that sell here have characters like this, but the model size because fairly large and any change is changing the base model vs the modular approach of separate models and stitching. Overall, this is a little more complicated than the tree stuff.
  8. Did you look at opening a new map? There should be a bunch of maps in that project template that are more interesting.
  9. What are these probes? Are these things that we have to place in our scene in strategic areas and only do things in a certain volume?
  10. I'm not following why you are thinking that matters. The majority of people here only use the main thread anyway and you can still update the visuals inside the callback function if a progress bar is needed.
  11. You can loop over the world->entities list after the map is loaded to do this. Also, you could still use that callback to add to a list. That wouldn't need to change.
  12. @Josh, why not have it called as each model is loaded?
  13. Oh, I see it's because Josh doesn't declare the parameter as a function pointer. #include <stdio.h> void print(); void execute(void()); int main() { execute(print); // sends address of print return 0; } void print() { printf("Hello!"); } void execute(void f()) // receive address of print { f(); } vs #include <stdio.h> void print(); void execute(void (*f)()); int main() { execute(&print); // sends address of print return 0; } void print() { printf("Hello!"); } void execute(void (*f)()) // receive address of print { f(); } I'll have to test it out as well. How many entities do you have? Are you expecting CSG to call this because those won't.
  14. Strange that it would even get called at all without passing the actual address of the function in with the &.
  15. @hank that would be for Lua not C++ like he's using.
  16. I can't help but feel like you got ripped off with paying $2k for that model. The thing looks deformed in certain areas and the animations don't even seem that high of quality. Tim could have done a better job and would have probably been cheaper. In fact you might want to talk to him about our DA Gavin character to see if he'd be interested in selling it to you and adding/tweaking some animations for it. Could possibly add another high quality character really quickly for fairly cheap I would imagine. Not to put words into Tim's mouth but it might pay to ask him.
  17. It has to be an axe to chop trees. So craft an axe (see tooltip in crafting menu), right click it in your inventory (should show up on your char) and then click a tree. There is a bug around right clicking equippable things (if you have something equipped already and then right click another thing). Just keep right clicking until you see the axe in your hand and then click a tree. I think we will look into intro tutorials to craft an axe and a fire to get the feel for the game. Once you get those things the rest should flow.
  18. What happens if you actually set the move variable in SetInput()? I might be remembering the old way of how this worked. In one version of LE they were separate. I haven't used the controller in 4 months or so in this version of LE so I don't recall.
  19. My memory is that SetInput() is for the rotation of the character controller which is a separate rotation than the model itself. So I would think player:GetRotation() is getting the model rotation and not the physics character controller rotation. I assume your character goes where you want it to direction wise, which would validate that. Then question I suppose is how to get the character controllers rotation value (but I guess you already have that with that variable right).
  20. What if you set a variable for that and always call SetInput() with the variable vs calling it only when keys are hit.
  21. I'm confused a little by this paragraph. If DLC's work really really well then why wouldn't you want to spend a large chunk of your time doing it? I mean if it's that good and you don't seem to be needing to charge for LE updates then why wouldn't it warrant your time? You make money 2 ways it seems, engine sales and DLC's. Engine sales is pretty much set in motion. You spend 50% of your time doing tweaks/additions and the rest on DLC content. Why is that a bad business model that you don't want to do?
  22. I question if I should give thoughts on the structure as I don't think you generally care about that but I can't help myself. Those sections in the UpdateWorld() would be best to be their own functions for readability segregation of duties. Also the massive nesting you have would be a lot easier to read if they were inverted pre-conditions at the top of the function. ie: if entity == extra then return end if entity.script == nil then return end etc... The conditions are much more self contained vs building on each other and also trying to match up end's with if's if someone was to edit the code later. You break out UpdateMuzzleFlash() but not search for target? Why is UpdateMuzzleFlash() special to get it's own function but not search for target? Again, these are just readability and maintainability tips that can make things easier on the users/and even you, when we start diving into these scripts.
  23. Yes, C++ hasn't been given much love these days it seems, but to answer your question, yes you can do what you want in Lua except, the multiplayer part. You'll need to get into C++ for that. at this time. If you find a Lua networking library you may be able to load that from Lua. I generally just use C++.
  24. If you look at this chart you'll see why (my guess). Prop and character collides (which is why you can still walk around), but LineOfSight and Prop do not cause a collision. The enemy NPC is probably doing a pick from it's position to yours with the LineOfSight collision type on it's ray, which doesn't collide with Prop types so it saw right through your model and to you. http://www.leadwerks.com/werkspace/page/api-reference/_/command-reference/collision-r778
  25. What do you have as the collision type for you level model? I would guess a line of sight pick is done in the script? (I don't have it), so that may be it?
×
×
  • Create New...