// 添加到CByteArray bool CShape::CodeToDataBlock(DBWriteSet& setWriteDB, bool bExData) { CBaseObject::CodeToDataBlock(setWriteDB,bExData); setWriteDB.AddToByteArray((BYTE)GetCurRgnType()); setWriteDB.AddToByteArray(GetRegionID()); setWriteDB.AddToByteArray(GetRegionExID()); setWriteDB.AddToByteArray(GetPosX()); setWriteDB.AddToByteArray(GetPosY()); setWriteDB.AddToByteArray(GetDir()); setWriteDB.AddToByteArray(GetPos()); setWriteDB.AddToByteArray(GetSpeed()); setWriteDB.AddToByteArray(GetState()); setWriteDB.AddToByteArray(GetAction()); return true; }
// 添加到CByteArray bool CShape::AddShapeToByteArray(vector<BYTE>* pByteArray) { _AddToByteArray(pByteArray,(CGUID&)GetExID()); _AddToByteArray(pByteArray, (long)GetCurRgnType()); _AddToByteArray(pByteArray, GetRegionID()); _AddToByteArray(pByteArray, GetRegionExID()); _AddToByteArray(pByteArray, GetPosX()); _AddToByteArray(pByteArray, GetPosY()); _AddToByteArray(pByteArray, GetDir()); _AddToByteArray(pByteArray, GetPos()); _AddToByteArray(pByteArray, GetSpeed()); _AddToByteArray(pByteArray, GetState()); _AddToByteArray(pByteArray, GetAction()); return true; }
// Processes a single CLatentEffect* and finds the expression to evaluate for // activation/deactivation and attempts to apply bool CLatentEffectContainer::ProcessLatentEffect(CLatentEffect& latentEffect) { // Our default case un-finds our latent prevent us from toggling a latent we don't have programmed auto expression = false; auto latentFound = true; // find the latent type from the enum and find the expression to tests againts switch (latentEffect.GetConditionsID()) { case LATENT_HP_UNDER_PERCENT: expression = ((float)m_POwner->health.hp / m_POwner->health.maxhp) * 100 <= latentEffect.GetConditionsValue(); break; case LATENT_HP_OVER_PERCENT: expression = ((float)m_POwner->health.hp / m_POwner->health.maxhp) * 100 >= latentEffect.GetConditionsValue(); break; case LATENT_HP_UNDER_TP_UNDER_100: expression = ((float)m_POwner->health.hp / m_POwner->health.maxhp) * 100 <= latentEffect.GetConditionsValue() && m_POwner->health.tp < 1000; break; case LATENT_HP_OVER_TP_UNDER_100: expression = ((float)m_POwner->health.hp / m_POwner->health.maxhp) * 100 >= latentEffect.GetConditionsValue() && m_POwner->health.tp < 1000; break; case LATENT_MP_UNDER_PERCENT: expression = m_POwner->health.maxmp && (float)(m_POwner->health.mp / m_POwner->health.maxmp) * 100 <= latentEffect.GetConditionsValue(); break; case LATENT_MP_UNDER: expression = m_POwner->health.mp <= latentEffect.GetConditionsValue(); break; case LATENT_TP_UNDER: expression = m_POwner->health.tp < latentEffect.GetConditionsValue(); break; case LATENT_TP_OVER: expression = m_POwner->health.tp > latentEffect.GetConditionsValue(); break; case LATENT_SUBJOB: expression = m_POwner->GetSJob() == latentEffect.GetConditionsValue(); break; case LATENT_PET_ID: expression = m_POwner->PPet != nullptr && m_POwner->PPet->objtype == TYPE_PET && ((CPetEntity*)m_POwner->PPet)->m_PetID == latentEffect.GetConditionsValue(); break; case LATENT_WEAPON_DRAWN: expression = m_POwner->animation == ANIMATION_ATTACK; break; case LATENT_WEAPON_SHEATHED: expression = m_POwner->animation != ANIMATION_ATTACK; break; case LATENT_STATUS_EFFECT_ACTIVE: expression = m_POwner->StatusEffectContainer->HasStatusEffect((EFFECT)latentEffect.GetConditionsValue()); break; case LATENT_NO_FOOD_ACTIVE: expression = !m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_FOOD); break; case LATENT_PARTY_MEMBERS: expression = m_POwner->PParty != nullptr && latentEffect.GetConditionsValue() <= m_POwner->PParty->members.size(); break; case LATENT_PARTY_MEMBERS_IN_ZONE: { auto inZone = 0; if (m_POwner->PParty != nullptr) { for (auto member : m_POwner->PParty->members) { if (member->getZone() == m_POwner->getZone()) { ++inZone; } } } expression = latentEffect.GetConditionsValue() <= inZone; break; } case LATENT_AVATAR_IN_PARTY: if (m_POwner->PParty != nullptr) { for (auto member : m_POwner->PParty->members) { if (member->PPet != nullptr) { auto PPet = (CPetEntity*)member->PPet; if (PPet->m_PetID == latentEffect.GetConditionsValue() && PPet->PAI->IsSpawned()) { expression = true; break; } } } } else if (m_POwner->PParty == nullptr && m_POwner->PPet != nullptr) { auto PPet = (CPetEntity*)m_POwner->PPet; if (PPet->m_PetID == latentEffect.GetConditionsValue() && !PPet->isDead()) { expression = true; } } break; case LATENT_JOB_IN_PARTY: if (m_POwner->PParty != nullptr) { for (auto member : m_POwner->PParty->members) { if (member->id != m_POwner->id) { if (member->GetMJob() == latentEffect.GetConditionsValue()) { expression = true; break; } } } } break; case LATENT_ZONE: expression = latentEffect.GetConditionsValue() == m_POwner->getZone(); break; case LATENT_SYNTH_TRAINEE: // todo: figure this out break; case LATENT_SONG_ROLL_ACTIVE: expression = m_POwner->StatusEffectContainer->HasStatusEffectByFlag(EFFECTFLAG_ROLL | EFFECTFLAG_SONG); break; case LATENT_TIME_OF_DAY: { uint32 VanadielHour = CVanaTime::getInstance()->getHour(); switch (latentEffect.GetConditionsValue()) { case 0: //daytime: 06:00 to 18:00 expression = VanadielHour >= 6 && VanadielHour < 18; break; case 1: //nighttime: 18:00 to 06:00 expression = VanadielHour >= 18 || VanadielHour < 6; break; case 2: //dusk - dawn: 17:00 to 7:00 expression = VanadielHour >= 17 || VanadielHour < 7; break; } break; } case LATENT_HOUR_OF_DAY: { uint32 VanadielHour = CVanaTime::getInstance()->getHour(); switch (latentEffect.GetConditionsValue()) { case 1: //new day expression = VanadielHour == 4; break; case 2: //dawn expression = VanadielHour >= 6 && VanadielHour < 7; break; case 3: //day expression = VanadielHour >= 7 && VanadielHour < 17; break; case 4: //dusk expression = VanadielHour >= 16 && VanadielHour < 18; break; case 5: //evening expression = VanadielHour >= 18 && VanadielHour < 20; break; case 6: //dead of night expression = VanadielHour >= 20 || VanadielHour < 4; break; } break; } case LATENT_FIRESDAY: expression = CVanaTime::getInstance()->getWeekday() == FIRESDAY; break; case LATENT_EARTHSDAY: expression = CVanaTime::getInstance()->getWeekday() == EARTHSDAY; break; case LATENT_WATERSDAY: expression = CVanaTime::getInstance()->getWeekday() == WATERSDAY; break; case LATENT_WINDSDAY: expression = CVanaTime::getInstance()->getWeekday() == WINDSDAY; break; case LATENT_DARKSDAY: expression = CVanaTime::getInstance()->getWeekday() == DARKSDAY; break; case LATENT_ICEDAY: expression = CVanaTime::getInstance()->getWeekday() == ICEDAY; break; case LATENT_LIGHTNINGSDAY: expression = CVanaTime::getInstance()->getWeekday() == LIGHTNINGDAY; break; case LATENT_LIGHTSDAY: expression = CVanaTime::getInstance()->getWeekday() == LIGHTSDAY; break; case LATENT_MOON_PHASE: { uint32 MoonPhase = CVanaTime::getInstance()->getMoonPhase(); uint32 MoonDirection = CVanaTime::getInstance()->getMoonDirection(); //directions: 1 = waning, 2 = waxing, 0 = neither switch (latentEffect.GetConditionsValue()) { case 0: //New Moon - 10% waning -> 5% waxing expression = MoonPhase <= 5 || (MoonPhase <= 10 && MoonDirection == 1); break; case 1: //Waxing Crescent - 7% -> 38% waxing expression = MoonPhase >= 7 && MoonPhase <= 38 && MoonDirection == 2; break; case 2: //First Quarter - 40%% -> 55% waxing expression = MoonPhase >= 40 && MoonPhase <= 55 && MoonDirection == 2; break; case 3: //Waxing Gibbous - 57% -> 88% expression = MoonPhase >= 57 && MoonPhase <= 88 && MoonDirection == 2; break; case 4: //Full Moon - waxing 90% -> waning 95% expression = MoonPhase >= 95 || (MoonPhase >= 90 && MoonDirection == 2); break; case 5: //Waning Gibbous - 93% -> 62% expression = MoonPhase >= 62 && MoonPhase <= 93 && MoonDirection == 1; break; case 6: //Last Quarter - 60% -> 45% expression = MoonPhase >= 45 && MoonPhase <= 60 && MoonDirection == 1; break; case 7: //Waning Crescent - 43% -> 12% expression = MoonPhase >= 12 && MoonPhase <= 43 && MoonDirection == 1; break; } break; } case LATENT_JOB_MULTIPLE_5: expression = m_POwner->GetMLevel() % 5 == 0; break; case LATENT_JOB_MULTIPLE_10: expression = m_POwner->GetMLevel() % 10 == 0; break; case LATENT_JOB_MULTIPLE_13_NIGHT: expression = m_POwner->GetMLevel() % 13 == 0 && CVanaTime::getInstance()->SyncTime() == TIME_NIGHT; break; case LATENT_JOB_LEVEL_ODD: expression = m_POwner->GetMLevel() % 2 == 1; break; case LATENT_JOB_LEVEL_EVEN: expression = m_POwner->GetMLevel() % 2 == 0; break; case LATENT_WEAPON_DRAWN_HP_UNDER: expression = m_POwner->health.hp < latentEffect.GetConditionsValue() && m_POwner->animation == ANIMATION_ATTACK; break; case LATENT_MP_UNDER_VISIBLE_GEAR: //TODO: figure out if this is actually right //CItemArmor* head = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_HEAD])); //CItemArmor* body = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_BODY])); //CItemArmor* hands = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_HANDS])); //CItemArmor* legs = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_LEGS])); //CItemArmor* feet = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_FEET])); //int32 visibleMp = 0; //visibleMp += (head ? head->getModifier(Mod::MP) : 0); //visibleMp += (body ? body->getModifier(Mod::MP) : 0); //visibleMp += (hands ? hands->getModifier(Mod::MP) : 0); //visibleMp += (legs ? legs->getModifier(Mod::MP) : 0); //visibleMp += (feet ? feet->getModifier(Mod::MP) : 0); //TODO: add mp percent too //if ((float)( mp / ((m_POwner->health.mp - m_POwner->health.modmp) + (m_POwner->PMeritPoints->GetMerit(MERIT_MAX_MP)->count * 10 ) + // visibleMp) ) <= m_LatentEffectList.at(i)->GetConditionsValue()) //{ // m_LatentEffectList.at(i)->Activate(); //} //else //{ // m_LatentEffectList.at(i)->Deactivate(); //} break; case LATENT_HP_OVER_VISIBLE_GEAR: //TODO: figure out if this is actually right //CItemArmor* head = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_HEAD])); //CItemArmor* body = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_BODY])); //CItemArmor* hands = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_HANDS])); //CItemArmor* legs = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_LEGS])); //CItemArmor* feet = (CItemArmor*)(m_POwner->getStorage(LOC_INVENTORY)->GetItem(m_POwner->equip[SLOT_FEET])); //int32 visibleHp = 0; //visibleHp += (head ? head->getModifier(Mod::HP) : 0); //visibleHp += (body ? body->getModifier(Mod::HP) : 0); //visibleHp += (hands ? hands->getModifier(Mod::HP) : 0); //visibleHp += (legs ? legs->getModifier(Mod::HP) : 0); //visibleHp += (feet ? feet->getModifier(Mod::HP) : 0); //TODO: add mp percent too //if ((float)( hp / ((m_POwner->health.hp - m_POwner->health.modhp) + (m_POwner->PMeritPoints->GetMerit(MERIT_MAX_HP)->count * 10 ) + // visibleHp) ) <= m_LatentEffectList.at(i)->GetConditionsValue()) //{ // m_LatentEffectList.at(i)->Activate(); //} //else //{ // m_LatentEffectList.at(i)->Deactivate(); //} break; case LATENT_WEAPON_BROKEN: { auto slot = latentEffect.GetSlot(); auto item = (CItemWeapon*)m_POwner->getEquip((SLOTTYPE)slot); switch (slot) { case SLOT_MAIN: case SLOT_SUB: case SLOT_RANGED: expression = item != nullptr && item->isUnlocked(); break; } break; } case LATENT_IN_DYNAMIS: expression = m_POwner->isInDynamis(); break; case LATENT_IN_ASSAULT: expression = m_POwner->isInAssault(); break; case LATENT_FOOD_ACTIVE: expression = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_FOOD) && m_POwner->StatusEffectContainer->GetStatusEffect(EFFECT_FOOD)->GetSubID() == latentEffect.GetConditionsValue(); break; case LATENT_JOB_LEVEL_BELOW: expression = m_POwner->GetMLevel() < latentEffect.GetConditionsValue(); break; case LATENT_JOB_LEVEL_ABOVE: expression = m_POwner->GetMLevel() >= latentEffect.GetConditionsValue(); break; case LATENT_WEATHER_ELEMENT: expression = latentEffect.GetConditionsValue() == zoneutils::GetWeatherElement(battleutils::GetWeather((CBattleEntity*)m_POwner, false)); break; case LATENT_NATION_CONTROL: { //player is logging in/zoning if (m_POwner->loc.zone == nullptr) { break; } auto region = m_POwner->loc.zone->GetRegionID(); auto hasSignet = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SIGNET); auto hasSanction = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SANCTION); auto hasSigil = m_POwner->StatusEffectContainer->HasStatusEffect(EFFECT_SIGIL); switch (latentEffect.GetConditionsValue()) { case 0: //under own nation's control expression = region < 28 && conquest::GetRegionOwner(region) == m_POwner->profile.nation && (hasSignet || hasSanction || hasSigil); break; case 1: //outside of own nation's control expression = region < 28 && m_POwner->profile.nation != conquest::GetRegionOwner(region) && (hasSignet || hasSanction || hasSigil); break; } break; } case LATENT_ZONE_HOME_NATION: { //player is logging in/zoning if (m_POwner->loc.zone == nullptr) { break; } auto PZone = m_POwner->loc.zone; auto region = (REGIONTYPE)latentEffect.GetConditionsValue(); switch (region) { case REGION_SANDORIA: expression = m_POwner->profile.nation == 0 && PZone->GetRegionID() == region; break; case REGION_BASTOK: expression = m_POwner->profile.nation == 1 && PZone->GetRegionID() == region; break; case REGION_WINDURST: expression = m_POwner->profile.nation == 2 && PZone->GetRegionID() == region; break; default: break; } break; } case LATENT_MP_OVER: expression = m_POwner->health.mp >= latentEffect.GetConditionsValue(); break; case LATENT_WEAPON_DRAWN_MP_OVER: expression = m_POwner->health.mp > latentEffect.GetConditionsValue() && m_POwner->animation == ANIMATION_ATTACK; break; case LATENT_ELEVEN_ROLL_ACTIVE: expression = m_POwner->StatusEffectContainer->CheckForElevenRoll(); break; default: latentFound = false; ShowWarning("Latent ID %d unhandled in ProcessLatentEffect\n", latentEffect.GetConditionsID()); break; } // if we did not hit the default case, attempt to apply the latent effect based on the expression if (latentFound) { return ApplyLatentEffect(latentEffect, expression); } return false; }