diff options
Diffstat (limited to 'internal_rewrite/ragebot_resolver.cpp')
| -rw-r--r-- | internal_rewrite/ragebot_resolver.cpp | 626 |
1 files changed, 0 insertions, 626 deletions
diff --git a/internal_rewrite/ragebot_resolver.cpp b/internal_rewrite/ragebot_resolver.cpp deleted file mode 100644 index 1b29305..0000000 --- a/internal_rewrite/ragebot_resolver.cpp +++ /dev/null @@ -1,626 +0,0 @@ -#include "ragebot.hpp"
-#include "context.hpp"
-#include "base_cheat.hpp"
-#include "math.hpp"
-#include "input_system.hpp"
-
-namespace features
-{
- constexpr float FLT_ANG_LBY = 360.f;
- constexpr float FLT_ANG_MOVING_LBY_UP = -360.f;
- constexpr float FLT_ANG_180 = 720.f;
- constexpr float FLT_ANG_FREESTANDING = -720.f;
- constexpr float FLT_ANG_90 = 480.f;
- constexpr float FLT_ANG_MINUS_90 = -480.f;
- constexpr float FLT_ANG_MINUS_135 = -700.f;
- constexpr float FLT_ANG_135 = 700.f;
- constexpr float FLT_ANG_PITCH_UP = 1080.f;
-
- static const std::vector< float > possible_angles_none = {
- FLT_ANG_MOVING_LBY_UP,
- FLT_ANG_180,
- FLT_ANG_90,
- FLT_ANG_MINUS_90,
- FLT_ANG_MINUS_135,
- FLT_ANG_135,
- };
-
- static const std::vector< float > possible_angles_normal = {
- FLT_ANG_MOVING_LBY_UP,
- FLT_ANG_180,
- FLT_ANG_135,
- FLT_ANG_MINUS_135
- };
-
- static const std::vector< float > possible_angles_freestanding = {
- 0.f,
- 45.f,
- 90.f,
- 135.f,
- 180.f,
- };
-
- bool dbg_resolver( ) {
- static con_var< bool > var{ &data::holder_, fnv( "dbg_resolver" ), false };
- return var( );
- }
-
- int c_ragebot::c_resolver::try_freestanding( c_base_player* ent ) {
- if( !( ent->m_fFlags( ) & FL_ONGROUND ) || ( ent->get_anim_velocity( ).length2d( ) > 0.1f && !ent->is_fakewalking( ) ) )
- return -1;
-
- int ret_dir = -1;
- float cur_damage = 0.f;
-
- vec3_t enemy_pos = ent->m_vecOrigin( );
- enemy_pos.z = ent->get_hitbox_pos( 0 ).z;
-
- vec3_t local_pos = g_ctx.m_local->get_eye_pos( );
- local_pos -= g_ctx.m_local->m_vecOrigin( );
- local_pos += g_ctx.m_last_origin;
-
- vec3_t aim_angle = math::vector_angles(
- enemy_pos,
- local_pos
- );
-
- auto get_damage = [ & ]( const vec3_t& start, const vec3_t& end, c_base_player* a, c_base_player* b ) {
- static weapon_info_t wpn_data{ };
- wpn_data.damage = 200;
- wpn_data.range_modifier = 1.0f;
- wpn_data.penetration = 3.0f;
- wpn_data.armor_ratio = 0.5f;
- wpn_data.range = 8192.f;
-
- fire_bullet_data_t data{ };
- data.src = start;
- data.travel_range = ( end - data.src ).length( );
- data.traveled = 0.f;
- data.to_travel = data.travel_range;
-
- vec3_t angle = math::vector_angles( start, end );
- data.direction = math::angle_vectors( angle );
-
- data.direction.normalize_vector( );
-
- if( g_cheat.m_autowall.fire_bullet( a, b, &wpn_data, data, false, false ) ) {
- return data.current_damage;
- }
-
- return -1.f;
- };
-
- auto trace_ent_pos = [ & ]( vec3_t start, vec3_t end, c_base_player* ent ) {
- Ray_t ray;
- CGameTrace tr;
- CTraceFilter filter;
-
- const vec3_t min( -2.f, -2.f, -2.f );
- const vec3_t max( 2.f, 2.f, 2.f );
-
- ray.Init( start, end, min, max );
- filter.pSkip = ent;
-
- g_csgo.m_trace( )->TraceRay( ray, MASK_SHOT, &filter, &tr );
-
- return tr.endpos;
- };
-
- float local_dist = 75.f;
- float enemy_dist = 75.f;
-
- float start_dmg = get_damage( enemy_pos, local_pos, g_ctx.m_local, ent );
-
- auto test_dmg = [ & ]( float dist, float enemy_dist, float delta = 50.f ) {
- vec3_t enemy_left = math::get_rotated_pos( enemy_pos, aim_angle.y - 90.f, enemy_dist );
- vec3_t enemy_right = math::get_rotated_pos( enemy_pos, aim_angle.y + 90.f, enemy_dist );
-
- enemy_left = trace_ent_pos( enemy_pos, enemy_left, ent );
- enemy_right = trace_ent_pos( enemy_pos, enemy_right, ent );
-
- vec3_t local_left = math::get_rotated_pos( local_pos, aim_angle.y + 90.f, dist );
- vec3_t local_right = math::get_rotated_pos( local_pos, aim_angle.y - 90.f, dist );
-
- local_left = trace_ent_pos( local_pos, local_left, g_ctx.m_local );
- local_right = trace_ent_pos( local_pos, local_right, g_ctx.m_local );
-
- float dmg_left = get_damage( local_left, enemy_left, g_ctx.m_local, ent )
- + get_damage( local_right, enemy_left, g_ctx.m_local, ent );
-
- float dmg_right = get_damage( local_left, enemy_right, g_ctx.m_local, ent )
- + get_damage( local_right, enemy_right, g_ctx.m_local, ent );
-
- if( std::abs( dmg_left - dmg_right ) < delta )
- return false;
-
- float max_dmg = math::max( dmg_left, dmg_right );
- ret_dir = dmg_left > dmg_right;
-
- cur_damage = max_dmg;
- return max_dmg > delta;
- };
-
- float radius = std::floorf( ( g_ctx.m_local->get_hitbox_pos( 0 ) - g_ctx.m_local->get_hitbox_pos( HITBOX_PELVIS ) ).length2d( ) );
- radius = radius >= 15.f ? 20.f : 10.f;
-
- float enemy_radius = std::floorf( ( ent->get_hitbox_pos( 0 ) - ent->get_hitbox_pos( HITBOX_PELVIS ) ).length2d( ) );
- enemy_radius = enemy_radius >= 15.f ? 20.f : 10.f;
-
- if( !test_dmg( enemy_radius + 1.f, radius + 1.f, 25.f ) ) {
- if( cur_damage < start_dmg * 2.f )
- return -1;
- }
-
- bool found = false;
-
- for( size_t i = 5; i > 0; --i ) {
- float cur_dist = local_dist / i;
- float cur_enemy_dist = enemy_dist / i;
-
- if( cur_dist < radius )
- continue;
-
- if( cur_enemy_dist < enemy_radius )
- continue;
-
- if( test_dmg( cur_enemy_dist, cur_dist, 125.f / i ) ) {
- found = true;
- break;
- } else if( cur_damage > 125.f / i )
- break;
- }
-
- if( !found )
- return -1;
-
- return ret_dir;
- }
-
- void c_ragebot::c_resolver::resolve_log_t::update( int ent_index ) {
- static C_AnimationLayer last_layer[ 65 ]{ };
- auto ent = g_csgo.m_entlist( )->GetClientEntity< >( ent_index );
-
- if( !ent || ent == g_ctx.m_local || !ent->is_player( ) || !ent->is_alive( ) || ent->ce( )->IsDormant( ) || !ent->has_valid_anim( ) ) {
- m_was_invalid = true;
- m_has_valid_lby = false;
- return;
- }
-
- if( m_was_invalid && m_last_pos.dist_to( ent->m_vecOrigin( ) ) > 4.f )
- reset( );
-
- if( !( ent->m_fFlags( ) & FL_ONGROUND ) ) {
- m_state = R_NONE;
- return;
- }
-
- if( ent->get_anim_velocity( ).length2d( ) > 0.1f && !ent->is_fakewalking( ) ) {
- m_state = R_NONE;
- m_has_valid_lby = true;
- m_last_moving_lby = ent->m_flLowerBodyYawTarget( );
- return;
- }
-
- m_last_pos = ent->m_vecOrigin( );
-
- m_was_invalid = false;
-
- int freestanding = g_cheat.m_ragebot.m_resolver->try_freestanding( ent );
-
- if( freestanding != -1 ) {
- m_state = R_FREESTANDING;
- }
- else
- m_state = R_NORMAL;
-
- if( m_last_freestanding != freestanding )
- m_angle_change = true;
-
- m_last_freestanding = freestanding;
- m_has_valid_lby = true;
- }
-
- void c_ragebot::c_resolver::resolve_log_t::reset( ) {
- //assuming theyre STILL not moving this shouldnt change
- //however if they are, it will be reset to none anyway
- m_state = R_NONE;
- m_last_update = 0.f;
- m_last_lby = 0.f;
- m_missed_shots = 0;
- memset( m_shots, 0, sizeof( m_shots ) );
- memset( m_logged, 0, sizeof( m_logged ) );
- memset( m_logged_shots, 0, sizeof( m_logged ) );
- }
-
- std::vector< float > c_ragebot::c_resolver::get_shot_vec( int ent ) {
- auto& data = m_data[ ent ];
-
- if( data.m_state == R_NORMAL )
- return possible_angles_normal;
- if( data.m_state == R_FREESTANDING )
- return possible_angles_freestanding;
-
- return possible_angles_none;
- }
-
- float c_ragebot::c_resolver::get_shot_yaw( int shots, int ent_index ) {
- auto& data = m_data[ ent_index ];
- auto ent = g_csgo.m_entlist( )->GetClientEntity< >( ent_index );
-
- auto vec = get_shot_vec( ent_index );
-
- float new_ang = vec.at( shots % vec.size( ) );
- float new_yaw = 0.f;
-
- float ang = math::vector_angles( ent->m_vecOrigin( ), g_ctx.m_last_origin ).y;
-
- if( data.m_state == R_FREESTANDING ) {
- ang += ( data.m_last_freestanding == 1 ? 90.f : -90.f );
-
- float sign = data.m_last_freestanding == 1 ? 1.f : -1.f;
-
- return ang + new_ang * sign;
- }
-
- if( new_ang == FLT_ANG_LBY )
- new_yaw = ent->m_flLowerBodyYawTarget( );
- else if( new_ang == FLT_ANG_MOVING_LBY_UP ) {
- if( !data.m_has_valid_lby && !g_settings.rage.pitch_resolver ) {
- return get_shot_yaw( ++get_resolver_shots( ent_index ), ent_index );
- }
-
- auto delta = std::remainderf( data.m_last_moving_lby - data.m_last_lby, 360.f );
- bool breaking_lby = std::abs( delta ) > 35.f;
-
- new_yaw = breaking_lby ? data.m_last_moving_lby : data.m_last_lby;
- }
- else if( new_ang == FLT_ANG_180 ) {
- new_yaw = ang - 180.f;
- }
- else if( new_ang == FLT_ANG_MINUS_90 ) {
- new_yaw = ang - 90.f;
- }
- else if( new_ang == FLT_ANG_90 ) {
- new_yaw = ang + 90.f;
- }
- else if( new_ang == FLT_ANG_135 )
- new_yaw = ang + 135.f;
- else if( new_ang == FLT_ANG_MINUS_135 )
- new_yaw = ang - 135.f;
- else
- new_yaw = std::remainderf( ent->m_flLowerBodyYawTarget( ) + new_ang, 360.f );
-
- return new_yaw;
- }
-
- void c_ragebot::c_resolver::aimbot( int ent_index, int hitbox, vec3_t angle, vec3_t position, vec3_t min, vec3_t max, float radius ) {
- if( !g_cheat.m_player_mgr.is_cheater( ent_index ) )
- return;
-
- auto& data = m_data[ ent_index ];
-
- auto ent = g_csgo.m_entlist( )->GetClientEntity< >( ent_index );
- bool moving = ent->get_anim_velocity( ).length2d( ) > 0.1f && ( ent->m_fFlags( ) & FL_ONGROUND );
-
- if( moving && !ent->is_fakewalking( ) ) {
- return;
- }
-
- if( !data.m_state ) {
- increment_shots( ent_index );
- return;
- }
-
- auto model = ent->ce( )->GetModel( );
- auto hdr = g_csgo.m_model_info( )->GetStudiomodel( model );
- auto set = hdr->pHitboxSet( ent->m_nHitboxSet( ) );
-
- if( hitbox == HITBOX_HEAD ) {
- auto box = set->pHitbox( 0 );
- if( box ) {
- auto dist = box->bbmin.dist_to( box->bbmax );
-
- context::shot_data_t new_shot{ };
- new_shot.m_angle = angle;
- new_shot.m_enemy_pos = position;
- new_shot.m_enemy_index = ent_index;
- new_shot.m_local_pos = g_ctx.m_local->get_eye_pos( );
- new_shot.m_resolver_shots = get_resolver_shots( ent_index );
- new_shot.m_resolver_state = true;
- new_shot.m_hitbox.min = min;
- new_shot.m_hitbox.min = max;
- new_shot.m_hitbox.radius = radius;
- new_shot.m_missed = true;
- new_shot.m_hitgroup = HITGROUP_HEAD;
-
- g_ctx.m_last_shot++;
- g_ctx.m_last_shot %= 128;
- g_ctx.m_shot_data[ g_ctx.m_last_shot ] = new_shot;
-
- g_ctx.m_has_incremented_shots = true;
-
-
- data.m_snapshot[ g_ctx.m_last_shot ] = data;
-
- if( data.m_logged[ data.m_state ] ) {
- if( !--data.m_logged_shots[ data.m_state ] ) {
- data.m_logged[ data.m_state ] = false;
- }
- }
- else {
- int shots = get_resolver_shots( ent_index );
-
- increment_shots( ent_index );
-
-#if _DEBUG
- if( dbg_resolver( ) ) {
- char str[ 128 ];
- sprintf_s< 128 >( str, "[\3moneybot\1] incrementing shots from %d to %d"
- "[\3moneybot\1] resolver state: %d\n", shots, get_resolver_shots( ent_index ), data.m_state );
-
- g_csgo.m_clientmode( )->m_pChatElement->ChatPrintf( 0, 0, str );
- }
-#endif
- }
- }
- }
- else {
- matrix3x4 bone_matrix[ 128 ];
- if( model && hdr && set && ent->ce( )->SetupBones( bone_matrix, 128, 0x100, g_csgo.m_globals->m_curtime ) ) {
- auto box = set->pHitbox( hitbox );
- if( !box ) return;
-
- auto origin = ent->m_vecOrigin( );
-
- vec3_t shot_pos = position;
- vec3_t rotated_center;
-
- vec3_t offset = position - origin;
- float radius = offset.length2d( );
- float cosine = offset.x / radius;
-
- float deg = RAD2DEG( acos( cosine ) );
- if( offset.y < 0 ) deg += 360.f;
-
- float rot = ( deg - 180.f ) * ( M_PI / 180.f );
- rotated_center.x = origin.x + cos( rot ) * radius;
- rotated_center.y = origin.y + sin( rot ) * radius;
- rotated_center.z = position.z;
-
- Ray_t ray;
- CTraceFilterOneEntity filter;
- CGameTrace tr_center;
- CGameTrace tr_rot;
-
- filter.ent = ent;
-
- ray.Init( g_ctx.m_local->get_eye_pos( ), position );
- g_csgo.m_trace( )->TraceRay( ray, MASK_SHOT, &filter, &tr_center );
-
- ray.Init( g_ctx.m_local->get_eye_pos( ), rotated_center );
- g_csgo.m_trace( )->TraceRay( ray, MASK_SHOT, &filter, &tr_rot );
-
- bool is_within = tr_center.hitbox == tr_rot.hitbox;
-
- if( !is_within ) {
- auto dist = box->bbmin.dist_to( box->bbmax );
-
- context::shot_data_t new_shot{ };
- new_shot.m_angle = angle;
- new_shot.m_enemy_pos = position;
- new_shot.m_enemy_index = ent_index;
- new_shot.m_local_pos = g_ctx.m_local->get_eye_pos( );
- new_shot.m_resolver_shots = get_resolver_shots( ent_index );
- new_shot.m_resolver_state = true;
- new_shot.m_hitbox.min = min;
- new_shot.m_hitbox.min = max;
- new_shot.m_hitbox.radius = radius;
- new_shot.m_missed = true;
- new_shot.m_hitgroup = util::hitbox_to_hitgroup( hitbox );
-
- g_ctx.m_last_shot++;
- g_ctx.m_last_shot %= 128;
- g_ctx.m_shot_data[ g_ctx.m_last_shot ] = new_shot;
-
- g_ctx.m_has_incremented_shots = true;
-
- data.m_snapshot[ g_ctx.m_last_shot ] = data;
-
- if( data.m_logged[ data.m_state ] ) {
- if( !--data.m_logged_shots[ data.m_state ] ) {
- data.m_logged[ data.m_state ] = false;
- }
- }
- else {
- int shots = get_resolver_shots( ent_index );
- increment_shots( ent_index );
-
-#if _DEBUG
- if( dbg_resolver( ) ) {
- char str[ 128 ];
- sprintf_s< 128 >( str, "[\3moneybot\1] incrementing shots from %d to %d"
- "[\3moneybot\1] resolver state: %d\n", shots, get_resolver_shots( ent_index ), data.m_state );
-
- g_csgo.m_clientmode( )->m_pChatElement->ChatPrintf( 0, 0, str );
- }
-#endif
- }
- }
- }
- }
-
- //printf( "resolver: logging aimbot shot %d missed: %d state: %d time: %f\n",
- // data.m_shots, data.m_missed_shots[ data.m_breaking ], data.m_breaking, g_Interfaces.Globals->curtime );
- }
-
- void c_ragebot::c_resolver::increment_shots( int ent_index ) {
- get_resolver_shots( ent_index )++;
- m_data[ ent_index ].m_missed_shots++;
- m_data[ ent_index ].m_angle_change = true;
- }
-
- void c_ragebot::c_resolver::on_missed_spread( int ent_index, int shots ) {
- if( !g_cheat.m_player_mgr.is_cheater( ent_index ) )
- return;
-
- auto& data = m_data[ ent_index ];
- auto& snapshot = data.m_snapshot[ shots % 150 ];
-
- data.m_shots[ snapshot.m_state ] = snapshot.m_shots[ snapshot.m_state ];
-
- if( snapshot.m_logged[ snapshot.m_state ] ) {
- data.m_logged[ snapshot.m_state ] = true;
- data.m_logged_shots[ snapshot.m_state ] = snapshot.m_logged_shots[ snapshot.m_state ];
- }
- }
-
- void c_ragebot::c_resolver::listener( int ent_index, int shots ) {
- if( !g_cheat.m_player_mgr.is_cheater( ent_index ) )
- return;
-
- auto& data = m_data[ ent_index ];
- auto& snapshot = data.m_snapshot[ shots ];
-
- auto nci = g_csgo.m_engine( )->GetNetChannelInfo( );
- if( !nci )
- return;
-
- auto weapon = g_ctx.m_local->get_weapon( );
- if( !weapon )
- return;
-
- auto rate = weapon->get_wpn_info( )->cycle_time;
-
- data.m_shots[ snapshot.m_state ] = snapshot.m_shots[ snapshot.m_state ];
- data.m_logged[ snapshot.m_state ] = true;
-
- int latency_shots = ( nci->GetLatency( 0 ) + g_csgo.m_globals->m_frametime ) / rate + 1;
-
- data.m_logged_shots[ snapshot.m_state ] = latency_shots;
-
-#if _DEBUG
- if( dbg_resolver( ) ) {
- char str[ 128 ];
- sprintf_s< 128 >( str, "[\3moneybot\1] resolver: logging %d shots for %d with %d", data.m_logged_shots[ data.m_state ], ent_index, get_resolver_shots( ent_index ) );
-
- g_csgo.m_clientmode( )->m_pChatElement->ChatPrintf( 0, 0, str );
- }
-#endif
- }
-
- void c_ragebot::c_resolver::update_player( int i ) {
- if( !g_settings.rage.enabled( ) || !g_settings.rage.resolver( ) )
- return;
-
- if( !g_cheat.m_player_mgr.is_cheater( i ) )
- return;
-
- auto ent = g_csgo.m_entlist( )->GetClientEntity( i );
- bool was_invalid = m_data[ i ].m_was_invalid;
-
- m_data[ i ].update( i );
- if( g_settings.rage.resolver_override( ) ) {
- if( g_input.is_key_pressed( g_settings.rage.resolver_override_key( ) ) ) {
- int dir = manual_override( ent );
- if( dir ) {
- if( dir != m_data[ i ].m_overriding )
- m_data[ i ].m_angle_change = true;
-
- //to be finished
- m_data[ i ].m_overriding = dir;
- return;
- }
- }
- }
-
- m_data[ i ].m_overriding = 0;
- brute_force( ent );
- }
-
- void c_ragebot::c_resolver::frame_stage_notify( ) {
- if( !g_settings.rage.enabled( ) || !g_settings.rage.resolver( ) )
- return;
-
- if( !g_ctx.run_frame( ) || !g_ctx.m_local->is_valid( ) )
- return;
-
- for( int i{ 1 }; i < g_csgo.m_globals->m_maxclients; ++i ) {
- auto ent = g_csgo.m_entlist( )->GetClientEntity< >( i );
-
- if( !ent || ent == g_ctx.m_local || ent->ce( )->IsDormant( ) || !ent->is_player( )
- || !ent->is_alive( ) || !g_cheat.m_player_mgr.is_cheater( i ) ) {
- m_data[ i ].m_was_invalid = true;
- m_data[ i ].m_has_valid_lby = false;
- continue;
- }
-
- if( ent->m_iTeamNum( ) == g_ctx.m_local->m_iTeamNum( ) && !g_settings.rage.friendlies )
- continue;
-
- //update_player( i );
- }
- }
-
- void c_ragebot::c_resolver::force_yaw( c_base_player* ent, float yaw ) {
- ent->m_angEyeAngles( ).y = yaw;// + 180.f;
- }
-
- int c_ragebot::c_resolver::manual_override( c_base_player* ent ) {
- if( ent->get_animdata( ).m_anim_velocity.length2d( ) > 0.1f && !ent->is_fakewalking( ) ) { //no point in overriding moving targets, it will also fuck up backtrack records otherwise
- return OVERRIDE_NONE;
- }
-
- vec3_t pos;
- vec3_t angle;
- vec3_t local_angle;
- vec3_t local_pos;
- float delta;
- float dist;
-
-
- local_pos = g_ctx.m_local->m_vecOrigin( );
- g_csgo.m_engine( )->GetViewAngles( local_angle );
- pos = ent->get_hitbox_pos( 0 );
-
- angle = math::vector_angles( local_pos, pos );
- dist = pos.dist_to( local_pos );
- delta = ( angle - local_angle ).clamp( ).y;
- float yaw_delta = sin( DEG2RAD( ( angle - local_angle ).clamp( ).y ) ) * dist;
-
- if( std::abs( yaw_delta ) < 25.f ) {
- force_yaw( ent, angle.y );
- return OVERRIDE_CENTER;
- }
- else {
- force_yaw( ent, angle.y + ( ( delta < 0.f ) ? 90.f : -90.f ) );
- return delta > 0.f ? OVERRIDE_LEFT : OVERRIDE_RIGHT;
- }
- }
-
- void c_ragebot::c_resolver::force_lby( c_base_player* ent ) {
- force_yaw( ent, ent->m_flLowerBodyYawTarget( ) );
- }
-
- void c_ragebot::c_resolver::brute_force( c_base_player* ent ) {
- if( ent->m_flSimulationTime( ) == g_cheat.m_ragebot.m_lagcomp->get_last_updated_simtime( ent->ce( )->GetIndex( ) ) )
- return;
-
- if( ent->get_anim_velocity( ).length( ) > 0.1f && ( ent->m_fFlags( ) & FL_ONGROUND ) && !ent->is_fakewalking( ) ) {
- m_data[ ent->ce( )->GetIndex( ) ].m_last_moving_lby = ent->m_flLowerBodyYawTarget( );
- m_data[ ent->ce( )->GetIndex( ) ].m_has_valid_lby = true;
- force_lby( ent );
- return;
- }
-
- int i = ent->ce( )->GetIndex( );
- int s = get_resolver_shots( i );
- auto vec = get_shot_vec( i );
-
- if( vec.at( s % vec.size( ) ) == FLT_ANG_MOVING_LBY_UP && g_settings.rage.pitch_resolver )
- ent->m_angEyeAngles( ).x = -89.f;
-
- float new_yaw = get_shot_yaw( get_resolver_shots( i ), i );
-
- force_yaw( ent, new_yaw );
- }
-}
\ No newline at end of file |
