Jump to content

TylerH

Members
  • Posts

    525
  • Joined

  • Last visited

Everything posted by TylerH

  1. This hard coded state based logic and animation is starting to seem like the wrong idea. How exactly should you handle the logic of weapons? For example, going from Idle to Moving, Firing, Reloading, Zooming (iron sights), etc. Right now I use a large combination of weapon:SetState, weapon:SetAnimation, Get forms of those, etc. Then the weapon's update loop just plays the current animation (which defaults to Idle if nothing is set). This is the DRAFT DRAFT! pre-pre-pre-alpha version of wepaon.lua and the first weapon inheriting it gold_xix. Just note that the functionality you see in the videos and such was implemented using if statements and hackish stuff in the render loop of the fps script. I am porting over to the actual class-based weapon setup, and so far only have states and animation working, with the functionality already more powerful, as you can see from the code: weapon.lua dofile("scripts/utilities.lua") -- Defaults -- States WEAPON_IDLE = 0 WEAPON_TAKE_OUT = 1 WEAPON_PUT_AWAY = 2 WEAPON_FIRE = 3 WEAPON_RELOAD = 4 WEAPON_ZOOM_IDLE = 5 WEAPON_ZOOM_FIRE = 6 WEAPON_TO_ZOOM = 7 WEAPON_TO_NORMAL = 8 WEAPON_MOVING = 9 WEAPON_ZOOM_MOVING = 10 -- Globals WEAPON_SCALE = 0.6 -- Global scale shared by all weapons. Gun specific scaling is multiplied by this factor. It allows guns of different scales to appear similarly sized. -- Variables firstweapon=nil lastweapon=nil -- Weapons Table weapons={} function CreateWeapon( weapon_table ) local weapon = {} -- Sub Tables weapon.Animations = { } -- Table containing all animations weapon.Sounds = { } -- Table containing all sounds weapon.Effects = { } -- Table containing all effects (emitter, muzzle flash, brass, etc.) weapon.Attachments = { } -- Table containing attachments (ironsights, scopes, etc.) -- Properties weapon.AnimationBlending = 0.5 weapon.SwayScale = 0 -- X Axis Movement weapon.BobScale = 0 -- Y Axis Movement weapon.Zoomed = false weapon.Moving = false weapon.AutoReload = false -- Gun will automatically go to reload state if you try to fire with an empty clip -- Sound weapon.Volume = 1.0 weapon.Pitch = 1.0 -- Animation weapon.AnimationStartTime = AppTime() weapon.CurrentAnimation = "" weapon.CurrentAnimationFrame = 0 weapon.Animating = false -- Primary weapon.Primary = { } weapon.Primary.ClipSize = 1 -- Number of rounds in the clip weapon.Primary.Clip = 1 -- Current number of rounds in the clip weapon.Primary.Ammo = 1 -- Current total ammo (not including current clip) weapon.Primary.Damage = 0 -- Damage done per round weapon.Primary.ShotCount = 0 -- Bullets ejected per round weapon.Primary.Cone = 0 -- Spread cone (X,Y) weapon.Primary.Delay = 0 -- Time between current shot and next shot weapon.Primary.NextFire = AppTime() -- Time next shot can be fired -- Secondary weapon.Secondary = { } weapon.Secondary.ClipSize = 0 weapon.Secondary.Clip = 0 weapon.Secondary.Ammo = 0 weapon.Secondary.Damage = 0 weapon.Secondary.ShotCount = 0 weapon.Secondary.Cone = 0 weapon.Secondary.Delay = 0 weapon.Secondary.NextFire = AppTime() -- Finite State Logic weapon.State = 0 -- Weapons's current logic state -- World/View Models weapon.WorldModel = nil -- World View Model weapon.ViewModel = LoadMesh(weapon_table.ViewModel) -- First Person View Model weapon.ViewModel:SetParent(fw.main.camera,0) local vwep_offset, vwep_scale = weapon_table.Offset, weapon_table.Scale weapon.ViewModel:SetPosition(Vec3(-0.01*WEAPON_SCALE,-0.005*WEAPON_SCALE,0.05*WEAPON_SCALE),0) weapon.ViewModel:SetScale(Vec3(0.04*WEAPON_SCALE,0.04*WEAPON_SCALE,0.04*WEAPON_SCALE)) weapon.ViewModel:SetShadowMode(0,1) AppLog("We loaded and positioned the view model...") -- Future AABB Random Culling Fix... --vwep.localaabb.x0=-3 --vwep.localaabb.x1=3 --vwep.localaabb.y0=-3 --vwep.localaabb.y1=3 --vwep.localaabb.z0=-3 --vwep.localaabb.z1=3 --vwep:UpdateAABB() -- Positioning / Offsets weapon.Offset = weapon.ViewModel.position:Copy() local gundisplayposition = weapon.ViewModel:GetPosition() local positionentity = FindChild(weapon.ViewModel,"FIRESPOT") or weapon.ViewModel -- Entity used for firespot location local displayposition = EntityPosition(positionentity) -- Muzzleflash weapon.Effects.MuzzleFlash = CreatePointLight(3) weapon.Effects.MuzzleFlash:SetParent( weapon.ViewModel ) local muzzleflash_color = weapon_table.muzzleflash_color or Vec4(1,0.6,0.0,1.0) weapon.Effects.MuzzleFlash:SetColor(muzzleflash_color) weapon.Effects.MuzzleFlash:SetPosition( displayposition ) weapon.Effects.MuzzleFlash:SetShadowMode(0) weapon.Effects.MuzzleFlash:Hide() function weapon:Update() --[[-- Idle State if (self:IsIdle()) then if (self:IsZoomed()) then self:LoopAnimation("WEAPON_ZOOM_IDLE") else if (self.IsMoving()) then self:LoopAnimation("WEAPON_MOVE") else self:LoopAnimation("WEAPON_IDLE") end end -- Fire State elseif (self:IsFiring()) then -- Zoom Fire State if (self:IsZoomed()) then self:SetAnimating(true) self:PlayAnimation("WEAPON_ZOOM_FIRE") -- Normal Fire State else self:SetAnimating(true) self:PlayAnimation("WEAPON_FIRE") end if (not self:IsAnimating()) then self:SetState(WEAPON_IDLE) end -- No State? (Idle) else self:LoopAnimation("WEAPON_IDLE") end]]-- -- State Correction if (self:IsFiring() and not self.Animating) then self:SetState(WEAPON_IDLE) self:SetAnimation("WEAPON_IDLE") end self:PlayAnimation(self.CurrentAnimation) self.ViewModel:SetPosition(self.Offset:Copy()) self:UpdateSounds() end function weapon:Think() -- This can be used for AI, etc. Implement it if you want end -- Animation function weapon:AddAnimation(name,startframe,endframe,speedmodifier,oneshot) self.Animations[name] = {Name = name, StartFrame = startframe, EndFrame = endframe, Length = (endframe-startframe), Modifier = speedmodifier, OneShot = oneshot or false, Running = false} end --[[function weapon:LoopAnimation(animation) local time = ((AppTime() - self.AnimationStartTime) / 100.0) local currentanim = self.Animations[animation] self.CurrentAnimationFrame = ((time * currentanim.Modifier * HOST_TIMESCALE) % currentanim.Length) + currentanim.StartFrame if (self.CurrentAnimationFrame < currentanim.StartFrame) then self.CurrentAnimationFrame = currentanim.StartFrame end if (self.CurrentAnimationFrame > currentanim.EndFrame) then self.CurrentAnimationFrame = currentanim.EndFrame end self.ViewModel:Animate(self.CurrentAnimationFrame, self.AnimationBlending, 0, 1) end]] function weapon:SetAnimation(animation) self.AnimationStartTime = AppTime() self.CurrentAnimation = animation self.Animating = true end function weapon:PlayAnimation(animation) if (not self.Animating) then return end if (animation == nil or animation == "") then return end local time = (AppTime() - self.AnimationStartTime) / 100.0 local currentanim = self.Animations[animation] currentanim.Running = true if (not self.Animating) then currentanim.Running = false end self.CurrentAnimationFrame = (time * currentanim.Modifier * HOST_TIMESCALE) % currentanim.Length + currentanim.StartFrame if (self.CurrentAnimationFrame < currentanim.StartFrame) then self.CurrentAnimationFrame = currentanim.StartFrame end if (self.CurrentAnimationFrame > currentanim.EndFrame) then self.CurrentAnimationFrame = currentanim.EndFrame end self.ViewModel:Animate(self.CurrentAnimationFrame, self.AnimationBlending, 0, 1) if ((self.CurrentAnimationFrame > currentanim.EndFrame-0.5 and currentanim.OneShot) or currentanim.Running == false) then self.Animating = false currentanim.Running = false end end -- Sound function weapon:AddSound(name,soundfile,frame) local sound = LoadSound(soundfile) local sound_table = {Name = name, Frame = frame, Sound = sound, Source = CreateSource(sound)} local Weapon = self function sound_table:Update() self.Source:SetVolume(Weapon.Volume) self.Source:SetPitch(Weapon.Pitch) end table.insert(self.Sounds,sound_table) end function weapon:UpdateSounds() for k,v in pairs(self.Sounds) do if (v.Frame == self.CurrentFrame) then v.Source:Play() v:Update() end end end -- States function weapon:GetState() return self.State end function weapon:SetState(state) self.State = state end function weapon:IsIdle() return self.State == WEAPON_IDLE or self.State == WEAPON_ZOOM_IDLE end function weapon:IsFiring() return self.State == WEAPON_FIRE end function weapon:IsReloading() return self.State == WEAPON_RELOAD end function weapon:IsZoomed() return self.State == WEAPON_ZOOM_IDLE or self.State == WEAPON_ZOOM_FIRE or self.Zoomed end function weapon:IsEmpty() return self:IsPrimaryClipEmpty() end function weapon:IsAnimating() return self.Animating end function weapon:IsMoving() return ((KeyDown(KEY_W) - KeyDown(KEY_S)) ~= 0) or ((KeyDown(KEY_A) - KeyDown(KEY_D)) ~= 0) end function weapon:SetAnimating(anim) self.Animating = anim end -- Weapon Functionality -- Reload function weapon:Reload() if (not self:IsIdle()) then return end self:SetState(WEAPON_RELOAD) end -- Primary Fire Mode function weapon:GetPrimaryClip() return self.Primary.Clip end function weapon:GetPrimaryClipSize() return self.Primary.ClipSize end function weapon:GetPrimaryAmmo() return self.Primary.Ammo end function weapon:IsPrimaryClipEmpty() return self.Primary.Clip <= 0 end function weapon:CanPrimaryFire() return (AppTime() >= self:GetNextPrimaryFire()) and (self:IsIdle() or self.IsMoving()) and (not self:IsPrimaryClipEmpty()) end function weapon:SetNextPrimaryFire(time) self.Primary.NextFire = time end function weapon:GetNextPrimaryFire() return self.Primary.NextFire end function weapon:TakePrimaryAmmo(num) self.Primary.Clip = self.Primary.Clip - num end function weapon:PrimaryFire() if (not self:CanPrimaryFire()) then return end -- We can not perform a primary fire self:SetNextPrimaryFire(AppTime() + self.Primary.Delay) self:SetNextSecondaryFire(AppTime() + self.Secondary.Delay) self:SetState(WEAPON_FIRE) self:SetAnimation("WEAPON_FIRE") end -- Secondary Fire Mode function weapon:GetSecondaryClip() return self.Secondary.Clip end function weapon:GetSecondaryClipSize() return self.Secondary.ClipSize end function weapon:GetSecondaryAmmo() return self.Secondary.Ammo end function weapon:IsSecondaryClipEmpty() return self.Secondary.Clip <= 0 end function weapon:CanSecondaryFire() return (AppTime() >= self:GetNextSecondaryFire()) and (self:IsIdle()) and (not self:IsSecondaryClipEmpty()) end function weapon:SetNextSecondaryFire(time) self.Secondary.NextFire = time end function weapon:GetNextSecondaryFire() return self.Secondary.NextFire end function weapon:TakeSecondaryAmmo(num) self.Secondary.Clip = self.Secondary.Clip - num end function weapon:SecondaryFire() if (not self:CanSecondaryFire()) then return end -- We can not perform a secondary fire self:SetNextPrimaryFire(AppTime() + self.Primary.Delay) self:SetNextSecondaryFire(AppTime() + self.Secondary.Delay) end -- Weapons Table Hierarchy if lastweapon==nil then firstweapon=weapon lastweapon=weapon else lastweapon.next=weapon weapon.prev=lastweapon end weapons[weapon]=weapon function weapon:Free() weapons[self]=nil end -- All weapons created from CreateWeapon inherit the base functionality implemented in this file weapon.Base = weapon return weapon end gold xix: dofile("scripts/classes/weapon.lua") GoldXIX = { } GoldXIX_WeaponTable = { ViewModel = "abstract::HUD.gmf", Offset = Vec3(-0.01,-0.005,0.05), Scale = Vec3(0.04,0.04,0.04) } GoldXIX = CreateWeapon(GoldXIX_WeaponTable) -- Animations GoldXIX:AddAnimation("WEAPON_IDLE", 277.0, 302.0, 1.0) GoldXIX:AddAnimation("WEAPON_ZOOM_IDLE", 212.0, 238.0, 1.0) GoldXIX:AddAnimation("WEAPON_MOVE", 304.0, 326.0, 2.0) GoldXIX:AddAnimation("WEAPON_FIRE", 62.0, 74.0, 3.0, true) GoldXIX:AddAnimation("WEAPON_ZOOM_FIRE", 262.0, 274.0, 3.0, true) GoldXIX:SetAnimation("WEAPON_IDLE") GoldXIX:SetState(WEAPON_IDLE)
  2. There is a refraction shader, except it causes your model to not be affected by light and must be rendered in the foreground world.
  3. Is there still a way to do sprites in Leadwerks? Or maybe a simple one-shot emitter could do the trick
  4. Here is an image with some generalized "important" bone placement. Feel free to use as many of the bones in the limit as you want to get good animation or whatever. The bones should be named in all caps, just for ease of code.
  5. TylerH

    send message

    SendMessage is a native BMX method exposed to Lua for TEntity types and derivatives.
  6. TylerH

    send message

    You can use that as well. I just prefer the OO approach when possible
  7. If you give FRAPs a higher priority than your System Idle Process you get higher FPS. I run FRAPs on the 2nd two cores of my CPU only so it doesn't affect Leadwerks running in the first and Newton running in the 1st and possibly? second.
  8. TylerH

    send message

    It will get fired no matter where you sent the message from. SendEntityMessage in C/BMX, model:SendMessage() in Lua.
  9. Some nice improvements: I switched from the velocity model I took from Josh's original implementation: nextpos = currentpos + velocity/60.0 to my own based on one-dimensional kinematics: -- This code is in the bullet:Update() function called every frame (no FPS impact) -- HOST_TIMESCALE is 1.0 for normal, 0.5 for half time bullettime, etc. -- bullet.gravity.y = -9.81 (m/s) -- bullet.mass = 0.0062 (9mm FMJ in KG) [Thanks to knowledgegranted] local delta_time = (AppTime() - bullet.starttime)/1000.0 * HOST_TIMESCALE nextpos.x = bullet.origin.x + (bullet.original_velocity.x * delta_time) nextpos.y = bullet.origin.y + (bullet.original_velocity.y * delta_time) + (0.5*bullet.gravity.y*bullet.mass*delta_time*delta_time/60.0) nextpos.z = bullet.origin.z + (bullet.original_velocity.z * delta_time) Bullet time is now implemented via HOST_TIMESCALE. I basically multiply all of the following by it (or some function of it): Bullet Velocity Move/Strafe/Jump Velocity Sound Pitch Animation Speed New video is up with a demo of bullet time (audio is stuff because my volume was too high ) Reminding everyone this is all debug, and I am aware of many of the things that need polished, like the empty chamber anim is off, muzzleflash comes too soon, locker door fail, etc.
  10. This seems reasonable.
  11. It may be messing up if that is a mesh and not a model. Try using it on the parent of mesh1. (Passing mesh1.parent or whatever to the TForm... functions)
  12. File Name: Debug Callstack/Trace/Globals Library File Submitter: TylerH File Submitted: 09 Dec 2009 File Category: Lua Scripts This is a simple add-on library I coded based on the Lua debug library and some example code in the Programming In Lua book. It features: Trace Traceback PrintGlobals LogGlobals Trace will run a trace from the point in code debug.Trace() is called up to the top of the stack. This is basically a call stack, and produces output like so: Trace: 1: Line 26 "Trace" Scripts/debug.lua 2: Line 40 "GetImpactDecal" scripts/classes/bullet.lua 3: Line 151 "UpdateBullets" scripts/classes/bullet.lua 4: Line 388 "N/A" [string "dofile("Scripts/constants/collision_const.l..."] It will even trace into C functions, area of code with no function (i.e. the "N/A" you see), and through multiple files (compiled bytecode or normal). Traceback is simply Lua's default implementation, except I print it out and log it in AppLog. PrintGlobals will print the key names of everything in the _G table, this includes all of the entities, Leadwerks functions, things you don't know of, etc. LogGlobals does the same as print globals, but prints to the AppLog and not the Console. To use this simply call dofile("Scripts/debug.lua") in any of your Lua files (be it entity, game, etc.) It is rather useful for tracing where errors occur more quickly than Lua error messages do. Click here to download this file
  13. I assume you want it local relative the mesh1 entity?
  14. Thanks for the comments everyone. An AVI-raped video is now up. OR One of the bugs you will notice is that the gun disappears. In fact, it disappears when it is aligned to any world axis exactly (X,Y,or Z). I am currently searching to see why this is.
  15. Very nice. Once you release the source, if you didn't mind, I would love to add Catmull-Rom and Quaternion support to it. We could get a nice Cinematic toolkit together with this. Great project Rick!
  16. I will upload a screenshot from Model Viewer with the Gold XIX weapon I have been using. I will have bones and hierarchy visible, and Photoshop some labels to the "important" bones. I am at school right now, it is 10 AM EST, I get home and can have the screenshot up around 4 - 4:30 PM EST.
  17. Sure, I can always use more weapons. The only thing I would really ask is that you make a bone called "FIRESPOT" where the bullet should leave the muzzle. This library is oriented towards artists who want to get their weapons working quickly or anyone who just wants some fun guns working with lots of features.
  18. I have animation working for both looped and one-shot animations in my Weaponwerks Library. For looping: frame = (AppTime()/100.0) % (endframe-startframe) + startframe For one shot animations: animstarttime = AppTime() -- Call this once when you first start the animation ... frame = ((AppTime()-animstarttime)/100.0) % (endframe-startframe) + startframe Then simply call model:Animate(frame,blend,0,1) In cases where you need to speed-up or slowdown the application, you multiply the value to the left of the % (modulus) sign by a speed factor. 1.0 plays at default (has no effect), 0.5 halves the speed, 2.0 doubles the speed, etc. If you need to compare the current frame (which is a floating point number) to a given frame (which is an integer) (i.e. I do this to check for sounds I have set to play at certain animation frames), round it to a whole frame using either math.ceil or math.floor (or code up a function like I did to ceil if the decimal place is .5 or higher and floor is less than .5)
  19. Right now I am using weapons done by Errant AI at the Game Creators. He is the same guy who made the AK74 Josh uses and calls an "SMG". I like the way he sets up his models with a FIRESPOT bone, BULLET bone, MAGAZINE bone, SLIDE Bone, etc. making it easy to setup any of his guns for use. The video was shot in FRAPs (2.16 GB AVI file), I converted it to 287 MB .mp4 with no loss of quality, stayed up for 2 hours to watch it upload on YouTube, then it failed because YouTube doesn't support the format. I will have to just compress the AVI itself and upload. That also gives me time to port more of the functionality into its own classes instead of a bunch of if...then...elseif...elseif...else...end statements.
  20. I believe Nilium said you can make some changes so the main program CAN use Lua tables...
  21. TylerH

    FAQ LUA

    Just curious: Local position is global position if it has no parent? Else local position is relative parent?
  22. TylerH

    Videos

    I needed better sound support in the projects I am working on, it was piss easy to integrate FMOD, and it even boosted my FPS 3-4 in situations where I was using lots of sounds compared to Leadwerks with OpenAL.
  23. Key / Legend: - Completed Feature - Feature is on hold / not started - Feature is in progress - Feature is in concpet / requires feedback and suggestions - Feature is suffering from one or more bugs - Feature is waiting on one or more art pieces - Feature is implemented in a Lua Game Script, but needs to be moved over to the class script - Feature depends on the WIP Mathwerks Lua Library Feature Tree: Weaponwerks - Bullet Class - Ray Cast via Line Pick - Hit Detection - Hit Filtering - [*]Physical Properties - Origin - Position - Distance - Maximum Distance - Velocity - Acceleration - , Gravity - Wind - User-Defined Impulses - [*]Mass - [*]Falloff - [*]Force - [*]Inertia - [*]Impulse - , [*]Bullet Properties - Damage - Minimal Damage - Falloff Rate - Impact Force - Damage Type - Bullet Type - Bullet Add-Ons - Armor Piercing - Incendiary - Generic Tracer - Colored Tracer - Glow Trail - [*]Dynamic Impact Decal System - Per-Entity Impact Type - Per-Surface/Per-Material Impact Type - [*]Impact Emitter - [*]Weapon Class - , Weapon Type - Fire Types - Single Shot - Shotgun - Rapid Fire - Plasma - [*]Fire Modes - Primary - Secondary - Attachment - Melee - Tactical - [*]Weapon Properties - Bullet Type - Recoil - Condition - [*]Weapon Attachments - Laser Sight Akimbo Iron Sight Scoped Sight Thermal Scope Night Scope Holographic Sight Flashlight Grip Extended Magazine Bayonet / Tactical Knife Silencer Grenade Launcher Rapid Fire Rate Hair Trigger Box Magazine [*]Dynamic Weapon Wearing System - Wear and Tear over time (Non-Use) Wear from incoming damage Wear from use Jamming Slow Reload Misfires [*]Finite State Machine Logic - States <-> Animation Links - States - Idle State - Fire State - Reload State - To Zoom Idle State - To Empty Idle State - [*]Zoom Idle State - Zoom Fire State - Reload State - To Idle State - To Empty Idle State - [*]Fire State - To Idle State - To Empty Idle State - Reload State - [*]Zoom Fire State - To Zoom Idle - Reload State - [*]Reload State - Tactical Reload State (Current Ammo >= 0.5*ClipSize) - Example: Clip out, Clip in [*]Slide Reload State (Current Ammo > 0, Current Ammo < 0.5*ClipSize) - Example: Clip out, Clip in, Slide Clicks Forward [*]Full Reload State (Current Ammo == 0) - Example: Clip out, Clip in, Manual Full Slide **** [*]To Idle State - [*]To Zoom Idle State - [*]Empty Idle State - Fire State (Dry) - Reload State - [*]Animation Library - Table of possible animations - Names - Frame Range - Speed Modifier - [*]Sound Library - Table of possible sounds - Animation links - Play at Frame 'X' - [*]Ammo Class - [*]Hit Info Class - [*]Damage Info Class - [*]Unsorted / Feature Creep Ideas Bullet Time - Primary Fire / Secondary Fire switches to melee if out of ammo Clip SystemPenalized for reloading non-empty clips (i.e. your bullet count is organized per clip. You have a clip with 5 and a full clip. You reload when you have half a clip left, and you now have the clip of 5. This is how it would work in real life...) [TODO: Expanding this post over the lifespan of this library] Videos: Bugs: (SOLVED) Gun disappears when aligned along the X,Y,Z World Axes Cause: AABB is not aligned properly Fix: Set mesh.localaabb manually Will be Fixed: Next Leadwerks update (Josh is adding access to localaabb in Lua script)
×
×
  • Create New...