Member
Join Date: Feb 2017
Location: Turkey
|
02-03-2020
, 07:48
attach_view code alternative
|
#1
|
is there a alternative for 'attach_view' code ?
like camera plugins, setting view to entitys
i saw in arkshine's 'Prototype Groundspike Graveyard' Plugin, how does he did ?
Code:
/* - - - - - - - - - - -
AMX Mod X script.
¦ Author : Andrade, Arkshine
¦ Plugin : Prototype Groundspike Graveyard
¦ Version : v1.0.0
(¡) Support : http://forums.alliedmods.net/showthread.php?t=146984
This plugin is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This plugin is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this plugin; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Description
─ ─ ─ ─ ─ ─
This plugin features a special attack borrowed from the game Prototype now in Counter-Strike style.
Instead of explaining by words, check yourself by viewing this video.
Requirements
─ ─ ─ ─ ─ ─ ─
CS 1.6, CZ.
AMX Mod X 1.8.x or higher.
Commands
─ ─ ─ ─ ─
* protospike : Start the protospike attack.
* protospike_help : Show the plugin help.
Credits
─ ─ ─ ─
* joaquimandrade : Original author.
* Tirant : Spike model.
- - - - - - - - - - - */
#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fakemeta_util>
#include <hamsandwich>
#include <xs>
#include <cstrike>
new const Plugin [] = "Prototype Groundspike Graveyard";
new const Author [] = "Andrade, Arkshine";
new const Version[] = "1.0";
/*
[ PLAYER ]
├ GENERAL CONSTANT
*/
const MaxSlots = 32;
/*
├ PRIVATE DATA OFFSETS
*/
const m_iHideHUD = 361;
const m_iClientHideHUD = 362;
const m_pClientActiveItem = 374;
const m_fInitHUD = 348;
/*
├ PLAYER HANDLING
*/
const ViewmodelMaxLen = 150;
const Float:BloodInterval = 1.5;
new bool:PlayerIsUsingAttack [ MaxSlots + 1 ];
new bool:PlayerPreventCorpse [ MaxSlots + 1 ];
new PlayerLookalike [ MaxSlots + 1 ];
new PlayerOriginalFlags [ MaxSlots + 1 ];
new Float:PlayerOriginalAngles[ MaxSlots + 1 ][ 3 ];
new Float:PlayerOriginalOrigin[ MaxSlots + 1 ][ 3 ];
new PlayerOriginalViewmodel [ MaxSlots + 1 ][ ViewmodelMaxLen + 1 ];
new PlayerOriginalActiveItem [ MaxSlots + 1 ];
/*
├ CAMERA HANDLING
*/
const Float:FramesPerCameraRotation = 300.0;
const Float:RotationDegrees = 160.0;
const Float:RotationRadius = 100.0;
new Float:DegreeIncreasePerFrame;
new Array:PlayerCameraOriginQueue[ MaxSlots + 1 ];
new Array:PlayerCameraAnglesQueue[ MaxSlots + 1 ];
/*
├ CLIENT CVARS PERMISSION
*/
new bool:AskPermission [ MaxSlots + 1 ];
new bool:CommandAllowed[ MaxSlots + 1 ];
new Trie:TrieAuthIdCache;
new PermissionMenu[ 512 ];
/*
[ SPIKE ]
├ ENTITY CONSTANTS
*/
new const SpikeModel[] = "models/spike.mdl";
new const SpikeEmergeSound [] = "weapons/hegrenade-1.wav";
new const SpikeUnemergeSound[] = "ImpaleLaunch1.wav";
new const SpikeClassname[] = "protospike";
/*
├ ANIMATION HANDLING
*/
enum Animation
{
Summon,
};
enum AnimationProperty
{
Sequence,
FirstFrame,
FinalFrame,
FramesPerServerFrame,
};
new AnimationsData[ Animation ][ AnimationProperty ] =
{
{
29,
115,
30,
2
}
};
new Array:AnimationsPacked[ Animation ];
enum _:EntityAnimation
{
EntityID,
Array:AnimationPack,
CallbackFuncID
};
new PlayerAnimationQueue[ MaxSlots + 1 ][ EntityAnimation ];
/*
├ DATAS
*/
const SpikesNumber = 9;
const Float:SpikeCalcRadiusStart = 50.0;
const Float:SpikeCalcRadiusIncrement = 10.0;
const SpikesFirstCircle = 5;
const SpikesPerCircleIncrease = 4;
const SpikesCircles = 3;
const Float:SpikesMaxHeightMax = 130.0;
const Float:SpikesMaxHeightMin = 90.0;
const Float:SpikeMinHeight = 10.0;
const Float:SpikeHeightIncrementPerFrame = 6.0;
const Float:SpikeHeightDecrementPerFrame = 1.5;
const SpikeFramesIdle = 400;
enum _:PlayerSpikeData
{
SpikeID,
Array:SpikeOrigins
}
enum _:PlayerSpikeOriginQueueData
{
Array:Queue,
SpikeCallbackFuncID,
UnemergeFramesMissing
}
new PlayerSpikeOriginQueue[ MaxSlots + 1 ][ PlayerSpikeOriginQueueData ];
public plugin_precache()
{
precache_model( SpikeModel );
precache_sound( SpikeEmergeSound );
precache_sound( SpikeUnemergeSound );
}
public plugin_init()
{
register_plugin( Plugin, Version, Author );
register_clcmd( "protospike", "ClientCommand_Protospike" );
register_clcmd( "protospike_help", "ClientCommand_ProtospikeHelp" );
register_touch( "player", SpikeClassname, "Spike_PlayerTouch" );
RegisterHam( Ham_Spawn, "player", "CBasePlayer_Spawn" );
register_message( get_user_msgid( "ClCorpse" ), "Event_ClCorpse" );
handlePermissionMenu();
}
public plugin_cfg()
{
packAnimations();
DegreeIncreasePerFrame = RotationDegrees / FramesPerCameraRotation;
}
/*
┌──────────────────┐
│ GENERAL PLAYER │
└──────────────────┘
→ client_authorized()
→ client_disconnect()
└ protospikeFinish()
→ CBasePlayer_Spawn()
└ protospikeFinish()
→ Event_ClCorpse()
→ handlePermissionMenu()
→ MenuPermissionHandler()
*/
public client_authorized( client )
{
static authId[ 34 ];
get_user_authid( client, authId, charsmax( authId ) );
if( !TrieKeyExists( TrieAuthIdCache, authId ) )
{
TrieSetCell( TrieAuthIdCache, authId, true );
AskPermission[ client ] = true;
}
}
public client_disconnect( client )
{
AskPermission[ client ] = false;
if( PlayerIsUsingAttack[ client ] )
{
protospikeFinish( client, .fixPosition = false, .fixAngles = false, .fixHud = false );
}
}
public CBasePlayer_Spawn( const player )
{
if( PlayerIsUsingAttack[ player ] )
{
protospikeFinish( player, .fixPosition = false, .fixAngles = false, .fixHud = true );
}
else if( AskPermission[ player ] )
{
show_menu( player, MENU_KEY_1 | MENU_KEY_0, PermissionMenu, .title = "PlayerPermissionMenu" );
}
}
public Event_ClCorpse()
{
new player = get_msg_arg_int( 12 );
if( PlayerPreventCorpse[ player ] )
{
PlayerPreventCorpse[ player ] = false;
return PLUGIN_HANDLED;
}
return PLUGIN_CONTINUE;
}
handlePermissionMenu()
{
TrieAuthIdCache = TrieCreate();
register_menu( "PlayerPermissionMenu", 0x3FF, "MenuPermissionHandler" );
new len = formatex( PermissionMenu, charsmax( PermissionMenu ), "\rProtospike Attack^n^n" );
len += formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "\wThis server features a special attack borrowed from the game Prototype^n" );
len += formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "now in Counter-Strike style.^n^nTo launch it use the console command ^"\dprotospike\w^".^n^n" );
len += formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "Beware that it modifies settings of your configuration It restores them when^n" );
len += formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "the attack is finished. If you leave the game meanwhile you will have to^n" );
len += formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "restore them yourself. Use the command ^"\dprotospike_help\w^" to view^n" );
len += formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "the settings that are modified and their current values.^n^n" );
formatex( PermissionMenu[ len ], charsmax( PermissionMenu ) - len, "\r1.\w Ok^n^n^n\r0.\w Cancel" );
}
public MenuPermissionHandler( const player, const key )
{
CommandAllowed[ player ] = bool:( key + 1 );
return PLUGIN_HANDLED;
}
/*
┌───────────────────┐
│ CLIENT COMMANDS │
└───────────────────┘
→ ClientCommand_Protospike()
→ ClientCommand_ProtospikeHelp()
*/
public ClientCommand_Protospike( const player )
{
if( !CommandAllowed[ player ] )
{
client_print( player, print_chat, "The command is disabled for you." );
}
else if( !is_user_alive( player ) )
{
client_print( player, print_chat, "You have to be alive to launch the attack" );
}
else if( PlayerIsUsingAttack[ player ] )
{
client_print( player, print_chat, "You are already using the attack" );
}
else if( ~pev( player, pev_flags ) & FL_ONGROUND )
{
client_print( player, print_chat, "You have to be on ground to launch the attack" );
}
else
{
protospikeStart( player );
}
return PLUGIN_HANDLED
}
public ClientCommand_ProtospikeHelp( const client )
{
console_print( client, " --- " );
console_print( client, "This server features a special attack borrowed from the game Prototype now in Counter-Strike style." );
console_print( client, "To launch it use the console command ^"protospike^"^n" );
console_print( client, "Beware that it modifies settings of your configuration It restores them when the attack is finished." );
console_print( client, "If you leave the game meanwhile you will have to restore them yourself.^n" );
console_print( client, "Here a list of settings that are modified with their default value :" );
console_print( client, "cl_vsmoothing 0.05^ncl_nosmooth 0^ncl_smoothtime 0.1" );
console_print( client, " --- " );
return PLUGIN_HANDLED;
}
/*
┌───────────────────────┐
│ PROTOSPIKE HANDLING │
└───────────────────────┘
→ protospikeStart()
├ getLookalike()
├ getAnimationPack()
├ calculatePlayerCameraData()
└ removeClientPrediction()
→ protospikeFinish()
├ restoreClientPrediction()
├ tryDeletePlayerCameraData()
├ tryDeleteSpikesData()
└ tryDeleteAnimationData()
→ client_PreThink()
└ makeBloodAt()
*/
protospikeStart( const player )
{
set_pev( player, pev_effects,pev( player, pev_effects) | EF_NODRAW );
new Float:angles[ 3 ];
new Float:origin[ 3 ];
pev( player, pev_angles, angles );
pev( player,pev_origin,origin );
xs_vec_copy( angles, PlayerOriginalAngles[ player ] );
xs_vec_copy( origin, PlayerOriginalOrigin[ player ] );
angles[ 0 ] = 0.0;
set_pev( player, pev_angles,angles );
set_pev( player, pev_v_angle,angles );
set_pev( player, pev_fixangle, 1 );
set_pev( player, pev_movetype, MOVETYPE_NOCLIP );
set_pev( player, pev_solid, SOLID_NOT );
new lookalike = getLookalike( player );
PlayerLookalike[ player ] = lookalike;
entity_set_origin( lookalike, PlayerOriginalOrigin[ player ] );
set_pev( lookalike, pev_angles, PlayerOriginalAngles[ player ] );
set_pev( lookalike, pev_sequence, AnimationsData[ Summon ][ Sequence ] );
fm_set_user_rendering( lookalike, kRenderFxGlowShell, .amount = 30, .r = 50, .g = 50, .b = 50 );
PlayerAnimationQueue[ player ][ EntityID ] = lookalike
PlayerAnimationQueue[ player ][ AnimationPack ] = _:getAnimationPack( Summon );
PlayerAnimationQueue[ player ][ CallbackFuncID ] = get_func_id( "finishSummoningAnimation" );
PlayerOriginalActiveItem[ player ] = get_pdata_cbase( player, m_pClientActiveItem );
set_pdata_int( player, m_iHideHUD, ~0 );
set_pdata_int( player, m_iClientHideHUD, 0 );
set_pdata_cbase( player, m_pClientActiveItem, FM_NULLENT );
client_cmd( player, "stopsound" );
pev( player, pev_viewmodel, PlayerOriginalViewmodel[ player ], ViewmodelMaxLen );
set_pev( player, pev_viewmodel, "" );
calculatePlayerCameraData( player, origin, angles );
set_pev( player, pev_flags, ( PlayerOriginalFlags[ player ] = pev( player, pev_flags ) ) | FL_FLY | FL_FROZEN | FL_GODMODE & ~FL_ONGROUND )
PlayerIsUsingAttack[ player ] = true;
removeClientPrediction( player );
}
getLookalike( const player )
{
new entity = create_entity( "info_target" );
set_pev( entity, pev_movetype, MOVETYPE_NONE );
set_pev( entity, pev_owner, player );
set_pev( entity, pev_framerate, 0.0 );
static model[ 20 ];
static modelPath[ 100 ];
cs_get_user_model( player, model, charsmax( model ) );
formatex( modelPath, charsmax( modelPath ), "models/player/%s/%s.mdl", model, model );
entity_set_model( entity, modelPath );
return entity;
}
protospikeFinish( const player, fixPosition = true, fixAngles = true, fixHud = true )
{
set_pev( player, pev_effects, pev( player, pev_effects ) & ~EF_NODRAW );
if( fixAngles )
{
set_pev( player, pev_angles, PlayerOriginalAngles[ player ] )
set_pev( player, pev_v_angle, PlayerOriginalAngles[ player ] )
set_pev( player, pev_fixangle,1 );
}
set_pev( player, pev_movetype, MOVETYPE_WALK );
set_pev( player, pev_solid, SOLID_SLIDEBOX );
if( fixPosition )
{
entity_set_origin( player, PlayerOriginalOrigin[ player ] );
}
remove_entity( PlayerLookalike[ player ] );
if( fixHud )
{
set_pdata_int( player, m_iHideHUD, 0 );
set_pdata_int( player, m_iClientHideHUD, 0 );
set_pdata_cbase( player, m_pClientActiveItem, PlayerOriginalActiveItem[ player ] );
set_pdata_int( player, m_fInitHUD, 1 );
static msgIdCrosshair;
if( msgIdCrosshair || ( msgIdCrosshair = get_user_msgid( "Crosshair" ) ) )
{
message_begin( MSG_ONE_UNRELIABLE, msgIdCrosshair, .player = player );
write_byte( 0 );
message_end();
}
set_pev( player, pev_weaponmodel, PlayerOriginalViewmodel[ player ] );
new weaponID = get_pdata_cbase( player, m_pClientActiveItem );
if( weaponID > 0 )
{
ExecuteHam( Ham_Item_Deploy, weaponID );
}
}
set_pev( player, pev_flags, PlayerOriginalFlags[ player ] );
PlayerIsUsingAttack[ player ] = false;
restoreClientPrediction( player );
tryDeletePlayerCameraData( player );
tryDeleteSpikesData( player );
tryDeleteAnimationData( player );
}
tryDeletePlayerCameraData( const player )
{
if( PlayerCameraOriginQueue[ player ] )
{
ArrayDestroy( PlayerCameraOriginQueue[ player ] );
ArrayDestroy( PlayerCameraAnglesQueue[ player ] );
PlayerCameraOriginQueue[ player ] = Array:0;
PlayerCameraAnglesQueue[ player ] = Array:0;
}
}
tryDeleteSpikesData( const player )
{
new Array:playerSpikeOriginQueue = PlayerSpikeOriginQueue[ player ][ Queue ];
if( playerSpikeOriginQueue )
{
new playerSpikeData[ PlayerSpikeData ];
new Array:bodies;
new spike;
new queueSize = ArraySize( playerSpikeOriginQueue );
for( new i = 0, j, bodiesSize; i < queueSize; i++ )
{
ArrayGetArray( playerSpikeOriginQueue, i, playerSpikeData );
spike = playerSpikeData[ SpikeID ];
bodies = Array:pev( spike, pev_iuser1 );
if( bodies )
{
bodiesSize = ArraySize( bodies );
for( j = 0; j < bodiesSize; j++ )
{
remove_entity( ArrayGetCell( bodies, j ) );
}
}
remove_entity( spike );
}
ArrayDestroy( playerSpikeOriginQueue );
PlayerSpikeOriginQueue[ player ][ Queue ] = 0;
}
}
tryDeleteAnimationData( const player )
{
new animatingEntity = PlayerAnimationQueue[ player ][ EntityID ];
if( animatingEntity )
{
ArrayDestroy( PlayerAnimationQueue[ player ][AnimationPack] );
PlayerAnimationQueue[ player ][ EntityID ] = 0;
}
}
public client_PreThink( player )
{
static Float:origin[ 3 ];
static Float:angles[ 3 ];
if( PlayerCameraOriginQueue[ player ] )
{
new Array:cameraOrigins = PlayerCameraOriginQueue[ player ];
new Array:cameraAngles = PlayerCameraAnglesQueue[ player ];
ArrayGetArray( cameraOrigins, 0, origin );
ArrayGetArray( cameraAngles, 0, angles );
entity_set_origin( player, origin );
set_pev( player, pev_angles, angles );
set_pev( player, pev_v_angle, angles );
set_pev( player, pev_fixangle, 1 );
if( ArraySize( cameraOrigins ) > 1 )
{
ArrayDeleteItem( cameraOrigins, 0 );
ArrayDeleteItem( cameraAngles, 0 );
}
}
new Array:playerSpikeOriginQueue = PlayerSpikeOriginQueue[ player ][ Queue ];
if( playerSpikeOriginQueue )
{
static playerSpikeData[ PlayerSpikeData ];
static Float:lastTimeMadeBlood;
static Float:currentTime;
static Array:spikesOrigins;
static Array:bodies;
static spike;
static bodiesSize;
static body;
for( new i = 0, j, k; i < ArraySize( playerSpikeOriginQueue ); i++ )
{
ArrayGetArray( playerSpikeOriginQueue, i, playerSpikeData );
spike = playerSpikeData[ SpikeID ];
spikesOrigins = playerSpikeData[ SpikeOrigins ];
if( ArraySize( spikesOrigins ) > 0 )
{
ArrayGetArray( spikesOrigins, 0, origin );
bodies = Array:pev( spike, pev_iuser1 );
if( bodies )
{
static Float:oldOrigin[ 3 ];
static Float:originDiff[ 3 ];
static Float:bodyOrigin[ 3 ];
pev( spike, pev_origin, oldOrigin );
xs_vec_sub( origin, oldOrigin, originDiff );
bodiesSize = ArraySize( bodies );
for( j = 0; j < bodiesSize; j++ )
{
body = ArrayGetCell( bodies, j );
pev( body, pev_origin, bodyOrigin );
pev( body, pev_fuser1, lastTimeMadeBlood );
xs_vec_add( bodyOrigin, originDiff, bodyOrigin );
entity_set_origin( body, bodyOrigin );
currentTime = get_gametime();
if( ( lastTimeMadeBlood + BloodInterval + random_float( -1.0, 1.0 ) ) <= currentTime )
{
set_pev( body, pev_fuser1, currentTime );
makeBloodAt( bodyOrigin );
}
}
}
entity_set_origin( spike, origin );
ArrayDeleteItem( spikesOrigins, 0 );
if( !ArraySize( spikesOrigins ) )
{
ArrayDeleteItem( playerSpikeOriginQueue, i-- );
remove_entity( spike );
if( bodies )
{
for( k = 0; k < ArraySize( bodies ); k++ )
{
remove_entity( ArrayGetCell( bodies, i ) );
}
}
}
}
}
if( --PlayerSpikeOriginQueue[ player ][ UnemergeFramesMissing ] == 0 )
{
pev( PlayerLookalike[ player ], pev_origin, origin );
engfunc( EngFunc_EmitAmbientSound, 0, origin, SpikeUnemergeSound, VOL_NORM, ATTN_NORM, 0, PITCH_NORM );
}
if( !ArraySize( playerSpikeOriginQueue ) )
{
PlayerSpikeOriginQueue[ player ][ Queue ] = 0;
new callbackFuncID = PlayerSpikeOriginQueue[ player ][ SpikeCallbackFuncID ];
if( callbackFuncID )
{
callfunc_begin_i( callbackFuncID );
callfunc_push_int( player );
callfunc_end();
}
}
}
new animatingEntity = PlayerAnimationQueue[ player ][ EntityID ];
if( animatingEntity )
{
new Array:animationPack = Array:PlayerAnimationQueue[ player ][ AnimationPack ];
new frame = ArrayGetCell( animationPack, 0 );
set_pev( animatingEntity, pev_frame, frame );
ArrayDeleteItem( animationPack, 0 );
if( !ArraySize( animationPack ) )
{
PlayerAnimationQueue[ player ][ EntityID ] = 0;
new callbackFuncID = PlayerAnimationQueue[ player ][ CallbackFuncID ];
if( callbackFuncID )
{
callfunc_begin_i( callbackFuncID );
callfunc_push_int( animatingEntity );
callfunc_end();
}
}
}
}
makeBloodAt( const Float:origin[ 3 ] )
{
message_begin( MSG_BROADCAST, SVC_TEMPENTITY );
write_byte( TE_BLOODSTREAM );
engfunc( EngFunc_WriteCoord, origin[ 0 ] );
engfunc( EngFunc_WriteCoord, origin[ 1 ] );
engfunc( EngFunc_WriteCoord, origin[ 2 ] );
write_coord( random_num( -360, 360 ) );
write_coord( random_num( -360, 360 ) );
write_coord( random_num( 180, 360 ) );
write_byte( 70 );
write_byte( 100 );
message_end();
}
/*
┌───────────────────┐
│ CAMERA HANDLING │
└───────────────────┘
→ calculatePlayerCameraData()
*/
calculatePlayerCameraData( const player, Float:origin[ 3 ], Float:angles[ 3 ] )
{
new Array:cameraOrigins = ArrayCreate( 3 );
new Array:cameraAngles = ArrayCreate( 3 );
new Float:dislocationVector[ 3 ];
new Float:dislocation[ 3 ];
new Float:dislocatedOrigin[ 3 ];
angle_vector( angles, ANGLEVECTOR_FORWARD, dislocationVector );
xs_vec_mul_scalar( dislocationVector, RotationRadius, dislocation );
xs_vec_add( origin, dislocation, dislocatedOrigin );
angles[ 1 ] -= 180.0;
new Float:point[ 3 ];
new Float:pointOriginDiff[ 3 ];
new Float:cameraAngle[ 3 ];
for( new i = 1; i <= FramesPerCameraRotation; i++ )
{
angle_vector( angles, ANGLEVECTOR_FORWARD, point );
xs_vec_mul_scalar( point, RotationRadius, point );
xs_vec_add( dislocatedOrigin, point, point );
ArrayPushArray( cameraOrigins, point );
xs_vec_sub( origin, point, pointOriginDiff );
xs_vec_normalize( pointOriginDiff, pointOriginDiff );
vector_to_angle( pointOriginDiff, cameraAngle );
ArrayPushArray( cameraAngles, cameraAngle );
angles[ 1 ] += DegreeIncreasePerFrame;
}
PlayerCameraOriginQueue[ player ] = cameraOrigins;
PlayerCameraAnglesQueue[ player ] = cameraAngles;
}
/*
┌───────────────────────────┐
│ PACK ANIMATION HANDLING │
└───────────────────────────┘
→ packAnimations()
→ getAnimationPack()
*/
packAnimations()
{
new Array:animationPack;
new animationFirstFrame;
new animationFinalFrame;
new animationFramesPerServerFrame;
new increment;
for( new Animation:i = Animation:0, frame, frameCopy; i < Animation; i++ )
{
animationPack = ArrayCreate()
animationFirstFrame = AnimationsData[ i ][ FirstFrame ];
animationFinalFrame = AnimationsData[ i ][ FinalFrame ];
animationFramesPerServerFrame = AnimationsData[ i ][ FramesPerServerFrame ];
increment = ( animationFirstFrame < animationFinalFrame ) ? 1 : -1;
for( frame = animationFirstFrame; frame != animationFinalFrame + increment ; frame += increment )
{
for( frameCopy = 1; frameCopy <= animationFramesPerServerFrame; frameCopy++ )
{
ArrayPushCell( animationPack ,float( frame ) );
}
}
AnimationsPacked[ i ] = animationPack;
}
}
Array:getAnimationPack( Animation:animation )
{
new Array:animationPack = ArrayCreate();
new Array:originalAnimationPack = AnimationsPacked[ animation ];
new pachSize = ArraySize( originalAnimationPack );
for(new i = 0; i < pachSize; i++)
{
ArrayPushCell( animationPack, ArrayGetCell( originalAnimationPack, i ) );
}
return animationPack;
}
/*
┌─────────────────────────┐
│ CLIENT CVARS HANDLING │
└─────────────────────────┘
→ removeClientPrediction()
→ restoreClientPrediction()
*/
removeClientPrediction( const player )
{
client_cmd( player, "cl_vsmoothing 0" );
client_cmd( player, "cl_nosmooth 1" );
client_cmd( player, "cl_smoothtime 0" );
}
restoreClientPrediction( const player )
{
client_cmd( player, "cl_vsmoothing 0.05" );
client_cmd( player, "cl_nosmooth 0" );
client_cmd( player, "cl_smoothtime 0.1" );
}
/*
┌──────────────────┐
│ SPIKE HANDLING │
└──────────────────┘
→ Spike_PlayerTouch()
└ attachToSpike()
└ createBody()
→ finishSummoningAnimation()
└ calculateSpikesData()
└ getSpike()
→ finishSpikeMovement()
└ protospikeFinish()
*/
public Spike_PlayerTouch( const player, const spike )
{
if( is_user_alive( player ) )
{
attachToSpike( spike, createBody( player, spike ) );
ExecuteHam (Ham_Killed, player, pev( spike, pev_owner ), 0 );
set_pev( player, pev_effects, pev( player, pev_effects ) | EF_NODRAW );
PlayerPreventCorpse[ player ] = true;
}
}
attachToSpike( const spike, const body )
{
new Array:bodies = Array:pev( spike, pev_iuser1 );
if( !bodies )
{
set_pev( spike, pev_iuser1, bodies = ArrayCreate() );
}
ArrayPushCell( bodies, body );
fm_set_user_rendering( spike, kRenderFxGlowShell, .amount = 10, .r = 50, .g = 50, .b = 50 );
}
createBody( const player, const spike )
{
new body = create_entity( "info_target" );
const sequence = 8;
static model[ 20 ];
static modelPath[ 100 ];
cs_get_user_model( player, model, charsmax( model ) );
formatex( modelPath, charsmax( modelPath ), "models/player/%s/%s.mdl", model, model );
set_pev( body, pev_framerate, 0.0 );
set_pev( body, pev_sequence, sequence );
set_pev( body, pev_frame, random_float( 17.0, 22.0 ) );
entity_set_model( body, modelPath );
set_pev( body, pev_movetype, MOVETYPE_NONE );
set_pev( body ,pev_solid, SOLID_NOT );
static Float:origin[ 3 ];
static Float:angles[ 3 ];
static Float:spikeOrigin[ 3 ];
pev( player, pev_origin, origin );
pev( player, pev_angles, angles );
set_pev( body, pev_angles, angles );
set_pev( body, pev_fixangle, 1 );
pev( spike, pev_origin, spikeOrigin );
engfunc( EngFunc_TraceModel, origin, spikeOrigin, HULL_POINT, spike, 0 );
get_tr2( 0, TR_vecEndPos, origin );
origin[ 2 ] -= random_float( 30.0, 40.0 );
entity_set_origin( body, origin );
return body;
}
public finishSummoningAnimation( const entity )
{
calculateSpikesData( pev( entity, pev_owner ) );
new Float:origin[ 3 ];
pev( entity, pev_origin, origin );
engfunc( EngFunc_EmitAmbientSound, 0, origin, SpikeEmergeSound, VOL_NORM, ATTN_NORM, 0, PITCH_NORM );
}
public finishSpikeMovement( const player )
{
protospikeFinish( player );
}
calculateSpikesData( const player )
{
new lookalike = PlayerLookalike[ player ];
new Float:origin[ 3 ];
new Float:angles[ 3 ];
new Float:position[ 3 ];
new Float:positionTrace[ 3 ];
pev( lookalike, pev_origin, origin );
new spikesNumber = SpikesFirstCircle;
new Float:radius = SpikeCalcRadiusStart;
new Float:radiusIncrement = SpikeCalcRadiusIncrement;
new Array:playerSpikes = ArrayCreate( _:PlayerSpikeData );
new Array:spikesOrigins;
new longerAnimationFrames;
new longerAnimationFramesFramesDown;
new playerSpikeData[ PlayerSpikeData ];
new Float:maxHeight;
new Float:anglesIncrement;
new spike;
new framesUp;
new framesDown;
new frames;
for( new i = 0, j, k; i < SpikesCircles; i++ )
{
angles[ 1 ] = random_float( 0.0, 360.0 );
anglesIncrement = 360.0 / spikesNumber;
for( j = 0; j < spikesNumber; j++ )
{
angle_vector( angles, ANGLEVECTOR_FORWARD, position );
xs_vec_mul_scalar( position, radius, position );
xs_vec_add( origin, position, position );
xs_vec_copy( position, positionTrace );
positionTrace[ 2 ] = -9999.99;
trace_line( 0, position, positionTrace, position );
position[ 2 ] += SpikeMinHeight;
spike = getSpike( player );
maxHeight = random_float( SpikesMaxHeightMin, SpikesMaxHeightMax );
framesUp = floatround( ( maxHeight + floatabs( SpikeMinHeight ) ) / SpikeHeightIncrementPerFrame, floatround_ceil );
framesDown = floatround( ( maxHeight + floatabs( SpikeMinHeight) ) / SpikeHeightDecrementPerFrame, floatround_ceil );
frames = framesUp + SpikeFramesIdle + framesDown;
if( frames > longerAnimationFrames )
{
longerAnimationFrames = frames;
longerAnimationFramesFramesDown = framesDown;
}
spikesOrigins = ArrayCreate( 3 );
ArrayPushArray( spikesOrigins, position );
for( k = 0; k < framesUp; k++ )
{
position[ 2 ] += SpikeHeightIncrementPerFrame;
ArrayPushArray( spikesOrigins, position );
}
for( k = 0; k < SpikeFramesIdle; k++ )
{
ArrayPushArray( spikesOrigins, position );
}
for( k = 0; k < framesDown; k++ )
{
position[ 2 ] -= SpikeHeightDecrementPerFrame + random_float( -1.2, 1.2 );
ArrayPushArray( spikesOrigins, position );
}
playerSpikeData[ SpikeID ] = spike;
playerSpikeData[ SpikeOrigins ] = _:spikesOrigins;
ArrayPushArray( playerSpikes, playerSpikeData );
radius += radiusIncrement;
angles[ 1 ] += anglesIncrement;
}
spikesNumber += SpikesPerCircleIncrease;
}
PlayerSpikeOriginQueue[ player ][ Queue ] = _:playerSpikes
PlayerSpikeOriginQueue[ player ][ SpikeCallbackFuncID ] = get_func_id( "finishSpikeMovement" );
PlayerSpikeOriginQueue[ player ][ UnemergeFramesMissing ] = longerAnimationFrames - floatround( ( float( longerAnimationFramesFramesDown ) / 1.2 ) );
}
getSpike( const player )
{
new entity = create_entity( "info_target" );
set_pev( entity, pev_owner, player );
set_pev( entity, pev_classname, SpikeClassname );
set_pev( entity, pev_solid, SOLID_BBOX );
entity_set_model( entity, SpikeModel );
entity_set_origin( entity, Float:{ 0.0, 0.0, 0.0 } );
entity_set_size( entity, Float:{ -5.0, -5.0, -100.0 }, Float:{ 5.0, 5.0, 100.0 } );
return entity;
}
|
|