void CPythonPlayer::UseGuildSkill(DWORD dwSkillSlotIndex) { CInstanceBase* pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) return; if (!pkInstMain->CanUseSkill()) return; /////////////////////////////////////////////////////////////////////////////////////////////// if (dwSkillSlotIndex >= SKILL_MAX_NUM) { Tracenf("CPythonPlayer::UseGuildSkill(dwSkillSlotIndex=%d) It's not available skill slot number", dwSkillSlotIndex); return; } TSkillInstance & rkSkillInst = m_playerStatus.aSkill[dwSkillSlotIndex]; DWORD dwSkillIndex = rkSkillInst.dwIndex; CPythonSkill::TSkillData * pSkillData; if (!CPythonSkill::Instance().GetSkillData(dwSkillIndex, &pSkillData)) return; if (__CheckRestSkillCoolTime(dwSkillSlotIndex)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "WAIT_COOLTIME")); return; } if (pSkillData->IsOnlyForGuildWar()) { if (!CPythonGuild::Instance().IsDoingGuildWar()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "ONLY_FOR_GUILD_WAR")); return; } } DWORD dwMotionIndex = pSkillData->GetSkillMotionIndex(); if (!pkInstMain->NEW_UseSkill(dwSkillIndex, dwMotionIndex, 1, false)) { Tracenf("CPythonPlayer::UseGuildSkill(%d) - pkInstMain->NEW_UseSkill - ERROR", dwSkillIndex); } /////////////////////////////////////////////////////////////////////////////////////////////// CPythonNetworkStream::Instance().SendGuildUseSkillPacket(dwSkillIndex, 0); __RunCoolTime(dwSkillSlotIndex); }
void CPythonPlayer::ChangeCurrentSkillNumberOnly(DWORD dwSlotIndex) { if (dwSlotIndex >= SKILL_MAX_NUM) return; TSkillInstance & rkSkillInst = m_playerStatus.aSkill[dwSlotIndex]; CPythonSkill::TSkillData * pSkillData; if (!CPythonSkill::Instance().GetSkillData(rkSkillInst.dwIndex, &pSkillData)) return; if (!pSkillData->IsCanUseSkill()) return; if (!__IsRightButtonSkillMode()) { if (!__IsTarget()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NEED_TARGET")); return; } ClickSkillSlot(dwSlotIndex); } else { m_dwcurSkillSlotIndex = dwSlotIndex; PyCallClassMemberFunc(m_ppyGameWindow, "ChangeCurrentSkill", Py_BuildValue("(i)", dwSlotIndex)); } }
void CPythonPlayer::__OnPressSmart(CInstanceBase& rkInstMain, bool isAuto) { DWORD dwPickedItemID; DWORD dwPickedActorID; TPixelPosition kPPosPickedGround; bool isPickedItemID=__GetPickedItemID(&dwPickedItemID); bool isPickedActorID=__GetPickedActorID(&dwPickedActorID); bool isPickedGroundPos=__GetPickedGroundPos(&kPPosPickedGround); if (isPickedItemID) { __OnPressItem(rkInstMain, dwPickedItemID); } else if (isPickedActorID && dwPickedActorID != GetMainCharacterIndex()) { __OnPressActor(rkInstMain, dwPickedActorID, isAuto); } else if (isPickedGroundPos) { __OnPressGround(rkInstMain, kPPosPickedGround); } else { __OnPressScreen(rkInstMain); } }
bool CPythonPlayer::__CheckSpecialSkill(DWORD dwSkillIndex) { CInstanceBase* pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) return false; // Fishing if (c_iSkillIndex_Fishing == dwSkillIndex) { if (pkInstMain->IsFishingMode()) { NEW_Fishing(); } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "EQUIP_FISHING_ROD")); } return true; } // Combo else if (c_iSkillIndex_Combo == dwSkillIndex) { DWORD dwSlotIndex; if (!GetSkillSlotIndex(dwSkillIndex, &dwSlotIndex)) return false; int iLevel = GetSkillLevel(dwSlotIndex); if (iLevel > 0) { CPythonNetworkStream::Instance().SendUseSkillPacket(dwSkillIndex); } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_YET_LEARN")); } return true; } return false; }
bool CPythonPlayer::__HasEnoughArrow() { CItemData * pItemData; if (CItemManager::Instance().GetItemDataPointer(GetItemIndex(TItemPos(INVENTORY, c_Equipment_Arrow)), &pItemData)) if (CItemData::ITEM_TYPE_WEAPON == pItemData->GetType()) if (CItemData::WEAPON_ARROW == pItemData->GetSubType()) { return true; } PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotShotError", Py_BuildValue("(is)", GetMainCharacterIndex(), "EMPTY_ARROW")); return false; }
//Запрос на диалог, если возвратить true то в этот момент можно начать диалог bool LAi_type_guardian_CanDialog(aref chr, aref by) { //Если просто стоим, то согласимся на диалог if(chr.chr_ai.tmpl == LAI_TMPL_STAY) { if(LAi_CanNearEnemy(chr, 5.0)) return false; return true; } if(sti(by.index) == GetMainCharacterIndex()) { if(chr.chr_ai.tmpl == LAI_TMPL_DIALOG) { if(LAi_tmpl_dialog_StopNPC(chr)) return true; } } return false; }
bool CPythonPlayer::__ProcessEnemySkillTargetRange(CInstanceBase& rkInstMain, CInstanceBase& rkInstTarget, CPythonSkill::TSkillData& rkSkillData, DWORD dwSkillSlotIndex) { DWORD dwSkillTargetRange=__GetSkillTargetRange(rkSkillData); float fSkillTargetRange = float(dwSkillTargetRange); if (fSkillTargetRange <= 0.0f) return true; // #0000806: [M2EU] 수룡에게 무사(나한군) 탄환격 스킬 사용 안됨 float fTargetDistance = rkInstMain.GetDistance(&rkInstTarget); extern bool IS_HUGE_RACE(unsigned int vnum); if (IS_HUGE_RACE(rkInstTarget.GetRace())) { fTargetDistance -= 200.0f; // TEMP: 일단 하드 코딩 처리. 정석적으로는 바운드 스피어를 고려해야함 } if (fTargetDistance >= fSkillTargetRange) { if (rkSkillData.IsChargeSkill()) { if (!__IsReservedUseSkill(dwSkillSlotIndex)) __SendUseSkill(dwSkillSlotIndex, 0); } __ReserveUseSkill(rkInstTarget.GetVirtualID(), dwSkillSlotIndex, dwSkillTargetRange); return false; } // 2004.07.05.myevan. 궁신탄영 사용시 맵에 끼임. 사용하기전 갈수 있는곳 체크 TPixelPosition kPPosTarget; rkInstTarget.NEW_GetPixelPosition(&kPPosTarget); IBackground& rkBG=IBackground::Instance(); if (rkBG.IsBlock(kPPosTarget.x, kPPosTarget.y)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "CANNOT_APPROACH")); return false; } return true; }
bool CPythonPlayer::__UseSkill(DWORD dwSlotIndex) { // PrivateShop if (IsOpenPrivateShop()) { return true; } if (!__CanUseSkill()) { return false; } if (dwSlotIndex >= SKILL_MAX_NUM) { Tracenf("CPythonPlayer::__UseSkill(dwSlotIndex=%d) It's not available skill slot number", dwSlotIndex); return false; } TSkillInstance & rkSkillInst = m_playerStatus.aSkill[dwSlotIndex]; if (__CheckSpecialSkill(rkSkillInst.dwIndex)) { return true; } CPythonSkill::TSkillData * pSkillData; if (!CPythonSkill::Instance().GetSkillData(rkSkillInst.dwIndex, &pSkillData)) { Tracenf("CPythonPlayer::__UseSkill(dwSlotIndex=%d) There is no skill data", dwSlotIndex); return false; } if (pSkillData->IsToggleSkill()) { if (IsSkillActive(dwSlotIndex)) { CPythonNetworkStream::Instance().SendUseSkillPacket(rkSkillInst.dwIndex, dwSlotIndex); return false; } } if (!__CheckSkillUsable(dwSlotIndex)) { return false; } CInstanceBase * pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) { Tracenf("CPythonPlayer::__UseSkill(dwSlotIndex=%d) There is no main player", dwSlotIndex); return false; } if (pkInstMain->IsUsingSkill()) { return false; } CInstanceBase * pkInstTarget = NULL; // NOTE : 타겟이 필요한 경우 if (pSkillData->IsNeedTarget() || pSkillData->CanChangeDirection() || pSkillData->IsAutoSearchTarget()) { if (pSkillData->IsNeedCorpse()) pkInstTarget=__GetDeadTargetInstancePtr(); else pkInstTarget=__GetAliveTargetInstancePtr(); // 현재 타겟이 없으면.. if (!pkInstTarget) { // 업데이트하고.. __ChangeTargetToPickedInstance(); // 다시 얻어낸다. if (pSkillData->IsNeedCorpse()) pkInstTarget=__GetDeadTargetInstancePtr(); else pkInstTarget=__GetAliveTargetInstancePtr(); } if (pkInstTarget) { if (pSkillData->IsOnlyForAlliance()) { if (pkInstMain == pkInstTarget) { if (!pSkillData->CanUseForMe()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "CANNOT_USE_SELF")); return false; } } else if (!pkInstMain->IsAttackableInstance(*pkInstTarget) && pkInstTarget->IsPC()) { DWORD dwSkillRange = __GetSkillTargetRange(*pSkillData); if (dwSkillRange > 0) { float fDistance=pkInstMain->GetDistance(pkInstTarget); if (fDistance>=float(dwSkillRange)) { __ReserveUseSkill(pkInstTarget->GetVirtualID(), dwSlotIndex, dwSkillRange); return false; } } } else { if (pSkillData->CanUseForMe()) { pkInstTarget = pkInstMain; Tracef(" [ALERT] 동료에게 사용하는 기술임에도 적에게 타겟팅 되어있어서 자신에게로 재설정\n"); } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "ONLY_FOR_ALLIANCE")); return false; } } } else { if (pkInstTarget->IsInSafe()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "CANNOT_ATTACK_ENEMY_IN_SAFE_AREA")); return false; } if (pkInstMain->IsAttackableInstance(*pkInstTarget)) { if (!__ProcessEnemySkillTargetRange(*pkInstMain, *pkInstTarget, *pSkillData, dwSlotIndex)) return false; } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "CANNOT_ATTACK")); return false; } } pkInstMain->SetFlyTargetInstance(*pkInstTarget); if (pkInstMain != pkInstTarget) { if (pkInstMain->IsFlyTargetObject()) { pkInstMain->NEW_LookAtFlyTarget(); } else { pkInstMain->NEW_LookAtDestInstance(*pkInstTarget); } } } else { if (pSkillData->IsAutoSearchTarget()) { if (pkInstMain->NEW_GetFrontInstance(&pkInstTarget, 2000.0f)) { SetTarget(pkInstTarget->GetVirtualID()); if (!__ProcessEnemySkillTargetRange(*pkInstMain, *pkInstTarget, *pSkillData, dwSlotIndex)) return false; } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NEED_TARGET")); return false; } } if (pSkillData->CanUseForMe()) { pkInstTarget = pkInstMain; pkInstMain->SetFlyTargetInstance(*pkInstMain); Tracef(" [ALERT] 타겟이 없어서 플레이어에게 사용합니다\n"); } else if (pSkillData->IsNeedCorpse()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "ONLY_FOR_CORPSE")); return false; } else { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NEED_TARGET")); return false; } } } if (pSkillData->CanChangeDirection()) { DWORD dwPickedActorID; TPixelPosition kPPosPickedGround; if (pkInstTarget && pkInstTarget!=pkInstMain) { pkInstMain->NEW_LookAtDestInstance(*pkInstTarget); } else if (__GetPickedActorID(&dwPickedActorID)) { CInstanceBase* pkInstVictim=NEW_FindActorPtr(dwPickedActorID); if (pkInstVictim) pkInstMain->NEW_LookAtDestInstance(*pkInstVictim); } else if (__GetPickedGroundPos(&kPPosPickedGround)) { pkInstMain->NEW_LookAtDestPixelPosition(kPPosPickedGround); } else { Tracenf("CPythonPlayer::__UseSkill(%d) - 화면 기준 방향 설정을 해야함", dwSlotIndex); } } // 관격술 처리 DWORD dwTargetMaxCount = pSkillData->GetTargetCount(rkSkillInst.fcurEfficientPercentage); DWORD dwRange = __GetSkillTargetRange(*pSkillData); if (dwTargetMaxCount>0 && pkInstTarget) { DWORD dwTargetCount=1; std::vector<CInstanceBase*> kVct_pkInstTarget; if (pSkillData->IsFanRange()) { if (pkInstMain->NEW_GetInstanceVectorInFanRange(float(dwRange), *pkInstTarget, &kVct_pkInstTarget)) { std::vector<CInstanceBase*>::iterator i; for (i=kVct_pkInstTarget.begin(); i!=kVct_pkInstTarget.end(); ++i) { if (dwTargetCount>=dwTargetMaxCount) break; CInstanceBase* pkInstEach=*i; if (pkInstTarget!=pkInstEach && !pkInstEach->IsDead()) { pkInstMain->AddFlyTargetInstance(*pkInstEach); CPythonNetworkStream::Instance().SendAddFlyTargetingPacket(pkInstEach->GetVirtualID(), pkInstEach->GetGraphicThingInstanceRef().OnGetFlyTargetPosition()); dwTargetCount++; } } } } else if (pSkillData->IsCircleRange()) { if (pkInstMain->NEW_GetInstanceVectorInCircleRange(float(dwRange), &kVct_pkInstTarget)) { std::vector<CInstanceBase*>::iterator i; for (i=kVct_pkInstTarget.begin(); i!=kVct_pkInstTarget.end(); ++i) { if (dwTargetCount>=dwTargetMaxCount) break; CInstanceBase* pkInstEach=*i; if (pkInstTarget!=pkInstEach && !pkInstEach->IsDead()) { pkInstMain->AddFlyTargetInstance(*pkInstEach); CPythonNetworkStream::Instance().SendAddFlyTargetingPacket(pkInstEach->GetVirtualID(), pkInstEach->GetGraphicThingInstanceRef().OnGetFlyTargetPosition()); dwTargetCount++; } } } } if (dwTargetCount<dwTargetMaxCount) { while (dwTargetCount<dwTargetMaxCount) { TPixelPosition kPPosDst; pkInstMain->NEW_GetRandomPositionInFanRange(*pkInstTarget, &kPPosDst); kPPosDst.x=kPPosDst.x; kPPosDst.y=-kPPosDst.y; pkInstMain->AddFlyTargetPosition(kPPosDst); CPythonNetworkStream::Instance().SendAddFlyTargetingPacket(0, kPPosDst); dwTargetCount++; } } } ///// // NOTE : 멀리서 적을 클릭해놓고 스킬을 쓰면 스킬을 쓴뒤 바로 적을 공격하는 문제를 수정하기 위한 코드 - [levites] __ClearReservedAction(); ///// if (!pSkillData->IsNoMotion()) { DWORD dwMotionIndex = pSkillData->GetSkillMotionIndex(rkSkillInst.iGrade); DWORD dwLoopCount = pSkillData->GetMotionLoopCount(rkSkillInst.fcurEfficientPercentage); if (!pkInstMain->NEW_UseSkill(rkSkillInst.dwIndex, dwMotionIndex, dwLoopCount, pSkillData->IsMovingSkill() ? true : false)) { Tracenf("CPythonPlayer::__UseSkill(%d) - pkInstMain->NEW_UseSkill - ERROR", dwSlotIndex); return false; } } DWORD dwTargetVID=pkInstTarget ? pkInstTarget->GetVirtualID() : 0; __SendUseSkill(dwSlotIndex, dwTargetVID); return true; }
bool CPythonPlayer::__CheckSkillUsable(DWORD dwSlotIndex) { CInstanceBase * pkInstMain = NEW_GetMainActorPtr(); if (!pkInstMain) return false; if (dwSlotIndex >= SKILL_MAX_NUM) return false; TSkillInstance & rkSkillInst = m_playerStatus.aSkill[dwSlotIndex]; CPythonSkill::TSkillData * pSkillData; if (!CPythonSkill::Instance().GetSkillData(rkSkillInst.dwIndex, &pSkillData)) return false; if (pkInstMain->IsMountingHorse()) { if (!pSkillData->IsHorseSkill()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_HORSE_SKILL")); return false; } } if (pSkillData->IsHorseSkill()) { if (!pkInstMain->IsMountingHorse()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "HAVE_TO_RIDE")); return false; } } // 2004.07.26.levites - 안전지대에서 공격 못하도록 수정 // NOTE : 공격 스킬은 안전지대에서 사용하지 못합니다 - [levites] if (pSkillData->IsAttackSkill()) { if (pkInstMain->IsInSafe()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "IN_SAFE")); return false; } } // NOTE : 패시브 스킬은 사용하지 못합니다 - [levites] if (!pSkillData->IsCanUseSkill()) return false; // if (CPythonSkill::SKILL_TYPE_PASSIVE == pSkillData->byType) // return false; // NOTE : [Only Assassin] 빈병이 있는지 체크 합니다. if (pSkillData->IsNeedEmptyBottle()) { if (!__HasItem(27995)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NEED_EMPTY_BOTTLE")); return false; } } // NOTE : [Only Assassin] 독병이 있는지 체크 합니다. if (pSkillData->IsNeedPoisonBottle()) { if (!__HasItem(27996)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NEED_POISON_BOTTLE")); return false; } } // NOTE : 낚시 중일때는 스킬을 사용하지 못합니다. if (pkInstMain->IsFishingMode()) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "REMOVE_FISHING_ROD")); return false; } // NOTE : 레벨 체크 if (m_sysIsLevelLimit) { if (rkSkillInst.iLevel <= 0) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_YET_LEARN")); return false; } } // NOTE : 들고 있는 무기 체크 if (!pSkillData->CanUseWeaponType(pkInstMain->GetWeaponType())) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_MATCHABLE_WEAPON")); return false; } if (!pSkillData->IsHorseSkill()) // HORSE 스킬 중에 화살을 쓰지 않는 스킬이 있기 때문에 { if (__CheckShortArrow(rkSkillInst, *pSkillData)) return false; // NOTE : 활이 필요할 경우 화살 개수 체크 if (pSkillData->IsNeedBow()) { if (!__HasEnoughArrow()) return false; } } if (__CheckDashAffect(*pkInstMain)) { if (!pSkillData->IsChargeSkill()) { if (__CheckRestSkillCoolTime(dwSlotIndex)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "WAIT_COOLTIME")); return false; } } } else { if (__CheckRestSkillCoolTime(dwSlotIndex)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "WAIT_COOLTIME")); return false; } if (__CheckShortLife(rkSkillInst, *pSkillData)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_ENOUGH_HP")); return false; } if (__CheckShortMana(rkSkillInst, *pSkillData)) { PyCallClassMemberFunc(m_ppyGameWindow, "OnCannotUseSkill", Py_BuildValue("(is)", GetMainCharacterIndex(), "NOT_ENOUGH_SP")); return false; } } return true; }