-- 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 sqrt = math.sqrt local balls = {} local thrust = 3 local controlEnt = nil local namedEmitter = { imploder = { 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 = { 6.5, 6.5, 6.5, 6.5 }, alpha = { 100, 100, 100, 100 } } } -- 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 local function getBall() for k, v in pairs( balls ) do --if k ~= controlEnt and if v.state == 'idle' then return k end end end function throw_ball_init( e ) Include( "utillib.lua" ) Include( "physlib.lua" ) Hide( e ) CollisionOff( e ) balls[ e ] = nil end local mouseClicked = false local timer = 0 local reload = 300 local pe = nil local pe_frame = 16 local pe_image = pe_image or ParticlesLoadImage( "effectbank\\particles\\imploder.dds" ) local pxp, pyp, pzp, paX, paY, paZ local width = 4 function AddParticle( ball ) if ball.frame == nil then ball.frame = 1 else -- calculate sight line between player and entity -- calculate offset to outside of entity -- place particle at reqauired position local x, y, z = GetObjectPosAng( ball.obj ) local xd, yd, zd = pxp - x, pyp - y, pzp - z local dist = sqrt( xd*xd + yd*yd + zd*zd ) local dX = width/dist local xo, yo, zo = xd*dX, yd*dX, zd*dX ParticlesSetFrames( pe, 1, ball.frame, ball.frame ) ParticlesSetLife ( pe, -1, 25, 25, 100, 0, 20) -- ParticlesSetAngle( pe, deg( ax ), deg( ay ), deg( az ) ) ParticlesSpawnParticle( pe, x + xo, y + yo, z + zo ) ball.frame = ball.frame + 1 if ball.frame > pe_frame then ball.frame = 1 end end end function throw_ball_main( e ) if controlEnt == nil then controlEnt = e if pe == nil then pe = PE_CreateNamedEmitter( 'imploder', pe_image, pe_frame ) end end local ball = balls[ e ] if ball == nil then balls[ e ] = { obj = g_Entity[ e ].obj, state = 'idle', vec = { x = 0, y = 0, z = 0 } } return elseif ball.state == 'push1' then AddParticle( ball ) SetObjectDamping( ball.obj, 0.01, 0 ) PushObject( ball.obj, 0, 0, 0 ) ball.state = 'push2' elseif ball.state == 'push2' then PushObject( ball.obj, ball.vec.x, ball.vec.y, ball.vec.z ) ball.state = 'done' AddParticle( ball ) -- register object to collision detection AddObjectCollisionCheck( ball.obj ) ball.timer = g_Time + 10000 elseif ball.state == 'done' then AddParticle( ball ) local numCols = GetObjectNumCollisions( ball.obj ) if numCols > 0 then for i = 1, numCols do local objB, x, y, z, f = GetObjectCollisionDetails( ball.obj, i ) if objB ~= nil then if f > 0.001 then local ent = P.ObjectToEntity( objB ) if ent ~= nil then PlaySound( ent, 0 ) StopSound( e, 0 ) end end end end RemoveObjectCollisionCheck( ball.obj ) end if g_Time > ball.timer then ball.state = 'idle' CollisionOff( e ) RemoveObjectCollisionCheck( ball.obj ) end end if controlEnt ~= e then return end pxp, pyp, pzp = g_PlayerPosX, g_PlayerPosY + 28, g_PlayerPosZ if GetGamePlayerStatePlayerDucking() == 1 then pyp = pyp - 18 end if g_MouseClick == 1 then if not mouseClicked then if g_Time > timer then timer = g_Time + reload mouseClicked = true local Ent = getBall() if Ent ~= nil then ball = balls[ Ent ] paX, paY, paZ = rad( g_PlayerAngX ), rad( g_PlayerAngY ), rad( g_PlayerAngZ ); local vX, vY, vZ = U.Rotate3D ( 0, 0, 1, paX, paY, paZ ) CollisionOff( Ent ) SetPosition( Ent, pxp + vX * 50, pyp + vY * 50 - 5, pzp + vZ * 50) CollisionOn( Ent ) --Show( Ent ) ball.state = 'push1' ball.vec.x = vX * thrust ball.vec.y = vY * thrust ball.vec.z = vZ * thrust end end end else mouseClicked = false end end