void CStatusEffectContainer::RemoveStatusEffect(uint32 id) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(id); luautils::OnEffectLose(m_POwner, PStatusEffect); m_POwner->delModifiers(&PStatusEffect->modList); m_POwner->UpdateHealth(); m_StatusEffectList.erase(m_StatusEffectList.begin() + id); if (m_POwner->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_POwner; if (PStatusEffect->GetIcon() != 0) { UpdateStatusIcons(); PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, PStatusEffect->GetIcon(), 0, 206)); } if (PChar->status == STATUS_NORMAL) PChar->status = STATUS_UPDATE; PChar->pushPacket(new CCharHealthPacket(PChar)); PChar->pushPacket(new CCharSyncPacket(PChar)); } delete PStatusEffect; }
void CStatusEffectContainer::Fold(uint32 charid) { CStatusEffect* oldestRoll = nullptr; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { if ((m_StatusEffectList.at(i)->GetStatusID() >= EFFECT_FIGHTERS_ROLL && m_StatusEffectList.at(i)->GetStatusID() <= EFFECT_SCHOLARS_ROLL) || m_StatusEffectList.at(i)->GetStatusID() == EFFECT_BUST)//is a cor effect { if (m_StatusEffectList.at(i)->GetSubID() == charid || m_StatusEffectList.at(i)->GetStatusID() == EFFECT_BUST) { if (oldestRoll == nullptr) { oldestRoll = m_StatusEffectList.at(i); } else if (oldestRoll->GetStatusID() != EFFECT_BUST && m_StatusEffectList.at(i)->GetStatusID() == EFFECT_BUST) { oldestRoll = m_StatusEffectList.at(i); } else if (m_StatusEffectList.at(i)->GetDuration() + m_StatusEffectList.at(i)->GetStartTime() < oldestRoll->GetDuration() + oldestRoll->GetStartTime()) { oldestRoll = m_StatusEffectList.at(i); } } } } if (oldestRoll != nullptr) { DelStatusEffectSilent(oldestRoll->GetStatusID()); DelStatusEffectSilent(EFFECT_DOUBLE_UP_CHANCE); } }
CStatusEffect* CStatusEffectContainer::StealStatusEffect() { std::vector<uint16> dispelableList; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { if (m_StatusEffectList.at(i)->GetFlag() & EFFECTFLAG_DISPELABLE && m_StatusEffectList.at(i)->GetDuration() > 0) { dispelableList.push_back(i); } } if (!dispelableList.empty()) { uint16 rndIdx = WELL512::GetRandomNumber(dispelableList.size()); uint16 effectIndex = dispelableList.at(rndIdx); CStatusEffect* oldEffect = m_StatusEffectList.at(effectIndex); //make a copy CStatusEffect* EffectCopy = new CStatusEffect(oldEffect->GetStatusID(), oldEffect->GetIcon(), oldEffect->GetPower(), oldEffect->GetTickTime()/1000, oldEffect->GetDuration()/1000); RemoveStatusEffect(effectIndex); return EffectCopy; } return 0; }
bool CAttack::CheckAnticipated() { CStatusEffect* effect = m_victim->StatusEffectContainer->GetStatusEffect(EFFECT_THIRD_EYE, 0); if (effect == nullptr) { return false; } //power stores how many times this effect has anticipated auto pastAnticipations = effect->GetPower(); if (pastAnticipations > 7) { //max 7 anticipates! m_victim->StatusEffectContainer->DelStatusEffect(EFFECT_THIRD_EYE); return false; } bool hasSeigan = m_victim->StatusEffectContainer->HasStatusEffect(EFFECT_SEIGAN, 0); if (!hasSeigan && pastAnticipations == 0) { m_victim->StatusEffectContainer->DelStatusEffect(EFFECT_THIRD_EYE); m_anticipated = true; return true; } else if (!hasSeigan) { m_victim->StatusEffectContainer->DelStatusEffect(EFFECT_THIRD_EYE); return false; } else { //do have seigan, decay anticipations correctly (guesstimated) //5-6 anticipates is a 'lucky' streak, going to assume 15% decay per proc, with a 100% base w/ Seigan if (dsprand::GetRandomNumber(100) < (100 - (pastAnticipations * 15) + m_victim->getMod(Mod::THIRD_EYE_ANTICIPATE_RATE))) { //increment power and don't remove effect->SetPower(effect->GetPower() + 1); //chance to counter - 25% base if (dsprand::GetRandomNumber(100) < 25 + m_victim->getMod(Mod::THIRD_EYE_COUNTER_RATE)) { if (m_victim->PAI->IsEngaged()) { m_isCountered = true; m_isCritical = (dsprand::GetRandomNumber(100) < battleutils::GetCritHitRate(m_victim, m_attacker, false)); } } m_anticipated = true; return true; } m_victim->StatusEffectContainer->DelStatusEffect(EFFECT_THIRD_EYE); return false; } return false; }
void CParty::DisbandParty(bool playerInitiated) { if (m_PAlliance) { m_PAlliance->removeParty(this); } m_PSyncTarget = nullptr; SetQuarterMaster(nullptr); m_PLeader = nullptr; m_PAlliance = nullptr; if (m_PartyType == PARTY_PCS) { PushPacket(0, 0, new CPartyDefinePacket(nullptr)); for (uint8 i = 0; i < members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)members.at(i); PChar->PParty = nullptr; PChar->PLatentEffectContainer->CheckLatentsPartyJobs(); PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->PLatentEffectContainer->CheckLatentsPartyAvatar(); PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, 0, PChar->getZone())); // TODO: TreasurePool должен оставаться у последнего персонажа, но сейчас это не критично 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); } 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); } Sql_Query(SqlHandle, "DELETE FROM accounts_parties WHERE charid = %u;", PChar->id); } // make sure chat server isn't notified of a disband if this came from the chat server already if (playerInitiated) { uint8 data[8] {}; ref<uint32>(data, 0) = m_PartyID; ref<uint32>(data, 4) = m_PartyID; message::send(MSG_PT_DISBAND, data, sizeof data, nullptr); } } delete this; }
void CStatusEffectContainer::LoadStatusEffects() { DSP_DEBUG_BREAK_IF(m_POwner->objtype != TYPE_PC); const int8* Query = "SELECT " "effectid," "icon," "power," "tick," "duration," "subid," "subpower," "tier " "FROM char_effects " "WHERE charid = %u;"; int32 ret = Sql_Query(SqlHandle, Query, m_POwner->id); std::vector<CStatusEffect*> PEffectList; if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { CStatusEffect* PStatusEffect = new CStatusEffect( (EFFECT)Sql_GetUIntData(SqlHandle, 0), (uint16)Sql_GetUIntData(SqlHandle, 1), (uint16)Sql_GetUIntData(SqlHandle, 2), (uint32)Sql_GetUIntData(SqlHandle, 3), (uint32)Sql_GetUIntData(SqlHandle, 4), (uint16)Sql_GetUIntData(SqlHandle, 5), (uint16)Sql_GetUIntData(SqlHandle, 6), (uint16)Sql_GetUIntData(SqlHandle, 7)); PEffectList.push_back(PStatusEffect); // load shadows left if (PStatusEffect->GetStatusID() == EFFECT_COPY_IMAGE) { m_POwner->setModifier(MOD_UTSUSEMI, PStatusEffect->GetPower()); } else if (PStatusEffect->GetStatusID() == EFFECT_BLINK) { m_POwner->setModifier(MOD_BLINK, PStatusEffect->GetPower()); } } } for (auto&& PStatusEffect : PEffectList) { AddStatusEffect(PStatusEffect); } m_POwner->UpdateHealth(); // после загрузки эффектов пересчитываем максимальное количество HP/MP }
void CStatusEffectContainer::CheckEffects(uint32 tick) { DSP_DEBUG_BREAK_IF(m_POwner == nullptr); if (!m_POwner->isDead()) { if ((tick - m_EffectCheckTime) < 1000 ) { return; } m_EffectCheckTime = tick; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(i); if (PStatusEffect->GetTickTime() != 0 && PStatusEffect->GetLastTick() + PStatusEffect->GetTickTime() <= tick) { PStatusEffect->SetLastTick(tick); luautils::OnEffectTick(m_POwner,PStatusEffect); } if (PStatusEffect->GetDuration() != 0 && PStatusEffect->GetDuration() + PStatusEffect->GetStartTime() <= tick && i <m_StatusEffectList.size()) { RemoveStatusEffect(i--); } } } }
void CStatusEffectContainer::CheckEffects(time_point tick) { DSP_DEBUG_BREAK_IF(m_POwner == nullptr); if (!m_POwner->isDead()) { if ((tick - m_EffectCheckTime) < 1s && (tick - m_EffectCheckTime > 0s)) { return; } m_POwner->PAI->EventHandler.triggerListener("EFFECT_TICK", m_POwner); m_EffectCheckTime = tick; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(i); if (PStatusEffect->GetTickTime() != 0 && PStatusEffect->GetLastTick() + std::chrono::milliseconds(PStatusEffect->GetTickTime()) <= tick) { PStatusEffect->SetLastTick(tick); luautils::OnEffectTick(m_POwner, PStatusEffect); } if (PStatusEffect->GetDuration() != 0 && std::chrono::milliseconds(PStatusEffect->GetDuration()) + PStatusEffect->GetStartTime() <= tick && i < m_StatusEffectList.size()) { RemoveStatusEffect(i--); } } } }
bool CStatusEffectContainer::ApplyBardEffect(CStatusEffect* PStatusEffect, uint8 maxSongs) { //if all match tier/id/effect then overwrite //if tier/effect match then overwrite //but id doesn't, NO EFFECT //if targ has <2 of your songs on, then just apply //if targ has 2 of your songs, remove oldest one and apply this one. uint8 numOfEffects = 0; CStatusEffect* oldestSong = nullptr; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { if (m_StatusEffectList.at(i)->GetStatusID() >= EFFECT_REQUIEM && m_StatusEffectList.at(i)->GetStatusID() <= EFFECT_NOCTURNE) //is a brd effect { if (m_StatusEffectList.at(i)->GetTier() == PStatusEffect->GetTier() && m_StatusEffectList.at(i)->GetStatusID()==PStatusEffect->GetStatusID()){//same tier/type, overwrite //OVERWRITE DelStatusEffectByTier(PStatusEffect->GetStatusID(), PStatusEffect->GetTier()); AddStatusEffect(PStatusEffect); return true; } if(m_StatusEffectList.at(i)->GetSubID() == PStatusEffect->GetSubID()){//YOUR BRD effect numOfEffects++; if(!oldestSong){ oldestSong = m_StatusEffectList.at(i); } else if(m_StatusEffectList.at(i)->GetDuration() + m_StatusEffectList.at(i)->GetStartTime() < oldestSong->GetDuration() + oldestSong->GetStartTime()){ oldestSong = m_StatusEffectList.at(i); } } } } if(numOfEffects<maxSongs){ AddStatusEffect(PStatusEffect); return true; } else if (oldestSong){ //overwrite oldest DelStatusEffectByTier(oldestSong->GetStatusID(), oldestSong->GetTier()); AddStatusEffect(PStatusEffect); return true; } return false; }
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; }
/************************************************************************ * * * Deletes all status effects without sending messages * * * ************************************************************************/ void CStatusEffectContainer::KillAllStatusEffect() { for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(i); if (PStatusEffect->GetDuration() != 0) { luautils::OnEffectLose(m_POwner, PStatusEffect); m_POwner->delModifiers(&PStatusEffect->modList); m_StatusEffectList.erase(m_StatusEffectList.begin() + i); delete PStatusEffect; } } m_POwner->UpdateHealth(); }
/************************************************************************ * * * ????????? ??????? ????????? * * * ************************************************************************/ void CStatusEffectContainer::LoadStatusEffects() { DSP_DEBUG_BREAK_IF(m_POwner->objtype != TYPE_PC); const int8* Query = "SELECT " "effectid," "icon," "power," "tick," "duration," "subid," "subpower," "tier " "FROM char_effects " "WHERE charid = %u;"; int32 ret = Sql_Query(SqlHandle, Query, m_POwner->id); if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { CStatusEffect* PStatusEffect = new CStatusEffect( (EFFECT)Sql_GetUIntData(SqlHandle,0), (uint16)Sql_GetUIntData(SqlHandle,1), (uint16)Sql_GetUIntData(SqlHandle,2), (uint32)Sql_GetUIntData(SqlHandle,3), (uint32)Sql_GetUIntData(SqlHandle,4), (uint16)Sql_GetUIntData(SqlHandle,5), (uint16)Sql_GetUIntData(SqlHandle,6), (uint16)Sql_GetUIntData(SqlHandle,7)); AddStatusEffect(PStatusEffect); // load shadows left if(PStatusEffect->GetStatusID() == EFFECT_COPY_IMAGE){ m_POwner->setModifier(MOD_UTSUSEMI, PStatusEffect->GetPower()); } else if(PStatusEffect->GetStatusID() == EFFECT_BLINK){ m_POwner->setModifier(MOD_BLINK, PStatusEffect->GetPower()); } } } m_POwner->UpdateHealth(); // ????? ???????? ???????? ????????????? ???????????? ?????????? HP/MP }
void CStatusEffectContainer::RemoveOldestManeuver() { CStatusEffect* oldest = nullptr; int index = 0; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(i); if (PStatusEffect->GetStatusID() >= EFFECT_FIRE_MANEUVER && PStatusEffect->GetStatusID() <= EFFECT_DARK_MANEUVER) { if (!oldest || PStatusEffect->GetStartTime() < oldest->GetStartTime()) { oldest = PStatusEffect; index = i; } } } if (oldest) { RemoveStatusEffect(index, true); } }
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::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 CAutomatonController::TryTPMove() { if (PAutomaton->health.tp >= 1000) { const auto& FamilySkills = battleutils::GetMobSkillList(PAutomaton->m_Family); std::vector<CMobSkill*> validSkills; //load the skills that the automaton has access to with it's skill SKILLTYPE skilltype = SKILL_AME; if (PAutomaton->getFrame() == FRAME_SHARPSHOT) skilltype = SKILL_ARA; for (auto skillid : FamilySkills) { auto PSkill = battleutils::GetMobSkill(skillid); if (PSkill && PAutomaton->GetSkill(skilltype) > PSkill->getParam() && PSkill->getParam() != -1 && distance(PAutomaton->loc.p, PTarget->loc.p) < PSkill->getRadius()) { validSkills.push_back(PSkill); } } int16 currentSkill = -1; CMobSkill* PWSkill = nullptr; int8 currentManeuvers = -1; bool attemptChain = (PAutomaton->getMod(Mod::AUTO_TP_EFFICIENCY) != 0); if (attemptChain) { CStatusEffect* PSCEffect = PTarget->StatusEffectContainer->GetStatusEffect(EFFECT_SKILLCHAIN, 0); if (PSCEffect) { std::list<SKILLCHAIN_ELEMENT> resonanceProperties; if (PSCEffect->GetTier() == 0) { if (PSCEffect->GetStartTime() + 3s < m_Tick) { if (PSCEffect->GetPower()) { CWeaponSkill* PWeaponSkill = battleutils::GetWeaponSkill(PSCEffect->GetPower()); resonanceProperties.push_back((SKILLCHAIN_ELEMENT)PWeaponSkill->getPrimarySkillchain()); resonanceProperties.push_back((SKILLCHAIN_ELEMENT)PWeaponSkill->getSecondarySkillchain()); resonanceProperties.push_back((SKILLCHAIN_ELEMENT)PWeaponSkill->getTertiarySkillchain()); } else { CBlueSpell* oldSpell = (CBlueSpell*)spell::GetSpell(static_cast<SpellID>(PSCEffect->GetSubPower())); resonanceProperties.push_back((SKILLCHAIN_ELEMENT)oldSpell->getPrimarySkillchain()); resonanceProperties.push_back((SKILLCHAIN_ELEMENT)oldSpell->getSecondarySkillchain()); } } } else { resonanceProperties.push_back((SKILLCHAIN_ELEMENT)PSCEffect->GetPower()); } for (auto PSkill : validSkills) { if (PSkill->getParam() > currentSkill) { std::list<SKILLCHAIN_ELEMENT> skillProperties; skillProperties.push_back((SKILLCHAIN_ELEMENT)PSkill->getPrimarySkillchain()); skillProperties.push_back((SKILLCHAIN_ELEMENT)PSkill->getSecondarySkillchain()); skillProperties.push_back((SKILLCHAIN_ELEMENT)PSkill->getTertiarySkillchain()); if (battleutils::FormSkillchain(resonanceProperties, skillProperties) != SC_NONE) { currentManeuvers = 1; currentSkill = PSkill->getParam(); PWSkill = PSkill; } } } } } if (!attemptChain || (currentManeuvers == -1 && PAutomaton->PMaster && PAutomaton->PMaster->health.tp < PAutomaton->getMod(Mod::AUTO_TP_EFFICIENCY))) { for (auto PSkill : validSkills) { int8 maneuvers = luautils::OnMobAutomatonSkillCheck(PTarget, PAutomaton, PSkill); if (maneuvers > -1 && (maneuvers > currentManeuvers || (maneuvers == currentManeuvers && PSkill->getParam() > currentSkill))) { currentManeuvers = maneuvers; currentSkill = PSkill->getParam(); PWSkill = PSkill; } } } // No WS was chosen (waiting on master's TP to skillchain probably) if (currentManeuvers == -1) return false; if (PWSkill) return MobSkill(PTarget->targid, PWSkill->getID()); } return false; }
bool CStatusEffectContainer::ApplyCorsairEffect(CStatusEffect* PStatusEffect, uint8 maxRolls, uint8 bustDuration) { //break if not a COR roll. DSP_DEBUG_BREAK_IF(!(PStatusEffect->GetStatusID() >= EFFECT_FIGHTERS_ROLL && PStatusEffect->GetStatusID() <= EFFECT_SCHOLARS_ROLL)); //if all match tier/id/effect then overwrite //if tier/effect match then overwrite //but id doesn't, NO EFFECT //if targ has <2 of your rolls on, then just apply //if targ has 2 of your rolls, remove oldest one and apply this one. uint8 numOfEffects = 0; CStatusEffect* oldestRoll = nullptr; for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { if ((m_StatusEffectList.at(i)->GetStatusID() >= EFFECT_FIGHTERS_ROLL && m_StatusEffectList.at(i)->GetStatusID() <= EFFECT_SCHOLARS_ROLL) || m_StatusEffectList.at(i)->GetStatusID() == EFFECT_BUST)//is a cor effect { if(m_StatusEffectList.at(i)->GetStatusID() == PStatusEffect->GetStatusID() && m_StatusEffectList.at(i)->GetSubID() == PStatusEffect->GetSubID() && m_StatusEffectList.at(i)->GetSubPower() < PStatusEffect->GetSubPower()){//same type, double up if( PStatusEffect->GetSubPower() < 12) { PStatusEffect->SetDuration(m_StatusEffectList.at(i)->GetDuration()); DelStatusEffectSilent(PStatusEffect->GetStatusID()); AddStatusEffect(PStatusEffect, true); return true; } else { if (!CheckForElevenRoll()) { uint16 duration = 300; duration -= bustDuration; CStatusEffect* bustEffect = new CStatusEffect(EFFECT_BUST, EFFECT_BUST, PStatusEffect->GetPower(), 0, duration, PStatusEffect->GetTier(), PStatusEffect->GetStatusID()); AddStatusEffect(bustEffect, true); } DelStatusEffectSilent(PStatusEffect->GetStatusID()); return true; } } if(m_StatusEffectList.at(i)->GetSubID() == PStatusEffect->GetSubID() || m_StatusEffectList.at(i)->GetStatusID() == EFFECT_BUST){//YOUR cor effect numOfEffects++; if(oldestRoll==nullptr){ oldestRoll = m_StatusEffectList.at(i); } else if(m_StatusEffectList.at(i)->GetDuration() + m_StatusEffectList.at(i)->GetStartTime() < oldestRoll->GetDuration() + oldestRoll->GetStartTime()){ oldestRoll = m_StatusEffectList.at(i); } } } } if(numOfEffects<maxRolls){ AddStatusEffect(PStatusEffect, true); return true; } else{ //i'm a liar, can overwrite rolls DelStatusEffect(oldestRoll->GetStatusID()); AddStatusEffect(PStatusEffect); return true; } return false; }
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); } } } } } } }
bool CStatusEffectContainer::CanGainStatusEffect(EFFECT statusEffect, uint16 power) { // check for immunities first switch(statusEffect){ case EFFECT_SLEEP: case EFFECT_SLEEP_II: case EFFECT_LULLABY: if(m_POwner->hasImmunity(IMMUNITY_SLEEP)) return false; break; case EFFECT_WEIGHT: if(m_POwner->hasImmunity(IMMUNITY_GRAVITY)) return false; break; case EFFECT_BIND: if(m_POwner->hasImmunity(IMMUNITY_BIND)) return false; break; case EFFECT_STUN: if(m_POwner->hasImmunity(IMMUNITY_STUN)) return false; break; case EFFECT_SILENCE: if(m_POwner->hasImmunity(IMMUNITY_SILENCE)) return false; break; case EFFECT_PARALYSIS: if(m_POwner->hasImmunity(IMMUNITY_PARALYZE)) return false; break; case EFFECT_BLINDNESS: if(m_POwner->hasImmunity(IMMUNITY_BLIND)) return false; break; case EFFECT_SLOW: if(m_POwner->hasImmunity(IMMUNITY_SLOW)) return false; break; case EFFECT_POISON: if(m_POwner->hasImmunity(IMMUNITY_POISON)) return false; break; case EFFECT_ELEGY: if(m_POwner->hasImmunity(IMMUNITY_ELEGY)) return false; break; case EFFECT_REQUIEM: if(m_POwner->hasImmunity(IMMUNITY_REQUIEM)) return false; break; } // make sure pets can't be charmed if((statusEffect == EFFECT_CHARM || statusEffect == EFFECT_CHARM_II) && m_POwner->PMaster != nullptr) { return false; } CStatusEffect* PStatusEffect; // check if a status effect blocks this EFFECT blockId = effects::EffectsParams[statusEffect].BlockId; if(blockId != 0 && HasStatusEffect(blockId)){ return false; } // check if negative is strong enough to stop this EFFECT negativeId = effects::EffectsParams[statusEffect].NegativeId; if(negativeId != 0){ PStatusEffect = GetStatusEffect(negativeId); if(PStatusEffect != nullptr){ if(statusEffect == EFFECT_HASTE && PStatusEffect->GetStatusID() == EFFECT_SLOW && PStatusEffect->GetSubPower() == 1) { // slow i remote return true; } // new status effect must be stronger return power >= PStatusEffect->GetPower(); } } PStatusEffect = GetStatusEffect(statusEffect); // check overwrite if(PStatusEffect != nullptr){ uint16 currentPower = PStatusEffect->GetPower(); EFFECTOVERWRITE overwrite = effects::EffectsParams[statusEffect].Overwrite; if(overwrite == EFFECTOVERWRITE_ALWAYS || overwrite == EFFECTOVERWRITE_IGNORE){ return true; } if(overwrite == EFFECTOVERWRITE_NEVER){ return false; } if(overwrite == EFFECTOVERWRITE_EQUAL_HIGHER){ if(power >= currentPower){ return true; } } else if(overwrite == EFFECTOVERWRITE_HIGHER){ // overwrite only if higher if(power > currentPower){ return true; } } return false; } return true; }
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 CStatusEffectContainer::SaveStatusEffects(bool logout) { DSP_DEBUG_BREAK_IF(m_POwner->objtype != TYPE_PC); Sql_Query(SqlHandle,"DELETE FROM char_effects WHERE charid = %u", m_POwner->id); for (uint16 i = 0; i < m_StatusEffectList.size(); ++i) { CStatusEffect* PStatusEffect = m_StatusEffectList.at(i); if (logout && PStatusEffect->GetFlag() & EFFECTFLAG_LOGOUT) continue; uint32 realduration = (PStatusEffect->GetDuration() + PStatusEffect->GetStartTime() - gettick()) / 1000; if (realduration > 0) { const int8* Query = "INSERT INTO char_effects (charid, effectid, icon, power, tick, duration, subid, subpower, tier) VALUES(%u,%u,%u,%u,%u,%u,%u,%u,%u);"; // save power of utsusemi and blink if (PStatusEffect->GetStatusID() == EFFECT_COPY_IMAGE) { PStatusEffect->SetPower(m_POwner->getMod(MOD_UTSUSEMI)); } else if (PStatusEffect->GetStatusID() == EFFECT_BLINK) { PStatusEffect->SetPower(m_POwner->getMod(MOD_BLINK)); } else if (PStatusEffect->GetStatusID() == EFFECT_STONESKIN) { PStatusEffect->SetPower(m_POwner->getMod(MOD_STONESKIN)); } uint32 tick = PStatusEffect->GetTickTime() == 0 ? 0 : PStatusEffect->GetTickTime() / 100; uint32 duration = PStatusEffect->GetDuration() == 0 ? 0 : realduration; Sql_Query(SqlHandle, Query, m_POwner->id, PStatusEffect->GetStatusID(), PStatusEffect->GetIcon(), PStatusEffect->GetPower(), tick, duration, PStatusEffect->GetSubID(), PStatusEffect->GetSubPower(), PStatusEffect->GetTier()); } } }
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; } } } }