Hi guys!
This is one of my earlier posts on the new forums, which shouldn't be the case as the 3rd person to have registered, but I have been a bit tied up with my existing projects.
Anyways, I have set out on a project to setup a nice framework (entirely in Lua) to handle various bullets, weapons, damage types, etc. so that we can start to gather an arsenal of scripted weapons that community members can use to try out some combat dynamics in their own games.
I am taking the first step here in having added damage, inertia, and falloff to the bullet class Josh has included with the Editor:
dofile("scripts/utilities.lua")
-- Defaults
BULLET_MAXRANGE = 500 -- Max Range for bullet movement (Def. 500 meters)
BULLET_MINDAMAGE = 5 -- Minimal damage a bullet can do. A bullet is guranteed to do this much damage (Def. 5 health units)
BULLET_DAMAGE = 15 -- Damage that the bullet would do if shot at point blank range with no falloff dampening (Def. 15 health units)
BULLET_FALLOFFBASE = 0.85 -- Range from 0 to 1, 0 being instantly to 2 being max range, for the bullet to lose damage. Values higher than 1 give the bullet more
-- damage the farther away it gets.
BULLET_FALLOFF = 500 -- The distance falloff (Def. 500 meters)
BULLET_SPREAD = 0.0 -- The spread of the "pellets" of a single bullet (Def. 0 meters)
BULLET_INERTIA = 50.0 -- The intertia of the bullet, the amount of force transferred to the target (Def. 50 joules)
-- Variables
firstbullet=nil
lastbullet=nil
-- Bullet Table
bullets={}
-- Materials
material_impactdust=LoadMaterial("abstract::dust.mat")
-- Function to create a bullet at the given position with the given velocity
function CreateBullet( position, velocity )
local bullet = {}
bullet.position = position
bullet.velocity = velocity
bullet.origin = position:Copy()
bullet.minimal_damage = BULLET_MINDAMAGE
bullet.initialdamage = BULLET_DAMAGE
bullet.damage = BULLET_DAMAGE
bullet.falloff_base = BULLET_FALLOFFBASE
bullet.falloff_distance = BULLET_FALLOFF
bullet.inertia = BULLET_INERTIA
function bullet:Update()
end
if lastbullet==nil then
firstbullet=bullet
lastbullet=bullet
else
lastbullet.next=bullet
bullet.prev=lastbullet
end
bullets[bullet]=bullet
function bullet:Free()
bullets[self]=nil
end
return bullet
end
-- Called per frame to update the state of all bullets in the scene
function UpdateBullets()
local bullet
local pick
local nextpos = Vec3(0)
local emitter,model
local bulletforce
local distance
for bullet,nothing in pairs(bullets) do
-- Get the distance the bullet has traveled
distance = PointDistance(bullet.origin,bullet.position)
-- Our bullet has gone too far...
if distance > BULLET_MAXRANGE then
bullet:Free()
end
-- Determine where the bullet will be next frame
nextpos.x = bullet.position.x + bullet.velocity.x / 60.0
nextpos.y = bullet.position.y + bullet.velocity.y / 60.0
nextpos.z = bullet.position.z + bullet.velocity.z / 60.0
-- Perform a pick between the current bullet position and the next bullet position to see if we have hit anything
pick = LinePick( bullet.position, nextpos )
-- Set position to the next position
bullet.position.x = nextpos.x
bullet.position.y = nextpos.y
bullet.position.z = nextpos.z
-- Update the damage of the bullet for falloff
bullet.damage = math.max(bullet.initialdamage * bullet.falloff_base ^ (distance / bullet.falloff_distance), bullet.minimal_damage)
-- Check if the pick succeeded
if pick~=nil then
-- Create a cust impact emitter
SetWorld(fw.transparency.world)
emitter=CreateEmitter(5,700,pick.normal,1)
emitter:SetVelocity( pick.normal )
emitter:SetRadius(0.1,0.5)
emitter:SetWaver(10)
emitter:SetColorf(0.5,0.5,0.5,0.1)
emitter:Paint(material_impactdust)
emitter:SetPosition( pick.position )
emitter:SetRotationSpeed(0.1)
bullet:Free()
SetWorld(fw.main.world)
-- If we hit a model, attempt to get it
model=GetMeshModel(pick.entity)
-- Check if the model exists
if model~=nil then
-- Calculate the direction of the bullet (Normalized velocity will have a magnitude of 1, making it a unit vector telling simply direction)
bulletforce = bullet.velocity:Normalize()
-- Not sure why this was commented out by Josh?
-- Seems like it applied some kind of ricochet ability based on normal?
--d=-Dot(pick.normal,bullet.bulletforce)
--d=math.max(0,d)
-- Calculate force (direction * intertia)
bulletforce.x = bulletforce.x * bullet.inertia-- * d
bulletforce.y = bulletforce.y * bullet.inertia-- * d
bulletforce.z = bulletforce.z * bullet.inertia-- * d
-- Apply bullet force
model:AddForceAtPoint( bulletforce, pick.position )
end
end
end
collectgarbage()
end
The project will run in two phases that, granted enough participation, occur simultaneously.
Phase 1 of this project is aimed at FUNCTIONALITY, not APPEARANCE, and should involve mostly coders.. The goal is to how weapons implemented, minus the actual models and art associated with them.
What Phase 1 is going to entail is:
Creating a basic structure to derive other things from, for example we have bullet.lua, we should strive to create a base weapon.lua, projectile.lua (Missiles, Arrows, etc.), melee.lua (Fists, Knife/Knives, Swords, etc.), and any other classes.
Adding features and weapon properties to the base structure, including: Damage, Minimal Damage, Damage Type, Bullets Per Shot, Cycle Time, Burst Shot Count, Burst Cycle Time, Fire Modes, Falloff, Melee Damage, Melee Cycle Time, Velocity, Turning Speed (guided projectiles), Explosion Force, Explosion Radius, Grenade Time, etc.
Implement a cyclable system (similar to the current UpdateBullets) that can receive and route information regarding hit info. This is a table of information from when a bullet hits an entity, mainly damage type, damage amount, etc. It is used in higher level game logic to provide the affect of weapons on the health of props and players.
Specialize from the base structure, to create pistols, machine guns, sub-machine guns, rocket launchers, mounted turrets, cross bows, sniper rifles, everything imaginable.
Phase 2 is all about the art. Models, textures, emitter particles, blood decals, muzzle flashes, scope textures, accessories, etc. for the APPEARANCE of weapons should be done during this phase. This can also extend into a Phase 3, where artists and coders work together to add full animation set support to the weapon classes, support for accessories (silencers, lasers, scopes, etc.), sounds, etc.
The goal of the project, again, is to create a set of weapons that the whole community is allowed to use for testing and development. Coders and artists wishing to participate should be aware from the start that your code/art is intended to be released free (I am assuming Creative Commons 2.0 should be an appropriate license?) for the entire community to use.
Let me know what you guys think, and if feedback is positive, we can get going more on this, and I will create a WIP Thread with checklists for all 3 phases and get this going as a full on community project.
Cheers,
Tyler