[Beta] Realistic Bullet Holes

Started by Sebastian, Oct 16, 2020, 02:30 PM

Previous topic - Next topic

Sebastian

https://www.youtube.com/watch?v=WixAU9OWt8w

Sorry for being late, but I've faced a surprise which is just amazing!
The Bullet Holes I told you about, won't be just local, but synced on everybody's screen !!
What ?? Yes!  And all just by client-side. (no data is sent to server)

(onPlayerShoot is called for everybody, not just for the local player)

I've set a limit for bullet holes, as we don't want to use too many resources.
(even if I'm not sure how hard will this hit some low-end pc)
So, if you face lag when playing alongside other players, reply to this post with your pc details, and according to the replies I get, I will try to find a way around to fix it.



How does it work ?
Well, it creates a sprite on the hit position, in client side.
With help from habi, sprites are rotated to be facing the player in the moment of shooting, so they won't look like ugly dots around.
Every player has a limit of 10 bullet holes that can create, so once the limit is touched, the first one created will be removed, and so on.

Sprites won't be removed, because:
Quote from: MEGAMIND on Oct 14, 2020, 06:24 AMSuggestion : Donot let the holes fade away, it will bring more realism,  if anyone passes by he/she may see that someone here fought here before

But, as I said, if some players will start facing lag using this script, then I will rethink it and solve it out.
Meanwhile, big thanks goes to @habi for his math skills which I Iack alot !



That's all I guess, so I will just post the code which you need to use CLIENT-SIDE
Also, better save the "hole.png" and place it in server/store/sprites


 TOP
const MAX_PLAYERS = 100;
llplayer <- World.FindLocalPlayer();

/* per player */
const MAX_HOLES = 10; // -1 for never removing holes, 0 for turning off the effect

local bulletTable = array( MAX_PLAYERS ),
holes = array( MAX_PLAYERS ),
last_hole_picked = array( MAX_PLAYERS );

bulletTable[ llplayer.ID ] = {};
holes[ llplayer.ID ] = 0;
last_hole_picked[ llplayer.ID ] = 0;

class leHole
{
    inst = null;
    ID = null;
}

function Player::PlayerShoot( player, weapon, hitEntity, hitPosition )
{
    if( hitEntity && hitEntity.Type == OBJ_BUILDING )
    {
CreateBulletHole( player, hitPosition );
    }
}

function CreateBulletHole( player, pos )
{
local ppos = player.Position;
if( MAX_HOLES == 0 ) return 0;
else if( !bulletTable[ player.ID ] )
{
// this means the 'player' was not registered by this client, yet
bulletTable[ player.ID ] = null;
bulletTable[ player.ID ] = {};
holes[ player.ID ] = 0;
last_hole_picked[ player.ID ] = 0;
}

local   hole,
id = holes[ player.ID ],
angle = atan2( pos.X - ppos.X, pos.Y - ppos.Y );

if( MAX_HOLES != -1 && holes[ player.ID ] == MAX_HOLES )
{
if( bulletTable[ player.ID ].rawin( last_hole_picked[ player.ID ] ) )
{
id = last_hole_picked[ player.ID ];
local lhp = id + 1;

hole = bulletTable[ player.ID ].rawget( id );
hole.inst = null;
bulletTable[ player.ID ].rawdelete( id );
holes[ player.ID ]--;

if( last_hole_picked[ player.ID ] == MAX_HOLES-1 ) lhp = 0;

last_hole_picked[ player.ID ] = lhp;
}
}

bulletTable[ player.ID ].rawset( id, leHole() );
hole = bulletTable[ player.ID ].rawget( id );
hole.ID = id;

hole.inst = GUISprite( "hole.png", VectorScreen( 0, 0 ) );
hole.inst.Alpha = 90;

hole.inst.AddFlags( GUI_FLAG_3D_ENTITY );
hole.inst.Set3DTransform( Vector( pos.X, pos.Y, pos.Z ),  Vector( -PI/2, 0, -angle ), Vector( 0.35, 0.35, 0.0 ) );
fixsprite( hole.inst );
centersprite( hole.inst );
holes[ player.ID ]++;
}

@habi 's magic
// habi's magic
function move( pos, distance, angle )
{
local newx = pos.X - sin( angle ) * distance,
newy = pos.Y + cos( angle ) * distance;
return Vector( newx, newy, pos.Z ); //assuming z more or less same.
}

function move2( pos, pangle, dis, angle )
{
return move( pos, dis, pangle + angle )
}
function fixsprite( sp )
{
local x = sp.Position3D,
rot = sp.Rotation3D,
size = sp.Size3D, //(pos,pangle,dis,angle)
newPos = move2( x, rot.Z, 1, PI );

sp.Position3D = newPos;
}
function centersprite( sp )
{
local x = sp.Position3D,
rot = sp.Rotation3D,
size = sp.Size3D, //(pos,pangle,dis,angle)
newPos = move2( x, rot.Z, size.X / 2, PI / 2 );

newPos.Z += 1.15;
sp.Position3D = newPos;
}

PS: If you find bugs, let me know!

Inferno

Viva la VU
VFS Developer
VCCNR Administrator

habi

it is a very cool feature.

You have to download the client side script, put it in your store folder and go ingame to see the beauty of it..

the beauty of the bullet holes..





Sebastian

Quote from: habi on Oct 17, 2020, 12:45 AMit is very cool feature

Also customizable,  which makes it funny,  but you need to play with the script a bit.
You can get different holes' sprite for different types of weapons,  or personalized for different teams (red holes for the red team,  blue for the blue team,  etc)

NicusorN5

Ery nice. Never thought this was ever possible in VCMP. (I didn't even think about implementing anything like that in VCMP).


ressam


Luis_Labarca

My server RP
IP: 51.222.28.159:8194