#include "StdAfx.h" #include "EtherEmissionDevice.h" #include "ItemManager.h" #include "Skill.h" #include "SkillInfoParser.h" #include "SCItemSlotContainer.h" #include "SkillAttrCalculator.h" CEtherEmissionDevice::CEtherEmissionDevice() : is_active_(false), owner_(NULL) { } CEtherEmissionDevice::~CEtherEmissionDevice() { is_active_ = false; owner_ = NULL; device_info_.Init(); } void CEtherEmissionDevice::Init(Player* const owner) { is_active_ = false; owner_ = owner; device_info_.Init(); } bool CEtherEmissionDevice::ActiveBulletItem(const POSTYPE bullet_pos) { Player* const owner = GetOwner(); if (owner == NULL) { return false; } if (is_active_) { return false; } const ItemManager* const item_manager = owner->GetItemManager(); if (item_manager == NULL) { return false; } SCSlotContainer* const inven_container = item_manager->GetItemSlotContainer(SI_INVENTORY); if (inven_container == NULL) { return false; } SCSlotContainer* const equip_container = item_manager->GetItemSlotContainer(SI_EQUIPMENT); if (equip_container == NULL) { return false; } if (item_manager->ValidPos(SI_INVENTORY, bullet_pos) == false) { return false; } SCItemSlot& bullet_slot = (SCItemSlot&)inven_container->GetSlot(bullet_pos); if (bullet_slot.GetItemInfo() == NULL) { return false; } SCItemSlot& weapon_slot = (SCItemSlot&)equip_container->GetSlot(eEQUIPCONTAINER_WEAPON); if (weapon_slot.GetItemInfo() == NULL) { return false; } if (bullet_slot.GetItemInfo()->m_wType != eITEMTYPE_ETHER_BULLET || bullet_slot.GetNum() == 0) { return false; } if (weapon_slot.IsEquipEtherDevice() == false) { return false; } if ((!bullet_slot.GetLaxLock()->CanLock()) || (!weapon_slot.GetLaxLock()->CanLock())) { return false; } device_info_.Init(); if (SetBulletOption(bullet_slot) == false) { return false; } device_info_.bullet_slot_pos = bullet_pos; device_info_.bullet_slot = &bullet_slot; device_info_.weapon_slot = &weapon_slot; is_active_ = true; bullet_slot.GetLaxLock()->EnterLock(); weapon_slot.GetLaxLock()->EnterLock(); owner->GetCharInfo()->m_bActiveEtherDevice = TRUE; owner->GetCharInfo()->m_byEtherBulletPos = bullet_pos; return true; } bool CEtherEmissionDevice::InActiveBulletItem(const POSTYPE bullet_pos, const bool is_force) { Player* const owner = GetOwner(); if (owner == NULL) { return false; } if (is_force == false) { if (is_active_ == false) { return false; } if (device_info_.bullet_slot_pos != bullet_pos) { return false; } if (device_info_.apply_attack_speed != 0) { RemoveAttackSpeed(); } if (device_info_.is_apply_option) { return false; } } if (device_info_.bullet_slot != NULL) { (device_info_.bullet_slot)->GetLaxLock()->LeaveLock(); } if (device_info_.weapon_slot != NULL) { (device_info_.weapon_slot)->GetLaxLock()->LeaveLock(); } device_info_.Init(); is_active_ = false; owner->GetCharInfo()->m_bActiveEtherDevice = FALSE; owner->GetCharInfo()->m_byEtherBulletPos = INVALID_POSTYPE_VALUE; return true; } bool CEtherEmissionDevice::SetBulletOption(const SCItemSlot& bullet_slot) { const Player* const owner = GetOwner(); if (owner == NULL) { return false; } if (owner->GetItemManager() == NULL) { return false; } device_info_.bullet_info = EtherBulletInfoParser::Instance()->GetEtherBulletInfoByItemCode(bullet_slot.GetItemCode()); if (device_info_.bullet_info == NULL) { return false; } return true; } tagEtherBulletInfo* CEtherEmissionDevice::GetBulletOption() const { if (IsActive() == false) { return NULL; } return device_info_.bullet_info; } void CEtherEmissionDevice::ApplyOption() { Player* const owner = GetOwner(); if (owner == NULL) { return; } if (device_info_.is_apply_option) { return; } int combo_index = device_info_.combo_state - 1; if (device_info_.combo_state == tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL) { combo_index = tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL; } SkillAttrCalculator skill_calc(owner->GetAttr()); for (int i = 0; i < MAX_BULLET_OPTION_COUNT; ++i) { const tagEtherBulletInfo* const bullet_info = device_info_.bullet_info; if (bullet_info == NULL) { continue; } if (bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i] != 0 && bullet_info->m_EtherBulletOption[combo_index].m_iValue[i] != 0 && bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i] < _countof(g_ITEM_OPTION)) { skill_calc.AddAttr( g_ITEM_OPTION[bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i]], bullet_info->m_EtherBulletOption[combo_index].m_byValueType[i], bullet_info->m_EtherBulletOption[combo_index].m_iValue[i] ); } } device_info_.is_apply_option = true; } void CEtherEmissionDevice::RemoveOption() { Player* const owner = GetOwner(); if (owner == NULL) { return; } int combo_index = device_info_.combo_state - 1; if (device_info_.combo_state == tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL) { combo_index = tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL; } SkillAttrCalculator skill_calc(owner->GetAttr()); for (int i = 0; i < MAX_BULLET_OPTION_COUNT; ++i) { const tagEtherBulletInfo* const bullet_info = device_info_.bullet_info; if (bullet_info == NULL) { continue; } #ifdef _NA_008220_20150414_BUG_ETHERBULLET_ATTR if (bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i] != 0 && bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i] < _countof(g_ITEM_OPTION)) { skill_calc.ClearAttr( g_ITEM_OPTION[bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i]], bullet_info->m_EtherBulletOption[combo_index].m_byValueType[i] ); } #else if (bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i] != 0 && bullet_info->m_EtherBulletOption[combo_index].m_iValue[i] != 0 && bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i] < _countof(g_ITEM_OPTION)) { skill_calc.DelAttr( g_ITEM_OPTION[bullet_info->m_EtherBulletOption[combo_index].m_wOptionKind[i]], bullet_info->m_EtherBulletOption[combo_index].m_byValueType[i], bullet_info->m_EtherBulletOption[combo_index].m_iValue[i] ); } #endif //_NA_008220_20150414_BUG_ETHERBULLET_ATTR } device_info_.is_apply_option = false; } void CEtherEmissionDevice::ApplyCombo(const AttackType attack_type, const DWORD target_key) { if (attack_type == kNone) { if (device_info_.apply_attack_speed > 0) { RemoveAttackSpeed(); } device_info_.combo_state = tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL; } else if (attack_type == kSkill) { if (device_info_.apply_attack_speed > 0) { RemoveAttackSpeed(); } device_info_.combo_state = tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL; } else if (attack_type == kNormal) { if (device_info_.apply_attack_speed > 0) { RemoveAttackSpeed(); } if (target_key == device_info_.target_key) { if (device_info_.combo_state < tagEtherBulletInfo::eETHER_DEVICE_COMBO_MAX) { device_info_.combo_state++; IncreaseAttackSpeed(); } } else { device_info_.combo_state = tagEtherBulletInfo::eETHER_DEVICE_COMBO_1; device_info_.target_key = target_key; IncreaseAttackSpeed(); } device_info_.combo_tick = GetTickCount(); } } void CEtherEmissionDevice::IncreaseAttackSpeed() { Player* const owner = GetOwner(); if (owner == NULL) { return; } if (device_info_.combo_state == tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL) { return; } if (device_info_.apply_attack_speed > 0) { SkillAttrCalculator skill_calc(owner->GetAttr()); skill_calc.DelAttr( eATTR_ATTACK_SPEED, VALUE_TYPE_PERCENT_PER_CUR, device_info_.apply_attack_speed); device_info_.apply_attack_speed = 0; } if (device_info_.combo_state <= tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL || device_info_.combo_state >= tagEtherBulletInfo::eETHER_DEVICE_COMBO_MAX) { return; } device_info_.apply_attack_speed = device_info_.bullet_info->m_iAttackSpeed[device_info_.combo_state - 1]; SkillAttrCalculator skill_calc(owner->GetAttr()); skill_calc.AddAttr( eATTR_ATTACK_SPEED, VALUE_TYPE_PERCENT_PER_CUR, device_info_.apply_attack_speed); MSG_CG_STATUS_ETHER_ATTACK_SPEED_CMD cmd; cmd.m_AttackSpeedValue = device_info_.apply_attack_speed; owner->SendPacket(&cmd, sizeof(cmd)); } void CEtherEmissionDevice::RemoveAttackSpeed() { Player* const owner = GetOwner(); if (owner == NULL) { return; } if (device_info_.apply_attack_speed == 0) { return; } SkillAttrCalculator skill_calc(owner->GetAttr()); skill_calc.DelAttr( eATTR_ATTACK_SPEED, VALUE_TYPE_PERCENT_PER_CUR, device_info_.apply_attack_speed); MSG_CG_STATUS_ETHER_ATTACK_SPEED_CMD cmd; cmd.m_AttackSpeedValue = 0; owner->SendPacket(&cmd, sizeof(cmd)); device_info_.apply_attack_speed = 0; } Player* CEtherEmissionDevice::GetOwner() const { if (obj_util::IsValid(owner_) == false) { return NULL; } return owner_; } CEtherEmissionDevice::AttackType CEtherEmissionDevice::CanApplyBulletSkill( const Skill* const skill) const { const SCItemSlot* const bullet_item = device_info_.bullet_slot; if (bullet_item == NULL) { return kNone; } if (bullet_item->GetItemInfo()->m_wType != eITEMTYPE_ETHER_BULLET || bullet_item->GetNum() == 0) { return kNone; } const eSKILL_TYPE skill_type = skill->GetSkillType(); switch (skill_type) { case SKILL_TYPE_NORMAL: case SKILL_TYPE_NORMAL_AREA: case SKILL_TYPE_STYLE: return kNormal; } const SkillScriptInfo* const skill_info = skill->GetSkillBaseInfo(); if (skill_info == NULL) { return kNone; } if (skill_info->m_byEtherBulletInfo == 0) { return kNone; } #ifdef _NA_004605_20120417_ACTIVE_ETHER_BULLET_TO_SKILL return kSkill; #else return kNone; #endif } int CEtherEmissionDevice::StartEtherEmissionDevice(Skill* const skill, const DWORD target_key) { const Player* const owner = GetOwner(); if (owner == NULL) { return 0; } if (is_active_ == false) { return 0; } #ifdef _NA_008679_20160202_REWORK_BATTLEGROUND if (owner->IsThereBattleGroundZone() == true ) { return 0; } #endif //_NA_008679_20160202_REWORK_BATTLEGROUND //_NA_008456_20150819_ETHER_BULLET_PVP_CHECK GameField* game_field = owner->GetField(); if (game_field == NULL) { return 0; } Character* main_target = game_field->FindCharacter(target_key); if (main_target == NULL) { return 0; } if (main_target->GetObjectKey() != owner->GetObjectKey() && main_target->IsEqualObjectKind(PLAYER_OBJECT) == TRUE && GetBulletOption()->apply_pvp_damage_ == FALSE) { //źȯÀÌ µ¿ÀÛÇÏÁö ¾Ê´Â Á¶°Ç //Ÿ°ÙÀÌ Ç÷¹À̾îÀε¥, PvPźȯÀÌ ¾Æ´Ò °æ¿ì return 0; } //---------------------------------------------------------- const AttackType attack_type = CanApplyBulletSkill(skill); ApplyCombo(attack_type, target_key); if (attack_type == kNone) { return 0; } ApplyOption(); skill->SetAppliedEtherBulletOption(TRUE); skill->SetAppliedEtherBulletInfo(device_info_.bullet_info); return device_info_.combo_state; } void CEtherEmissionDevice::EndEtherEmissionDevice(Skill* const skill) { //Á¶°Çüũ------------------------------------------------------------------------------------ Player* const owner = GetOwner(); if (owner == NULL) { return; } if (is_active_ == false) { return; } if (device_info_.bullet_info == NULL) { return; } if (device_info_.apply_attack_speed != 0) { RemoveAttackSpeed(); } if (device_info_.is_apply_option == false) { return; } //Ãß°¡µÈ ¿É¼Ç Á¦°Å ---------------------------------------------------------------------------- RemoveOption(); skill->SetAppliedEtherBulletOption(FALSE); skill->SetAppliedEtherBulletInfo(NULL); //źȯ ¼ö·® 1°¨¼Ò (»ç¿ë¿¡ ´ëÇÑ Ã³¸®) ---------------------------------------------------------- ItemManager* const item_manager = owner->GetItemManager(); if (item_manager == NULL) { return; } SCSlotContainer* const inven_container = item_manager->GetItemSlotContainer(SI_INVENTORY); if (inven_container == NULL) { return; } GAMELOG->LogItem(ITEM_USE, owner, device_info_.bullet_slot); const POSTYPE del_pos = device_info_.bullet_slot_pos; if ((device_info_.bullet_slot)->GetNum() == 1) { MSG_CG_ITEM_INACTIVE_ETHER_BULLET_CMD cmd; owner->SendPacket(&cmd, sizeof(cmd)); InActiveBulletItem(0, true); } item_manager->Lose(inven_container, del_pos, 1); MSG_CG_ITEM_USE_CMD cmd; cmd.m_ItemPos = del_pos; owner->SendPacket(&cmd, sizeof(cmd)); } void CEtherEmissionDevice::Update() { if (is_active_ == false) { return; } if (device_info_.combo_state >= tagEtherBulletInfo::eETHER_DEVICE_COMBO_1) { if (device_info_.combo_tick + 2000 < GetTickCount()) { if (device_info_.apply_attack_speed > 0) { RemoveAttackSpeed(); } device_info_.combo_state = tagEtherBulletInfo::eETHER_DEVICE_COMBO_NORMAL; } } } POSTYPE CEtherEmissionDevice::GetBulletItemPos() const { if (is_active_ == false) { return INVALID_POSTYPE_VALUE; } return device_info_.bullet_slot_pos; }