tester12 1 Posted October 2, 2019 Share Posted October 2, 2019 Hello, I have one problem with mounts. System is mount around you (like horse), and here problem: when i call mount it, with click in print he come on and give bonus (load from item_proto applytype0..), but shouldn't, and when i click ctrl+G to climb on him, it give yet the same bonuses(x2). I want to give bonus only when print in panel slot mount. Have any method for check item in slot with lua? Or what are some ideas to fix this? Link to comment Share on other sites More sharing options...
tester12 1 Posted October 27, 2019 Author Share Posted October 27, 2019 up Link to comment Share on other sites More sharing options...
OkamiRo 5 Posted August 19, 2020 Share Posted August 19, 2020 Same problem here. Link to comment Share on other sites More sharing options...
Catalin2o14 142 Posted August 20, 2020 Share Posted August 20, 2020 post the do_ride from cmd_general. Link to comment Share on other sites More sharing options...
OkamiRo 5 Posted August 20, 2020 Share Posted August 20, 2020 10 hours ago, Catalin2o14 said: post the do_ride from cmd_general. Here: ACMD(do_ride) { // dev_log(LOG_DEB0, "[DO_RIDE] start"); if (ch->IsDead() || ch->IsStun()) return; if (ch->GetMapIndex() == 113) return; #ifdef ENABLE_MOUNT_COSTUME_SYSTEM if (ch->IsPolymorphed() == true){ ch->ChatPacket(CHAT_TYPE_INFO, "Cannot use a mount when you're transformed."); return; } if(ch->GetWear(WEAR_COSTUME_MOUNT)) { CMountSystem* mountSystem = ch->GetMountSystem(); LPITEM mount = ch->GetWear(WEAR_COSTUME_MOUNT); DWORD mobVnum = 0; if (!mountSystem && !mount) return; #ifdef __CHANGELOOK_SYSTEM__ if(mount->GetTransmutation()) { const TItemTable* itemTable = ITEM_MANAGER::instance().GetTable(mount->GetTransmutation()); if (itemTable) mobVnum = itemTable->alValues[1]; else mobVnum = mount->GetValue(1); } else mobVnum = mount->GetValue(1); #else if(mount->GetValue(1) != 0) mobVnum = mount->GetValue(1); #endif if (ch->GetMountVnum()) { if(mountSystem->CountSummoned() == 0) { mountSystem->Unmount(mobVnum); } } else { if(mountSystem->CountSummoned() == 1) { mountSystem->Mount(mobVnum, mount); } } return; } #endif if (ch->IsHorseRiding()) { ch->StopRiding(); return; } if (ch->GetHorse() != NULL) { ch->StartRiding(); return; } for (BYTE i=0; i<INVENTORY_MAX_NUM; ++i) { LPITEM item = ch->GetInventoryItem(i); if (NULL == item) continue; if (item->GetType() == ITEM_COSTUME && item->GetSubType() == COSTUME_MOUNT) { ch->UseItem(TItemPos (INVENTORY, i)); return; } } ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("cmd_general.cpp line 2452: Summon the horse first.")); } Link to comment Share on other sites More sharing options...
Catalin2o14 142 Posted August 20, 2020 Share Posted August 20, 2020 6 hours ago, Dogariu Ionuț Gabriel said: Here: ACMD(do_ride) { // dev_log(LOG_DEB0, "[DO_RIDE] start"); if (ch->IsDead() || ch->IsStun()) return; if (ch->GetMapIndex() == 113) return; #ifdef ENABLE_MOUNT_COSTUME_SYSTEM if (ch->IsPolymorphed() == true){ ch->ChatPacket(CHAT_TYPE_INFO, "Cannot use a mount when you're transformed."); return; } if(ch->GetWear(WEAR_COSTUME_MOUNT)) { CMountSystem* mountSystem = ch->GetMountSystem(); LPITEM mount = ch->GetWear(WEAR_COSTUME_MOUNT); DWORD mobVnum = 0; if (!mountSystem && !mount) return; #ifdef __CHANGELOOK_SYSTEM__ if(mount->GetTransmutation()) { const TItemTable* itemTable = ITEM_MANAGER::instance().GetTable(mount->GetTransmutation()); if (itemTable) mobVnum = itemTable->alValues[1]; else mobVnum = mount->GetValue(1); } else mobVnum = mount->GetValue(1); #else if(mount->GetValue(1) != 0) mobVnum = mount->GetValue(1); #endif if (ch->GetMountVnum()) { if(mountSystem->CountSummoned() == 0) { mountSystem->Unmount(mobVnum); } } else { if(mountSystem->CountSummoned() == 1) { mountSystem->Mount(mobVnum, mount); } } return; } #endif if (ch->IsHorseRiding()) { ch->StopRiding(); return; } if (ch->GetHorse() != NULL) { ch->StartRiding(); return; } for (BYTE i=0; i<INVENTORY_MAX_NUM; ++i) { LPITEM item = ch->GetInventoryItem(i); if (NULL == item) continue; if (item->GetType() == ITEM_COSTUME && item->GetSubType() == COSTUME_MOUNT) { ch->UseItem(TItemPos (INVENTORY, i)); return; } } ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("cmd_general.cpp line 2452: Summon the horse first.")); } this function seems ok. put this function: mountSystem->Mount Link to comment Share on other sites More sharing options...
OkamiRo 5 Posted August 20, 2020 Share Posted August 20, 2020 58 minutes ago, Catalin2o14 said: this function seems ok. put this function: mountSystem->Mount Could you please let me know exactly what do you need? I don't really understeand where i can find this function: mountSystem->Mount MountSystem.cpp #include "stdafx.h" #include "config.h" #include "utils.h" #include "vector.h" #include "char.h" #include "sectree_manager.h" #include "char_manager.h" #include "mob_manager.h" #include "MountSystem.h" #include "../../common/VnumHelper.h" #include "packet.h" #include "item_manager.h" #include "item.h" EVENTINFO(mountsystem_event_info) { CMountSystem* pMountSystem; }; EVENTFUNC(mountsystem_update_event) { mountsystem_event_info* info = dynamic_cast<mountsystem_event_info*>( event->info ); if ( info == NULL ) { sys_err( "<mountsystem_update_event> <Factor> Null pointer" ); return 0; } CMountSystem* pMountSystem = info->pMountSystem; if (NULL == pMountSystem) return 0; pMountSystem->Update(0); return PASSES_PER_SEC(1) / 4; } /////////////////////////////////////////////////////////////////////////////////////// // CMountActor /////////////////////////////////////////////////////////////////////////////////////// CMountActor::CMountActor(LPCHARACTER owner, DWORD vnum) { m_dwVnum = vnum; m_dwVID = 0; m_dwLastActionTime = 0; m_pkChar = 0; m_pkOwner = owner; m_originalMoveSpeed = 0; m_dwSummonItemVID = 0; m_dwSummonItemVnum = 0; } CMountActor::~CMountActor() { this->Unsummon(); m_pkOwner = 0; } void CMountActor::SetName() { std::string petName = m_pkOwner->GetName(); if (true == IsSummoned()) { petName += " Mount"; m_pkChar->SetName(petName); } m_name = petName; } bool CMountActor::Mount(LPITEM mountItem) { if (0 == m_pkOwner) return false; if(!mountItem) return false; if (m_pkOwner->IsHorseRiding()) m_pkOwner->StopRiding(); if (m_pkOwner->GetHorse()) m_pkOwner->HorseSummon(false); Unmount(); m_pkOwner->AddAffect(AFFECT_MOUNT, POINT_MOUNT, m_dwVnum, AFF_NONE, (DWORD)mountItem->GetSocket(0) - time(0), 0, true); for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i) { if (mountItem->GetProto()->aApplies[i].bType == APPLY_NONE) continue; m_pkOwner->AddAffect(AFFECT_MOUNT_BONUS, aApplyInfo[mountItem->GetProto()->aApplies[i].bType].bPointType, mountItem->GetProto()->aApplies[i].lValue, AFF_NONE, (DWORD)mountItem->GetSocket(0) - time(0), 0, false); } return m_pkOwner->GetMountVnum() == m_dwVnum; } void CMountActor::Unmount() { if (0 == m_pkOwner) return; if (!m_pkOwner->GetMountVnum()) return; m_pkOwner->RemoveAffect(AFFECT_MOUNT); m_pkOwner->RemoveAffect(AFFECT_MOUNT_BONUS); m_pkOwner->MountVnum(0); if (m_pkOwner->IsHorseRiding()) m_pkOwner->StopRiding(); if (m_pkOwner->GetHorse()) m_pkOwner->HorseSummon(false); m_pkOwner->MountVnum(0); } void CMountActor::Unsummon() { if (true == this->IsSummoned()) { this->SetSummonItem(NULL); if (NULL != m_pkChar) M2_DESTROY_CHARACTER(m_pkChar); m_pkChar = 0; m_dwVID = 0; } } DWORD CMountActor::Summon(LPITEM pSummonItem, bool bSpawnFar) { long x = m_pkOwner->GetX(); long y = m_pkOwner->GetY(); long z = m_pkOwner->GetZ(); if (true == bSpawnFar) { x += (number(0, 1) * 2 - 1) * number(2000, 2500); y += (number(0, 1) * 2 - 1) * number(2000, 2500); } else { x += number(-100, 100); y += number(-100, 100); } if (0 != m_pkChar) { m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y); m_dwVID = m_pkChar->GetVID(); return m_dwVID; } m_pkChar = CHARACTER_MANAGER::instance().SpawnMob(m_dwVnum, m_pkOwner->GetMapIndex(), x, y, z, false, (int)(m_pkOwner->GetRotation()+180), false); if (0 == m_pkChar) { sys_err("[CMountActor::Summon] Failed to summon the mount. (vnum: %d)", m_dwVnum); return 0; } m_pkChar->SetMount(); m_pkChar->SetEmpire(m_pkOwner->GetEmpire()); m_dwVID = m_pkChar->GetVID(); this->SetName(); this->SetSummonItem(pSummonItem); //m_pkOwner->ComputePoints(); m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z); return m_dwVID; } bool CMountActor::_UpdateFollowAI() { if (0 == m_pkChar->m_pkMobData) { return false; } if (0 == m_originalMoveSpeed) { const CMob* mobData = CMobManager::Instance().Get(m_dwVnum); if (0 != mobData) m_originalMoveSpeed = mobData->m_table.sMovingSpeed; } float START_FOLLOW_DISTANCE = 300.0f; float START_RUN_DISTANCE = 900.0f; float RESPAWN_DISTANCE = 4500.f; int APPROACH = 200; bool bRun = false; DWORD currentTime = get_dword_time(); long ownerX = m_pkOwner->GetX(); long ownerY = m_pkOwner->GetY(); long charX = m_pkChar->GetX(); long charY = m_pkChar->GetY(); float fDist = DISTANCE_APPROX(charX - ownerX, charY - ownerY); if (fDist >= RESPAWN_DISTANCE) { float fOwnerRot = m_pkOwner->GetRotation() * 3.141592f / 180.f; float fx = -APPROACH * cos(fOwnerRot); float fy = -APPROACH * sin(fOwnerRot); if (m_pkChar->Show(m_pkOwner->GetMapIndex(), ownerX + fx, ownerY + fy)) { return true; } } if (fDist >= START_FOLLOW_DISTANCE) { m_pkChar->SetNowWalking(false); Follow(APPROACH); m_pkChar->SetLastAttacked(currentTime); m_dwLastActionTime = currentTime; } else m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0); return true; } bool CMountActor::Update(DWORD deltaTime) { bool bResult = true; if (m_pkOwner->IsDead() || (IsSummoned() && m_pkChar->IsDead()) || NULL == ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID()) || ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())->GetOwner() != this->GetOwner() ) { this->Unsummon(); return true; } if (this->IsSummoned()) bResult = bResult && this->_UpdateFollowAI(); return bResult; } bool CMountActor::Follow(float fMinDistance) { if( !m_pkOwner || !m_pkChar) return false; float fOwnerX = m_pkOwner->GetX(); float fOwnerY = m_pkOwner->GetY(); float fPetX = m_pkChar->GetX(); float fPetY = m_pkChar->GetY(); float fDist = DISTANCE_SQRT(fOwnerX - fPetX, fOwnerY - fPetY); if (fDist <= fMinDistance) return false; m_pkChar->SetRotationToXY(fOwnerX, fOwnerY); float fx, fy; float fDistToGo = fDist - fMinDistance; GetDeltaByDegree(m_pkChar->GetRotation(), fDistToGo, &fx, &fy); if (!m_pkChar->Goto((int)(fPetX+fx+0.5f), (int)(fPetY+fy+0.5f)) ) return false; m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0, 0); return true; } void CMountActor::SetSummonItem(LPITEM pItem) { if (NULL == pItem) { m_dwSummonItemVID = 0; m_dwSummonItemVnum = 0; return; } m_dwSummonItemVID = pItem->GetVID(); m_dwSummonItemVnum = pItem->GetVnum(); } /////////////////////////////////////////////////////////////////////////////////////// // CMountSystem /////////////////////////////////////////////////////////////////////////////////////// CMountSystem::CMountSystem(LPCHARACTER owner) { m_pkOwner = owner; m_dwUpdatePeriod = 400; m_dwLastUpdateTime = 0; } CMountSystem::~CMountSystem() { Destroy(); } void CMountSystem::Destroy() { for (TMountActorMap::iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter) { CMountActor* mountActor = iter->second; if (0 != mountActor) { delete mountActor; } } event_cancel(&m_pkMountSystemUpdateEvent); m_mountActorMap.clear(); } bool CMountSystem::Update(DWORD deltaTime) { bool bResult = true; DWORD currentTime = get_dword_time(); if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime) return true; std::vector <CMountActor*> v_garbageActor; for (TMountActorMap::iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter) { CMountActor* mountActor = iter->second; if (0 != mountActor && mountActor->IsSummoned()) { LPCHARACTER pMount = mountActor->GetCharacter(); if (NULL == CHARACTER_MANAGER::instance().Find(pMount->GetVID())) { v_garbageActor.push_back(mountActor); } else { bResult = bResult && mountActor->Update(deltaTime); } } } for (std::vector<CMountActor*>::iterator it = v_garbageActor.begin(); it != v_garbageActor.end(); it++) DeleteMount(*it); m_dwLastUpdateTime = currentTime; return bResult; } void CMountSystem::DeleteMount(DWORD mobVnum) { TMountActorMap::iterator iter = m_mountActorMap.find(mobVnum); if (m_mountActorMap.end() == iter) { sys_err("[CMountSystem::DeleteMount] Can't find mount on my list (VNUM: %d)", mobVnum); return; } CMountActor* mountActor = iter->second; if (0 == mountActor) sys_err("[CMountSystem::DeleteMount] Null Pointer (mountActor)"); else delete mountActor; m_mountActorMap.erase(iter); } void CMountSystem::DeleteMount(CMountActor* mountActor) { for (TMountActorMap::iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter) { if (iter->second == mountActor) { delete mountActor; m_mountActorMap.erase(iter); return; } } sys_err("[CMountSystem::DeleteMount] Can't find mountActor(0x%x) on my list(size: %d) ", mountActor, m_mountActorMap.size()); } void CMountSystem::Unsummon(DWORD vnum, bool bDeleteFromList) { //if (m_pkOwner->IncreaseMountCounter() >= 5) //{ // m_pkOwner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("_TRANSLATE_CHAT_TYPE_PACKETS_FROM_SOURCE_TO_GLOBAL__TRANSLATE_LIST_110")); // return; //} CMountActor* actor = this->GetByVnum(vnum); if (0 == actor) { sys_err("[CMountSystem::Unsummon(%d)] Null Pointer (actor)", vnum); return; } actor->Unsummon(); if (true == bDeleteFromList) this->DeleteMount(actor); bool bActive = false; for (TMountActorMap::iterator it = m_mountActorMap.begin(); it != m_mountActorMap.end(); it++) { bActive |= it->second->IsSummoned(); } if (false == bActive) { event_cancel(&m_pkMountSystemUpdateEvent); m_pkMountSystemUpdateEvent = NULL; } } void CMountSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, bool bSpawnFar) { //if (m_pkOwner->IncreaseMountCounter() >= 5) //{ // m_pkOwner->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("_TRANSLATE_CHAT_TYPE_PACKETS_FROM_SOURCE_TO_GLOBAL__TRANSLATE_LIST_110")); // return; //} CMountActor* mountActor = this->GetByVnum(mobVnum); if (0 == mountActor) { mountActor = M2_NEW CMountActor(m_pkOwner, mobVnum); m_mountActorMap.insert(std::make_pair(mobVnum, mountActor)); } DWORD mountVID = mountActor->Summon(pSummonItem, bSpawnFar); if (!mountVID) sys_err("[CMountSystem::Summon(%d)] Null Pointer (mountVID)", pSummonItem->GetID()); if (NULL == m_pkMountSystemUpdateEvent) { mountsystem_event_info* info = AllocEventInfo<mountsystem_event_info>(); info->pMountSystem = this; m_pkMountSystemUpdateEvent = event_create(mountsystem_update_event, info, PASSES_PER_SEC(1) / 4); } //return mountActor; } void CMountSystem::Mount(DWORD mobVnum, LPITEM mountItem) { CMountActor* mountActor = this->GetByVnum(mobVnum); if (!mountActor) { sys_err("[CMountSystem::Mount] Null Pointer (mountActor)"); return; } if(!mountItem) return; //check timer // if (m_pkOwner->IncreaseMountCounter() >= 5) // { // m_pkOwner->ChatPacket(CHAT_TYPE_INFO, "<Mount> Asteapta 5 secunde pentru a face aceasta actiune"); // return; // } this->Unsummon(mobVnum, false); mountActor->Mount(mountItem); } void CMountSystem::Unmount(DWORD mobVnum) { CMountActor* mountActor = this->GetByVnum(mobVnum); if (!mountActor) { sys_err("[CMountSystem::Mount] Null Pointer (mountActor)"); return; } //check timer // if (m_pkOwner->IncreaseMountCounter() >= 5) // { // m_pkOwner->ChatPacket(CHAT_TYPE_INFO, "<Mount> Asteapta 5 secunde pentru a face aceasta actiune"); // return; // } if(LPITEM pSummonItem = m_pkOwner->GetWear(WEAR_COSTUME_MOUNT)) { this->Summon(mobVnum, pSummonItem, false); } mountActor->Unmount(); } CMountActor* CMountSystem::GetByVID(DWORD vid) const { CMountActor* mountActor = 0; bool bFound = false; for (TMountActorMap::const_iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter) { mountActor = iter->second; if (0 == mountActor) { sys_err("[CMountSystem::GetByVID(%d)] Null Pointer (mountActor)", vid); continue; } bFound = mountActor->GetVID() == vid; if (true == bFound) break; } return bFound ? mountActor : 0; } CMountActor* CMountSystem::GetByVnum(DWORD vnum) const { CMountActor* mountActor = 0; TMountActorMap::const_iterator iter = m_mountActorMap.find(vnum); if (m_mountActorMap.end() != iter) mountActor = iter->second; return mountActor; } size_t CMountSystem::CountSummoned() const { size_t count = 0; for (TMountActorMap::const_iterator iter = m_mountActorMap.begin(); iter != m_mountActorMap.end(); ++iter) { CMountActor* mountActor = iter->second; if (0 != mountActor) { if (mountActor->IsSummoned()) ++count; } } return count; } MountSystem.h #ifndef __HEADER_MOUNT_SYSTEM__ #define __HEADER_MOUNT_SYSTEM__ class CHARACTER; class CMountActor { protected: friend class CMountSystem; CMountActor(LPCHARACTER owner, DWORD vnum); virtual ~CMountActor(); virtual bool Update(DWORD deltaTime); virtual bool _UpdateFollowAI(); private: bool Follow(float fMinDistance = 50.f); public: LPCHARACTER GetCharacter() const { return m_pkChar; } LPCHARACTER GetOwner() const { return m_pkOwner; } DWORD GetVID() const { return m_dwVID; } DWORD GetVnum() const { return m_dwVnum; } void SetName(); bool Mount(LPITEM mountItem); void Unmount(); DWORD Summon(LPITEM pSummonItem, bool bSpawnFar = false); void Unsummon(); bool IsSummoned() const { return 0 != m_pkChar; } void SetSummonItem (LPITEM pItem); DWORD GetSummonItemVID () { return m_dwSummonItemVID; } private: DWORD m_dwVnum; DWORD m_dwVID; DWORD m_dwLastActionTime; DWORD m_dwSummonItemVID; DWORD m_dwSummonItemVnum; short m_originalMoveSpeed; std::string m_name; LPCHARACTER m_pkChar; LPCHARACTER m_pkOwner; }; class CMountSystem { public: typedef boost::unordered_map<DWORD, CMountActor*> TMountActorMap; public: CMountSystem(LPCHARACTER owner); virtual ~CMountSystem(); CMountActor* GetByVID(DWORD vid) const; CMountActor* GetByVnum(DWORD vnum) const; bool Update(DWORD deltaTime); void Destroy(); size_t CountSummoned() const; public: void SetUpdatePeriod(DWORD ms); void Summon(DWORD mobVnum, LPITEM pSummonItem, bool bSpawnFar); void Unsummon(DWORD mobVnum, bool bDeleteFromList = false); void Unsummon(CMountActor* mountActor, bool bDeleteFromList = false); void Mount(DWORD mobVnum, LPITEM mountItem); void Unmount(DWORD mobVnum); void DeleteMount(DWORD mobVnum); void DeleteMount(CMountActor* mountActor); private: TMountActorMap m_mountActorMap; LPCHARACTER m_pkOwner; DWORD m_dwUpdatePeriod; DWORD m_dwLastUpdateTime; LPEVENT m_pkMountSystemUpdateEvent; }; #endif Link to comment Share on other sites More sharing options...
Catalin2o14 142 Posted August 21, 2020 Share Posted August 21, 2020 (edited) On 10/2/2019 at 10:48 PM, tester12 said: give bonus (load from item_proto applytype0..), but shouldn't https://metin2.download/picture/2a4K3cXj6vLavwiDKS73IRpw9OQe3L7e/.png --remove this Edited September 4, 2022 by Metin2 Dev Core X - External 2 Internal 1 3 Link to comment Share on other sites More sharing options...
OkamiRo 5 Posted August 21, 2020 Share Posted August 21, 2020 (edited) 3 hours ago, Catalin2o14 said: https://metin2.download/picture/XVfK5UEnsX1pQb857rs3EZ2IOu8c85cU/.png --remove this Thank you so much, i've been struggling with this bug since 3 months ago, now it's working perfectly! Edited September 4, 2022 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Catalin2o14 142 Posted August 21, 2020 Share Posted August 21, 2020 2 hours ago, Dogariu Ionuț Gabriel said: Thank you so much, i've been struggling with this bug since 3 months ago, now it's working perfectly! I'm glad to help 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now