CLinkshellMessagePacket::CLinkshellMessagePacket(const int8* poster, const int8* message, const int8* lsname, uint32 posttime, bool ls1) { CBasicPacket::id(id); this->size = 0x58; ref<uint8>(0x04) = 0x03; ref<uint8>(0x05) = 0x90; ref<uint8>(0x04) = 0x70; ref<uint8>(0x05) = 0x06; if (!ls1) { ref<uint8>(0x05) |= 0x40; //LS2 } if (message) { memcpy(data + (0x08), message, dsp_min(strlen(message), 115)); memcpy(data + (0x8C), poster, dsp_min(strlen(poster), 15)); memcpy(data + (0xA0), lsname, dsp_min(strlen(lsname), 16)); ref<uint32>(0x88) = posttime; } ref<uint32>(0x9C) = 0x02; }
CTradeUpdatePacket::CTradeUpdatePacket(CItem* PItem, uint8 SlotID) { this->type = 0x23; this->size = 0x14; WBUFL(data,(0x04)-4) = PItem->getReserve(); WBUFW(data,(0x0A)-4) = PItem->getID(); WBUFB(data,(0x0D)-4) = SlotID; if (PItem->isSubType(ITEM_CHARGED)) { WBUFB(data,(0x0E)-4) = 0x01; if (((CItemUsable*)PItem)->getCurrentCharges() > 0) { WBUFB(data,(0x0F)-4) = ((CItemUsable*)PItem)->getCurrentCharges(); } } if (PItem->isType(ITEM_LINKSHELL)) { WBUFL(data,(0x0E)-4) = ((CItemLinkshell*)PItem)->GetLSID(); WBUFW(data,(0x14)-4) = ((CItemLinkshell*)PItem)->GetLSRawColor(); WBUFB(data,(0x16)-4) = ((CItemLinkshell*)PItem)->GetLSType(); memcpy(data+(0x17)-4, PItem->getSignature(), dsp_min(strlen(PItem->getSignature()),15)); } else { memcpy(data+(0x15)-4, PItem->getSignature(), dsp_min(strlen(PItem->getSignature()),12)); } }
uint16 CBattleEntity::ATT() { //TODO: consider which weapon! int32 ATT = 8 + m_modStat[MOD_ATT]; if (m_Weapons[SLOT_MAIN]->isTwoHanded()) { ATT += (STR() * 3) / 4; } else { ATT += (STR()) / 2; } if (this->StatusEffectContainer->HasStatusEffect(EFFECT_ENDARK)) ATT += this->getMod(MOD_ENSPELL_DMG); if (this->objtype & TYPE_PC) { ATT += GetSkill(m_Weapons[SLOT_MAIN]->getSkillType()) + m_Weapons[SLOT_MAIN]->getILvlSkill(); } else if (this->objtype == TYPE_PET && ((CPetEntity*)this)->getPetType() == PETTYPE_AUTOMATON) { ATT += PMaster->GetSkill(SKILL_AME); return ATT + (ATT * (m_modStat[MOD_ATTP] + ((CCharEntity*)PMaster)->PMeritPoints->GetMeritValue(MERIT_OPTIMIZATION, (CCharEntity*)PMaster)) / 100) + dsp_min((ATT * m_modStat[MOD_FOOD_ATTP] / 100), m_modStat[MOD_FOOD_ATT_CAP]); } return ATT + (ATT * m_modStat[MOD_ATTP] / 100) + dsp_min((ATT * m_modStat[MOD_FOOD_ATTP] / 100), m_modStat[MOD_FOOD_ATT_CAP]); }
uint16 CBattleEntity::ACC(uint8 attackNumber, uint8 offsetAccuracy) { if (this->objtype & TYPE_PC) { uint8 skill = 0; uint16 iLvlSkill = 0; if (attackNumber == 0) { skill = m_Weapons[SLOT_MAIN]->getSkillType(); iLvlSkill = m_Weapons[SLOT_MAIN]->getILvlSkill(); if (skill == SKILL_NON && GetSkill(SKILL_H2H) > 0) skill = SKILL_H2H; } else if (attackNumber == 1) { skill = m_Weapons[SLOT_SUB]->getSkillType(); iLvlSkill = m_Weapons[SLOT_SUB]->getILvlSkill(); if (skill == SKILL_NON && GetSkill(SKILL_H2H) > 0 && (m_Weapons[SLOT_MAIN]->getSkillType() == SKILL_NON || m_Weapons[SLOT_MAIN]->getSkillType() == SKILL_H2H)) skill = SKILL_H2H; } else if (attackNumber == 2) { iLvlSkill = m_Weapons[SLOT_MAIN]->getILvlSkill(); skill = SKILL_H2H; } int16 ACC = GetSkill(skill) + iLvlSkill; ACC = (ACC > 200 ? (((ACC - 200)*0.9) + 200) : ACC); if (m_Weapons[SLOT_MAIN]->isTwoHanded() == true) { ACC += DEX() * 0.75; } else { ACC += DEX() * 0.5; } ACC = (ACC + m_modStat[MOD_ACC] + offsetAccuracy); ACC = ACC + (ACC * m_modStat[MOD_ACCP] / 100) + dsp_min((ACC * m_modStat[MOD_FOOD_ACCP] / 100), m_modStat[MOD_FOOD_ACC_CAP]); return dsp_max(0, ACC); } else if (this->objtype == TYPE_PET && ((CPetEntity*)this)->getPetType() == PETTYPE_AUTOMATON) { int16 ACC = PMaster->GetSkill(SKILL_AME); ACC = (ACC > 200 ? (((ACC - 200)*0.9) + 200) : ACC); ACC += DEX() * 0.5; ACC += m_modStat[MOD_ACC] + offsetAccuracy + ((CCharEntity*)PMaster)->PMeritPoints->GetMeritValue(MERIT_FINE_TUNING, (CCharEntity*)PMaster); ACC = ACC + (ACC * m_modStat[MOD_ACCP] / 100) + dsp_min((ACC * m_modStat[MOD_FOOD_ACCP] / 100), m_modStat[MOD_FOOD_ACC_CAP]); return dsp_max(0, ACC); } else { int16 ACC = m_modStat[MOD_ACC]; ACC = ACC + (ACC * m_modStat[MOD_ACCP] / 100) + dsp_min((ACC * m_modStat[MOD_FOOD_ACCP] / 100), m_modStat[MOD_FOOD_ACC_CAP]) + DEX() / 2; //food mods here for Snatch Morsel return dsp_max(0, ACC); } }
uint16 CBattleEntity::RATT(uint8 skill, uint16 bonusSkill) { int32 ATT = 8 + GetSkill(skill) + bonusSkill + m_modStat[MOD_RATT] + battleutils::GetRangedAttackBonuses(this) + STR() / 2; if (this->objtype == TYPE_PET && ((CPetEntity*)this)->getPetType() == PETTYPE_AUTOMATON) { return ATT + (ATT * (m_modStat[MOD_ATTP] + ((CCharEntity*)PMaster)->PMeritPoints->GetMeritValue(MERIT_OPTIMIZATION, (CCharEntity*)PMaster)) / 100) + dsp_min((ATT * m_modStat[MOD_FOOD_ATTP] / 100), m_modStat[MOD_FOOD_ATT_CAP]); } return ATT + (ATT * m_modStat[MOD_RATTP] / 100) + dsp_min((ATT * m_modStat[MOD_FOOD_RATTP] / 100), m_modStat[MOD_FOOD_RATT_CAP]); }
uint8 CGuild::addGuildPoints(CCharEntity* PChar, CItem* PItem, int16& pointsAdded) { uint8 rank = PChar->RealSkills.rank[m_id + 48]; rank = dsp_cap(rank, 3, 9); if (PItem) { int32 curPoints = charutils::GetVar(PChar, "[GUILD]daily_points"); if (curPoints >= 0) { for (auto& GPItem : m_GPItems[rank - 3]) { if (GPItem.item->getID() == PItem->getID()) { uint8 quantity = dsp_min(((GPItem.maxpoints - curPoints) / GPItem.points) + 1, PItem->getQuantity()); uint16 points = GPItem.points * quantity; if (points > GPItem.maxpoints - curPoints) { points = GPItem.maxpoints - curPoints; } charutils::AddPoints(PChar, pointsName.c_str(), points); pointsAdded = points; Sql_Query(SqlHandle, "REPLACE INTO char_vars VALUES (%d, '[GUILD]daily_points', %u);", PChar->id, curPoints + points); return quantity; } } } } return 0; }
void CTradeContainer::setConfirmedStatus(uint8 slotID, uint8 amount) { if (slotID < m_PItem.size() && m_PItem[slotID]) { m_confirmed[slotID] = dsp_min(amount, m_PItem[slotID]->getQuantity()); } }
bool CMeritPoints::AddLimitPoints(uint16 points) { m_LimitPoints += points; if (m_LimitPoints >= MAX_LIMIT_POINTS) { //check if player has reached cap if (m_MeritPoints == map_config.max_merit_points + GetMeritValue(MERIT_MAX_MERIT, m_PChar)) { m_LimitPoints = MAX_LIMIT_POINTS -1; return false; } uint8 MeritPoints = dsp_min(m_MeritPoints + m_LimitPoints / MAX_LIMIT_POINTS, map_config.max_merit_points + GetMeritValue(MERIT_MAX_MERIT, m_PChar)); m_LimitPoints = m_LimitPoints % MAX_LIMIT_POINTS; if (m_MeritPoints != MeritPoints) { m_MeritPoints = MeritPoints; return true; } } return false; }
uint16 CBattleEntity::RATT(uint8 skill) { int32 ATT = 8 + GetSkill(skill) + m_modStat[MOD_RATT] + battleutils::GetRangedAttackBonuses(this) + STR() / 2; return ATT + (ATT * m_modStat[MOD_RATTP] / 100) + dsp_min((ATT * m_modStat[MOD_FOOD_RATTP] / 100), m_modStat[MOD_FOOD_RATT_CAP]); }
bool CMeritPoints::AddLimitPoints(uint16 points) { m_LimitPoints += points; if (m_LimitPoints >= MAX_LIMIT_POINTS) { //check if player has reached cap if (m_MeritPoints == MAX_MERIT_POINTS) { m_LimitPoints = MAX_LIMIT_POINTS -1; return false; } uint8 MeritPoints = dsp_min(m_MeritPoints + m_LimitPoints / MAX_LIMIT_POINTS, MAX_MERIT_POINTS); m_LimitPoints = m_LimitPoints % MAX_LIMIT_POINTS; if (m_MeritPoints != MeritPoints) { m_MeritPoints = MeritPoints; return true; } } return false; }
bool CTradeContainer::setConfirmedStatus(uint8 slotID, uint8 amount) { if (slotID < m_PItem.size() && m_PItem[slotID] && m_PItem[slotID]->getQuantity() >= amount) { m_confirmed[slotID] = dsp_min(amount, m_PItem[slotID]->getQuantity()); return true; } return false; }
void CEnmityContainer::UpdateEnmityFromAttack(CBattleEntity* PEntity, uint16 Damage) { if (m_EnmityList.lower_bound(PEntity->id) == m_EnmityList.end()) { return; } float reduction = (100.f - dsp_min(PEntity->getMod(MOD_ENMITY_LOSS_REDUCTION), 100)) / 100.0f; UpdateEnmity(PEntity, -(1800 * Damage / PEntity->GetMaxHP()) * reduction, 0); }
uint16 CBattleEntity::DEF() { if (this->StatusEffectContainer->HasStatusEffect(EFFECT_COUNTERSTANCE, 0)) { return VIT() / 2 + 1; } int32 DEF = 8 + m_modStat[MOD_DEF] + VIT() / 2; return DEF + (DEF * m_modStat[MOD_DEFP] / 100) + dsp_min((DEF * m_modStat[MOD_FOOD_DEFP] / 100), m_modStat[MOD_FOOD_DEF_CAP]); }
uint16 CBattleEntity::ACC(uint8 attackNumber, uint8 offsetAccuracy) { if (this->objtype & TYPE_PC){ uint8 skill = 0; if (attackNumber == 0) { skill = m_Weapons[SLOT_MAIN]->getSkillType(); if(skill == SKILL_NON && GetSkill(SKILL_H2H) > 0) skill = SKILL_H2H; } else if (attackNumber == 1) { skill = m_Weapons[SLOT_SUB]->getSkillType(); if(skill == SKILL_NON && GetSkill(SKILL_H2H) > 0 && (m_Weapons[SLOT_MAIN]->getSkillType() == SKILL_NON || m_Weapons[SLOT_MAIN]->getSkillType() == SKILL_H2H)) skill = SKILL_H2H; } else if (attackNumber == 2) { skill = SKILL_H2H; } int16 ACC = GetSkill(skill); ACC = (ACC > 200 ? (((ACC - 200)*0.9)+200) : ACC); if(m_Weapons[SLOT_MAIN]->isTwoHanded() == true) { ACC += DEX() * 0.75; } else { ACC += DEX() * 0.5; } ACC = (ACC + m_modStat[MOD_ACC] + offsetAccuracy); ACC = ACC + (ACC * m_modStat[MOD_ACCP] / 100) + dsp_min((ACC * m_modStat[MOD_FOOD_ACCP] / 100), m_modStat[MOD_FOOD_ACC_CAP]); return dsp_max(0, ACC); } else{ int16 ACC = m_modStat[MOD_ACC]; ACC = ACC + (ACC * m_modStat[MOD_ACCP] / 100) + dsp_min((ACC * m_modStat[MOD_FOOD_ACCP] / 100), m_modStat[MOD_FOOD_ACC_CAP]) + DEX() / 2; //food mods here for Snatch Morsel return dsp_max(0, ACC); } }
CSpoofMessagePacket::CSpoofMessagePacket(CCharEntity* PChar, int8* name, CHAT_MESSAGE_TYPE MessageType, int8* buff) { int32 buffSize = (strlen(buff) > 108) ? 108 : strlen(buff); this->type = 0x17; this->size = dsp_min((32 + (buffSize + 1) + ((4 - ((buffSize + 1) % 4)) % 4)) / 2, 128); WBUFB(data, (0x04) - 4) = MessageType; WBUFW(data, (0x06) - 4) = PChar->getZone(); memcpy(data + (0x08) - 4, name, size); memcpy(data + (0x18) - 4, buff, buffSize); }
int32 CMeritPoints::GetMeritValue(Merit_t* merit, CCharEntity* PChar) { uint8 meritValue = 0; if (merit->catid < 5 || (merit->jobs & (1 << (PChar->GetMJob() - 1)) && PChar->GetMLevel() >= 75)) meritValue = dsp_min(merit->count, cap[PChar->GetMLevel()]); meritValue *= merit->value; return meritValue; }
CLinkshellMessagePacket::CLinkshellMessagePacket(CLinkshell* PLinkshell) { this->type = 0xCC; this->size = 0x58; WBUFB(data,(0x04)-4) = 0x03; WBUFB(data,(0x05)-4) = 0x90; if (PLinkshell != nullptr) { WBUFB(data,(0x04)-4) = 0x70; WBUFB(data,(0x05)-4) = 0x86; // +0x80 - show, +0x40 - set memcpy(data+(0x08)-4, PLinkshell->getMessage(), dsp_min(strlen(PLinkshell->getMessage()), 115)); memcpy(data+(0x8C)-4, PLinkshell->getPoster(), dsp_min(strlen(PLinkshell->getPoster()), 15)); memcpy(data+(0xA0)-4, PLinkshell->getName(), dsp_min(strlen(PLinkshell->getName()), 16)); WBUFL(data,(0x88)-4) = PLinkshell->getMessageTime(); } WBUFL(data,(0x9C)-4) = 0x01; }
int32 CMeritPoints::GetMeritValue(MERIT_TYPE merit, CCharEntity* PChar) { Merit_t* PMerit = GetMeritPointer(merit); uint8 meritValue = 0; if (PMerit->catid < 5 || (PMerit->jobs & (1 << (PChar->GetMJob() - 1)) && PChar->GetMLevel() >= 75)) meritValue = dsp_min(PMerit->count, cap[PChar->GetMLevel()]); meritValue *= PMerit->value; return meritValue; }
void CBattleEntity::UpdateHealth() { int32 dif = (getMod(MOD_CONVMPTOHP) - getMod(MOD_CONVHPTOMP)); health.modmp = ((health.maxmp) * (100 + getMod(MOD_MPP)) / 100) + dsp_min((health.maxmp * m_modStat[MOD_FOOD_MPP] / 100), m_modStat[MOD_FOOD_MP_CAP]) + getMod(MOD_MP); health.modhp = ((health.maxhp) * (100 + getMod(MOD_HPP)) / 100) + dsp_min((health.maxhp * m_modStat[MOD_FOOD_HPP] / 100), m_modStat[MOD_FOOD_HP_CAP]) + getMod(MOD_HP); dif = (health.modmp - 0) < dif ? (health.modmp - 0) : dif; dif = (health.modhp - 1) < -dif ? -(health.modhp - 1) : dif; health.modhp += dif; health.modmp -= dif; if (objtype == TYPE_PC) { health.modhp = dsp_cap(health.modhp, 0, 9999); health.modmp = dsp_cap(health.modmp, 0, 9999); } health.hp = dsp_cap(health.hp, 0, health.modhp); health.mp = dsp_cap(health.mp, 0, health.modmp); updatemask |= UPDATE_HP; }
uint16 CBattleEntity::ATT() { int32 ATT = 8 + m_modStat[MOD_ATT]; if (m_Weapons[SLOT_MAIN]->isTwoHanded()) { ATT += (STR() * 3) / 4; } else { ATT += (STR()) / 2; } if (this->objtype & TYPE_PC){ ATT += GetSkill(m_Weapons[SLOT_MAIN]->getSkillType()); } return ATT + (ATT * m_modStat[MOD_ATTP] / 100) + dsp_min((ATT * m_modStat[MOD_FOOD_ATTP] / 100), m_modStat[MOD_FOOD_ATT_CAP]); }
void CEnmityContainer::UpdateEnmityFromAttack(CBattleEntity* PEntity, uint16 Damage) { if (m_EnmityList.find(PEntity->id) == m_EnmityList.end()) { return; } float reduction = (100.f - dsp_min(PEntity->getMod(Mod::ENMITY_LOSS_REDUCTION), 100)) / 100.0f; int16 CE = -(1800 * Damage / PEntity->GetMaxHP()) * reduction; auto enmity_obj = m_EnmityList.find(PEntity->id); if (enmity_obj != m_EnmityList.end()) { enmity_obj->second.CE = dsp_cap(enmity_obj->second.CE + CE, 0, 10000); } }
CChatMessagePacket::CChatMessagePacket(CCharEntity* PChar, CHAT_MESSAGE_TYPE MessageType, int8* buff) { // Determine the return message length.. int32 buffSize = (strlen(buff) > 108) ? 108 : strlen(buff); // Build the packet.. this->type = 0x17; this->size = dsp_min((32 + (buffSize + 1) + ((4 - ((buffSize + 1) % 4)) % 4)) / 2, 128); WBUFB(data, (0x04) - 4) = MessageType; if (PChar->nameflags.flags & FLAG_GM) WBUFB(data, (0x05) - 4) = 0x01; WBUFW(data, (0x06) - 4) = PChar->getZone(); memcpy(data + (0x08) - 4, PChar->GetName(), PChar->name.size()); memcpy(data + (0x18) - 4, buff, buffSize); }
uint16 CBattleEntity::RACC(uint8 skill, uint16 bonusSkill) { int skill_level = GetSkill(skill) + bonusSkill; uint16 acc = skill_level; if (skill_level > 200) { acc = 200 + (skill_level - 200)*0.9; } acc += getMod(MOD_RACC); acc += battleutils::GetRangedAccuracyBonuses(this); acc += AGI() / 2; if (this->objtype == TYPE_PET && ((CPetEntity*)this)->getPetType() == PETTYPE_AUTOMATON) { acc += ((CCharEntity*)PMaster)->PMeritPoints->GetMeritValue(MERIT_FINE_TUNING, (CCharEntity*)PMaster); } return ((100 + getMod(MOD_RACCP)) * acc) / 100 + dsp_min(((100 + getMod(MOD_FOOD_RACCP)) * acc) / 100, getMod(MOD_FOOD_RACC_CAP)); }
void CItemArmor::addModifier(CModifier* modifier) { if (IsShield() && modifier->getModID() == MOD_DEF) { // reduction calc source: www.bluegartr.com/threads/84830-Shield-Asstery int16 pdt = modifier->getModAmount() / 2; switch(m_shieldSize) { case 1: pdt += 22; break; // Bucker 22% case 2: pdt += 40; break; // Round 40% case 3: pdt += 50; break; // Kite 50% case 4: pdt += 55; break; // Tower 55% case 5: pdt += 60; break; // Aegis 60% } m_absorption = dsp_min(pdt,100); } modList.push_back(modifier); }
void CMeritPoints::SetMeritPoints(uint16 points) { m_MeritPoints = dsp_min(points, MAX_MERIT_POINTS); }
void CMeritPoints::SetLimitPoints(uint16 points) { m_LimitPoints = dsp_min(points, MAX_LIMIT_POINTS - 1); }
/************************************************************************ * * * Multihit calculator. * * * ************************************************************************/ uint8 getHitCount(uint8 hits) { uint8 distribution = WELL512::irand()%100; uint8 num = 1; switch (hits) { case 0: break; case 1: break; case 2: // cdf = 55,100 if(distribution < 55){ break; } else{ num+=1; break;} break; case 3: // cdf = 30,80,100 if(distribution < 30){ break; } else if(distribution < 80){ num+=1; break; } else{ num+=2; break; } break; case 4: // cdf = 20,50,80,100 if(distribution < 20){ break; } else if(distribution < 50){ num+=1; break; } else if(distribution < 80){ num+=2; break; } else{ num+=3; break; } break; case 5: // cdf = 10,30,60,90,100 if(distribution < 10){ break; } else if(distribution < 30){ num+=1; break; } else if(distribution < 60){ num+=2; break; } else if(distribution < 90){ num+=3; break; } else{ num+=4; break; } break; case 6: // cdf = 10,30,50,70,90,100 if(distribution < 10){ break; } else if(distribution < 30){num+=1; break; } else if(distribution < 50){num+=2; break; } else if(distribution < 70){num+=3; break; } else if(distribution < 90){num+=4; break; } else{ num+=5; break; } break; case 7: // cdf = 5,20,45,70,85,95,100 if(distribution < 5){ break; } else if(distribution < 20){num+=1; break; } else if(distribution < 45){num+=2; break; } else if(distribution < 70){num+=3; break; } else if(distribution < 85){num+=4; break; } else if(distribution < 95){num+=5; break; } else{ num+=6; break; } break; case 8: // cdf = 5,20,45,70,85,95,98,100 if(distribution < 5){ break; } else if(distribution < 20){num+=1; break; } else if(distribution < 45){num+=2; break; } else if(distribution < 70){num+=3; break; } else if(distribution < 85){num+=4; break; } else if(distribution < 95){num+=5; break; } else if(distribution < 98){num+=6; break; } else{ num+=7; break; } break; } return dsp_min(num,8); // не более восьми ударов за одну атаку }
void CBattleEntity::UpdateHealth() { int32 dif = (getMod(MOD_CONVMPTOHP) - getMod(MOD_CONVHPTOMP)); health.modmp = ((health.maxmp + getMod(MOD_MP)) * (100 + getMod(MOD_MPP)) / 100) + dsp_min((health.maxmp * m_modStat[MOD_FOOD_MPP] / 100), m_modStat[MOD_FOOD_MP_CAP]); health.modhp = ((health.maxhp + getMod(MOD_HP)) * (100 + getMod(MOD_HPP)) / 100) + dsp_min((health.maxhp * m_modStat[MOD_FOOD_HPP] / 100), m_modStat[MOD_FOOD_HP_CAP]); dif = (health.modmp - 0) < dif ? (health.modmp - 0) : dif; dif = (health.modhp - 1) < -dif ? -(health.modhp - 1) : dif; health.modhp += dif; health.modmp -= dif; health.hp = dsp_cap(health.hp, 0, health.modhp); health.mp = dsp_cap(health.mp, 0, health.modmp); }
uint8 CItemContainer::AddBuff(int8 buff) { m_buff += buff; return SetSize(dsp_min(m_buff, 80)); // ограничение в 80 ячеек для персонажа }
void CMeritPoints::SetMeritPoints(uint16 points) { m_MeritPoints = dsp_min(points, map_config.max_merit_points + GetMeritValue(MERIT_MAX_MERIT, m_PChar)); }