void CCharacterPhysicsSupport::in_Hit( SHit &H, bool is_killing ) { m_sv_hit = H; m_hit_valide_time = Device.dwTimeGlobal + hit_valide_time; if( m_EntityAlife.use_simplified_visual ( ) || esRemoved == m_eState ) return; if( m_flags.test( fl_block_hit ) ) { VERIFY2( !m_EntityAlife.g_Alive( ), make_string("entity [%s][%d] is dead", m_EntityAlife.Name(), m_EntityAlife.ID()).c_str()); if( Device.dwTimeGlobal - m_EntityAlife.GetLevelDeathTime( ) >= 2000 ) m_flags.set(fl_block_hit,FALSE); else return; } //is_killing = is_killing || ( m_eState==esAlive && !m_EntityAlife.g_Alive( ) ); if( m_EntityAlife.g_Alive( ) && is_killing && H.type( ) == ALife::eHitTypeExplosion && H.damage( ) > 70.f ) CPHDestroyable::Destroy( ); if( ( !m_EntityAlife.g_Alive() || is_killing ) ) m_character_shell_control.set_kill_hit( H ); if(!m_pPhysicsShell&&is_killing) KillHit( H ); if( m_flags.test(fl_use_hit_anims) && Type() != etBitting && !m_flags.test(fl_death_anim_on) ) //&& Type() == etStalker { m_hit_animations.PlayHitMotion( H.direction( ), H.bone_space_position(), H.bone( ), m_EntityAlife ); } if( !( m_pPhysicsShell && m_pPhysicsShell->isActive( ) ) ) { if( !is_killing && m_EntityAlife.g_Alive( ) ) m_PhysicMovementControl->ApplyHit( H.direction( ), H.phys_impulse( ), H.type( ) ); } else { #ifdef DEBUG if( is_killing && death_anim_debug && !is_imotion( m_interactive_motion ) ) { Msg( "death anim: applied fatal impulse dir: (%f,%f,%f), value: (%f) ", H.dir.x,H.dir.y,H.dir.z, H.impulse ); } #endif m_pPhysicsShell->applyHit( H.bone_space_position( ), H.direction( ), H.phys_impulse( ), H.bone(), H.type( ) ); } }
void CCar::PHHit(SHit &H) { if(!m_pPhysicsShell) return; if(m_bone_steer==H.bone()) return; if(CPHUpdateObject::IsActive()) { Fvector vimpulse;vimpulse.set(H.direction()); vimpulse.mul( H.phys_impulse( ) ); vimpulse.y *=GravityFactorImpulse(); float mag=vimpulse.magnitude(); if(!fis_zero(mag)) { vimpulse.mul(1.f/mag); m_pPhysicsShell->applyHit(H.bone_space_position(),vimpulse,mag,H.bone(),H.type()); } } else { m_pPhysicsShell->applyHit( H.bone_space_position(), H.direction(), H.phys_impulse(), H.bone(), H.type() ); } }
type_motion::edirection type_motion::dir( CEntityAlive& ea, const SHit& H, float& angle ) { Fvector dir = H.direction(); dir.y = 0; float m = dir.magnitude(); if( fis_zero( m ) ) { edirection dr; dr = (edirection) ::Random.randI( 0, (s32) not_definite ); VERIFY( dr < not_definite ); return dr; } dir.mul( 1.f / m ); Fvector z_dir = { ea.XFORM().k.x, 0.f, ea.XFORM().k.z }; Fvector x_dir = { ea.XFORM().i.x, 0.f, ea.XFORM().i.z }; z_dir.normalize_safe();x_dir.normalize_safe(); float front_factor = dir.dotproduct( z_dir ); float sidefactor = dir.dotproduct( x_dir ); if( _abs( front_factor ) > M_SQRT1_2 ) { float sign = front_factor < 0.f ? -1.f : 1.f; angle = atan2( -sign * sidefactor, sign * front_factor ); return sign < 0.f ? front : back; } else { float sign = sidefactor > 0.f ? 1.f : -1.f; angle = atan2( sign * front_factor, sign * sidefactor ); return sign > 0.f ? left : right; } }
void CAI_Stalker::Hit(SHit* pHDS) { //хит может меняться в зависимости от ранга (новички получают больше хита, чем ветераны) SHit HDS = *pHDS; HDS.add_wound = true; float hit_power = HDS.power * m_fRankImmunity; if(m_boneHitProtection && HDS.hit_type == ALife::eHitTypeFireWound) { float BoneArmor = m_boneHitProtection->getBoneArmor(HDS.bone()); float ap = HDS.armor_piercing; if(!fis_zero(BoneArmor, EPS)) { if(ap > BoneArmor) { float d_hit_power = (ap - BoneArmor) / ap; if(d_hit_power < m_boneHitProtection->m_fHitFracNpc) d_hit_power = m_boneHitProtection->m_fHitFracNpc; hit_power *= d_hit_power; VERIFY(hit_power>=0.0f); } else { hit_power *= m_boneHitProtection->m_fHitFracNpc; HDS.add_wound = false; } } if ( wounded() ) //уже лежит => добивание { hit_power = 1000.f; } } HDS.power = hit_power; if (g_Alive()) { bool already_critically_wounded = critically_wounded(); if (!already_critically_wounded) { const CCoverPoint *cover = agent_manager().member().member(this).cover(); if ( !invulnerable() && cover && HDS.initiator() && ( HDS.initiator()->ID() != ID() ) && !fis_zero( HDS.damage() ) && brain().affect_cover() ) { agent_manager().location().add( xr_new<CDangerCoverLocation>(cover,Device.dwTimeGlobal,DANGER_INTERVAL,DANGER_DISTANCE) ); } } const CEntityAlive *entity_alive = smart_cast<const CEntityAlive*>(HDS.initiator()); if (entity_alive && !wounded()) { if (is_relation_enemy(entity_alive)) sound().play (eStalkerSoundInjuring); // else // sound().play (eStalkerSoundInjuringByFriend); } int weapon_type = -1; if (best_weapon()) weapon_type = best_weapon()->object().ef_weapon_type(); if ( !wounded() && !already_critically_wounded) { bool became_critically_wounded = update_critical_wounded(HDS.boneID,HDS.power); if ( !became_critically_wounded && animation().script_animations().empty() && (HDS.bone() != BI_NONE) ) { Fvector D; float yaw, pitch; D.getHP (yaw,pitch); #pragma todo("Dima to Dima : forward-back bone impulse direction has been determined incorrectly!") float power_factor = m_power_fx_factor * HDS.damage() / 100.f; clamp (power_factor,0.f,1.f); //IKinematicsAnimated *tpKinematics = smart_cast<IKinematicsAnimated*>(Visual()); IKinematics *tpKinematics = smart_cast<IKinematics*>(Visual()); #ifdef DEBUG tpKinematics->LL_GetBoneInstance (HDS.bone()); if (HDS.bone() >= tpKinematics->LL_BoneCount()) { Msg ("tpKinematics has no bone_id %d",HDS.bone()); HDS._dump (); } #endif // int fx_index = iFloor(tpKinematics->LL_GetBoneInstance(HDS.bone()).get_param(1) + (angle_difference(movement().m_body.current.yaw,-yaw) <= PI_DIV_2 ? 0 : 1)); // if (fx_index != -1) // animation().play_fx (power_factor,fx_index); } else { if (!already_critically_wounded && became_critically_wounded) { if (HDS.who) { CAI_Stalker *stalker = smart_cast<CAI_Stalker*>(HDS.who); if ( stalker && stalker->g_Alive() ) stalker->on_critical_wound_initiator (this); } } } } } if ( g_Alive() && ( !m_hit_callback || m_hit_callback( &HDS ) ) ) { float const damage_factor = invulnerable() ? 0.f : 100.f; memory().hit().add ( damage_factor*HDS.damage(), HDS.direction(), HDS.who, HDS.boneID ); } //conditions().health() = 1.f; inherited::Hit ( &HDS ); }
void CPhysicsShellHolder::PHHit( SHit &H ) { if(H.phys_impulse() >0) if(m_pPhysicsShell) m_pPhysicsShell->applyHit(H.bone_space_position(),H.direction(),H.phys_impulse(),H.bone(),H.type()); }