void CScriptGameObject::set_smart_cover_target_lookout () { CAI_Stalker *stalker = smart_cast<CAI_Stalker*>(&object()); if (!stalker) { ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"CAI_Stalker : cannot access class member smart_cover_setup_lookout_target!"); return; } if (!stalker->g_Alive()) { ai().script_engine().script_log (ScriptStorage::eLuaMessageTypeError,"CAI_Stalker : do not call smart_cover_setup_lookout_target when stalker is dead!"); return; } stalker->movement().target_lookout (); }
void CAI_Stalker::notify_on_wounded_or_killed (CObject *object) { CAI_Stalker *stalker = smart_cast<CAI_Stalker*>(object); if (!stalker) return; if ( !stalker->g_Alive() ) return; stalker->on_enemy_wounded_or_killed (this); typedef CAgentCorpseManager::MEMBER_CORPSES MEMBER_CORPSES; const MEMBER_CORPSES &corpses = agent_manager().corpse().corpses(); if (std::find(corpses.begin(),corpses.end(),this) != corpses.end()) return; agent_manager().corpse().register_corpse(this); }
void RELATION_REGISTRY::Action (CEntityAlive* from, CEntityAlive* to, ERelationAction action) { static CHARACTER_GOODWILL friend_kill_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "friend_kill_goodwill"); static CHARACTER_GOODWILL neutral_kill_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "neutral_kill_goodwill"); static CHARACTER_GOODWILL enemy_kill_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "enemy_kill_goodwill"); static CHARACTER_GOODWILL community_member_kill_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "community_member_kill_goodwill"); static CHARACTER_REPUTATION_VALUE friend_kill_reputation = pSettings->r_s32(ACTIONS_POINTS_SECT, "friend_kill_reputation"); static CHARACTER_REPUTATION_VALUE neutral_kill_reputation = pSettings->r_s32(ACTIONS_POINTS_SECT, "neutral_kill_reputation"); static CHARACTER_REPUTATION_VALUE enemy_kill_reputation = pSettings->r_s32(ACTIONS_POINTS_SECT, "enemy_kill_reputation"); //(с) мин. время через которое снова будет зарегестрировано сообщение об атаке на персонажа static u32 min_attack_delta_time = u32(1000.f * pSettings->r_float(ACTIONS_POINTS_SECT, "min_attack_delta_time")); static CHARACTER_GOODWILL friend_fight_help_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "friend_fight_help_goodwill"); static CHARACTER_GOODWILL neutral_fight_help_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "neutral_fight_help_goodwill"); static CHARACTER_GOODWILL enemy_fight_help_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "enemy_fight_help_goodwill"); static CHARACTER_GOODWILL community_member_fight_help_goodwill = pSettings->r_s32(ACTIONS_POINTS_SECT, "community_member_fight_help_goodwill"); static CHARACTER_REPUTATION_VALUE friend_fight_help_reputation = pSettings->r_s32(ACTIONS_POINTS_SECT, "friend_fight_help_reputation"); static CHARACTER_REPUTATION_VALUE neutral_fight_help_reputation = pSettings->r_s32(ACTIONS_POINTS_SECT, "neutral_fight_help_reputation"); static CHARACTER_REPUTATION_VALUE enemy_fight_help_reputation = pSettings->r_s32(ACTIONS_POINTS_SECT, "enemy_fight_help_reputation"); CActor* actor = smart_cast<CActor*> (from); CInventoryOwner* inv_owner_from = smart_cast<CInventoryOwner*> (from); CAI_Stalker* stalker_from = smart_cast<CAI_Stalker*> (from); CAI_Stalker* stalker = smart_cast<CAI_Stalker*> (to); //вычисление изменения репутации и рейтинга пока ведется //только для актера if(!inv_owner_from || from->cast_base_monster()) return; ALife::ERelationType relation = ALife::eRelationTypeDummy; if(stalker) { stalker->m_actor_relation_flags.set(action, TRUE); relation = GetRelationType(smart_cast<CInventoryOwner*>(stalker), inv_owner_from); } switch(action) { case ATTACK: { if(actor) { //учитывать ATTACK и FIGHT_HELP, только если прошло время //min_attack_delta_time FIGHT_DATA* fight_data_from = FindFight (from->ID(), true); if(Device.dwTimeGlobal - fight_data_from->attack_time < min_attack_delta_time) break; fight_data_from->attack_time = Device.dwTimeGlobal; //если мы атаковали персонажа или монстра, который //кого-то атаковал, то мы помогли тому, кто защищался FIGHT_DATA* fight_data = FindFight (to->ID(),true); if(fight_data) { CAI_Stalker* defending_stalker = smart_cast<CAI_Stalker*>(Level().Objects.net_Find(fight_data->defender)); if(defending_stalker) { CAI_Stalker* attacking_stalker = smart_cast<CAI_Stalker*>(Level().Objects.net_Find(fight_data->attacker)); Action(actor, defending_stalker, attacking_stalker?FIGHT_HELP_HUMAN:FIGHT_HELP_MONSTER); } } } if(stalker) { bool bDangerScheme = false; const CEntityAlive* stalker_enemy = stalker->memory().enemy().selected(); if(actor && stalker_enemy) { const CInventoryOwner* const_inv_owner_from = inv_owner_from; if(stalker_enemy->human_being()) { const CInventoryOwner* const_inv_owner_stalker_enemy = smart_cast<const CInventoryOwner*>(stalker_enemy); ALife::ERelationType relation_to_actor = GetRelationType(const_inv_owner_stalker_enemy, const_inv_owner_from); if(relation_to_actor == ALife::eRelationTypeEnemy) bDangerScheme = true; } } SAttackGoodwillStorage* st = bDangerScheme?&gw_danger:&gw_free; CHARACTER_GOODWILL delta_goodwill = 0; CHARACTER_REPUTATION_VALUE delta_reputation = 0; switch (relation) { case ALife::eRelationTypeEnemy: { delta_goodwill = st->enemy_attack_goodwill; delta_reputation = st->enemy_attack_reputation; }break; case ALife::eRelationTypeNeutral: { delta_goodwill = st->neutral_attack_goodwill; delta_reputation = st->neutral_attack_reputation; }break; case ALife::eRelationTypeFriend: { delta_goodwill = st->friend_attack_goodwill; delta_reputation = st->friend_attack_reputation; }break; }; //сталкер при нападении на членов своей же группировки отношения не меняют //(считается, что такое нападение всегда случайно) // change relation only for pairs actor->stalker, do not use pairs stalker->stalker bool stalker_attack_team_mate = stalker && stalker_from; if (delta_goodwill && !stalker_attack_team_mate) { //изменить отношение ко всем членам атакованой группы (если такая есть) //как к тому кого атаковали CGroupHierarchyHolder& group = Level().seniority_holder().team(stalker->g_Team()).squad(stalker->g_Squad()).group(stalker->g_Group()); for(std::size_t i = 0; i < group.members().size(); i++) { ChangeGoodwill(group.members()[i]->ID(), from->ID(), delta_goodwill); } //*(CHARACTER_GOODWILL)( stalker->Sympathy() * (float)(delta_goodwill)); CHARACTER_GOODWILL community_goodwill = (CHARACTER_GOODWILL)( stalker->Sympathy() * (float)(st->community_member_attack_goodwill) ); if (community_goodwill) { ChangeCommunityGoodwill(stalker->Community(), from->ID(), community_goodwill); } } if(delta_reputation) { inv_owner_from->ChangeReputation(delta_reputation); } } } break; case KILL: { if(stalker) { //FIGHT_DATA* fight_data_from = FindFight (from->ID(), true); //мы помним то, какое отношение обороняющегося к атакующему //было перед началом драки ALife::ERelationType relation_before_attack = ALife::eRelationTypeDummy; //if(fight_data_from) // relation_before_attack = fight_data_from->defender_to_attacker; //else relation_before_attack = relation; CHARACTER_GOODWILL delta_goodwill = 0; CHARACTER_REPUTATION_VALUE delta_reputation = 0; switch (relation_before_attack) { case ALife::eRelationTypeEnemy: { delta_goodwill = enemy_kill_goodwill; delta_reputation = enemy_kill_reputation; }break; case ALife::eRelationTypeNeutral: { delta_goodwill = neutral_kill_goodwill; delta_reputation = neutral_kill_reputation; }break; case ALife::eRelationTypeFriend: { delta_goodwill = friend_kill_goodwill; delta_reputation = friend_kill_reputation; }break; }; //сталкер при нападении на членов своей же группировки отношения не меняют //(считается, что такое нападение всегда случайно) bool stalker_kills_team_mate = stalker_from && (stalker_from->Community() == stalker->Community()); if(delta_goodwill && !stalker_kills_team_mate) { //изменить отношение ко всем членам группы (если такая есть) //убитого, кроме него самого CGroupHierarchyHolder& group = Level().seniority_holder().team(stalker->g_Team()).squad(stalker->g_Squad()).group(stalker->g_Group()); for(std::size_t i = 0; i < group.members().size(); i++) { if(stalker->ID() != group.members()[i]->ID()) { ChangeGoodwill(group.members()[i]->ID(), from->ID(), delta_goodwill); } } //(CHARACTER_GOODWILL)( stalker->Sympathy() * (float)(delta_goodwill+community_member_kill_goodwill)); CHARACTER_GOODWILL community_goodwill = (CHARACTER_GOODWILL)( stalker->Sympathy() * (float)(community_member_kill_goodwill) ); if (community_goodwill) { ChangeCommunityGoodwill(stalker->Community(), from->ID(), community_goodwill); } } if(delta_reputation) { inv_owner_from->ChangeReputation(delta_reputation); } CHARACTER_RANK_VALUE delta_rank = 0; delta_rank = CHARACTER_RANK::rank_kill_points(CHARACTER_RANK::ValueToIndex(stalker->Rank())); if(delta_rank) inv_owner_from->ChangeRank(delta_rank); } } break; case FIGHT_HELP_HUMAN: case FIGHT_HELP_MONSTER: { if(stalker && stalker->g_Alive()) { CHARACTER_GOODWILL delta_goodwill = 0; CHARACTER_REPUTATION_VALUE delta_reputation = 0; switch (relation) { case ALife::eRelationTypeEnemy: { delta_goodwill = enemy_fight_help_goodwill; delta_reputation = enemy_fight_help_reputation; }break; case ALife::eRelationTypeNeutral: { delta_goodwill = neutral_fight_help_goodwill; delta_reputation = neutral_fight_help_reputation; }break; case ALife::eRelationTypeFriend: { delta_goodwill = friend_fight_help_goodwill; delta_reputation = friend_fight_help_reputation; }break; }; if(delta_goodwill) { //изменить отношение ко всем членам атакованой группы (если такая есть) //как к тому кого атаковали CGroupHierarchyHolder& group = Level().seniority_holder().team(stalker->g_Team()).squad(stalker->g_Squad()).group(stalker->g_Group()); for(std::size_t i = 0; i < group.members().size(); i++) { ChangeGoodwill(group.members()[i]->ID(), from->ID(), delta_goodwill); } //* ChangeCommunityGoodwill(stalker->Community(), from->ID(), (CHARACTER_GOODWILL)( stalker->Sympathy() * (float)delta_goodwill )); CHARACTER_GOODWILL community_goodwill = (CHARACTER_GOODWILL)( stalker->Sympathy() * (float)(community_member_fight_help_goodwill) ); if (community_goodwill) { ChangeCommunityGoodwill(stalker->Community(), from->ID(), community_goodwill); } } if(delta_reputation) { inv_owner_from->ChangeReputation(delta_reputation); } } } break; } }
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 ); }