void CPHCollisionDamageReceiver::Hit(u16 source_id,u16 bone_id,float power,const Fvector& dir,Fvector &pos ) { DAMAGE_BONES_I i=FindBone(bone_id); if(i==m_controled_bones.end())return; power*=i->second; if(power<hit_threthhold)return; NET_Packet P; CPhysicsShellHolder *ph=PPhysicsShellHolder(); SHit HS; HS.GenHeader(GE_HIT,ph->ID()); // ph->u_EventGen(P,GE_HIT,ph->ID()); HS.whoID = ph->ID(); // P.w_u16 (ph->ID()); HS.weaponID = source_id; // P.w_u16 (source_id); HS.dir = dir; // P.w_dir (dir); HS.power = power; // P.w_float (power); HS.boneID = s16(bone_id); // P.w_s16 (s16(bone_id)); HS.p_in_bone_space = pos; // P.w_vec3 (pos); HS.impulse = 0.f; // P.w_float (0.f); HS.hit_type = (ALife::eHitTypeStrike); // P.w_u16 (ALife::eHitTypeStrike); HS.Write_Packet(P); ph->u_EventSend(P); }
//void CHangingLamp::Hit(float P,Fvector &dir, CObject* who,s16 element, // Fvector p_in_object_space, float impulse, ALife::EHitType hit_type) void CHangingLamp::Hit (SHit* pHDS) { SHit HDS = *pHDS; callback(GameObject::eHit)( lua_game_object(), HDS.power, HDS.dir, smart_cast<const CGameObject*>(HDS.who)->lua_game_object(), HDS.bone() ); #ifdef HLAMP_AFFECT_IMMUNITIES HDS.power = CHitImmunity::AffectHit(HDS.power,HDS.hit_type); inherited::Hit(pHDS); #endif BOOL bWasAlive = Alive () || light_render->get_active(); if(m_pPhysicsShell) m_pPhysicsShell->applyHit(pHDS->p_in_bone_space,pHDS->dir,pHDS->impulse,pHDS->boneID,pHDS->hit_type); if (!bWasAlive) return; if (pHDS->boneID==light_bone) SetHealth ( 0.f ); else { float damage = pHDS->damage() * 100.f; Msg("DEBUG: %s health = %.3f, damage = %.3f", Name_script(), GetHealth(), damage); SetHealth(GetHealth() - damage); } if (bWasAlive && (!Alive())) TurnOff (); }
void CStalkerActionKillWounded::execute () { inherited::execute (); if (!object().memory().enemy().selected()) return; const CEntityAlive *enemy = object().memory().enemy().selected(); object().sight().setup (CSightAction(enemy,true)); object().set_goal (eObjectActionFire1,weapon_to_kill(&object()),MIN_QUEUE,MAX_QUEUE,MIN_INTERVAL,MAX_INTERVAL); if (object().memory().visual().visible_now(enemy) && object().can_kill_enemy() && !object().can_kill_member()) return; // this is fake // but sometimes enemy can not be visible // when it plays animation inside another object // therefore we should use this ugly workaround // and hit enemy virtually NET_Packet P; SHit HS; HS.GenHeader (GE_HIT, enemy->ID()); HS.whoID = object().ID(); HS.weaponID = weapon_to_kill(&object())->object().ID(); HS.dir = Fvector().set(0.f,0.f,1.f); HS.power = 1.f; HS.boneID = smart_cast<CKinematics*>((const_cast<CEntityAlive*>(enemy))->Visual())->LL_GetBoneRoot(); HS.p_in_bone_space = Fvector().set(0.f,0.f,0.f); HS.impulse = 1.f; HS.hit_type = ALife::eHitTypeWound; HS.Write_Packet (P); object().u_EventSend (P); }
bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const { if( H.initiator() != Level().CurrentControlEntity()) return false; if(H.type() == ALife::eHitTypeExplosion) { edirection dr = dir( ea, H, angle ); m = motion( dr ); type_motion_diagnostic( "type_motion6: 7. √ранта", dr, ea, H, m ); return true; } CObject* O = Level().Objects.net_Find( H.weaponID ); if(!O) { m = MotionID(); return false; } if( smart_cast<CExplosive*>( O ) != 0 ) { edirection dr = dir( ea, H, angle ); m = motion( dr ); type_motion_diagnostic( "type_motion6: 7. √ранта - осколок", dr, ea, H, m ); return true; } return false; }
void CAI_Rat::Exec_Action(float /**dt/**/) { switch (m_tAction) { case eRatActionAttackBegin : { u32 dwTime = Device.dwTimeGlobal; sound().play (eRatSoundAttack);//,0,0,m_dwHitInterval+1,m_dwHitInterval); if (memory().enemy().selected() && memory().enemy().selected()->g_Alive() && (dwTime - m_dwStartAttackTime > m_dwHitInterval)) { m_bActionStarted = true; m_dwStartAttackTime = dwTime; Fvector tDirection; Fvector position_in_bone_space; position_in_bone_space.set(0.f,0.f,0.f); tDirection.sub(memory().enemy().selected()->Position(),this->Position()); vfNormalizeSafe(tDirection); if (this->Local() && memory().enemy().selected()) { CEntityAlive *entity_alive = const_cast<CEntityAlive*>(memory().enemy().selected()); VERIFY (entity_alive); // entity_alive->Hit(m_fHitPower,tDirection,this,0,position_in_bone_space,0); u16 id_to = entity_alive->ID(); u16 id_from = ID(); NET_Packet l_P; SHit HS; HS.GenHeader(GE_HIT, id_to); // u_EventGen (l_P,GE_HIT, id_to); HS.whoID = (id_from); // l_P.w_u16 (id_from); HS.weaponID = (id_from); // l_P.w_u16 (id_from); HS.dir = (tDirection); // l_P.w_dir (tDirection); HS.power = (m_fHitPower); // l_P.w_float (m_fHitPower); HS.boneID = (0); // l_P.w_s16 (0); HS.p_in_bone_space = (position_in_bone_space); // l_P.w_vec3 (position_in_bone_space); HS.impulse = (0.f); // l_P.w_float (0.f); HS.hit_type = (ALife::eHitTypeWound); // l_P.w_u16 ((u16)ALife::eHitTypeWound); HS.Write_Packet(l_P); u_EventSend (l_P); } } else m_bActionStarted = false; break; } case eRatActionAttackEnd : { m_bActionStarted = false; break; } default: break; } }
void CExplosive::ExplodeWaveProcessObject(collide::rq_results& storage, CPhysicsShellHolder*l_pGO) { Fvector l_goPos; if(l_pGO->Visual()) l_pGO->Center (l_goPos); else return; //мне непонятно зачем наносить хит от взрыва по объектам не имеющим вижуал - поэтому игнорируем #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_OpenCashedDraw(); } #endif float l_effect=ExplosionEffect(storage,this,l_pGO,m_vExplodePos,m_fBlastRadius); float l_impuls = m_fBlastHitImpulse * l_effect; float l_hit = m_fBlastHit * l_effect; if(l_impuls > .001f||l_hit> 0.001) { Fvector l_dir;l_dir.sub(l_goPos,m_vExplodePos); float rmag=_sqrt(m_fUpThrowFactor*m_fUpThrowFactor+1.f+2.f*m_fUpThrowFactor*l_dir.y); l_dir.y += m_fUpThrowFactor; //rmag -модуль l_dir после l_dir.y += m_fUpThrowFactor, модуль=_sqrt(l_dir^2+y^2+2.*(l_dir,y)),y=(0,m_fUpThrowFactor,0) (до этого модуль l_dir =1) l_dir.mul(1.f/rmag);//перенормировка NET_Packet P; SHit HS; HS.GenHeader(GE_HIT, l_pGO->ID()); // cast_game_object()->u_EventGen (P,GE_HIT,l_pGO->ID()); HS.whoID =Initiator(); // P.w_u16 (Initiator()); HS.weaponID = cast_game_object()->ID(); // P.w_u16 (cast_game_object()->ID()); HS.dir = l_dir; // P.w_dir (l_dir); HS.power = l_hit; // P.w_float (l_hit); HS.p_in_bone_space = l_goPos; // P.w_vec3 (l_goPos); HS.impulse = l_impuls; // P.w_float (l_impuls); HS.hit_type = (m_eHitTypeBlast); // P.w_u16 (u16(m_eHitTypeBlast)); HS.boneID = 0; // P.w_s16 (0); HS.Write_Packet(P); cast_game_object()->u_EventSend (P); } #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_ClosedCashedDraw(100000); } #endif }
void CBaseMonster::Hit_Wound(CObject *object, float value, const Fvector &dir, float impulse) { NET_Packet P; SHit HS; HS.GenHeader(GE_HIT, object->ID()); // u_EventGen (P,GE_HIT, object->ID()); HS.whoID = (ID()); // P.w_u16 (ID()); HS.weaponID = (ID()); // P.w_u16 (ID()); HS.dir = (dir); // P.w_dir (dir); HS.power = (value); // P.w_float (value); HS.boneID = (smart_cast<IKinematics*>(object->Visual())->LL_GetBoneRoot()); // P.w_s16 (smart_cast<IKinematics*>(object->Visual())->LL_GetBoneRoot()); HS.p_in_bone_space = (Fvector().set(0.f,0.f,0.f)); // P.w_vec3 (Fvector().set(0.f,0.f,0.f)); HS.impulse = (impulse); // P.w_float (impulse); HS.hit_type = (ALife::eHitTypeWound); // P.w_u16 (u16(ALife::eHitTypeWound)); HS.Write_Packet(P); u_EventSend (P); }
void CBaseMonster::Hit_Psy(CObject *object, float value) { NET_Packet P; SHit HS; HS.GenHeader (GE_HIT, object->ID()); // // u_EventGen (P,GE_HIT, object->ID()); // HS.whoID = (ID()); // own // P.w_u16 (ID()); // own HS.weaponID = (ID()); // own // P.w_u16 (ID()); // own HS.dir = (Fvector().set(0.f,1.f,0.f)); // direction // P.w_dir (Fvector().set(0.f,1.f,0.f)); // direction HS.power = (value); // hit value // P.w_float (value); // hit value HS.boneID = (BI_NONE); // bone // P.w_s16 (BI_NONE); // bone HS.p_in_bone_space = (Fvector().set(0.f,0.f,0.f)); // P.w_vec3 (Fvector().set(0.f,0.f,0.f)); HS.impulse = (0.f); // P.w_float (0.f); HS.hit_type = (ALife::eHitTypeTelepatic); // P.w_u16 (u16(ALife::eHitTypeTelepatic)); HS.Write_Packet (P); u_EventSend (P); }
void CActor::g_Physics (Fvector& _accel, float jump, float dt) { // Correct accel Fvector accel; accel.set (_accel); hit_slowmo -= dt; if (hit_slowmo<0) hit_slowmo = 0.f; accel.mul (1.f-hit_slowmo); if(g_Alive()) { if(mstate_real&mcClimb&&!cameras[eacFirstEye]->bClampYaw)accel.set(0.f,0.f,0.f); character_physics_support()->movement()->Calculate (accel,cameras[cam_active]->vDirection,0,jump,dt,false); bool new_border_state=character_physics_support()->movement()->isOutBorder(); if(m_bOutBorder!=new_border_state && Level().CurrentControlEntity() == this) { SwitchOutBorder(new_border_state); } character_physics_support()->movement()->GetPosition (Position()); character_physics_support()->movement()->bSleep =false; } if (Local() && g_Alive()) { if (character_physics_support()->movement()->gcontact_Was) Cameras().AddCamEffector (xr_new<CEffectorFall> (character_physics_support()->movement()->gcontact_Power)); if (!fis_zero(character_physics_support()->movement()->gcontact_HealthLost)) { const ICollisionDamageInfo* di=character_physics_support()->movement()->CollisionDamageInfo(); Fvector hdir;di->HitDir(hdir); SetHitInfo(this, NULL, 0, Fvector().set(0, 0, 0), hdir); // Hit (m_PhysicMovementControl->gcontact_HealthLost,hdir,di->DamageInitiator(),m_PhysicMovementControl->ContactBone(),di->HitPos(),0.f,ALife::eHitTypeStrike);//s16(6 + 2*::Random.randI(0,2)) if (Level().CurrentControlEntity() == this) { SHit HDS = SHit(character_physics_support()->movement()->gcontact_HealthLost,hdir,di->DamageInitiator(),character_physics_support()->movement()->ContactBone(),di->HitPos(),0.f,di->HitType()); // Hit(&HDS); NET_Packet l_P; HDS.GenHeader(GE_HIT, ID()); HDS.whoID = di->DamageInitiator()->ID(); HDS.weaponID = di->DamageInitiator()->ID(); HDS.Write_Packet(l_P); u_EventSend (l_P); } } } }
bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const { m = MotionID(); if( H.initiator() != Level().CurrentControlEntity()) return false; VERIFY( ea.Visual( ) ); IKinematics *K = ea.Visual()->dcast_PKinematics(); VERIFY( K ); if( is_bone_head( *K, H.bone() ) ) { edirection dr = dir( ea, H, angle ); m = motion( dr ); type_motion_diagnostic( " type_motion3: 4. ’едшот (по веро¤тности), кроме 5 (4)", dr, ea, H, m ); return true; } return false; }
bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const { if( H.initiator() != Level().CurrentControlEntity()) return false; m = MotionID(); VERIFY( ea.Visual( ) ); IKinematics *K = ea.Visual()->dcast_PKinematics(); VERIFY( K ); if(is_snipper( H.weaponID ) && !is_bone_head( *K, H.bone() )) { edirection dr = dir( ea, H, angle ); m = motion( dr ); type_motion_diagnostic( "type_motion5: 6. —найперка в тело", dr, ea, H, m ); return true; } return false; }
bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const { m = MotionID(); if( H.initiator() != Level().CurrentControlEntity()) return false; VERIFY( ea.Visual( ) ); IKinematics *K = ea.Visual()->dcast_PKinematics(); VERIFY( K ); if( !is_bone_head( *K, H.bone() )) return false; //CAI_Stalker* s = ea.cast_stalker (); CCharacterPhysicsSupport* chs = ea.character_physics_support(); if( !chs || chs->Type( ) == CCharacterPhysicsSupport::etBitting ) return false; VERIFY( chs->movement() ); const Fvector stalker_velocity = chs->movement()->GetVelocity(); const float stalker_speed = stalker_velocity.magnitude(); const float min_stalker_speed = 3.65f; if(stalker_speed < min_stalker_speed ) return false; const Fvector stalker_velocity_dir = Fvector().mul( stalker_velocity, 1.f/stalker_speed ); const Fvector dir_to_actor = Fvector().sub( H.initiator()->Position(), ea.Position() ).normalize_safe(); const float front_angle_cos = _cos( deg2rad ( 20.f ) ); if( stalker_velocity_dir.dotproduct(dir_to_actor) < front_angle_cos ) return false; if( type_motion::front != type_motion::dir( ea, H, angle ) ) return false; Fvector p; if( Fvector().sub( H.initiator()->Position(), global_hit_position( p, ea, H ) ).magnitude() > 30.f ) return false; m = motion( front ); type_motion_diagnostic( " type_motion0: 1. = »нерционное движение вперед от попадани¤ в голову ", front, ea, H, m ); return true; }
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 CBreakableObject::ProcessDamage() { NET_Packet P; SHit HS; HS.GenHeader (GE_HIT, ID()); HS.whoID = (ID()); HS.weaponID = (ID()); HS.dir = (m_contact_damage_dir); HS.power = (m_max_frame_damage); HS.boneID = (PKinematics(Visual())->LL_GetBoneRoot()); HS.p_in_bone_space = (m_contact_damage_pos); HS.impulse = (0.f); HS.hit_type = (ALife::eHitTypeStrike); HS.Write_Packet (P); u_EventSend (P); m_max_frame_damage = 0.f; b_resived_damage =false; }
//void CCar::Hit(float P,Fvector &dir,CObject * who,s16 element,Fvector p_in_object_space, float impulse, ALife::EHitType hit_type) void CCar::Hit (SHit* pHDS) { SHit HDS = *pHDS; //if(CDelayedActionFuse::isActive()||Initiator()==u16(-1)&&HDS.hit_type==ALife::eHitTypeStrike) //{ // HDS.power=0.f; //} //if(HDS.who->ID()!=ID()) //{ // CExplosive::SetInitiator(HDS.who->ID()); //} WheelHit(HDS.damage(),HDS.bone(),HDS.hit_type); DoorHit(HDS.damage(),HDS.bone(),HDS.hit_type); float hitScale=1.f,woundScale=1.f; if(HDS.hit_type!=ALife::eHitTypeStrike) CDamageManager::HitScale(HDS.bone(), hitScale, woundScale); HDS.power *= GetHitImmunity(HDS.hit_type)*hitScale; inherited::Hit(&HDS); if(!CDelayedActionFuse::isActive()) { CDelayedActionFuse::CheckCondition(GetfHealth()); } CDamagableItem::HitEffect(); // if(Owner()&&Owner()->ID()==Level().CurrentEntity()->ID()) // CurrentGameUI()->UIMainIngameWnd->CarPanel().SetCarHealth(GetfHealth()); }
void CRadioactiveZone::UpdateWorkload (u32 dt) { if (IsEnabled() && GameID() != GAME_SINGLE) { OBJECT_INFO_VEC_IT it; Fvector pos; XFORM().transform_tiny(pos,CFORM()->getSphere().P); for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) { if( !(*it).object->getDestroy() && (*it).object->CLS_ID == CLSID_OBJECT_ACTOR) { //===================================== NET_Packet l_P; l_P.write_start(); l_P.read_start(); float dist = (*it).object->Position().distance_to(pos); float power = Power(dist)*dt/1000; /// Msg("Zone Dist %f, Radiation Power %f, ", dist, power); SHit HS; HS.GenHeader(GE_HIT, (*it).object->ID()); HS.whoID =ID(); HS.weaponID = ID(); HS.dir = Fvector().set(0,0,0); HS.power = power; HS.boneID = BI_NONE; HS.p_in_bone_space = Fvector().set(0, 0, 0); HS.impulse = 0.0f; HS.hit_type = ALife::eHitTypeRadiation; HS.Write_Packet_Cont(l_P); (*it).object->OnEvent(l_P, HS.PACKET_TYPE); //===================================== }; } } inherited::UpdateWorkload(dt); }
void CRadioactiveZone::UpdateWorkload (u32 dt) { if (IsEnabled() && GameID() != eGameIDSingle) { OBJECT_INFO_VEC_IT it; Fvector pos; XFORM().transform_tiny(pos,CFORM()->getSphere().P); for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) { if( !(*it).object->getDestroy() && smart_cast<CActor*>((*it).object)) { //===================================== NET_Packet l_P; l_P.write_start(); l_P.read_start(); float dist = (*it).object->Position().distance_to(pos); float power = Power(dist,nearest_shape_radius(it))*dt/1000; SHit HS; HS.GenHeader (GE_HIT, (*it).object->ID()); HS.whoID = ID(); HS.weaponID = ID(); HS.dir = Fvector().set(0,0,0); HS.power = power; HS.boneID = BI_NONE; HS.p_in_bone_space = Fvector().set(0, 0, 0); HS.impulse = 0.0f; HS.hit_type = m_eHitTypeBlowout; HS.Write_Packet_Cont(l_P); (*it).object->OnEvent(l_P, HS.PACKET_TYPE); //===================================== }; } } inherited::UpdateWorkload(dt); }
bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const { m = MotionID(); if( H.initiator() != Level().CurrentControlEntity()) return false; CObject* O = Level().Objects.net_Find( H.weaponID ); if(!O) return false; //static_cast<CGameObject*>(O)->cast_weapon() CWeaponShotgun* s = smart_cast< CWeaponShotgun* >( static_cast<CGameObject*>(O) ); if(!s) return false; Fvector p; const float max_distance = 20.f; if(Fvector().sub(H.initiator()->Position(),global_hit_position( p, ea, H )).magnitude() > max_distance) return false; edirection dr = dir( ea, H, angle ); m = motion( dr ); type_motion_diagnostic( " type_motion2: 3. Ўотган ", dr, ea, H, m ); return true; }
void type_motion_diagnostic( LPCSTR message, type_motion::edirection dr, const CEntityAlive& ea, const SHit& H, const MotionID &m ) { #ifdef DEBUG if(! death_anim_debug ) return; IKinematicsAnimated *KA = smart_cast<IKinematicsAnimated*>( ea.Visual() ); VERIFY( KA ); IKinematics *K = smart_cast<IKinematics*>( ea.Visual() ); LPCSTR bone_name = "not_definite"; if( H.bone() != BI_NONE ) { CBoneData& bd = K->LL_GetData( H.bone() ); bone_name = bd.name.c_str(); } LPCSTR motion_name = "not_set"; if( m.valid() ) motion_name = KA->LL_MotionDefName_dbg( m ).first; Msg( "death anims: %s, dir: %s, motion: %s, obj: %s, model: %s, bone: %s " ,message ,motion_dirs[ dr ].name, motion_name, ea.cName().c_str(), ea.cNameVisual().c_str(), bone_name ); #endif }
void CCustomZone::CreateHit ( u16 id_to, u16 id_from, const Fvector& hit_dir, float hit_power, s16 bone_id, const Fvector& pos_in_bone, float hit_impulse, ALife::EHitType hit_type) { if (OnServer()) { if(m_owner_id != u32(-1) ) id_from = (u16)m_owner_id; NET_Packet l_P; Fvector hdir = hit_dir; SHit Hit = SHit(hit_power, hdir, this, bone_id, pos_in_bone, hit_impulse, hit_type, 0.0f, false); Hit.GenHeader (GE_HIT, id_to); Hit.whoID = id_from; Hit.weaponID = this->ID(); Hit.Write_Packet (l_P); u_EventSend (l_P); }; }
//void CDestroyablePhysicsObject::Hit (float P,Fvector &dir,CObject *who,s16 element,Fvector p_in_object_space, float impulse, ALife::EHitType hit_type) void CDestroyablePhysicsObject::Hit (SHit* pHDS) { SHit HDS = *pHDS; callback(GameObject::eHit)( lua_game_object(), HDS.power, HDS.dir, smart_cast<const CGameObject*>(HDS.who)->lua_game_object(), HDS.bone() ); HDS.power=CHitImmunity::AffectHit(HDS.power,HDS.hit_type); float hit_scale=1.f,wound_scale=1.f; CDamageManager::HitScale(HDS.bone(),hit_scale,wound_scale); HDS.power*=hit_scale; // inherited::Hit(P,dir,who,element,p_in_object_space,impulse,hit_type); inherited::Hit(&HDS); m_fHealth-=HDS.power; if(m_fHealth<=0.f) { // CPHDestroyable::SetFatalHit(SHit(P,dir,who,element,p_in_object_space,impulse,hit_type)); CPHDestroyable::SetFatalHit(HDS); if(CPHDestroyable::CanDestroy())Destroy(); } }
void CScriptGameObject::Hit(CScriptHit *tpLuaHit) { CScriptHit &tLuaHit = *tpLuaHit; NET_Packet P; SHit HS; HS.GenHeader(GE_HIT,object().ID()); // object().u_EventGen(P,GE_HIT,object().ID()); THROW2 (tLuaHit.m_tpDraftsman,"Where is hit initiator??!"); // THROW2 (tLuaHit.m_tpDraftsman,"Where is hit initiator??!"); HS.whoID = u16(tLuaHit.m_tpDraftsman->ID()); // P.w_u16 (u16(tLuaHit.m_tpDraftsman->ID())); HS.weaponID = 0; // P.w_u16 (0); HS.dir = tLuaHit.m_tDirection; // P.w_dir (tLuaHit.m_tDirection); HS.power = tLuaHit.m_fPower; // P.w_float (tLuaHit.m_fPower); CKinematics *V = smart_cast<CKinematics*>(object().Visual()); // CKinematics *V = smart_cast<CKinematics*>(object().Visual()); VERIFY (V); // VERIFY (V); if (xr_strlen (tLuaHit.m_caBoneName)) // if (xr_strlen (tLuaHit.m_caBoneName)) HS.boneID = (V->LL_BoneID(tLuaHit.m_caBoneName)); // P.w_s16 (V->LL_BoneID(tLuaHit.m_caBoneName)); else // else HS.boneID = (s16(0)); // P.w_s16 (s16(0)); HS.p_in_bone_space = Fvector().set(0,0,0); // P.w_vec3 (Fvector().set(0,0,0)); HS.impulse = tLuaHit.m_fImpulse; // P.w_float (tLuaHit.m_fImpulse); HS.hit_type = (ALife::EHitType)(tLuaHit.m_tHitType); // P.w_u16 (u16(tLuaHit.m_tHitType)); HS.Write_Packet(P); object().u_EventSend(P); }
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 CBlackGraviArtefact::GraviStrike() { xr_list<s16> elements_list; xr_list<Fvector> bone_position_list; Fvector object_pos ; Fvector strike_dir ; rq_storage.r_clear (); for(GAME_OBJECT_LIST_it it = m_GameObjectList.begin(); m_GameObjectList.end() != it; ++it) { CPhysicsShellHolder* pGameObject = *it; if(pGameObject->Visual()) pGameObject->Center(object_pos); else object_pos.set(pGameObject->Position()); strike_dir.sub(object_pos, Position()); float distance = strike_dir.magnitude(); float impulse = 100.f*m_fStrikeImpulse * (1.f - (distance/m_fRadius)* (distance/m_fRadius)); if(impulse > .001f) { //? BOOL enabled = getEnabled(); //? setEnabled (FALSE); impulse *= CExplosive::ExplosionEffect (rq_storage,NULL,pGameObject, Position(),m_fRadius); //? setEnabled (enabled); } float hit_power ; CEntityAlive* pEntityAlive = smart_cast<CEntityAlive*>(pGameObject); if(pGameObject->m_pPhysicsShell) hit_power = 0; else if(pEntityAlive && pEntityAlive->g_Alive() && pEntityAlive->character_physics_support()->movement()->CharacterExist()) hit_power = 0; else hit_power = impulse; if(impulse > .001f) { while(!elements_list.empty()) { s16 element = elements_list.front(); Fvector bone_pos = bone_position_list.front(); NET_Packet P; SHit HS; HS.GenHeader(GE_HIT, pGameObject->ID()); // u_EventGen (P,GE_HIT, pGameObject->ID()); HS.whoID =ID(); // P.w_u16 (ID()); HS.weaponID = ID(); // P.w_u16 (ID()); HS.dir = strike_dir; // P.w_dir (strike_dir); HS.power = hit_power; // P.w_float (hit_power); HS.boneID = element; // P.w_s16 (element); HS.p_in_bone_space = bone_pos; // P.w_vec3 (bone_pos); HS.impulse = impulse; // P.w_float (impulse); HS.hit_type = (ALife::eHitTypeWound); // P.w_u16 (u16(ALife::eHitTypeWound)); HS.Write_Packet(P); u_EventSend (P); elements_list.pop_front(); bone_position_list.pop_front(); } } } }
void CGameObject::OnEvent (NET_Packet& P, u16 type) { switch (type) { case GE_HIT: case GE_HIT_STATISTIC: { /* u16 id,weapon_id; Fvector dir; float power, impulse; s16 element; Fvector position_in_bone_space; u16 hit_type; float ap = 0.0f; P.r_u16 (id); P.r_u16 (weapon_id); P.r_dir (dir); P.r_float (power); P.r_s16 (element); P.r_vec3 (position_in_bone_space); P.r_float (impulse); P.r_u16 (hit_type); //hit type if ((ALife::EHitType)hit_type == ALife::eHitTypeFireWound) { P.r_float (ap); } CObject* Hitter = Level().Objects.net_Find(id); CObject* Weapon = Level().Objects.net_Find(weapon_id); SHit HDS = SHit(power, dir, Hitter, element, position_in_bone_space, impulse, (ALife::EHitType)hit_type, ap); */ SHit HDS; HDS.PACKET_TYPE = type; HDS.Read_Packet_Cont(P); // Msg("Hit received: %d[%d,%d]", HDS.whoID, HDS.weaponID, HDS.BulletID); CObject* Hitter = Level().Objects.net_Find(HDS.whoID); CObject* Weapon = Level().Objects.net_Find(HDS.weaponID); HDS.who = Hitter; if (!HDS.who) { Msg("! ERROR: hitter object [%d] is NULL on client.", HDS.whoID); } //------------------------------------------------------- switch (HDS.PACKET_TYPE) { case GE_HIT_STATISTIC: { if (GameID() != eGameIDSingle) Game().m_WeaponUsageStatistic->OnBullet_Check_Request(&HDS); }break; default: { }break; } SetHitInfo(Hitter, Weapon, HDS.bone(), HDS.p_in_bone_space, HDS.dir); Hit (&HDS); //--------------------------------------------------------------------------- if (GameID() != eGameIDSingle) { Game().m_WeaponUsageStatistic->OnBullet_Check_Result(false); game_cl_mp* mp_game = smart_cast<game_cl_mp*>(&Game()); if (mp_game->get_reward_generator()) mp_game->get_reward_generator()->OnBullet_Hit(Hitter, this, Weapon, HDS.boneID); } //--------------------------------------------------------------------------- } break; case GE_DESTROY: { if ( H_Parent() ) { Msg( "! ERROR (GameObject): GE_DESTROY arrived to object[%d][%s], that has parent[%d][%s], frame[%d]", ID(), cNameSect().c_str(), H_Parent()->ID(), H_Parent()->cName().c_str(), Device.dwFrame ); // This object will be destroy on call function <H_Parent::Destroy> // or it will be call <H_Parent::Reject> ==> H_Parent = NULL // !!! ___ it is necessary to be check! break; } #ifdef MP_LOGGING Msg("--- Object: GE_DESTROY of [%d][%s]", ID(), cNameSect().c_str()); #endif // MP_LOGGING setDestroy (TRUE); // MakeMeCrow (); } break; } }
void CAI_Stalker::Hit (SHit* pHDS) { // pHDS->power *= .1f; //хит может меняться в зависимости от ранга (новички получают больше хита, чем ветераны) SHit HDS = *pHDS; HDS.power *= m_fRankImmunity; if (m_boneHitProtection && HDS.hit_type == ALife::eHitTypeFireWound){ float BoneArmour = m_boneHitProtection->getBoneArmour(HDS.bone()); float NewHitPower = HDS.damage() - BoneArmour; if (NewHitPower < HDS.power*m_boneHitProtection->m_fHitFrac) HDS.power = HDS.power*m_boneHitProtection->m_fHitFrac; else HDS.power = NewHitPower; if (wounded()) HDS.power = 1000.f; } if (g_Alive()) { bool already_critically_wounded = critically_wounded(); if (!already_critically_wounded) { const CCoverPoint *cover = agent_manager().member().member(this).cover(); if (cover && pHDS->initiator() && (pHDS->initiator()->ID() != ID()) && !fis_zero(pHDS->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*>(pHDS->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() && (pHDS->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*pHDS->damage()/100.f; clamp (power_factor,0.f,1.f); CKinematicsAnimated *tpKinematics = smart_cast<CKinematicsAnimated*>(Visual()); #ifdef DEBUG tpKinematics->LL_GetBoneInstance (pHDS->bone()); if (pHDS->bone() >= tpKinematics->LL_BoneCount()) { Msg ("tpKinematics has no bone_id %d",pHDS->bone()); pHDS->_dump (); } #endif int fx_index = iFloor(tpKinematics->LL_GetBoneInstance(pHDS->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->on_critical_wound_initiator (this); } } } } } inherited::Hit (&HDS); }
void CPolterFlame::update_schedule() { inherited::update_schedule(); //--------------------------------------------------------------------- // Update Scanner if (m_object->g_Alive()) { // check the start of scanning if (!m_state_scanning && !m_object->EnemyMan.get_enemy()) { // check radius if (Actor()->Position().distance_to(m_object->Position()) < m_scan_radius) { // check timing if (m_scan_next_time < time()) { // start here m_state_scanning = true; // играть звук //m_scan_sound.play_at_pos(m_object, get_head_position(Actor()),sm_2D); ::Sound->play_at_pos(m_scan_sound, 0, Actor()->Position()); // постпроцесс Actor()->Cameras().AddPPEffector(new CMonsterEffector(m_scan_effector_info, m_scan_effector_time, m_scan_effector_time_attack, m_scan_effector_time_release)); } } } // check stop of scanning (it currently scans) else { if (!m_scan_sound._feedback()) { // stop here m_state_scanning = false; // count next scan time m_scan_next_time = time() + Random.randI(m_scan_delay_min,m_scan_delay_max); } } } //--------------------------------------------------------------------- // check all flames for (FLAME_ELEMS_IT it = m_flames.begin();it != m_flames.end();it++) { SFlameElement *elem = *it; // test switches to states switch(elem->state) { case ePrepare: // check if time_out if (elem->time_started + m_time_fire_delay < time()) select_state(elem,eFire); break; case eFire: if (elem->time_started + m_time_fire_play < time()) select_state(elem,eStop); else { // check if we need test hit to enemy if (elem->time_last_hit + m_hit_delay < time()) { // test hit collide::rq_result rq; if (Level().ObjectSpace.RayPick(elem->position, elem->target_dir, m_length, collide::rqtBoth, rq, NULL)) { if ((rq.O == elem->target_object) && (rq.range < m_length)) { float hit_value; hit_value = m_hit_value - m_hit_value * rq.range / m_length; NET_Packet P; SHit HS; HS.GenHeader (GE_HIT, elem->target_object->ID()); // u_EventGen (P,GE_HIT, element->target_object->ID()); HS.whoID = (m_object->ID()); // P.w_u16 (ID()); HS.weaponID = (m_object->ID()); // P.w_u16 (ID()); HS.dir = (elem->target_dir); // P.w_dir (element->target_dir); HS.power = (hit_value); // P.w_float (m_flame_hit_value); HS.boneID = (BI_NONE); // P.w_s16 (BI_NONE); HS.p_in_bone_space = (Fvector().set(0.f,0.f,0.f)); // P.w_vec3 (Fvector().set(0.f,0.f,0.f)); HS.impulse = (0.f); // P.w_float (0.f); HS.hit_type = (ALife::eHitTypeBurn); // P.w_u16 (u16(ALife::eHitTypeBurn)); HS.Write_Packet (P); m_object->u_EventSend (P); elem->time_last_hit = time(); } } } } break; case eStop: xr_delete(*it); break; } } // remove all flames in state stop // удалить все элементы, выполнение которых закончено m_flames.erase ( std::remove_if( m_flames.begin(), m_flames.end(), remove_predicate() ), m_flames.end() ); // check if we can create another flame if (m_object->g_Alive() && m_object->EnemyMan.get_enemy() && (m_flames.size() < m_count)) { // check aura radius and accessibility float dist = m_object->EnemyMan.get_enemy()->Position().distance_to(m_object->Position()); if ((dist < m_pmt_aura_radius) && m_object->control().path_builder().accessible(m_object->EnemyMan.get_enemy()->Position())) { // check timing if (m_time_flame_started + m_delay < time()) { create_flame(m_object->EnemyMan.get_enemy()); } } } }
void CBaseMonster::HitEntity(const CEntity *pEntity, float fDamage, float impulse, Fvector &dir, ALife::EHitType hit_type, bool draw_hit_marks) { if (!g_Alive()) return; if (!pEntity || pEntity->getDestroy()) return; if (!EnemyMan.get_enemy()) return; if (EnemyMan.get_enemy() == pEntity) { Fvector position_in_bone_space; position_in_bone_space.set(0.f,0.f,0.f); // перевод из локальных координат в мировые вектора направления импульса Fvector hit_dir; XFORM().transform_dir (hit_dir,dir); hit_dir.normalize (); CEntity *pEntityNC = const_cast<CEntity*>(pEntity); VERIFY (pEntityNC); NET_Packet l_P; SHit HS; HS.GenHeader(GE_HIT, pEntityNC->ID()); // u_EventGen (l_P,GE_HIT, pEntityNC->ID()); HS.whoID = (ID()); // l_P.w_u16 (ID()); HS.weaponID = (ID()); // l_P.w_u16 (ID()); HS.dir = (hit_dir); // l_P.w_dir (hit_dir); HS.power = (fDamage); // l_P.w_float (fDamage); HS.boneID = (smart_cast<IKinematics*>(pEntityNC->Visual())->LL_GetBoneRoot());// l_P.w_s16 (smart_cast<IKinematics*>(pEntityNC->Visual())->LL_GetBoneRoot()); HS.p_in_bone_space = (position_in_bone_space); // l_P.w_vec3 (position_in_bone_space); HS.impulse = (impulse); // l_P.w_float (impulse); HS.hit_type = hit_type; // l_P.w_u16 ( u16(ALife::eHitTypeWound) ); HS.Write_Packet(l_P); u_EventSend (l_P); if (pEntityNC == Actor() && draw_hit_marks) { START_PROFILE("BaseMonster/Animation/HitEntity"); SDrawStaticStruct* s = CurrentGameUI()->AddCustomStatic("monster_claws", false); float h1,p1; Device.vCameraDirection.getHP (h1,p1); Fvector hd = hit_dir; hd.mul (-1); float d = -h1 + hd.getH (); s->wnd()->SetHeading (d); Fvector2 wnd_pos = s->wnd()->GetWndPos(); wnd_pos.y += 400.0f*_cos(d); wnd_pos.x += 500.0f*_sin(d); s->wnd()->SetWndPos(wnd_pos); STOP_PROFILE; //SetAttackEffector (); float time_to_lock = fDamage * MAX_LOCK_TIME; clamp (time_to_lock, 0.f, MAX_LOCK_TIME); Actor()->lock_accel_for (int(time_to_lock * 1000)); ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// CEffectorCam* ce = Actor()->Cameras().GetCamEffector((ECamEffectorType)effBigMonsterHit); if(!ce) { const shared_str& eff_sect = pSettings->r_string(cNameSect(), "actor_hit_effect"); if(eff_sect.c_str()) { int id = -1; Fvector cam_pos,cam_dir,cam_norm; Actor()->cam_Active()->Get (cam_pos,cam_dir,cam_norm); cam_dir.normalize_safe (); dir.normalize_safe (); float ang_diff = angle_difference (cam_dir.getH(), dir.getH()); Fvector cp; cp.crossproduct (cam_dir,dir); bool bUp =(cp.y>0.0f); Fvector cross; cross.crossproduct (cam_dir, dir); VERIFY (ang_diff>=0.0f && ang_diff<=PI); float _s1 = PI_DIV_8; float _s2 = _s1+PI_DIV_4; float _s3 = _s2+PI_DIV_4; float _s4 = _s3+PI_DIV_4; if(ang_diff<=_s1){ id = 2; }else { if(ang_diff>_s1 && ang_diff<=_s2){ id = (bUp)?5:7; }else if(ang_diff>_s2 && ang_diff<=_s3){ id = (bUp)?3:1; }else if(ang_diff>_s3 && ang_diff<=_s4){ id = (bUp)?4:6; }else if(ang_diff>_s4){ id = 0; }else{ VERIFY(0); } } string64 sect_name; xr_sprintf (sect_name,"%s_%d",eff_sect.c_str(), id); AddEffector (Actor(), effBigMonsterHit, sect_name, fDamage); } } ////////////////////////////////////////////////////////////////////////// } Morale.on_attack_success(); m_time_last_attack_success = Device.dwTimeGlobal; } }
void CActor::Hit (SHit* pHDS) { pHDS->aim_bullet = false; SHit HDS = *pHDS; if( HDS.hit_type<ALife::eHitTypeBurn || HDS.hit_type >= ALife::eHitTypeMax ) { string256 err; sprintf (err, "Unknown/unregistered hit type [%d]", HDS.hit_type); R_ASSERT2 (0, err ); } #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgCharacterControl)) { DBG_OpenCashedDraw(); Fvector to;to.add(Position(),Fvector().mul(HDS.dir,HDS.phys_impulse())); DBG_DrawLine(Position(),to,D3DCOLOR_XRGB(124,124,0)); DBG_ClosedCashedDraw(500); } #endif bool bPlaySound = true; if (!g_Alive()) bPlaySound = false; if (!IsGameTypeSingle() && !g_pGamePersistent->bDedicatedServer) { game_PlayerState* ps = Game().GetPlayerByGameID(ID()); if (ps && ps->testFlag(GAME_PLAYER_FLAG_INVINCIBLE)) { bPlaySound = false; if (Device.dwFrame != last_hit_frame && HDS.bone() != BI_NONE) { // вычислить позицию и направленность партикла Fmatrix pos; CParticlesPlayer::MakeXFORM(this,HDS.bone(),HDS.dir,HDS.p_in_bone_space,pos); // установить particles CParticlesObject* ps = NULL; if (eacFirstEye == cam_active && this == Level().CurrentEntity()) ps = CParticlesObject::Create(invincibility_fire_shield_1st,TRUE); else ps = CParticlesObject::Create(invincibility_fire_shield_3rd,TRUE); ps->UpdateParent(pos,Fvector().set(0.f,0.f,0.f)); GamePersistent().ps_needtoplay.push_back(ps); }; }; last_hit_frame = Device.dwFrame; }; if( !g_pGamePersistent->bDedicatedServer && !sndHit[HDS.hit_type].empty() && (ALife::eHitTypeTelepatic != HDS.hit_type)) { ref_sound& S = sndHit[HDS.hit_type][Random.randI(sndHit[HDS.hit_type].size())]; bool b_snd_hit_playing = sndHit[HDS.hit_type].end() != std::find_if(sndHit[HDS.hit_type].begin(), sndHit[HDS.hit_type].end(), playing_pred()); if(ALife::eHitTypeExplosion == HDS.hit_type) { if (this == Level().CurrentControlEntity()) { S.set_volume(10.0f); if(!m_sndShockEffector){ m_sndShockEffector = xr_new<SndShockEffector>(); m_sndShockEffector->Start(this, float(S._handle()->length_ms()), HDS.damage() ); } } else bPlaySound = false; } if (bPlaySound && !b_snd_hit_playing) { Fvector point = Position(); point.y += CameraHeight(); S.play_at_pos (this, point); }; } //slow actor, only when he gets hit if(HDS.hit_type == ALife::eHitTypeWound || HDS.hit_type == ALife::eHitTypeStrike) { hit_slowmo = HDS.damage(); clamp (hit_slowmo,0.0f,1.f); } else hit_slowmo = 0.f; //--------------------------------------------------------------- if (Level().CurrentViewEntity() == this && !g_pGamePersistent->bDedicatedServer && HDS.hit_type == ALife::eHitTypeFireWound) { CObject* pLastHitter = Level().Objects.net_Find(m_iLastHitterID); CObject* pLastHittingWeapon = Level().Objects.net_Find(m_iLastHittingWeaponID); HitSector(pLastHitter, pLastHittingWeapon); }; if ((mstate_real&mcSprint) && Level().CurrentControlEntity() == this && HDS.hit_type != ALife::eHitTypeTelepatic && HDS.hit_type != ALife::eHitTypeRadiation ) { // mstate_real &=~mcSprint; mstate_wishful &=~mcSprint; }; if(!g_pGamePersistent->bDedicatedServer) { HitMark (HDS.damage(), HDS.dir, HDS.who, HDS.bone(), HDS.p_in_bone_space, HDS.impulse, HDS.hit_type); } switch (GameID()) { case GAME_SINGLE: { float hit_power = HitArtefactsOnBelt(HDS.damage(), HDS.hit_type); if (GodMode())//psActorFlags.test(AF_GODMODE)) { HDS.power = 0.0f; // inherited::Hit(0.f,dir,who,element,position_in_bone_space,impulse, hit_type); inherited::Hit(&HDS); return; } else { //inherited::Hit (hit_power,dir,who,element,position_in_bone_space, impulse, hit_type); HDS.power = hit_power; inherited::Hit(&HDS); }; } break; default: { m_bWasBackStabbed = false; if (HDS.hit_type == ALife::eHitTypeWound_2 && Check_for_BackStab_Bone(HDS.bone())) { // convert impulse into local coordinate system Fmatrix mInvXForm; mInvXForm.invert (XFORM()); Fvector vLocalDir; mInvXForm.transform_dir (vLocalDir,HDS.dir); vLocalDir.invert (); Fvector a = {0,0,1}; float res = a.dotproduct(vLocalDir); if (res < -0.707) { game_PlayerState* ps = Game().GetPlayerByGameID(ID()); if (!ps || !ps->testFlag(GAME_PLAYER_FLAG_INVINCIBLE)) m_bWasBackStabbed = true; } }; float hit_power = 0; if (m_bWasBackStabbed) hit_power = 100000; else hit_power = HitArtefactsOnBelt(HDS.damage(), HDS.hit_type); HDS.power = hit_power; inherited::Hit (&HDS); //inherited::Hit (hit_power,dir,who,element,position_in_bone_space, impulse, hit_type, 0.0f); } break; } }