314 lines
16 KiB
Plaintext
314 lines
16 KiB
Plaintext
#using scripts\codescripts\struct;
|
|
#using scripts\shared\clientfield_shared;
|
|
#using scripts\shared\math_shared;
|
|
#using scripts\shared\array_shared;
|
|
|
|
|
|
|
|
|
|
|
|
function autoexec main()
|
|
{
|
|
clientfield::register(
|
|
"actor",
|
|
"destructible_character_state",
|
|
1,
|
|
21,
|
|
"int" );
|
|
|
|
destructibles = struct::get_script_bundles( "destructiblecharacterdef" );
|
|
|
|
processedBundles = [];
|
|
|
|
// Process each destructible bundle to allow quick access to information in the future.
|
|
foreach ( destructibleName, destructible in destructibles )
|
|
{
|
|
destructBundle = SpawnStruct();
|
|
destructBundle.pieceCount = destructible.pieceCount;
|
|
destructBundle.pieces = [];
|
|
destructBundle.name = destructibleName;
|
|
|
|
for ( index = 1; index <= destructBundle.pieceCount; index++ )
|
|
{
|
|
pieceStruct = SpawnStruct();
|
|
pieceStruct.gibmodel = GetStructField( destructible, "piece" + index + "_gibmodel" );
|
|
pieceStruct.gibtag = GetStructField( destructible, "piece" + index + "_gibtag" );
|
|
pieceStruct.gibfx = GetStructField( destructible, "piece" + index + "_gibfx" );
|
|
pieceStruct.gibfxtag = GetStructField( destructible, "piece" + index + "_gibeffecttag" );
|
|
pieceStruct.gibdynentfx = GetStructField( destructible, "piece" + index + "_gibdynentfx" );
|
|
pieceStruct.gibsound = GetStructField( destructible, "piece" + index + "_gibsound" );
|
|
pieceStruct.hitlocation = GetStructField( destructible, "piece" + index + "_hitlocation" );
|
|
pieceStruct.hidetag = GetStructField( destructible, "piece" + index + "_hidetag" );
|
|
pieceStruct.detachmodel = GetStructField( destructible, "piece" + index + "_detachmodel" );
|
|
|
|
destructBundle.pieces[ destructBundle.pieces.size ] = pieceStruct;
|
|
}
|
|
|
|
processedBundles[ destructibleName ] = destructBundle;
|
|
}
|
|
|
|
// Replaces all destructible character define bundles with their processed form to free unncessary script variables.
|
|
level.scriptbundles[ "destructiblecharacterdef" ] = processedBundles;
|
|
}
|
|
|
|
#namespace DestructServerUtils;
|
|
|
|
function private _GetDestructState( entity )
|
|
{
|
|
if ( IsDefined( entity._destruct_state ) )
|
|
{
|
|
return entity._destruct_state;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
function private _SetDestructed( entity, destructFlag )
|
|
{
|
|
entity._destruct_state = (_GetDestructState( entity ) | destructFlag);
|
|
entity clientfield::set( "destructible_character_state", entity._destruct_state );
|
|
}
|
|
|
|
function CopyDestructState( originalEntity, newEntity )
|
|
{
|
|
newEntity._destruct_state = _GetDestructState( originalEntity );
|
|
|
|
ToggleSpawnGibs( newEntity, false );
|
|
|
|
ReapplyDestructedPieces( newEntity );
|
|
}
|
|
|
|
function DestructHitLocPieces( entity, hitLoc )
|
|
{
|
|
if ( IsDefined(entity.destructibledef) )
|
|
{
|
|
destructBundle = struct::get_script_bundle( "destructiblecharacterdef", entity.destructibledef );
|
|
|
|
for ( index = 1; index <= destructBundle.pieces.size; index++ )
|
|
{
|
|
piece = destructBundle.pieces[ index - 1 ];
|
|
|
|
if ( IsDefined( piece.hitlocation ) && piece.hitlocation == hitLoc )
|
|
{
|
|
DestructPiece( entity, index );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function DestructLeftArmPieces( entity )
|
|
{
|
|
DestructHitLocPieces( entity, "left_arm_upper" );
|
|
DestructHitLocPieces( entity, "left_arm_lower" );
|
|
DestructHitLocPieces( entity, "left_hand" );
|
|
}
|
|
|
|
function DestructLeftLegPieces( entity )
|
|
{
|
|
DestructHitLocPieces( entity, "left_leg_upper" );
|
|
DestructHitLocPieces( entity, "left_leg_lower" );
|
|
DestructHitLocPieces( entity, "left_foot" );
|
|
}
|
|
|
|
function DestructPiece( entity, pieceNumber )
|
|
{
|
|
/# assert( (1 <= pieceNumber && pieceNumber <= 20) ); #/
|
|
|
|
if ( IsDestructed( entity, pieceNumber ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
_SetDestructed( entity, (1 << pieceNumber) );
|
|
|
|
if ( !IsDefined(entity.destructibledef) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
destructBundle = struct::get_script_bundle( "destructiblecharacterdef", entity.destructibledef );
|
|
piece = destructBundle.pieces[ pieceNumber - 1 ];
|
|
|
|
if ( IsDefined( piece.hidetag ) && entity HasPart( piece.hidetag ) )
|
|
{
|
|
entity HidePart( piece.hidetag );
|
|
}
|
|
|
|
if ( IsDefined( piece.detachmodel ) )
|
|
{
|
|
entity Detach( piece.detachmodel, "" );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Destruct a specified number of pieces
|
|
// Use 0 to destruct all pieces
|
|
function DestructNumberRandomPieces( entity, num_pieces_to_destruct=0 )
|
|
{
|
|
// Array containing our desctructible pieces.
|
|
destructible_pieces_list = [];
|
|
|
|
// Get the total number of breakable pieces we have
|
|
destructablePieces = GetPieceCount( entity );
|
|
|
|
if (num_pieces_to_destruct == 0)
|
|
{
|
|
num_pieces_to_destruct = destructablePieces;
|
|
}
|
|
|
|
// Build the list of pieces
|
|
for ( i = 0; i < destructablePieces; i++ )
|
|
{
|
|
destructible_pieces_list[i] = i + 1;
|
|
}
|
|
|
|
// Shuffle the list of pieces so we break off pieces at random
|
|
destructible_pieces_list = array::randomize(destructible_pieces_list);
|
|
|
|
// Go through the randomized list breaking off pieces until we either run out of pieces or broke off all the pieces we needed to.
|
|
foreach(piece in destructible_pieces_list)
|
|
{
|
|
if(!IsDestructed(entity,piece))
|
|
{
|
|
DestructPiece(entity,piece);
|
|
num_pieces_to_destruct--;
|
|
if(num_pieces_to_destruct == 0 )
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function DestructRandomPieces( entity)
|
|
{
|
|
destructPieces = GetPieceCount( entity );
|
|
|
|
for ( index = 0; index < destructPieces; index++ )
|
|
{
|
|
if ( math::cointoss() )
|
|
{
|
|
DestructPiece( entity, index + 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
function DestructRightArmPieces( entity )
|
|
{
|
|
DestructHitLocPieces( entity, "right_arm_upper" );
|
|
DestructHitLocPieces( entity, "right_arm_lower" );
|
|
DestructHitLocPieces( entity, "right_hand" );
|
|
}
|
|
|
|
function DestructRightLegPieces( entity )
|
|
{
|
|
DestructHitLocPieces( entity, "right_leg_upper" );
|
|
DestructHitLocPieces( entity, "right_leg_lower" );
|
|
DestructHitLocPieces( entity, "right_foot" );
|
|
}
|
|
|
|
function GetPieceCount( entity )
|
|
{
|
|
if ( IsDefined(entity.destructibledef) )
|
|
{
|
|
destructBundle = struct::get_script_bundle( "destructiblecharacterdef", entity.destructibledef );
|
|
|
|
if ( IsDefined( destructBundle ) )
|
|
{
|
|
return destructBundle.piececount;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
function HandleDamage(
|
|
eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex, modelIndex )
|
|
{
|
|
entity = self;
|
|
|
|
if ( ( isdefined( entity.skipDeath ) && entity.skipDeath ) )
|
|
{
|
|
return iDamage;
|
|
}
|
|
|
|
if ( ( isdefined( entity.skipGibs ) && entity.skipGibs ) )
|
|
{
|
|
return iDamage;
|
|
}
|
|
|
|
ToggleSpawnGibs( entity, true );
|
|
|
|
DestructHitLocPieces( entity, sHitLoc );
|
|
|
|
return iDamage;
|
|
}
|
|
|
|
function IsDestructed( entity, pieceNumber )
|
|
{
|
|
/# assert( (1 <= pieceNumber && pieceNumber <= 20) ); #/
|
|
|
|
return (_GetDestructState( entity ) & (1 << pieceNumber));
|
|
}
|
|
|
|
function ReapplyDestructedPieces( entity )
|
|
{
|
|
if ( !IsDefined(entity.destructibledef) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
destructBundle = struct::get_script_bundle( "destructiblecharacterdef", entity.destructibledef );
|
|
|
|
for ( index = 1; index <= destructBundle.pieces.size; index++ )
|
|
{
|
|
if ( !IsDestructed( entity, index ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
piece = destructBundle.pieces[ index - 1];
|
|
|
|
if ( IsDefined( piece.hidetag ) && entity HasPart( piece.hidetag ) )
|
|
{
|
|
entity HidePart( piece.hidetag );
|
|
}
|
|
}
|
|
}
|
|
|
|
function ShowDestructedPieces( entity )
|
|
{
|
|
if ( !IsDefined(entity.destructibledef) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
destructBundle = struct::get_script_bundle( "destructiblecharacterdef", entity.destructibledef );
|
|
|
|
for ( index = 1; index <= destructBundle.pieces.size; index++ )
|
|
{
|
|
piece = destructBundle.pieces[ index - 1];
|
|
|
|
if ( IsDefined( piece.hidetag ) && entity HasPart( piece.hidetag ) )
|
|
{
|
|
entity ShowPart( piece.hidetag );
|
|
}
|
|
}
|
|
}
|
|
|
|
function ToggleSpawnGibs( entity, shouldSpawnGibs )
|
|
{
|
|
if ( shouldSpawnGibs )
|
|
{
|
|
entity._destruct_state = _GetDestructState( entity ) | 1;
|
|
}
|
|
else
|
|
{
|
|
entity._destruct_state = _GetDestructState( entity ) & ~1;
|
|
}
|
|
|
|
entity clientfield::set( "destructible_character_state", entity._destruct_state );
|
|
}
|
|
|
|
// end #namespace DestructServerUtils;
|