void CStatusEffectContainer::RemoveStatusEffect(uint32 id, bool silent) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(id); if (PStatusEffect->GetStatusID() >= EFFECT_FIRE_MANEUVER && PStatusEffect->GetStatusID() <= EFFECT_DARK_MANEUVER && m_POwner->objtype == TYPE_PC) { puppetutils::CheckAttachmentsForManeuver((CCharEntity*)m_POwner, PStatusEffect->GetStatusID(), false); } m_StatusEffectList.erase(m_StatusEffectList.begin() + id); luautils::OnEffectLose(m_POwner, PStatusEffect); m_POwner->delModifiers(&PStatusEffect->modList); m_POwner->UpdateHealth(); if (m_POwner->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_POwner; if (PStatusEffect->GetIcon() != 0) { UpdateStatusIcons(); if (silent == false) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, PStatusEffect->GetIcon(), 0, 206)); } } //check for latents PChar->PLatentEffectContainer->CheckLatentsFoodEffect(); PChar->PLatentEffectContainer->CheckLatentsStatusEffect(); PChar->PLatentEffectContainer->CheckLatentsRollSong(HasStatusEffectByFlag(EFFECTFLAG_SONG | EFFECTFLAG_ROLL)); PChar->UpdateHealth(); PChar->pushPacket(new CCharHealthPacket(PChar)); PChar->pushPacket(new CCharSyncPacket(PChar)); } else { if (silent == false && PStatusEffect->GetIcon() != 0 && ((PStatusEffect->GetFlag() & EFFECTFLAG_NO_LOSS_MESSAGE) == 0) && !m_POwner->isDead()) { m_POwner->loc.zone->PushPacket(m_POwner, CHAR_INRANGE, new CMessageBasicPacket(m_POwner, m_POwner, PStatusEffect->GetIcon(), 0, 206)); } } delete PStatusEffect; }
void CParty::DisbandParty() { DisableSync(); SetQuaterMaster(NULL); m_PLeader = NULL; m_PAlliance = NULL; if (m_PartyType == PARTY_PCS) { PushPacket(NULL, 0, new CPartyDefinePacket(NULL)); for (uint8 i = 0; i < members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)members.at(i); PChar->PParty = NULL; PChar->PLatentEffectContainer->CheckLatentsPartyJobs(); PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->PLatentEffectContainer->CheckLatentsPartyAvatar(); PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, PChar->getZone())); // TODO: TreasurePool должен оставаться у последнего персонажа, но сейчас это не критично if (PChar->PTreasurePool != NULL && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) { PChar->PTreasurePool->DelMember(PChar); PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); PChar->PTreasurePool->AddMember(PChar); PChar->PTreasurePool->UpdatePool(PChar); } CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(gettick()); sync->SetDuration(30000); } } Sql_Query(SqlHandle,"UPDATE accounts_sessions SET partyid = %u WHERE partyid = %u", 0, m_PartyID); } delete this; }
void CStatusEffectContainer::RemoveStatusEffect(uint32 id, bool silent) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(id); m_StatusEffectList.erase(m_StatusEffectList.begin() + id); luautils::OnEffectLose(m_POwner, PStatusEffect); m_POwner->delModifiers(&PStatusEffect->modList); m_POwner->UpdateHealth(); if (m_POwner->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_POwner; if (PStatusEffect->GetIcon() != 0) { UpdateStatusIcons(); if (silent == false) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, PStatusEffect->GetIcon(), 0, 206)); } } //check for latents CLatentEffectContainer* PLatentEffectContainer; PChar->PLatentEffectContainer->CheckLatentsFoodEffect(); PChar->PLatentEffectContainer->CheckLatentsStatusEffect(); PChar->UpdateHealth(); if (PChar->status == STATUS_NORMAL) PChar->status = STATUS_UPDATE; PChar->pushPacket(new CCharHealthPacket(PChar)); PChar->pushPacket(new CCharSyncPacket(PChar)); } else { if (silent == false && PStatusEffect->GetIcon() != 0 && ((PStatusEffect->GetFlag() & EFFECTFLAG_NO_LOSS_MESSAGE) == 0) && !m_POwner->isDead()) { m_POwner->loc.zone->PushPacket(m_POwner, CHAR_INRANGE, new CMessageBasicPacket(m_POwner, m_POwner, PStatusEffect->GetIcon(), 0, 206)); } } delete PStatusEffect; }
void CParty::ReloadParty() { //alliance if (this->m_PAlliance != NULL) { CAlliance* ourAlliance = this->m_PAlliance; for (uint8 a = 0; a < ourAlliance->partyList.size(); ++a) { for (uint8 i = 0; i < ourAlliance->partyList.at(a)->members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)ourAlliance->partyList.at(a)->members.at(i); PChar->pushPacket(new CPartyDefinePacket(ourAlliance->partyList.at(a))); for (uint8 y = 0; y < ourAlliance->partyList.at(a)->members.size(); ++y) { PChar->pushPacket(new CPartyMemberUpdatePacket((CCharEntity*)ourAlliance->partyList.at(a)->members.at(y),y, PChar->getZone())); } } } return; } //regular party for (uint8 i = 0; i < members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)members.at(i); PChar->PLatentEffectContainer->CheckLatentsPartyJobs(); PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->PLatentEffectContainer->CheckLatentsPartyAvatar(); PChar->pushPacket(new CPartyDefinePacket(this)); for (uint8 y = 0; y < members.size(); ++y) { PChar->pushPacket(new CPartyMemberUpdatePacket((CCharEntity*)members.at(y), y, PChar->getZone())); } } }
void CZoneEntities::DespawnPC(CCharEntity* PChar) { for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PC = PCurrentChar->SpawnPCList.find(PChar->id); if (PC != PCurrentChar->SpawnPCList.end()) { PCurrentChar->SpawnPCList.erase(PC); PCurrentChar->pushPacket(new CCharPacket(PChar, ENTITY_DESPAWN, 0)); } } }
void CZone::SpawnPCs(CCharEntity* PChar) { for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PC = PChar->SpawnPCList.find(PCurrentChar->id); if (PChar != PCurrentChar) { if(distance(PChar->loc.p, PCurrentChar->loc.p) < 50) { if( PC == PChar->SpawnPCList.end() ) { PChar->SpawnPCList[PCurrentChar->id] = PCurrentChar; PChar->pushPacket(new CCharPacket(PCurrentChar,ENTITY_SPAWN)); PChar->pushPacket(new CCharSyncPacket(PCurrentChar)); PCurrentChar->SpawnPCList[PChar->id] = PChar; PCurrentChar->pushPacket(new CCharPacket(PChar,ENTITY_SPAWN)); PCurrentChar->pushPacket(new CCharSyncPacket(PChar)); }else{ PCurrentChar->pushPacket(new CCharPacket(PChar,ENTITY_UPDATE)); } } else { if( PC != PChar->SpawnPCList.end() ) { PChar->SpawnPCList.erase(PC); PChar->pushPacket(new CCharPacket(PCurrentChar,ENTITY_DESPAWN)); PCurrentChar->SpawnPCList.erase(PChar->id); PCurrentChar->pushPacket(new CCharPacket(PChar,ENTITY_DESPAWN)); } } } } }
void CState::PushMessage(MSGBASIC_ID msgID, int32 param, int32 value) { CBattleEntity* PTarget = m_PTarget; // always need an entity sent if(PTarget == NULL) { PTarget = m_PEntity; } if(m_PEntity->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_PEntity; PChar->pushPacket(new CMessageBasicPacket(PChar,PTarget,param,value,msgID)); } m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE, new CMessageBasicPacket(m_PEntity,PTarget,param,value,msgID)); }
void CLinkshell::RemoveMemberByName(int8* MemberName) { PROFILE_FUNC(); for (uint32 i = 0; i < members.size(); ++i) { if (strcmp(MemberName, members.at(i)->GetName()) == 0) { CCharEntity* PMember = (CCharEntity*)members.at(i); CItemLinkshell* PItemLinkshell = (CItemLinkshell*)PMember->getStorage(LOC_INVENTORY)->GetItem(PMember->equip[SLOT_LINK]); if (PItemLinkshell != NULL && PItemLinkshell->isType(ITEM_LINKSHELL)) { linkshell::DelOnlineMember(PMember, PItemLinkshell); PItemLinkshell->setSubType(ITEM_UNLOCKED); PMember->equip[SLOT_LINK] = 0; PMember->nameflags.flags &= ~FLAG_LINKSHELL; PMember->pushPacket(new CInventoryAssignPacket(PItemLinkshell, INV_NORMAL)); PMember->pushPacket(new CLinkshellEquipPacket(PMember)); } CItemContainer* Inventory = PMember->getStorage(LOC_INVENTORY); for (uint8 SlotID = 0; SlotID < Inventory->GetSize(); ++SlotID) { CItemLinkshell* PItemLinkshell = (CItemLinkshell*)Inventory->GetItem(SlotID); if (PItemLinkshell != NULL && PItemLinkshell->isType(ITEM_LINKSHELL) && PItemLinkshell->GetLSID() == m_id) { const int8* Query = "UPDATE char_inventory SET itemid = (itemid+2) WHERE charid = %u AND location = %u AND slot = %u LIMIT 1"; Sql_Query(SqlHandle, Query, PMember->id, LOC_INVENTORY, SlotID); PItemLinkshell->SetLSID(0); PItemLinkshell->setID(PItemLinkshell->getID() + 2); PMember->pushPacket(new CInventoryItemPacket(PItemLinkshell, LOC_INVENTORY, SlotID)); } } charutils::SaveCharStats(PMember); charutils::SaveCharEquip(PMember); if (PMember->status == STATUS_NORMAL) PMember->status = STATUS_UPDATE; PMember->pushPacket(new CInventoryFinishPacket()); PMember->pushPacket(new CCharUpdatePacket(PMember)); PMember->pushPacket(new CMessageSystemPacket(0,0,109)); return; } } }
void CState::PushError(MSGBASIC_ID msgID, int32 param, int32 value) { PROFILE_FUNC(); if(m_PEntity->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_PEntity; CBattleEntity* PTarget = m_PTarget; // always need an entity sent if(PTarget == NULL) { PTarget = m_PEntity; } PChar->pushPacket(new CMessageBasicPacket(PChar,PTarget,param,value,msgID)); } }
void CParty::PushPacket(CCharEntity* PPartyMember, uint8 ZoneID, CBasicPacket* packet) { for (uint32 i = 0; i < members.size(); ++i) { if(members.at(i)->objtype != TYPE_PC) continue; CCharEntity* member = (CCharEntity*)members.at(i); if (member != PPartyMember && member->status != STATUS_DISAPPEAR && !jailutils::InPrison(member) ) { if (ZoneID == 0 || member->getZone() == ZoneID) { member->pushPacket(new CBasicPacket(*packet)); } } } delete packet; }
void CParty::RefreshSync() { CCharEntity* sync = (CCharEntity*)m_PSyncTarget; uint8 syncLevel = sync->jobs.job[sync->GetMJob()]; if (syncLevel < 10) { SetSyncTarget(NULL, 554); } for (uint32 i = 0; i < members.size(); ++i) { if(members.at(i)->objtype != TYPE_PC) continue; CCharEntity* member = (CCharEntity*)members.at(i); uint8 NewMLevel = 0; if (syncLevel < member->jobs.job[member->GetMJob()]) { NewMLevel = syncLevel; }else{ NewMLevel = member->jobs.job[member->GetMJob()]; } if (member->GetMLevel() != NewMLevel) { charutils::RemoveAllEquipMods(member); member->SetMLevel(NewMLevel); member->SetSLevel(member->jobs.job[member->GetSJob()]); charutils::ApplyAllEquipMods(member); blueutils::ValidateBlueSpells(member); charutils::BuildingCharSkillsTable(member); charutils::CalculateStats(member); charutils::BuildingCharTraitsTable(member); charutils::BuildingCharAbilityTable(member); charutils::CheckValidEquipment(member); // Handles rebuilding weapon skills as well. } member->pushPacket(new CMessageBasicPacket(member, member, 0, syncLevel, 540)); } m_PSyncTarget = sync; }
void CMagicState::CharAfterFinish() { if(m_PEntity->objtype != TYPE_PC) { return; } CCharEntity* PChar = (CCharEntity*)m_PEntity; charutils::RemoveStratagems(PChar, m_PSpell); charutils::UpdateHealth(PChar); // only skill up if the effect landed if(m_PSpell->tookEffect()){ charutils::TrySkillUP(PChar, (SKILLTYPE)m_PSpell->getSkillType(), m_PTarget->GetMLevel()); if (m_PSpell->getSkillType() == SKILL_SNG) { CItemWeapon* PItem = (CItemWeapon*)PChar->getEquip(SLOT_RANGED); if (PItem && PItem->isType(ITEM_ARMOR)) { SKILLTYPE Skilltype = (SKILLTYPE)PItem->getSkillType(); if (Skilltype == SKILL_STR || Skilltype == SKILL_WND || Skilltype == SKILL_SNG) { charutils::TrySkillUP(PChar, Skilltype, m_PTarget->GetMLevel()); } } } } PChar->pushPacket(new CCharUpdatePacket(PChar)); // make wyvern use breath if(PChar->PPet!=NULL && ((CPetEntity*)PChar->PPet)->getPetType() == PETTYPE_WYVERN) { ((CAIPetDummy*)PChar->PPet->PBattleAI)->m_MasterCommand = MASTERCOMMAND_HEALING_BREATH; PChar->PPet->PBattleAI->SetCurrentAction(ACTION_MOBABILITY_START); } SetHiPCLvl(m_PTarget, PChar->GetMLevel()); }
void CState::PushError(MSGBASIC_ID msgID, int32 param, int32 value, CBattleEntity* PTarget) { if(m_PEntity->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_PEntity; // always need an entity sent if(PTarget == nullptr) { if(m_PTarget != nullptr) { PTarget = m_PTarget; } else { PTarget = m_PEntity; } } PChar->pushPacket(new CMessageBasicPacket(PChar,PTarget,param,value,msgID)); } }
void CZone::InsertPET(CBaseEntity* PPet) { if ((PPet != NULL) && (PPet->objtype == TYPE_PET)) { uint16 targid = 0x700; for (EntityList_t::const_iterator it = m_petList.begin() ; it != m_petList.end() ; ++it) { if (targid != it->first) { break; } targid++; } if (targid >= 0x800) { ShowError(CL_RED"CZone::InsertPET : targid is high (03hX)\n" CL_RESET, targid); return; } PPet->id = 0x1000000 + (m_zoneID << 12) + targid; PPet->targid = targid; PPet->loc.zone = this; m_petList[PPet->targid] = PPet; for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; if(distance(PPet->loc.p, PCurrentChar->loc.p) < 50) { PCurrentChar->SpawnPETList[PPet->id] = PPet; PCurrentChar->pushPacket(new CEntityUpdatePacket(PPet, ENTITY_SPAWN)); } } return; } ShowError(CL_RED"CZone::InsertPET : entity is not pet\n" CL_RESET); }
void CZoneEntities::InsertPET(CBaseEntity* PPet) { if (PPet != nullptr) { uint16 targid = 0x700; for (EntityList_t::const_iterator it = m_petList.begin(); it != m_petList.end(); ++it) { if (targid != it->first) { break; } targid++; } if (targid >= 0x800) { ShowError(CL_RED"CZone::InsertPET : targid is high (03hX)\n" CL_RESET, targid); return; } PPet->id = 0x1000000 + (m_zone->GetID() << 12) + targid; PPet->targid = targid; PPet->loc.zone = m_zone; m_petList[PPet->targid] = PPet; for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; if (distance(PPet->loc.p, PCurrentChar->loc.p) < 50) { PCurrentChar->SpawnPETList[PPet->id] = PPet; PCurrentChar->pushPacket(new CEntityUpdatePacket(PPet, ENTITY_SPAWN, UPDATE_ALL_MOB)); } } return; } ShowError(CL_RED"CZone::InsertPET : entity is null\n" CL_RESET); }
void TryLearningSpells(CCharEntity* PChar, CMobEntity* PMob) { if (PMob->m_UsedSkillIds.size() == 0) { // minor optimisation. return; } // prune the learnable blue spells std::vector<CSpell*> PLearnableSpells; for (std::map<uint16, uint16>::iterator i=PMob->m_UsedSkillIds.begin(); i != PMob->m_UsedSkillIds.end(); ++i) { CSpell* PSpell = spell::GetSpellByMonsterSkillId(i->first); if (PSpell != nullptr) { PLearnableSpells.push_back(PSpell); } } if (PLearnableSpells.size() == 0) { return; } std::vector<CCharEntity*> PBlueMages; // populate PBlueMages if (PChar->PParty != nullptr) { for (uint8 i = 0; i < PChar->PParty->members.size(); i++) { if (PChar->PParty->members[i]->GetMJob() == JOB_BLU && PChar->PParty->members[i]->objtype == TYPE_PC) { PBlueMages.push_back((CCharEntity*)PChar->PParty->members[i]); } } } else if (PChar->GetMJob() == JOB_BLU) { PBlueMages.push_back(PChar); } // loop through the list of BLUs and see if they can learn. for (size_t i = 0; i < PBlueMages.size(); i++) { CCharEntity* PBlueMage = PBlueMages[i]; if (PBlueMage->isDead()) { // too dead to learn continue; } if (distance(PBlueMage->loc.p, PMob->loc.p) > 100) { // too far away to learn continue; } for (size_t spell = 0; spell < PLearnableSpells.size(); spell++) { CSpell* PSpell = PLearnableSpells[spell]; if (charutils::hasSpell(PBlueMage, static_cast<uint16>(PSpell->getID()))) { continue; } // get the skill cap for the spell level auto skillLvlForSpell = battleutils::GetMaxSkill(SKILL_BLUE_MAGIC, JOB_BLU, PSpell->getJob(JOB_BLU)); // get player skill level with bonus from gear auto playerSkillLvl = PBlueMage->GetSkill(SKILL_BLUE_MAGIC); // make sure the difference between spell skill and player is at most 31 points if (playerSkillLvl >= skillLvlForSpell - 31) { // TODO: check for blue learning bonus and adjust base percent if (dsprand::GetRandomNumber(100) < 33) { if (charutils::addSpell(PBlueMage, static_cast<uint16>(PSpell->getID()))) { PBlueMage->pushPacket(new CMessageBasicPacket(PBlueMage, PBlueMage, static_cast<uint16>(PSpell->getID()), 0, MSGBASIC_LEARNS_SPELL)); charutils::SaveSpell(PBlueMage, static_cast<uint16>(PSpell->getID())); PBlueMage->pushPacket(new CCharSpellsPacket(PBlueMage)); } } break; // only one attempt at learning a spell, regardless of learn or not. } } } }
void TryLearningSpells(CCharEntity* PChar, CMobEntity* PMob) { if (PMob->m_UsedSkillIds.size() == 0) { // minor optimisation. return; } // prune the learnable blue spells std::vector<CSpell*> PLearnableSpells; for (std::map<uint16, uint16>::iterator i=PMob->m_UsedSkillIds.begin(); i != PMob->m_UsedSkillIds.end(); ++i) { CSpell* PSpell = spell::GetSpellByMonsterSkillId(i->first); if (PSpell != NULL) { PLearnableSpells.push_back(PSpell); } } if (PLearnableSpells.size() == 0) { return; } std::vector<CCharEntity*> PBlueMages; // populate PBlueMages if (PChar->PParty != NULL) { for (uint8 i = 0; i < PChar->PParty->members.size(); i++) { if (PChar->PParty->members[i]->GetMJob() == JOB_BLU && PChar->PParty->members[i]->objtype == TYPE_PC) { PBlueMages.push_back((CCharEntity*)PChar->PParty->members[i]); } } } else if (PChar->GetMJob() == JOB_BLU) { PBlueMages.push_back(PChar); } // loop through the list of BLUs and see if they can learn. for (int i=0; i<PBlueMages.size(); i++) { CCharEntity* PBlueMage = PBlueMages[i]; if (PBlueMage->isDead()) { // too dead to learn continue; } if (distance(PBlueMage->loc.p, PMob->loc.p) > 100) { // too far away to learn continue; } for (int spell=0; spell<PLearnableSpells.size(); spell++) { CSpell* PSpell = PLearnableSpells[spell]; if (charutils::hasSpell(PBlueMage, PSpell->getID())) { continue; } uint8 learnableLevel = PSpell->getJob(JOB_BLU); if (learnableLevel > 0 && learnableLevel < PBlueMage->GetMLevel()+7) { // TODO: Use blue magic skill check rather than level if (rand()%100 < 33) { if (charutils::addSpell(PBlueMage, PSpell->getID())) { PBlueMage->pushPacket(new CMessageBasicPacket(PBlueMage, PBlueMage, PSpell->getID(), 0, MSGBASIC_LEARNS_SPELL)); charutils::SaveSpells(PBlueMage); PBlueMage->pushPacket(new CCharSpellsPacket(PBlueMage)); } } break; // only one attempt at learning a spell, regardless of learn or not. } } } }
void CParty::SetSyncTarget(CBattleEntity* PEntity, uint16 message) { if (map_config.level_sync_enable) { if (PEntity && PEntity->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)PEntity; //enable level sync if (PChar->GetMLevel() < 10 ) { ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 10, 541)); return; } else if (PChar->getZone() != GetLeader()->getZone()) { ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 542)); return; } else { for (uint32 i = 0; i < members.size(); ++i) { if(members.at(i)->StatusEffectContainer->HasStatusEffect(EFFECT_LEVEL_RESTRICTION)) { ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 543)); return; } } m_PSyncTarget = PChar; for (uint32 i = 0; i < members.size(); ++i) { if(members.at(i)->objtype != TYPE_PC) continue; CCharEntity* member = (CCharEntity*)members.at(i); if (member->status != STATUS_DISAPPEAR && member->getZone() == PChar->getZone() ) { member->pushPacket(new CMessageStandardPacket(PChar->GetMLevel(), 0, 0, 0, message)); member->StatusEffectContainer->AddStatusEffect(new CStatusEffect( EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, PChar->GetMLevel(), 0, 0), true); member->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE); member->loc.zone->PushPacket(member, CHAR_INRANGE, new CCharSyncPacket(member)); } } } } else { if (m_PSyncTarget != NULL) { //disable level sync for (uint32 i = 0; i < members.size(); ++i) { if(members.at(i)->objtype != TYPE_PC) continue; CCharEntity* member = (CCharEntity*)members.at(i); if (member->status != STATUS_DISAPPEAR && member->getZone() == m_PSyncTarget->getZone() ) { CStatusEffect* sync = member->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { member->pushPacket(new CMessageBasicPacket(member, member, 10, 30, message)); sync->SetStartTime(gettick()); sync->SetDuration(30000); } } } } } } }
void CZone::DecreaseZoneCounter(CCharEntity* PChar) { DSP_DEBUG_BREAK_IF(PChar == NULL); DSP_DEBUG_BREAK_IF(PChar->loc.zone != this); //remove pets if(PChar->PPet != NULL) { charutils::BuildingCharPetAbilityTable(PChar,(CPetEntity*)PChar->PPet,0);//blank the pet commands if(PChar->PPet->isCharmed) { petutils::DespawnPet(PChar); } else { PChar->PPet->status = STATUS_DISAPPEAR; if( ((CPetEntity*)(PChar->PPet))->getPetType() == PETTYPE_AVATAR ) PChar->setModifier(MOD_AVATAR_PERPETUATION, 0); } // It may have been nulled by DespawnPet if(PChar->PPet != NULL) { PChar->PPet->PBattleAI->SetCurrentAction(ACTION_NONE); DeletePET(PChar->PPet);//remove the TID for this pet for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it) { //inform other players of the pets removal CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PET = PCurrentChar->SpawnPETList.find(PChar->PPet->id); if( PET != PCurrentChar->SpawnPETList.end() ) { PCurrentChar->SpawnPETList.erase(PET); PCurrentChar->pushPacket(new CEntityUpdatePacket(PChar->PPet, ENTITY_DESPAWN)); } } PChar->PPet = NULL; } } //remove bcnm status if(m_InstanceHandler != NULL && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_BATTLEFIELD)) { if(m_InstanceHandler->disconnectFromBcnm(PChar)){ ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n",PChar->GetName()); } if(PChar->loc.destination==0){ //this player is disconnecting/logged out, so move them to the entrance //move depending on zone int pos[4] = {0,0,0,0}; instanceutils::getStartPosition(m_zoneID,pos); if(pos!=NULL){ PChar->loc.p.x = pos[0]; PChar->loc.p.y = pos[1]; PChar->loc.p.z = pos[2]; PChar->loc.p.rotation = pos[3]; charutils::SaveCharPosition(PChar); } else{ ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n",PChar->GetName()); } } } else if(m_InstanceHandler != NULL && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DYNAMIS, 0)) { if(m_InstanceHandler->disconnectFromDynamis(PChar)){ ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n",PChar->GetName()); } if(PChar->loc.destination==0){ //this player is disconnecting/logged out, so move them to the entrance //move depending on zone int pos[4] = {0,0,0,0}; instanceutils::getStartPosition(m_zoneID,pos); if(pos!=NULL){ PChar->loc.p.x = pos[0]; PChar->loc.p.y = pos[1]; PChar->loc.p.z = pos[2]; PChar->loc.p.rotation = pos[3]; charutils::SaveCharPosition(PChar); } else{ ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n",PChar->GetName()); } } } for (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it) { CMobEntity* PCurrentMob = (CMobEntity*)it->second; PCurrentMob->PEnmityContainer->Clear(PChar->id); if(PCurrentMob->m_OwnerID.id == PChar->id){ PCurrentMob->m_OwnerID.clean(); } } // TODO: могут возникать проблемы с переходом между одной и той же зоной (zone == prevzone) m_charList.erase(PChar->targid); ShowDebug(CL_CYAN"CZone:: %s DecreaseZoneCounter <%u> %s\n" CL_RESET, GetName(), m_charList.size(),PChar->GetName()); if (ZoneTimer && m_charList.empty()) { ZoneTimer->m_type = CTaskMgr::TASK_REMOVE; ZoneTimer = NULL; HealAllMobs(); } else { for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PC = PCurrentChar->SpawnPCList.find(PChar->id); if( PC != PCurrentChar->SpawnPCList.end() ) { PCurrentChar->SpawnPCList.erase(PC); PCurrentChar->pushPacket(new CCharPacket(PChar,ENTITY_DESPAWN)); } } } if (PChar->m_LevelRestriction != 0) { if (PChar->PParty) { if (PChar->PParty->GetSyncTarget() == PChar || PChar->PParty->GetLeader() == PChar) { PChar->PParty->SetSyncTarget(NULL, 551); } if (PChar->PParty->GetSyncTarget() != NULL) { uint8 count = 0; for (uint32 i = 0; i < PChar->PParty->members.size(); ++i) { if (PChar->PParty->members.at(i) != PChar && PChar->PParty->members.at(i)->getZone() == PChar->PParty->GetSyncTarget()->getZone()) { count++; } } if (count < 2) //3, because one is zoning out - thus at least 2 will be left { PChar->PParty->SetSyncTarget(NULL, 552); } } } PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_SYNC); PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_RESTRICTION); } if (PChar->PTreasurePool != NULL) // TODO: условие для устранения проблем с MobHouse, надо блин решить ее раз и навсегда { PChar->PTreasurePool->DelMember(PChar); } for (regionList_t::const_iterator region = m_regionList.begin(); region != m_regionList.end(); ++region) { if ((*region)->GetRegionID() == PChar->m_InsideRegionID) { luautils::OnRegionLeave(PChar, *region); break; } } PChar->loc.zone = NULL; PChar->loc.prevzone = m_zoneID; PChar->SpawnPCList.clear(); PChar->SpawnNPCList.clear(); PChar->SpawnMOBList.clear(); PChar->SpawnPETList.clear(); }
void CTransportHandler::TransportTimer() { uint32 VanaTime = CVanaTime::getInstance()->getDate(); // в портовых зонах необходимо написать макросы на случай, если персонаж вышел из игры в корабле. // при входе в игру он должен оказаться на пристани for(uint32 i = 0; i < TransportList.size(); ++i) { Transport_t* PTransport = TransportList.at(i); uint16 ShipTimerOffset = ((VanaTime - PTransport->TimeOffset) % PTransport->TimeInterval); // корабль появляется на горизонте if (ShipTimerOffset == 0) { PTransport->PTransportNPC->status = STATUS_NORMAL; PTransport->PTransportNPC->animation = PTransport->AnimationArrive; PTransport->PTransportNPC->loc = PTransport->Dock; WBUFL(&PTransport->PTransportNPC->name[0],4) = CVanaTime::getInstance()->getVanaTime(); PTransport->Dock.zone->PushPacket(NULL, CHAR_INZONE, new CEntityUpdatePacket(PTransport->PTransportNPC, ENTITY_SPAWN, UPDATE_ALL)); } // персонажи видят корабль, иначе ждем следующего прибытия else if (PTransport->PTransportNPC->status == STATUS_NORMAL) { // пора подтягивать пассажиров к выходу if (ShipTimerOffset == PTransport->TimeAnimationArrive - 10) { PTransport->PTransportNPC->loc.boundary = 0; zoneutils::GetZone(PTransport->Dock.prevzone)->TransportDepart(PTransport->PTransportNPC); } // корабль причалил, открываем двери пассажирам else if (ShipTimerOffset == PTransport->TimeAnimationArrive) { PTransport->PDoorNPC->animation = ANIMATION_OPEN_DOOR; PTransport->Dock.zone->PushPacket(PTransport->PDoorNPC, CHAR_INRANGE, new CEntityUpdatePacket(PTransport->PDoorNPC, ENTITY_UPDATE, UPDATE_COMBAT)); } //корабль отчаливает else if (ShipTimerOffset == PTransport->TimeAnimationArrive + PTransport->TimeWaiting) { PTransport->PDoorNPC->animation = ANIMATION_CLOSE_DOOR; PTransport->PTransportNPC->animation = PTransport->AnimationDepart; PTransport->PTransportNPC->loc.boundary = PTransport->Dock.boundary; WBUFL(&PTransport->PTransportNPC->name[0],4) = CVanaTime::getInstance()->getVanaTime(); PTransport->Dock.zone->TransportDepart(PTransport->PTransportNPC); PTransport->Dock.zone->PushPacket(PTransport->PDoorNPC, CHAR_INRANGE, new CEntityUpdatePacket(PTransport->PDoorNPC, ENTITY_UPDATE, UPDATE_COMBAT)); PTransport->Dock.zone->PushPacket(NULL, CHAR_INZONE, new CEntityUpdatePacket(PTransport->PTransportNPC, ENTITY_UPDATE, UPDATE_COMBAT)); } //корабль исчезает else if (ShipTimerOffset == PTransport->TimeAnimationArrive + PTransport->TimeWaiting + PTransport->TimeAnimationDepart) { PTransport->PTransportNPC->status = STATUS_DISAPPEAR; PTransport->Dock.zone->PushPacket(NULL, CHAR_INZONE, new CEntityUpdatePacket(PTransport->PTransportNPC, ENTITY_DESPAWN,UPDATE_NONE)); } } } for(uint32 i = 0; i < ElevatorList.size(); ++i) { Elevator_t * elevator = &ElevatorList.at(i); if (elevator->isStarted) { uint16 TimerOffset = (VanaTime % elevator->interval); if (elevator->id == ELEVATOR_PORT_BASTOK_DRWBRDG) { TimerOffset = (VanaTime % INTERVAL_PORT_BASTOK_DRWBRDG); if (TimerOffset == 0 || TimerOffset == 76) { CZone* PZone = zoneutils::GetZone(elevator->zone); EntityList_t charList = PZone->GetCharList(); if (!charList.empty()) { for (EntityList_t::const_iterator it = charList.begin() ; it != charList.end() ; ++it) { CCharEntity* PChar = (CCharEntity*)it->second; if ((PChar->GetXPos() > 54 && PChar->GetXPos() < 66) && (PChar->GetZPos() > -160 && PChar->GetZPos() < -80)) { PChar->pushPacket(new CEventPacket(PChar, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1)); } } } } else if (TimerOffset == 4 || TimerOffset == 80) { elevator->isMoving = true; startElevator(elevator); } else if (TimerOffset == 8 || TimerOffset == 84) { elevator->isMoving = true; startElevator(elevator); } else if (TimerOffset == 12 || TimerOffset == 88) { elevator->isMoving = false; arriveElevator(elevator); } } else if (elevator->id == ELEVATOR_KUFTAL_TUNNEL_DSPPRNG_RCK) { TimerOffset = (VanaTime % INTERVAL_KUFTAL_TUNNEL_DSPPRNG_RCK); if (TimerOffset == 60) { elevator->isMoving = true; startElevator(elevator); } } else { if (TimerOffset == 0) { elevator->isMoving = true; startElevator(elevator); } else if (TimerOffset == elevator->movetime) { if (elevator->isMoving) { if (!elevator->isPermanent) { elevator->isStarted = false; } elevator->isMoving = false; arriveElevator(elevator); } } } } } }
void CParty::DelMember(CBattleEntity* PEntity) { DSP_DEBUG_BREAK_IF(PEntity == NULL); DSP_DEBUG_BREAK_IF(PEntity->PParty != this); if (m_PLeader == PEntity) { RemovePartyLeader(PEntity); } else { for (uint32 i = 0; i < members.size(); ++i) { if (PEntity == members.at(i)) { members.erase(members.begin() + i); if (m_PartyType == PARTY_PCS) { CCharEntity* PChar = (CCharEntity*)PEntity; if (m_PQuaterMaster == PChar) { SetQuarterMaster(NULL); } if (m_PSyncTarget == PChar) { SetSyncTarget(NULL, 553); CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(gettick()); sync->SetDuration(30000); } DisableSync(); } if (m_PSyncTarget != NULL && m_PSyncTarget != PChar) { if (PChar->status != STATUS_DISAPPEAR && PChar->getZone() == m_PSyncTarget->getZone()) { CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(gettick()); sync->SetDuration(30000); } } } PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->pushPacket(new CPartyDefinePacket(NULL)); PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, PChar->getZone())); PChar->pushPacket(new CCharUpdatePacket(PChar)); PChar->PParty = NULL; if (PChar->PTreasurePool != NULL && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) { PChar->PTreasurePool->DelMember(PChar); PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); PChar->PTreasurePool->AddMember(PChar); PChar->PTreasurePool->UpdatePool(PChar); } } break; } } } }
/************************************************************************ * * * Creates up to many attacks for a particular hand. * * * ************************************************************************/ void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction) { uint8 num = 1; bool isPC = m_attacker->objtype == TYPE_PC; // Checking the players weapon hit count if (PWeapon->getReqLvl() <= m_attacker->GetMLevel()) { num = PWeapon->getHitCount(); } // If the attacker is a mobentity or derived from mobentity, check to see if it has any special mutli-hit capabilties if (dynamic_cast<CMobEntity*>(m_attacker)) { auto multiHitMax = static_cast<CMobEntity*>(m_attacker)->getMobMod(MOBMOD_MULTI_HIT); if (multiHitMax > 0) num = 1 + battleutils::getHitCount(multiHitMax); } AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, num); // Checking the players triple, double and quadruple attack int16 tripleAttack = m_attacker->getMod(Mod::TRIPLE_ATTACK); int16 doubleAttack = m_attacker->getMod(Mod::DOUBLE_ATTACK); int16 quadAttack = m_attacker->getMod(Mod::QUAD_ATTACK); //check for merit upgrades if (isPC) { CCharEntity* PChar = (CCharEntity*)m_attacker; //merit chance only applies if player has the job trait if (charutils::hasTrait(PChar, TRAIT_TRIPLE_ATTACK)) tripleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_TRIPLE_ATTACK_RATE, PChar); if (charutils::hasTrait(PChar, TRAIT_DOUBLE_ATTACK)) doubleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_DOUBLE_ATTACK_RATE, PChar); // TODO: Quadruple attack merits when SE release them. } quadAttack = dsp_cap(quadAttack, 0, 100); doubleAttack = dsp_cap(doubleAttack, 0, 100); tripleAttack = dsp_cap(tripleAttack, 0, 100); // Checking Mikage Effect - Hits Vary With Num of Utsusemi Shadows for Main Weapon if (m_attacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIKAGE) && m_attacker->m_Weapons[SLOT_MAIN]->getID() == PWeapon->getID()) { int16 shadows = m_attacker->getMod(Mod::UTSUSEMI); //ShowDebug(CL_CYAN"Create Attacks: Mikage Active, Rolling Attack Chance for %d Shadowss...\n" CL_RESET, shadows); AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, shadows); } else if (num == 1 && dsprand::GetRandomNumber(100) < quadAttack) AddAttackSwing(PHYSICAL_ATTACK_TYPE::QUAD, direction, 3); else if (num == 1 && dsprand::GetRandomNumber(100) < tripleAttack) AddAttackSwing(PHYSICAL_ATTACK_TYPE::TRIPLE, direction, 2); else if (num == 1 && dsprand::GetRandomNumber(100) < doubleAttack) AddAttackSwing(PHYSICAL_ATTACK_TYPE::DOUBLE, direction, 1); // Ammo extra swing - players only if (isPC && m_attacker->getMod(Mod::AMMO_SWING) > 0) { // Check for ammo CCharEntity* PChar = (CCharEntity*)m_attacker; CItemArmor* PAmmo = PChar->getEquip(SLOT_AMMO); CItemArmor* PMain = PChar->getEquip(SLOT_MAIN); CItemArmor* PSub = PChar->getEquip(SLOT_SUB); uint8 slot = PChar->equip[SLOT_AMMO]; uint8 loc = PChar->equipLoc[SLOT_AMMO]; uint8 ammoCount = 0; // Handedness check, checking mod of the weapon for the purposes of level scaling if (battleutils::GetScaledItemModifier(PChar, PMain, Mod::AMMO_SWING_TYPE) == 2 && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity()) { AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, 1); ammoCount += 1; } else { if (direction == RIGHTATTACK && battleutils::GetScaledItemModifier(PChar, PMain, Mod::AMMO_SWING_TYPE) == 1 && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity()) { AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, RIGHTATTACK, 1); ammoCount += 1; } if (direction == LEFTATTACK && PSub != nullptr && battleutils::GetScaledItemModifier(PChar, PSub, Mod::AMMO_SWING_TYPE) == 1 && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity()) { AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, LEFTATTACK, 1); ammoCount += 1; } } if (PAmmo != nullptr) { if (PAmmo->getQuantity() == ammoCount) { charutils::UnequipItem(PChar, SLOT_AMMO); charutils::SaveCharEquip(PChar); } charutils::UpdateItem(PChar, loc, slot, -ammoCount); PChar->pushPacket(new CInventoryFinishPacket()); } } // TODO: Possible Lua function for the nitty gritty stuff below. // Iga mod: Extra attack chance whilst dual wield is on. if (direction == LEFTATTACK && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::EXTRA_DUAL_WIELD_ATTACK)) AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, RIGHTATTACK, 1); }
void CParty::ReloadParty() { //check if partyflags have changed int ret = Sql_Query(SqlHandle, "SELECT charid, partyflag FROM accounts_parties WHERE partyid = %d;", m_PartyID); if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) > 0) { uint8 j = 0; while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { uint32 charid = Sql_GetUIntData(SqlHandle, 0); uint16 memberflags = Sql_GetUIntData(SqlHandle, 1); if (memberflags & PARTY_LEADER) { bool found = false; for (auto member : members) { if (member->id == charid) { m_PLeader = member; found = true; } } if (!found) { m_PLeader = NULL; } } if (memberflags & PARTY_QM) { bool found = false; for (auto member : members) { if (member->id == charid) { m_PQuaterMaster = member; found = true; } } if (!found) { m_PQuaterMaster = NULL; } } } } //alliance if (this->m_PAlliance != NULL) { for (uint8 a = 0; a < m_PAlliance->partyList.size(); ++a) { for (uint8 i = 0; i < m_PAlliance->partyList.at(a)->members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)m_PAlliance->partyList.at(a)->members.at(i); PChar->ReloadPartyDec(); uint16 alliance = 0; PChar->pushPacket(new CPartyDefinePacket(m_PAlliance->partyList.at(a))); int ret = Sql_Query(SqlHandle, "SELECT chars.charid, chars.charname, partyflag, pos_zone, partyid FROM accounts_parties \ LEFT JOIN chars ON accounts_parties.charid = chars.charid WHERE \ allianceid = %d ORDER BY partyflag & %u, timestamp;", m_PAlliance->m_AllianceID, PARTY_SECOND | PARTY_THIRD); if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) > 0) { uint8 j = 0; while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { if (Sql_GetUIntData(SqlHandle, 2) & (PARTY_SECOND | PARTY_THIRD) != alliance) { alliance = Sql_GetUIntData(SqlHandle, 2) & (PARTY_SECOND | PARTY_THIRD); j = 0; } CCharEntity* PPartyMember = zoneutils::GetChar(Sql_GetUIntData(SqlHandle, 0)); if (PPartyMember) { PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, PChar->getZone())); } else { PChar->pushPacket(new CPartyMemberUpdatePacket( Sql_GetUIntData(SqlHandle, 0), Sql_GetData(SqlHandle, 1), Sql_GetUIntData(SqlHandle, 2), Sql_GetUIntData(SqlHandle, 3))); } j++; } } } } } else //regular party for (uint8 i = 0; i < members.size(); ++i)
void CParty::RemoveMember(CBattleEntity* PEntity) { DSP_DEBUG_BREAK_IF(PEntity == nullptr); DSP_DEBUG_BREAK_IF(PEntity->PParty != this); if (m_PLeader == PEntity) { RemovePartyLeader(PEntity); } else { for (uint32 i = 0; i < members.size(); ++i) { if (PEntity == members.at(i)) { members.erase(members.begin() + i); if (m_PartyType == PARTY_PCS) { CCharEntity* PChar = (CCharEntity*)PEntity; if (m_PQuaterMaster == PChar) { SetQuarterMaster(nullptr); } if (m_PSyncTarget == PChar) { SetSyncTarget(nullptr, 553); CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(server_clock::now()); sync->SetDuration(30000); } DisableSync(); } if (m_PSyncTarget != nullptr && m_PSyncTarget != PChar) { if (PChar->status != STATUS_DISAPPEAR) { CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(server_clock::now()); sync->SetDuration(30000); } } } PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->pushPacket(new CPartyDefinePacket(nullptr)); PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, 0, PChar->getZone())); PChar->pushPacket(new CCharUpdatePacket(PChar)); PChar->PParty = nullptr; Sql_Query(SqlHandle, "DELETE FROM accounts_parties WHERE charid = %u;", PChar->id); uint8 data[4] {}; ref<uint32>(data, 0) = m_PartyID; message::send(MSG_PT_RELOAD, data, sizeof data, nullptr); if (PChar->PTreasurePool != nullptr && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) { PChar->PTreasurePool->DelMember(PChar); PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); PChar->PTreasurePool->AddMember(PChar); PChar->PTreasurePool->UpdatePool(PChar); } } break; } } } }
bool CStatusEffectContainer::AddStatusEffect(CStatusEffect* PStatusEffect, bool silent) { if(PStatusEffect == nullptr){ ShowWarning("status_effect_container::AddStatusEffect Status effect given was nullptr!\n"); return false; } uint16 statusId = PStatusEffect->GetStatusID(); if(statusId >= MAX_EFFECTID){ ShowWarning("status_effect_container::AddStatusEffect statusId given is OVER limit %d\n", statusId); return false; } if(CanGainStatusEffect((EFFECT)statusId, PStatusEffect->GetPower())) { // check for minimum duration if(PStatusEffect->GetDuration() < effects::EffectsParams[statusId].MinDuration){ PStatusEffect->SetDuration(effects::EffectsParams[statusId].MinDuration); } // remove clean up other effects OverwriteStatusEffect(PStatusEffect); PStatusEffect->SetOwner(m_POwner); SetEffectParams(PStatusEffect); // remove effects with same type DelStatusEffectsByType(PStatusEffect->GetType()); PStatusEffect->SetStartTime(gettick()); m_StatusEffectList.push_back(PStatusEffect); luautils::OnEffectGain(m_POwner, PStatusEffect); m_POwner->addModifiers(&PStatusEffect->modList); if (PStatusEffect->GetStatusID() >= EFFECT_FIRE_MANEUVER && PStatusEffect->GetStatusID() <= EFFECT_DARK_MANEUVER && m_POwner->objtype == TYPE_PC) { puppetutils::CheckAttachmentsForManeuver((CCharEntity*)m_POwner, PStatusEffect->GetStatusID(), true); } if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in { m_POwner->UpdateHealth(); } if (m_POwner->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_POwner; if (PStatusEffect->GetIcon() != 0) { UpdateStatusIcons(); } if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in { //check for latents PChar->PLatentEffectContainer->CheckLatentsFoodEffect(); PChar->PLatentEffectContainer->CheckLatentsStatusEffect(); PChar->PLatentEffectContainer->CheckLatentsRollSong(PStatusEffect->GetFlag() & (EFFECTFLAG_SONG | EFFECTFLAG_ROLL)); PChar->UpdateHealth(); PChar->pushPacket(new CCharHealthPacket(PChar)); } PChar->pushPacket(new CCharSyncPacket(PChar)); } m_POwner->updatemask |= UPDATE_HP; return true; } return false; }
void CParty::ReloadParty() { auto info = GetPartyInfo(); //alliance if (this->m_PAlliance != nullptr) { for (auto&& party : m_PAlliance->partyList) { party->RefreshFlags(info); for (auto&& member : party->members) { CCharEntity* PChar = (CCharEntity*)member; PChar->ReloadPartyDec(); uint16 alliance = 0; PChar->pushPacket(new CPartyDefinePacket(party)); //auto effects = std::make_unique<CPartyEffectsPacket>(); uint8 j = 0; for (auto&& memberinfo : info) { if ((memberinfo.flags & (PARTY_SECOND | PARTY_THIRD)) != alliance) { alliance = memberinfo.flags & (PARTY_SECOND | PARTY_THIRD); j = 0; } auto PPartyMember = zoneutils::GetChar(memberinfo.id); if (PPartyMember) { PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, memberinfo.flags, PChar->getZone())); //if (memberinfo.partyid == party->GetPartyID() && PPartyMember != PChar) // effects->AddMemberEffects(PChar); } else { uint16 zoneid = memberinfo.zone == 0 ? memberinfo.prev_zone : memberinfo.zone; PChar->pushPacket(new CPartyMemberUpdatePacket( memberinfo.id, (const int8*)memberinfo.name.c_str(), memberinfo.flags, j, zoneid)); } j++; } //PChar->pushPacket(effects.release()); } } } else { RefreshFlags(info); //regular party for (uint8 i = 0; i < members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)members.at(i); PChar->PLatentEffectContainer->CheckLatentsPartyJobs(); PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->PLatentEffectContainer->CheckLatentsPartyAvatar(); PChar->ReloadPartyDec(); PChar->pushPacket(new CPartyDefinePacket(this)); //auto effects = std::make_unique<CPartyEffectsPacket>(); uint8 j = 0; for (auto&& memberinfo : info) { auto PPartyMember = zoneutils::GetChar(memberinfo.id); if (PPartyMember) { PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, memberinfo.flags, PChar->getZone())); //if (PPartyMember != PChar) // effects->AddMemberEffects(PChar); } else { uint16 zoneid = memberinfo.zone == 0 ? memberinfo.prev_zone : memberinfo.zone; PChar->pushPacket(new CPartyMemberUpdatePacket( memberinfo.id, (const int8*)memberinfo.name.c_str(), memberinfo.flags, j, zoneid)); //effects->AddMemberEffects(memberinfo.id); } j++; } //PChar->pushPacket(effects.release()); } } }
void CZoneEntities::DecreaseZoneCounter(CCharEntity* PChar) { DSP_DEBUG_BREAK_IF(PChar == nullptr); DSP_DEBUG_BREAK_IF(PChar->loc.zone != m_zone); //remove pets if (PChar->PPet != nullptr) { charutils::BuildingCharPetAbilityTable(PChar, (CPetEntity*)PChar->PPet, 0);//blank the pet commands if (PChar->PPet->isCharmed) { petutils::DespawnPet(PChar); } else { PChar->PPet->status = STATUS_DISAPPEAR; if (((CPetEntity*)(PChar->PPet))->getPetType() == PETTYPE_AVATAR) PChar->setModifier(MOD_AVATAR_PERPETUATION, 0); } // It may have been nullptred by DespawnPet if (PChar->PPet != nullptr) { PChar->PPet->PBattleAI->SetCurrentAction(ACTION_NONE); DeletePET(PChar->PPet);//remove the TID for this pet for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) { //inform other players of the pets removal CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PET = PCurrentChar->SpawnPETList.find(PChar->PPet->id); if (PET != PCurrentChar->SpawnPETList.end()) { PCurrentChar->SpawnPETList.erase(PET); PCurrentChar->pushPacket(new CEntityUpdatePacket(PChar->PPet, ENTITY_DESPAWN, UPDATE_NONE)); } } PChar->PPet = nullptr; } } //remove bcnm status if (m_zone->m_BattlefieldHandler != nullptr && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_BATTLEFIELD)) { if (m_zone->m_BattlefieldHandler->disconnectFromBcnm(PChar)){ ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n", PChar->GetName()); } if (PChar->loc.destination == 0){ //this player is disconnecting/logged out, so move them to the entrance //move depending on zone int pos[4] = { 0, 0, 0, 0 }; battlefieldutils::getStartPosition(m_zone->GetID(), pos); if (pos != nullptr){ PChar->loc.p.x = pos[0]; PChar->loc.p.y = pos[1]; PChar->loc.p.z = pos[2]; PChar->loc.p.rotation = pos[3]; PChar->updatemask |= UPDATE_POS; charutils::SaveCharPosition(PChar); } else{ ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n", PChar->GetName()); } } } else if (m_zone->m_BattlefieldHandler != nullptr && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DYNAMIS, 0)) { if (m_zone->m_BattlefieldHandler->disconnectFromDynamis(PChar)){ ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n", PChar->GetName()); } if (PChar->loc.destination == 0){ //this player is disconnecting/logged out, so move them to the entrance //move depending on zone int pos[4] = { 0, 0, 0, 0 }; battlefieldutils::getStartPosition(m_zone->GetID(), pos); if (!(pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0)){ PChar->loc.p.x = pos[0]; PChar->loc.p.y = pos[1]; PChar->loc.p.z = pos[2]; PChar->loc.p.rotation = pos[3]; PChar->updatemask |= UPDATE_POS; charutils::SaveCharPosition(PChar); } else{ ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n", PChar->GetName()); } } } for (auto PCharIt : m_charList) { CCharEntity* PCurrentChar = (CCharEntity*)PCharIt.second; if (PCurrentChar->PBattleAI->m_PMagicState->GetTarget() == PChar) { PCurrentChar->PBattleAI->m_PMagicState->ClearTarget(); } } for (auto PMobIt : m_mobList) { CMobEntity* PCurrentMob = (CMobEntity*)PMobIt.second; PCurrentMob->PEnmityContainer->Clear(PChar->id); if (PCurrentMob->m_OwnerID.id == PChar->id) { PCurrentMob->m_OwnerID.clean(); PCurrentMob->updatemask |= UPDATE_STATUS; } if (PCurrentMob->PBattleAI->m_PMagicState->GetTarget() == PChar) { PCurrentMob->PBattleAI->m_PMagicState->ClearTarget(); } if (PCurrentMob->PBattleAI->GetBattleSubTarget() == PChar) { PCurrentMob->PBattleAI->SetBattleSubTarget(nullptr); } } for (auto PPetIt : m_petList) { CPetEntity* PCurrentPet = (CPetEntity*)PPetIt.second; if (PCurrentPet->PBattleAI->m_PMagicState->GetTarget() == PChar) { PCurrentPet->PBattleAI->m_PMagicState->ClearTarget(); } if (PCurrentPet->PBattleAI->GetBattleSubTarget() == PChar) { PCurrentPet->PBattleAI->SetBattleSubTarget(nullptr); } } // TODO: могут возникать проблемы с переходом между одной и той же зоной (zone == prevzone) m_charList.erase(PChar->targid); ShowDebug(CL_CYAN"CZone:: %s DecreaseZoneCounter <%u> %s\n" CL_RESET, m_zone->GetName(), m_charList.size(), PChar->GetName()); }
void CParty::SetSyncTarget(int8* MemberName, uint16 message) { CBattleEntity* PEntity = nullptr; if (MemberName) { PEntity = GetMemberByName(MemberName); } if (map_config.level_sync_enable) { if (PEntity && PEntity->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)PEntity; //enable level sync if (PChar->GetMLevel() < 10) { ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 10, 541)); return; } else if (PChar->getZone() != GetLeader()->getZone()) { ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 542)); return; } else { for (uint8 i = 0; i < members.size(); ++i) { if (members.at(i)->StatusEffectContainer->HasStatusEffect({EFFECT_LEVEL_RESTRICTION, EFFECT_LEVEL_SYNC})) { ((CCharEntity*)GetLeader())->pushPacket(new CMessageBasicPacket((CCharEntity*)GetLeader(), (CCharEntity*)GetLeader(), 0, 0, 543)); return; } } m_PSyncTarget = PChar; for (uint8 i = 0; i < members.size(); ++i) { if (members.at(i)->objtype != TYPE_PC) continue; CCharEntity* member = (CCharEntity*)members.at(i); if (member->status != STATUS_DISAPPEAR && member->getZone() == PChar->getZone()) { member->pushPacket(new CMessageStandardPacket(PChar->GetMLevel(), 0, 0, 0, message)); member->StatusEffectContainer->AddStatusEffect(new CStatusEffect( EFFECT_LEVEL_SYNC, EFFECT_LEVEL_SYNC, PChar->GetMLevel(), 0, 0), true); member->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DISPELABLE | EFFECTFLAG_ON_ZONE); member->loc.zone->PushPacket(member, CHAR_INRANGE, new CCharSyncPacket(member)); } } Sql_Query(SqlHandle, "UPDATE accounts_parties SET partyflag = partyflag & ~%d WHERE partyid = %u AND partyflag & %d", PARTY_SYNC, m_PartyID, PARTY_SYNC); Sql_Query(SqlHandle, "UPDATE accounts_parties SET partyflag = partyflag | %d WHERE partyid = %u AND charid = '%u';", PARTY_SYNC, m_PartyID, PChar->id); } } else { if (m_PSyncTarget != nullptr) { //disable level sync for (uint8 i = 0; i < members.size(); ++i) { if (members.at(i)->objtype != TYPE_PC) continue; CCharEntity* member = (CCharEntity*)members.at(i); if (member->status != STATUS_DISAPPEAR) { CStatusEffect* sync = member->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { member->pushPacket(new CMessageBasicPacket(member, member, 10, 30, message)); sync->SetStartTime(server_clock::now()); sync->SetDuration(30000); } } } } m_PSyncTarget = nullptr; Sql_Query(SqlHandle, "UPDATE accounts_parties SET partyflag = partyflag & ~%d WHERE partyid = %u AND partyflag & %d", PARTY_SYNC, m_PartyID, PARTY_SYNC); } } }
void CZoneEntities::PushPacket(CBaseEntity* PEntity, GLOBAL_MESSAGE_TYPE message_type, CBasicPacket* packet) { // Do not send packets that are updates of a hidden GM.. if (packet != nullptr && packet->id() == 0x00D && PEntity != nullptr && PEntity->objtype == TYPE_PC && ((CCharEntity*)PEntity)->m_isGMHidden) { // Ensure this packet is not despawning us.. if (packet->ref<uint8>(0x0A) != 0x20) { delete packet; return; } } if (!m_charList.empty()) { switch (message_type) { case CHAR_INRANGE_SELF: { if (PEntity->objtype == TYPE_PC) { ((CCharEntity*)PEntity)->pushPacket(new CBasicPacket(*packet)); } } case CHAR_INRANGE: { for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; if (PEntity != PCurrentChar) { if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 50 && ((PEntity->objtype != TYPE_PC) || (((CCharEntity*)PEntity)->m_moghouseID == PCurrentChar->m_moghouseID))) { if (packet != nullptr && packet->id() == 0x00E && (packet->ref<uint8>(0x0A) != 0x20 || packet->ref<uint8>(0x0A) != 0x0F)) { uint32 id = packet->ref<uint32>(0x04); uint16 targid = packet->ref<uint16>(0x08); CBaseEntity* entity = GetEntity(targid); SpawnIDList_t spawnlist; if (entity) { if (entity->targid < 0x400) { if (entity->objtype == TYPE_MOB) { spawnlist = PCurrentChar->SpawnMOBList; } else if (entity->objtype == TYPE_NPC) { spawnlist = PCurrentChar->SpawnNPCList; } } else if (entity->targid >= 0x700) { spawnlist = PCurrentChar->SpawnPETList; } else { entity = nullptr; } } if (!entity) { // got a char or nothing as the target of this entity update (which really shouldn't happen ever) // so we're just going to skip this packet break; } SpawnIDList_t::iterator iter = spawnlist.lower_bound(id); if (!(iter == spawnlist.end() || spawnlist.key_comp()(id, iter->first))) { PCurrentChar->pushPacket(new CBasicPacket(*packet)); } } else { PCurrentChar->pushPacket(new CBasicPacket(*packet)); } } } } } break; case CHAR_INSHOUT: { for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; if (PEntity != PCurrentChar) { if (distance(PEntity->loc.p, PCurrentChar->loc.p) < 180 && ((PEntity->objtype != TYPE_PC) || (((CCharEntity*)PEntity)->m_moghouseID == PCurrentChar->m_moghouseID))) { PCurrentChar->pushPacket(new CBasicPacket(*packet)); } } } } break; case CHAR_INZONE: { for (EntityList_t::const_iterator it = m_charList.begin(); it != m_charList.end(); ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; if (PCurrentChar->m_moghouseID == 0) { if (PEntity != PCurrentChar) { PCurrentChar->pushPacket(new CBasicPacket(*packet)); } } } } break; } } delete packet; }
int32 map_cleanup(uint32 tick, CTaskMgr::CTask* PTask) { map_session_list_t::iterator it = map_session_list.begin(); while (it != map_session_list.end()) { map_session_data_t* map_session_data = it->second; CCharEntity* PChar = map_session_data->PChar; if ((time(nullptr) - map_session_data->last_update) > 5) { if (PChar != nullptr && !(PChar->nameflags.flags & FLAG_DC)) { PChar->nameflags.flags |= FLAG_DC; PChar->updatemask |= UPDATE_HP; if (PChar->status == STATUS_NORMAL) { PChar->loc.zone->SpawnPCs(PChar); } } if ((time(nullptr) - map_session_data->last_update) > map_config.max_time_lastupdate) { if (PChar != nullptr) { if (map_session_data->shuttingDown == 0) { //[Alliance] fix to stop server crashing: //if a party within an alliance only has 1 char (that char will be party leader) //if char then disconnects we need to tell the server about the alliance change if (PChar->PParty != nullptr && PChar->PParty->m_PAlliance != nullptr && PChar->PParty->GetLeader() == PChar) { if (PChar->PParty->members.size() == 1) { if (PChar->PParty->m_PAlliance->partyList.size() == 1) { PChar->PParty->m_PAlliance->dissolveAlliance(); } else { PChar->PParty->m_PAlliance->removeParty(PChar->PParty); } } } // uncharm pet if player d/c if (PChar->PPet != nullptr && PChar->PPet->objtype == TYPE_MOB) { petutils::DespawnPet(PChar); } PChar->StatusEffectContainer->SaveStatusEffects(true); ShowDebug(CL_CYAN"map_cleanup: %s timed out, closing session\n" CL_RESET, PChar->GetName()); PChar->status = STATUS_SHUTDOWN; PacketParser[0x00D](map_session_data, PChar, 0); } else { map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(true); Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u;", map_session_data->PChar->id); aFree(map_session_data->server_packet_data); delete map_session_data->PChar; delete map_session_data; map_session_data = nullptr; map_session_list.erase(it++); continue; } } else if (map_session_data->shuttingDown == 0) { ShowWarning(CL_YELLOW"map_cleanup: WHITHOUT CHAR timed out, session closed\n" CL_RESET); const int8* Query = "DELETE FROM accounts_sessions WHERE client_addr = %u AND client_port = %u"; Sql_Query(SqlHandle, Query, map_session_data->client_addr, map_session_data->client_port); aFree(map_session_data->server_packet_data); map_session_list.erase(it++); delete map_session_data; continue; } } } else if (PChar != nullptr && (PChar->nameflags.flags & FLAG_DC)) { PChar->nameflags.flags &= ~FLAG_DC; PChar->updatemask |= UPDATE_HP; PChar->pushPacket(new CCharUpdatePacket(PChar)); if (PChar->status == STATUS_NORMAL) { PChar->loc.zone->SpawnPCs(PChar); } charutils::SaveCharStats(PChar); } ++it; } return 0; }