793 lines
28 KiB
Plaintext
793 lines
28 KiB
Plaintext
#using scripts\codescripts\struct;
|
|
#using scripts\shared\clientfield_shared;
|
|
#using scripts\shared\util_shared;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#namespace GibClientUtils;
|
|
|
|
function autoexec main()
|
|
{
|
|
|
|
clientfield::register(
|
|
"actor",
|
|
"gib_state",
|
|
1,
|
|
(9),
|
|
"int",
|
|
&GibClientUtils::_GibHandler,
|
|
!true,
|
|
!true);
|
|
|
|
clientfield::register(
|
|
"playercorpse",
|
|
"gib_state",
|
|
1,
|
|
(9+3+3),
|
|
"int",
|
|
&GibClientUtils::_GibHandler,
|
|
!true,
|
|
!true);
|
|
|
|
gibDefinitions = struct::get_script_bundles("gibcharacterdef");
|
|
|
|
gibPieceLookup = [];
|
|
gibPieceLookup[2] = "annihilate";
|
|
gibPieceLookup[8] = "head";
|
|
gibPieceLookup[16] = "rightarm";
|
|
gibPieceLookup[32] = "leftarm";
|
|
gibPieceLookup[128] = "rightleg";
|
|
gibPieceLookup[256] = "leftleg";
|
|
|
|
processedBundles = [];
|
|
|
|
// Process each gib bundle to allow quick access to information in the future.
|
|
foreach ( definitionName, definition in gibDefinitions )
|
|
{
|
|
gibBundle = SpawnStruct();
|
|
gibBundle.gibs = [];
|
|
gibBundle.name = definitionName;
|
|
|
|
foreach ( gibPieceFlag, gibPieceName in gibPieceLookup )
|
|
{
|
|
gibStruct = SpawnStruct();
|
|
gibStruct.gibmodel = GetStructField( definition, gibPieceLookup[ gibPieceFlag ] + "_gibmodel" );
|
|
gibStruct.gibtag = GetStructField( definition, gibPieceLookup[ gibPieceFlag ] + "_gibtag" );
|
|
gibStruct.gibfx = GetStructField( definition, gibPieceLookup[ gibPieceFlag ] + "_gibfx" );
|
|
gibStruct.gibfxtag = GetStructField( definition, gibPieceLookup[ gibPieceFlag ] + "_gibeffecttag" );
|
|
gibStruct.gibdynentfx = GetStructField( definition, gibPieceLookup[ gibPieceFlag ] + "_gibdynentfx" );
|
|
gibStruct.gibsound = GetStructField( definition, gibPieceLookup[ gibPieceFlag ] + "_gibsound" );
|
|
|
|
gibBundle.gibs[ gibPieceFlag ] = gibStruct;
|
|
}
|
|
|
|
processedBundles[ definitionName ] = gibBundle;
|
|
}
|
|
|
|
// Replaces all gib character define bundles with their processed form to free unncessary script variables.
|
|
level.scriptbundles[ "gibcharacterdef" ] = processedBundles;
|
|
|
|
// Thread that handles any corpse annihilate request.
|
|
level thread _AnnihilateCorpse();
|
|
}
|
|
|
|
|
|
function private _AnnihilateCorpse()
|
|
{
|
|
while( true )
|
|
{
|
|
level waittill( "corpse_explode", localClientNum, body, origin );
|
|
|
|
if ( !util::is_mature() || util::is_gib_restricted_build() )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( IsDefined( body ) && _HasGibDef( body ) && body IsRagdoll() )
|
|
{
|
|
ClientEntGibHead( localClientNum, body );
|
|
ClientEntGibRightArm( localClientNum, body );
|
|
ClientEntGibLeftArm( localClientNum, body );
|
|
ClientEntGibRightLeg( localClientNum, body );
|
|
ClientEntGibLeftLeg( localClientNum, body );
|
|
}
|
|
|
|
// TODO(David Young 6-8-15): Human bodies are currently the only supported gibbable corpse.
|
|
// Need to add support to the gib definition to flag if a corpse can be annihilated instead.
|
|
if( IsDefined( body ) && _HasGibDef( body ) && body.archetype == "human" )
|
|
{
|
|
// Only allow human gibbing at a 50% rate.
|
|
if ( RandomInt( 100 ) >= 50 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( IsDefined( origin ) && DistanceSquared( body.origin, origin ) <= ( 120 * 120 ) )
|
|
{
|
|
// Toggle hiding the ragdoll.
|
|
body.ignoreRagdoll = true;
|
|
|
|
body _GibEntity(
|
|
localClientNum,
|
|
2 |
|
|
16 |
|
|
32 |
|
|
(128+256),
|
|
true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function private _CloneGibData( localClientNum, entity, clone )
|
|
{
|
|
clone.gib_data = SpawnStruct();
|
|
|
|
// Copy gib data.
|
|
clone.gib_data.gib_state = entity.gib_state;
|
|
clone.gib_data.gibdef = entity.gibdef;
|
|
|
|
// Copy all model data.
|
|
clone.gib_data.hatmodel = entity.hatmodel;
|
|
clone.gib_data.head = entity.head;
|
|
clone.gib_data.legdmg1 = entity.legdmg1;
|
|
clone.gib_data.legdmg2 = entity.legdmg2;
|
|
clone.gib_data.legdmg3 = entity.legdmg3;
|
|
clone.gib_data.legdmg4 = entity.legdmg4;
|
|
clone.gib_data.torsodmg1 = entity.torsodmg1;
|
|
clone.gib_data.torsodmg2 = entity.torsodmg2;
|
|
clone.gib_data.torsodmg3 = entity.torsodmg3;
|
|
clone.gib_data.torsodmg4 = entity.torsodmg4;
|
|
clone.gib_data.torsodmg5 = entity.torsodmg5;
|
|
}
|
|
|
|
function private _GetGibDef( entity )
|
|
{
|
|
if ( entity IsPlayer() || entity IsPlayerCorpse() )
|
|
{
|
|
return entity GetPlayerGibDef();
|
|
}
|
|
else if ( IsDefined( entity.gib_data ) )
|
|
{
|
|
return entity.gib_data.gibdef;
|
|
}
|
|
|
|
return entity.gibdef;
|
|
}
|
|
|
|
function private _GetGibbedState( localClientNum, entity )
|
|
{
|
|
if ( IsDefined( entity.gib_data ) && IsDefined( entity.gib_data.gib_state ) )
|
|
{
|
|
return entity.gib_data.gib_state;
|
|
}
|
|
else if ( IsDefined( entity.gib_state ) )
|
|
{
|
|
return entity.gib_state;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
function private _GetGibbedLegModel( localClientNum, entity )
|
|
{
|
|
gibState = _GetGibbedState( localClientNum, entity );
|
|
rightLegGibbed = (gibState & 128);
|
|
leftLegGibbed = (gibState & 256);
|
|
|
|
if ( rightLegGibbed && leftLegGibbed)
|
|
{
|
|
return (isdefined(entity.gib_data)?entity.gib_data.legDmg4:entity.legDmg4);
|
|
}
|
|
else if ( rightLegGibbed )
|
|
{
|
|
return (isdefined(entity.gib_data)?entity.gib_data.legDmg2:entity.legDmg2);
|
|
}
|
|
else if ( leftLegGibbed )
|
|
{
|
|
return (isdefined(entity.gib_data)?entity.gib_data.legDmg3:entity.legDmg3);
|
|
}
|
|
|
|
return (isdefined(entity.gib_data)?entity.gib_data.legDmg1:entity.legDmg1);
|
|
}
|
|
|
|
function private _GetGibExtraModel( localClientNumm, entity, gibFlag )
|
|
{
|
|
if ( gibFlag == 4 )
|
|
return (isdefined(entity.gib_data)?entity.gib_data.hatmodel:entity.hatmodel);
|
|
else if ( gibFlag == 8 )
|
|
return (isdefined(entity.gib_data)?entity.gib_data.head:entity.head);
|
|
else
|
|
AssertMsg( "Unable to find gib model." );
|
|
}
|
|
|
|
function private _GetGibbedTorsoModel( localClientNum, entity )
|
|
{
|
|
gibState = _GetGibbedState( localClientNum, entity );
|
|
rightArmGibbed = (gibState & 16);
|
|
leftArmGibbed = (gibState & 32);
|
|
|
|
if ( rightArmGibbed && leftArmGibbed )
|
|
{
|
|
return (isdefined(entity.gib_data)?entity.gib_data.torsoDmg2:entity.torsoDmg2);
|
|
|
|
// TODO(David Young 5-14-14): Currently AI's don't support both arms getting blown off.
|
|
// return GIB_TORSO_NO_ARMS_MODEL( entity );
|
|
}
|
|
else if ( rightArmGibbed )
|
|
{
|
|
return (isdefined(entity.gib_data)?entity.gib_data.torsoDmg2:entity.torsoDmg2);
|
|
}
|
|
else if ( leftArmGibbed )
|
|
{
|
|
return (isdefined(entity.gib_data)?entity.gib_data.torsoDmg3:entity.torsoDmg3);
|
|
}
|
|
|
|
return (isdefined(entity.gib_data)?entity.gib_data.torsoDmg1:entity.torsoDmg1);
|
|
}
|
|
|
|
function private _GibPieceTag( localClientNum, entity, gibFlag )
|
|
{
|
|
if ( !_HasGibDef( self ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
gibBundle = struct::get_script_bundle("gibcharacterdef",_GetGibDef( entity ));
|
|
gibPiece = gibBundle.gibs[ gibFlag ];
|
|
|
|
if ( IsDefined( gibPiece ) )
|
|
{
|
|
return gibPiece.gibfxtag;
|
|
}
|
|
}
|
|
|
|
function private _GibEntity( localClientNum, gibFlags, shouldSpawnGibs )
|
|
{
|
|
entity = self;
|
|
|
|
if ( !_HasGibDef( entity ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Skip the toggle flag, GIB_TOGGLE_GIB_MODEL_FLAG.
|
|
currentGibFlag = 2;
|
|
gibDir = undefined;
|
|
|
|
if ( entity IsPlayer() || entity IsPlayerCorpse() )
|
|
{
|
|
// TODO(David Young 6-8-15): Add support for yaw bits for AI as well.
|
|
yaw_bits = ( ( gibFlags >> 9 ) & ( ( 1 << 3 ) - 1 ) );
|
|
yaw = getanglefrombits( yaw_bits, 3 );
|
|
gibDir = AnglesToForward( ( 0, yaw, 0 ) );
|
|
}
|
|
|
|
gibBundle = struct::get_script_bundle("gibcharacterdef",_GetGibDef( entity ));
|
|
|
|
// Handles any number of simultaneous gibbings.
|
|
while ( gibFlags >= currentGibFlag )
|
|
{
|
|
if ( gibFlags & currentGibFlag )
|
|
{
|
|
gibPiece = gibBundle.gibs[ currentGibFlag ];
|
|
|
|
if ( IsDefined( gibPiece ) )
|
|
{
|
|
if ( shouldSpawnGibs )
|
|
{
|
|
entity thread _GibPiece( localClientNum, entity, gibPiece.gibmodel, gibPiece.gibtag, gibPiece.gibdynentfx, gibDir );
|
|
}
|
|
|
|
_PlayGibFX( localClientNum, entity, gibPiece.gibfx, gibPiece.gibfxtag );
|
|
_PlayGibSound( localClientNum, entity, gibPiece.gibsound );
|
|
|
|
if ( currentGibFlag == 2 )
|
|
{
|
|
entity Hide();
|
|
entity.ignoreRagdoll = true;
|
|
}
|
|
}
|
|
|
|
_HandleGibCallbacks( localClientNum, entity, currentGibFlag );
|
|
}
|
|
|
|
currentGibFlag = currentGibFlag << 1;
|
|
}
|
|
}
|
|
|
|
function private _SetGibbed( localClientNum, entity, gibFlag )
|
|
{
|
|
gib_state = (_GetGibbedState( localClientNum, entity ) | ( gibFlag & ( ( 1 << 9 ) - 1 ) ));
|
|
|
|
if ( IsDefined( entity.gib_data ) )
|
|
{
|
|
entity.gib_data.gib_state = gib_state;
|
|
}
|
|
else
|
|
{
|
|
entity.gib_state = gib_state;
|
|
}
|
|
}
|
|
|
|
function private _GibClientEntityInternal( localClientNum, entity, gibFlag )
|
|
{
|
|
if ( !util::is_mature() || util::is_gib_restricted_build() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( !IsDefined( entity ) || !_HasGibDef( entity ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( entity.type !== "scriptmover" )
|
|
{
|
|
// Clientside gibbing currently only supports script models.
|
|
return;
|
|
}
|
|
|
|
if ( IsGibbed( localClientNum, entity, gibFlag ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( !(_GetGibbedState( localClientNum, entity ) < 16) )
|
|
{
|
|
legModel = _GetGibbedLegModel( localClientNum, entity );
|
|
entity Detach( legModel, "" );
|
|
}
|
|
|
|
_SetGibbed( localClientNum, entity, gibFlag );
|
|
|
|
entity SetModel( _GetGibbedTorsoModel( localClientNum, entity ) );
|
|
entity Attach( _GetGibbedLegModel( localClientNum, entity ), "" );
|
|
|
|
entity _GibEntity( localClientNum, gibFlag, true );
|
|
}
|
|
|
|
function private _GibClientExtraInternal( localClientNum, entity, gibFlag )
|
|
{
|
|
if ( !util::is_mature() || util::is_gib_restricted_build() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( !IsDefined( entity ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( entity.type !== "scriptmover" )
|
|
{
|
|
// Clientside gibbing currently only supports script models.
|
|
return;
|
|
}
|
|
|
|
if ( IsGibbed( localClientNum, entity, gibFlag ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
gibModel = _GetGibExtraModel( localClientNum, entity, gibFlag );
|
|
|
|
if ( IsDefined( gibModel ) && entity IsAttached( gibModel, "" ) )
|
|
{
|
|
entity Detach( gibModel, "" );
|
|
}
|
|
|
|
if ( gibFlag == 8 )
|
|
{
|
|
if ( IsDefined( (isdefined(entity.gib_data)?entity.gib_data.torsoDmg5:entity.torsoDmg5) ) )
|
|
{
|
|
entity Attach( (isdefined(entity.gib_data)?entity.gib_data.torsoDmg5:entity.torsoDmg5), "" );
|
|
}
|
|
}
|
|
|
|
_SetGibbed( localClientNum, entity, gibFlag );
|
|
entity _GibEntity( localClientNum, gibFlag, true );
|
|
}
|
|
|
|
function private _GibHandler( localClientNum, oldValue, newValue, bNewEnt, bInitialSnap, fieldName, wasDemoJump )
|
|
{
|
|
entity = self;
|
|
|
|
if ( entity IsPlayer() || entity IsPlayerCorpse() )
|
|
{
|
|
if ( !util::is_mature() || util::is_gib_restricted_build() )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( IsDefined( entity.maturegib ) && entity.maturegib && !util::is_mature() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( IsDefined( entity.restrictedgib ) && entity.restrictedgib && !IsShowGibsEnabled() )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
gibFlags = (oldValue ^ newValue);
|
|
shouldSpawnGibs = (!(newValue & 1));
|
|
|
|
// Don't use the old clientfield value for new entities.
|
|
if ( bNewEnt )
|
|
{
|
|
gibFlags = (0 ^ newValue);
|
|
}
|
|
|
|
entity _GibEntity( localClientNum, gibFlags, shouldSpawnGibs );
|
|
|
|
entity.gib_state = newValue;
|
|
}
|
|
|
|
function _GibPiece( localClientNum, entity, gibModel, gibTag, gibFx, gibDir )
|
|
{
|
|
if ( !IsDefined( gibTag ) || !IsDefined( gibModel ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
startPosition = entity GetTagOrigin( gibTag );
|
|
startAngles = entity GetTagAngles( gibTag );
|
|
endPosition = startPosition;
|
|
endAngles = startAngles;
|
|
forwardVector = undefined;
|
|
|
|
if ( !IsDefined( startPosition ) || !IsDefined( startAngles ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( IsDefined( gibDir ) )
|
|
{
|
|
startPosition = (0,0,0);
|
|
forwardVector = gibDir;
|
|
// TODO: define the scale on the server from the damage
|
|
forwardVector *= RandomFloatRange( 100.0, 500.0 );
|
|
}
|
|
else
|
|
{
|
|
// Let a frame pass to approximate the linear and angular velocity of the tag.
|
|
{wait(.016);};
|
|
|
|
if ( IsDefined( entity ) )
|
|
{
|
|
endPosition = entity GetTagOrigin( gibTag );
|
|
endAngles = entity GetTagAngles( gibTag );
|
|
}
|
|
else
|
|
{
|
|
// Entity already removed.
|
|
endPosition = startPosition + ( AnglesToForward( startAngles ) * 10 );
|
|
endAngles = startAngles;
|
|
}
|
|
|
|
if ( !IsDefined( endPosition ) || !IsDefined( endAngles ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
forwardVector = VectorNormalize( endPosition - startPosition );
|
|
forwardVector *= RandomFloatRange( 0.6, 1.0 );
|
|
forwardVector += ( RandomFloatRange( 0, 0.2 ), RandomFloatRange( 0, 0.2 ), RandomFloatRange( 0.2, 0.7 ) );
|
|
}
|
|
|
|
if( IsDefined( entity ) )
|
|
{
|
|
gibEntity = CreateDynEntAndLaunch( localClientNum, gibModel, endPosition, endAngles, startPosition, forwardVector, gibFx, true );
|
|
if ( IsDefined( gibEntity ) )
|
|
{
|
|
SetDynEntBodyRenderOptionsPacked( gibEntity, entity GetBodyRenderOptionsPacked() );
|
|
}
|
|
}
|
|
}
|
|
|
|
function private _HandleGibCallbacks( localClientNum, entity, gibFlag )
|
|
{
|
|
if ( IsDefined( entity._gibCallbacks ) &&
|
|
IsDefined( entity._gibCallbacks[gibFlag] ) )
|
|
{
|
|
foreach ( callback in entity._gibCallbacks[gibFlag] )
|
|
{
|
|
[[callback]]( localClientNum, entity, gibFlag );
|
|
}
|
|
}
|
|
}
|
|
|
|
function private _HandleGibAnnihilate( localClientNum )
|
|
{
|
|
entity = self;
|
|
entity endon( "entityshutdown" );
|
|
|
|
entity waittillmatch( "_anim_notify_", "gib_annihilate" );
|
|
GibClientUtils::ClientEntGibAnnihilate( localClientNum, entity );
|
|
}
|
|
|
|
function private _HandleGibHead( localClientNum )
|
|
{
|
|
entity = self;
|
|
entity endon( "entityshutdown" );
|
|
|
|
entity waittillmatch( "_anim_notify_", "gib = \"head\"" );
|
|
GibClientUtils::ClientEntGibHead( localClientNum, entity );
|
|
}
|
|
|
|
function private _HandleGibRightArm( localClientNum )
|
|
{
|
|
entity = self;
|
|
entity endon( "entityshutdown" );
|
|
|
|
entity waittillmatch( "_anim_notify_", "gib = \"arm_right\"" );
|
|
GibClientUtils::ClientEntGibRightArm( localClientNum, entity );
|
|
}
|
|
|
|
function private _HandleGibLeftArm( localClientNum )
|
|
{
|
|
entity = self;
|
|
entity endon( "entityshutdown" );
|
|
|
|
entity waittillmatch( "_anim_notify_", "gib = \"arm_left\"" );
|
|
GibClientUtils::ClientEntGibLeftArm( localClientNum, entity );
|
|
}
|
|
|
|
function private _HandleGibRightLeg( localClientNum )
|
|
{
|
|
entity = self;
|
|
entity endon( "entityshutdown" );
|
|
|
|
entity waittillmatch( "_anim_notify_", "gib = \"leg_right\"" );
|
|
GibClientUtils::ClientEntGibRightLeg( localClientNum, entity );
|
|
}
|
|
|
|
function private _HandleGibLeftLeg( localClientNum )
|
|
{
|
|
entity = self;
|
|
entity endon( "entityshutdown" );
|
|
|
|
entity waittillmatch( "_anim_notify_", "gib = \"leg_left\"" );
|
|
GibClientUtils::ClientEntGibLeftLeg( localClientNum, entity );
|
|
}
|
|
|
|
function private _HasGibDef( entity )
|
|
{
|
|
return ( IsDefined( entity.gib_data ) && IsDefined( entity.gib_data.gibdef ) ) ||
|
|
IsDefined( entity.gibdef ) ||
|
|
( ( entity GetPlayerGibDef() ) != "unknown" );
|
|
}
|
|
|
|
function _PlayGibFX( localClientNum, entity, fxFileName, fxTag )
|
|
{
|
|
if ( IsDefined( fxFileName ) && IsDefined( fxTag ) && entity hasDobj(localClientNum) )
|
|
{
|
|
fx = PlayFxOnTag( localClientNum, fxFileName, entity, fxTag );
|
|
if(isDefined(fx))
|
|
{
|
|
if(isDefined(entity.team))
|
|
{
|
|
SetFxTeam( localClientNum, fx, entity.team );
|
|
}
|
|
|
|
if( ( isdefined( level.SetGibFXToIgnorePause ) && level.SetGibFXToIgnorePause ) )
|
|
{
|
|
SetFXIgnorePause( localClientNum, fx, true );
|
|
}
|
|
}
|
|
|
|
return fx;
|
|
}
|
|
}
|
|
|
|
function _PlayGibSound( localClientNum, entity, soundAlias )
|
|
{
|
|
if ( IsDefined( soundAlias ) )
|
|
{
|
|
PlaySound( localClientNum, soundAlias, entity.origin );
|
|
}
|
|
}
|
|
|
|
/@
|
|
"Name: AddGibCallback( localClientNum, entity, gibFlag, callbackFunction )"
|
|
"Summary: Register a function callback that is called when the corresponding piece is gibbed."
|
|
"MandatoryArg: <num> : Client number."
|
|
"MandatoryArg: <entity> : Entity to add callbacks to."
|
|
"MandatoryArg: <num> : Gib piece to register for."
|
|
"MandatoryArg: <function> : Function to call, function is passed the localClientNum, entity, and gibFlag."
|
|
"Module: Gib"
|
|
@/
|
|
function AddGibCallback( localClientNum, entity, gibFlag, callbackFunction )
|
|
{
|
|
assert( IsFunctionPtr( callbackFunction ) );
|
|
|
|
if ( !IsDefined( entity._gibCallbacks ) )
|
|
{
|
|
entity._gibCallbacks = [];
|
|
}
|
|
|
|
if ( !IsDefined( entity._gibCallbacks[gibFlag] ) )
|
|
{
|
|
entity._gibCallbacks[gibFlag] = [];
|
|
}
|
|
|
|
gibCallbacks = entity._gibCallbacks[gibFlag];
|
|
gibCallbacks[gibCallbacks.size] = callbackFunction;
|
|
entity._gibCallbacks[gibFlag] = gibCallbacks;
|
|
}
|
|
|
|
function ClientEntGibAnnihilate( localClientNum, entity )
|
|
{
|
|
if ( !util::is_mature() || util::is_gib_restricted_build() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Toggle hiding the ragdoll.
|
|
entity.ignoreRagdoll = true;
|
|
|
|
entity _GibEntity(
|
|
localClientNum,
|
|
2 |
|
|
16 |
|
|
32 |
|
|
(128+256),
|
|
true );
|
|
}
|
|
|
|
function ClientEntGibHead( localClientNum, entity )
|
|
{
|
|
_GibClientExtraInternal( localClientNum, entity, 4 );
|
|
_GibClientExtraInternal( localClientNum, entity, 8 );
|
|
}
|
|
|
|
function ClientEntGibLeftArm( localClientNum, entity )
|
|
{
|
|
if ( IsGibbed( localClientNum, entity, 16 ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
_GibClientEntityInternal( localClientNum, entity, 32 );
|
|
}
|
|
|
|
function ClientEntGibRightArm( localClientNum, entity )
|
|
{
|
|
if ( IsGibbed( localClientNum, entity, 32 ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
_GibClientEntityInternal( localClientNum, entity, 16 );
|
|
}
|
|
|
|
function ClientEntGibLeftLeg( localClientNum, entity )
|
|
{
|
|
_GibClientEntityInternal( localClientNum, entity, 256 );
|
|
}
|
|
|
|
function ClientEntGibRightLeg( localClientNum, entity )
|
|
{
|
|
_GibClientEntityInternal( localClientNum, entity, 128 );
|
|
}
|
|
|
|
function CreateScriptModelOfEntity( localClientNum, entity )
|
|
{
|
|
clone = Spawn( localClientNum, entity.origin, "script_model" );
|
|
clone.angles = entity.angles;
|
|
|
|
_CloneGibData( localClientNum, entity, clone );
|
|
gibState = _GetGibbedState( localClientNum, clone );
|
|
|
|
if ( !util::is_mature() || util::is_gib_restricted_build() )
|
|
{
|
|
// Don't display gibbed entities for non-mature clients.
|
|
gibState = 0;
|
|
}
|
|
|
|
if ( !(_GetGibbedState( localClientNum, entity ) < 16) )
|
|
{
|
|
// Attach torso or full body model.
|
|
clone SetModel( _GetGibbedTorsoModel( localClientNum, entity ) );
|
|
// Only attach separate legs if the body is damage already.
|
|
clone Attach( _GetGibbedLegModel( localClientNum, entity ), "" );
|
|
}
|
|
else
|
|
{
|
|
// Attach full body model.
|
|
clone SetModel( entity.model );
|
|
}
|
|
|
|
if ( (gibState & 8) )
|
|
{
|
|
// Attach head stump.
|
|
if ( IsDefined( (isdefined(clone.gib_data)?clone.gib_data.torsoDmg5:clone.torsoDmg5) ) )
|
|
{
|
|
clone Attach( (isdefined(clone.gib_data)?clone.gib_data.torsoDmg5:clone.torsoDmg5), "" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Attach head.
|
|
if ( IsDefined( (isdefined(clone.gib_data)?clone.gib_data.head:clone.head) ) )
|
|
{
|
|
clone Attach( (isdefined(clone.gib_data)?clone.gib_data.head:clone.head), "" );
|
|
}
|
|
|
|
if ( !(gibState & 4) && IsDefined( (isdefined(clone.gib_data)?clone.gib_data.hatmodel:clone.hatmodel) ) )
|
|
{
|
|
clone Attach( (isdefined(clone.gib_data)?clone.gib_data.hatmodel:clone.hatmodel), "" );
|
|
}
|
|
}
|
|
|
|
return clone;
|
|
}
|
|
|
|
function IsGibbed( localClientNum, entity, gibFlag )
|
|
{
|
|
return (_GetGibbedState( localClientNum, entity ) & gibFlag);
|
|
}
|
|
|
|
function IsUndamaged( localClientNum, entity )
|
|
{
|
|
return _GetGibbedState( localClientNum, entity ) == 0;
|
|
}
|
|
|
|
function GibEntity( localClientNum, gibFlags )
|
|
{
|
|
self _GibEntity( localClientNum, gibFlags, true );
|
|
|
|
self.gib_state = (_GetGibbedState( localClientNum, self ) | ( gibFlags & ( ( 1 << 9 ) - 1 ) ));
|
|
}
|
|
|
|
function HandleGibNotetracks( localClientNum )
|
|
{
|
|
entity = self;
|
|
|
|
entity thread _HandleGibAnnihilate( localClientNum );
|
|
entity thread _HandleGibHead( localClientNum );
|
|
entity thread _HandleGibRightArm( localClientNum );
|
|
entity thread _HandleGibLeftArm( localClientNum );
|
|
entity thread _HandleGibRightLeg( localClientNum );
|
|
entity thread _HandleGibLeftLeg( localClientNum );
|
|
}
|
|
|
|
function PlayerGibLeftArm( localClientNum )
|
|
{
|
|
self GibEntity( localClientNum, 32 );
|
|
}
|
|
|
|
function PlayerGibRightArm( localClientNum )
|
|
{
|
|
self GibEntity( localClientNum, 16 );
|
|
}
|
|
|
|
function PlayerGibLeftLeg( localClientNum )
|
|
{
|
|
self GibEntity( localClientNum, 256 );
|
|
}
|
|
|
|
function PlayerGibRightLeg( localClientNum )
|
|
{
|
|
self GibEntity( localClientNum, 128 );
|
|
}
|
|
|
|
function PlayerGibLegs( localClientNum )
|
|
{
|
|
self GibEntity( localClientNum, 128 );
|
|
self GibEntity( localClientNum, 256 );
|
|
}
|
|
|
|
function PlayerGibTag( localClientNum, gibFlag )
|
|
{
|
|
return _GibPieceTag( localClientNum, self, gibFlag );
|
|
}
|
|
|