-- LUA Script - precede every function and global member with lowercase name of script + '_main' local U = require "scriptbank\\utillib" local P = require "scriptbank\\physlib" local rad = math.rad local deg = math.deg local abs = math.abs local atan = math.atan2 local modf = math.modf local sqrt = math.sqrt local validWeaponsList = { 'modern\\colt1911', 'modern\\uzi', 'modern\\sniperm700', 'modern\\magnum357' } local function validWeapon( name ) for _,v in pairs( validWeaponsList ) do if v == name then return true end end return false end local emitterList = {} local namedEmitter = { woodshot = { animSpd = 0, SR = 0, freq = -1, lifeMin = 0, lifeMax = 0, -- minX minY minZ maxX maxY maxZ offset = { 0, 0, 0, 0, 0, 0 }, speed = { 0, 0, 0, 0, 0, 0 }, rotate = { 0, 0 }, -- currently only Z rotate processed -- startMin startMax endMin endMax scale = { 4, 4, 4, 4 }, alpha = { 70, 90, 0, 0 } }, metalshot = { animSpd = 0, SR = 0, freq = -1, lifeMin = 0, lifeMax = 0, -- minX minY minZ maxX maxY maxZ offset = { 0, 0, 0, 0, 0, 0 }, speed = { 0, 0, 0, 0, 0, 0 }, rotate = { 0, 0 }, -- currently only Z rotate processed -- startMin startMax endMin endMax scale = { 2, 2, 2, 2 }, alpha = { 70, 90, 0, 0 } }, stoneshot = { animSpd = 0, SR = 0, freq = -1, lifeMin = 0, lifeMax = 0, -- minX minY minZ maxX maxY maxZ offset = { 0, 0, 0, 0, 0, 0 }, speed = { 0, 0, 0, 0, 0, 0 }, rotate = { 0, 0 }, -- currently only Z rotate processed -- startMin startMax endMin endMax scale = { 10, 10, 10, 10 }, alpha = { 70, 90, 0, 0 } } } -- caller must load image local function PE_CreateNamedEmitter( name, image, frames, object ) image = image or 1 -- default to smoke frames = frames or 64 local et = namedEmitter[ name ] if et == nil then return end local emitter = ParticlesGetFreeEmitter() if emitter == -1 then return end local pos, spd, scl = et.offset, et.speed, et.scale if object == nil then ParticlesAddEmitterEx( emitter, et.animSpd, et.SR, pos[1], pos[2], pos[3], pos[4], pos[5], pos[6], scl[1], scl[2], scl[3], scl[4], spd[1], spd[2], spd[3], spd[4], spd[5], spd[6], et.rotate[1], et.rotate[2], et.lifeMin, et.lifeMax, et.alpha[1], et.alpha[2], et.alpha[3], et.alpha[4], et.freq, 0, 0, image, frames ) else ParticlesAddEmitterEx( emitter, et.animSpd, et.SR, pos[1], pos[2], pos[3], pos[4], pos[5], pos[6], scl[1], scl[2], scl[3], scl[4], spd[1], spd[2], spd[3], spd[4], spd[5], spd[6], et.rotate[1], et.rotate[2], et.lifeMin, et.lifeMax, et.alpha[1], et.alpha[2], et.alpha[3], et.alpha[4], et.freq, object, 0, image, frames ) end return emitter end function bullet_holes_init(e) Include( "utillib.lua" ) Include( "physlib.lua" ) end local metalFile = metalFile or ParticlesLoadImage( "effectbank\\particles\\metalbh.dds", 10 ) local woodFile = woodFile or ParticlesLoadImage( "effectbank\\particles\\woodbh.dds", 11 ) local stoneFile = imageFile or ParticlesLoadImage( "effectbank\\particles\\stonebh2.dds", 12 ) local shotFired = false local rayX, rayY, rayZ function ObjectHit( bx, by, bz, t ) local pxp, pyp, pzp = g_PlayerPosX, g_PlayerPosY, g_PlayerPosZ local pxa, pya, pza = g_PlayerAngX, g_PlayerAngY, g_PlayerAngZ if GetGamePlayerStatePlayerDucking() == 0 then pyp = pyp + 31 else pyp = pyp + 10 end local playerObj = 0 if t > 0 then playerObj = g_Entity[ t ].obj end rayX, rayY, rayZ = U.Rotate3D ( 0, 0, 1, rad( pxa ), rad( pya ), rad( pza ) ) local obj = IntersectAll( pxp + 20 * rayX, pyp + 20 * rayY, pzp + 20 * rayZ, bx + rayX * 30, by + rayY * 30, bz + rayZ * 30 , playerObj ) local ox, oy, oz = bx - rayX / 2, by - rayY / 2, bz - rayZ / 2 if obj and obj ~= 0 then -- don't put bullet holes on active entities local e = P.ObjectToEntity( obj ) if e and g_Entity[ e ].active == 1 then return false end --PromptDuration( obj, 3000 ) -- check all around the hit point and figure out if we find the same object -- if so calculate the angles at which to position the decal local lrayX, lrayY, lrayZ = U.Rotate3D ( 1, 0, 0, rad( pxa ), rad( pya ), rad( pza ) ) local lobj = IntersectAll( pxp - lrayX, pyp, pzp - lrayZ, bx - lrayX + rayX * 30, by + rayY * 30, bz - lrayZ + rayZ * 30, playerObj ) if lobj ~= obj then return false end local lx, ly, lz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local robj = IntersectAll( pxp + lrayX, pyp, pzp + lrayZ, bx + lrayX + rayX * 30, by + rayY * 30, bz + lrayZ + rayZ * 30, playerObj ) if robj ~= obj then return false end local rx, ry, rz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local urayX, urayY, urayZ = U.Rotate3D ( 0, 1, 0, rad( pxa ), rad( pya ), rad( pza ) ) local uobj = IntersectAll( pxp, pyp + urayY, pzp, bx + rayX * 30, by + urayY + rayY * 30, bz + rayZ * 30, playerObj ) if uobj ~= obj then return false end local ux, uy, uz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local bobj = IntersectAll( pxp, pyp - urayY, pzp, bx + rayX * 30, by - urayY + rayY * 30, bz + rayZ * 30, playerObj ) if bobj ~= obj then return false end local bx, by, bz = GetIntersectCollisionX(), GetIntersectCollisionY(), GetIntersectCollisionZ() local ya = deg( atan( rx - lx, rz - lz ) ) - 90 local xa = deg( atan( abs( uy - by ), sqrt( ( ux - bx )^2 + ( uz - bz )^2 ) ) ) - 90 return true, ox, oy, oz, xa, ya, 0 end return false end function bullet_holes_main(e) local emitter = emitterList[e] if emitter == nil then emitterList[e] = { state = 'idle' } return end if emitter.state == 'idle' then if emitter.idstone ~= nil then ParticlesDeleteEmitter( emitter.idstone ) emitter.idstone = nil end if emitter.idwood ~= nil then ParticlesDeleteEmitter( emitter.idwood ) emitter.idwood = nil end if emitter.idmetal ~= nil then ParticlesDeleteEmitter( emitter.idmetal ) emitter.idmetal = nil end if validWeapon( g_PlayerGunName ) then emitter.state = 'init' end elseif emitter.state == 'init' then emitter.idstone = PE_CreateNamedEmitter( 'stoneshot', stoneFile, 16 ) ParticlesSetLife( emitter.idstone, -1, 30000, 30000, 100, 0, 1 ) emitter.idmetal = PE_CreateNamedEmitter( 'metalshot', metalFile, 64 ) ParticlesSetLife( emitter.idmetal, -1, 30000, 30000, 100, 0, 1 ) emitter.idwood = PE_CreateNamedEmitter( 'woodshot', woodFile, 64 ) ParticlesSetLife( emitter.idwood, -1, 30000, 30000, 100, 0, 1 ) emitter.state = 'ready' elseif emitter.state == 'ready' then if not validWeapon( g_PlayerGunName ) then emitter.state = 'idle' return end if g_PlayerGunFired == 1 then local bx, by, bz, m, t = GetBulletHit() if bx ~= nil then if not shotFired then shotFired = true local hit, x, y, z, xa, ya, zv = ObjectHit( bx, by, bz, t ) if hit then PromptDuration( m, 3000 ) if m == 11 then ParticlesSetAngle( emitter.idstone, xa, ya, za ) ParticlesSpawnParticle( emitter.idstone, x, y, z ) elseif m == 12 then ParticlesSetAngle( emitter.idmetal, xa, ya, za ) ParticlesSpawnParticle( emitter.idmetal, x, y, z ) elseif m == 13 then ParticlesSetAngle( emitter.idwood, xa, ya, za ) ParticlesSpawnParticle( emitter.idwood, x, y, z ) end end end -- PromptDuration( m - 10 .. ", " .. t, 3000 ) -- ParticlesSetLife( emitter.id, 1, 0, 0, 0, 0, 0 ) -- emitter.state = 'wait' else shotFired = false end end end end