void CEnmityContainer::UpdateEnmity(CBattleEntity* PEntity, int16 CE, int16 VE, bool withMaster) { // you're too far away so i'm ignoring you if (!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } auto enmity_obj = m_EnmityList.find(PEntity->id); if (enmity_obj != m_EnmityList.end()) { float bonus = CalculateEnmityBonus(PEntity); int newCE = enmity_obj->second.CE + ((CE > 0) ? CE * bonus : CE); int newVE = enmity_obj->second.VE + ((VE > 0) ? VE * bonus : VE); //Check for cap limit enmity_obj->second.CE = dsp_cap(newCE, 0, 10000); enmity_obj->second.VE = dsp_cap(newVE, 0, 10000); enmity_obj->second.active = true; if (CE + VE > 0 && PEntity->getMod(Mod::TREASURE_HUNTER) > enmity_obj->second.maxTH) enmity_obj->second.maxTH = (uint8)(PEntity->getMod(Mod::TREASURE_HUNTER)); } else if (CE >= 0 && VE >= 0) { bool initial = true; for (auto&& enmityObject : m_EnmityList) { if (enmityObject.second.active) { initial = false; break; } } if (initial) CE += 200; float bonus = CalculateEnmityBonus(PEntity); CE = dsp_cap(CE * bonus, 0, 10000); VE = dsp_cap(VE * bonus, 0, 10000); auto maxTH = 0; if (CE + VE > 0) maxTH = (uint8)(PEntity->getMod(Mod::TREASURE_HUNTER)); m_EnmityList.emplace(PEntity->id, EnmityObject_t {PEntity, CE, VE, true, (uint8)maxTH}); if (withMaster && PEntity->PMaster != nullptr) { //add master to the enmity list //add master to the enmity list (charmed mob) if (PEntity->objtype == TYPE_PET || PEntity->objtype == TYPE_MOB && PEntity->PMaster != nullptr && PEntity->PMaster->objtype == TYPE_PC) { AddBaseEnmity(PEntity->PMaster); } } } }
void CEnmityContainer::UpdateEnmityFromCure(CBattleEntity* PEntity, uint16 level, uint16 CureAmount, bool isCureV) { if (isCureV) { UpdateEnmity(PEntity, 400, 700); } else { CureAmount = (CureAmount < 1 ? 1 : CureAmount); uint16 mod = battleutils::GetEnmityModCure(level); uint16 CE = 40. / mod * CureAmount; uint16 VE = 240. / mod * CureAmount; // you're too far away so i'm ignoring you if (!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } // Crash fix, PEntity was in ACTION_FALL if (PEntity->PBattleAI->GetCurrentAction() == ACTION_FALL) return; EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if (PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float bonus = CalculateEnmityBonus(PEntity); float tranquilHeartReduction = 1.f - battleutils::HandleTranquilHeart(PEntity); int newCE = PEnmity->second->CE + (CE * bonus * tranquilHeartReduction); int newVE = PEnmity->second->VE + (VE * bonus * tranquilHeartReduction); //Check for cap limit PEnmity->second->CE = dsp_cap(newCE, 1, 10000); PEnmity->second->VE = dsp_cap(newVE, 0, 10000); } else if (CE >= 0 && VE >= 0) { EnmityObject_t* PEnmityObject = new EnmityObject_t; float bonus = CalculateEnmityBonus(PEntity); float tranquilHeartReduction = 1.f - battleutils::HandleTranquilHeart(PEntity); PEnmityObject->CE = dsp_cap(CE * bonus * tranquilHeartReduction, 1, 10000); PEnmityObject->VE = dsp_cap(VE * bonus * tranquilHeartReduction, 0, 10000); PEnmityObject->PEnmityOwner = PEntity; PEnmityObject->maxTH = 0; m_EnmityList.insert(PEnmity, EnmityList_t::value_type(PEntity->id, PEnmityObject)); } } }
void CBattleEntity::SetMLevel(uint8 mlvl) { m_modStat[MOD_DEF] -= m_mlvl + dsp_cap(m_mlvl - 50, 0, 10); m_mlvl = (mlvl == 0 ? 1 : mlvl); m_modStat[MOD_DEF] += m_mlvl + dsp_cap(m_mlvl - 50, 0, 10); if (this->objtype & TYPE_PC) Sql_Query(SqlHandle, "UPDATE char_stats SET mlvl = %u WHERE charid = %u LIMIT 1;", m_mlvl, this->id); }
/************************************************************************ * * * Creates up to many attacks for a particular hand. * * * ************************************************************************/ void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction) { uint8 num = 1; // Checking the players weapon hit count if (PWeapon->getReqLvl() <= m_attacker->GetMLevel()) { num = PWeapon->getHitCount(); } AddAttackSwing(ATTACK_NORMAL, direction, num); // Checking the players triple, double and quadruple attack int8 tripleAttack = m_attacker->getMod(MOD_TRIPLE_ATTACK); int8 doubleAttack = m_attacker->getMod(MOD_DOUBLE_ATTACK); int8 quadAttack = m_attacker->getMod(MOD_QUAD_ATTACK); //check for merit upgrades if (m_attacker->objtype == TYPE_PC) { 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); if (num == 1 && rand()%100 < quadAttack) { AddAttackSwing(QUAD_ATTACK, direction, 3); m_quadAttackOccured = true; } else if (num == 1 && rand()%100 < tripleAttack) { AddAttackSwing(TRIPLE_ATTACK, direction, 2); m_tripleAttackOccured = true; } else if (num == 1 && rand()%100 < doubleAttack && num == 1) { AddAttackSwing(DOUBLE_ATTACK, direction, 1); m_doubleAttackOccured = true; } // TODO: Possible Lua function for the nitty gritty stuff below. // Iga mod: Extra attack chance whilst dual wield is on. if (direction == LEFTATTACK && rand()%100 < m_attacker->getMod(MOD_EXTRA_DUAL_WIELD_ATTACK)) { AddAttackSwing(ATTACK_NORMAL, RIGHTATTACK, 1); } }
int32 CBattleEntity::addMP(int32 mp) { int32 cap = dsp_cap(health.mp + mp, 0, GetMaxMP()); mp = health.mp - cap; health.mp = cap; return abs(mp); }
int16 CBattleEntity::addTP(int16 tp) { // When adding TP, we must adjust for Inhibit TP effect, which reduces TP gain. if (tp > 0) { float tpReducePercent = this->getMod(MOD_INHIBIT_TP) / 100; tp = tp - (tp * tpReducePercent); float TPMulti = 1.0; if (objtype == TYPE_PC) { TPMulti = map_config.player_tp_multiplier; } else if (objtype == TYPE_MOB) { TPMulti = map_config.mob_tp_multiplier; } else if (objtype == TYPE_PET) { TPMulti = map_config.mob_tp_multiplier * 3; } tp = tp * TPMulti; } int16 cap = dsp_cap(health.tp + tp, 0, 3000); tp = health.tp - cap; health.tp = cap; return abs(tp); }
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 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); }
int32 CBattleEntity::addHP(int32 hp) { if (status == STATUS_NORMAL) status = STATUS_UPDATE; if (health.hp == 0 && hp < 0){ return 0; //if the entity is already dead, skip the rest to prevent killing it again } int32 cap = dsp_cap(health.hp + hp, 0, GetMaxHP()); hp = health.hp - cap; health.hp = cap; // если количество жизней достигает нуля, то сущность умирает if(hp > 0) { battleutils::MakeEntityStandUp(this); } if (health.hp == 0) { if (animation == ANIMATION_CHOCOBO) { StatusEffectContainer->DelStatusEffectSilent(EFFECT_CHOCOBO); } PBattleAI->SetCurrentAction(ACTION_FALL); } return abs(hp); }
/************************************************************************ * * * Creates kick attacks. * * * ************************************************************************/ void CAttackRound::CreateKickAttacks() { if (m_attacker->objtype == TYPE_PC) { // kick attack mod (All jobs) uint16 kickAttack = m_attacker->getMod(Mod::KICK_ATTACK); if (m_attacker->GetMJob() == JOB_MNK) // MNK (Main job) { kickAttack += ((CCharEntity*)m_attacker)->PMeritPoints->GetMeritValue(MERIT_KICK_ATTACK_RATE, (CCharEntity*)m_attacker); } kickAttack = dsp_cap(kickAttack, 0, 100); if (dsprand::GetRandomNumber(100) < kickAttack) { AddAttackSwing(PHYSICAL_ATTACK_TYPE::KICK, RIGHTATTACK, 1); m_kickAttackOccured = true; } // TODO: Possible Lua function for the nitty gritty stuff below. // Mantra set mod: Try an extra left kick attack. if (m_kickAttackOccured && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::EXTRA_KICK_ATTACK)) { AddAttackSwing(PHYSICAL_ATTACK_TYPE::KICK, LEFTATTACK, 1); } } }
int16 CMagicState::CalculateMPCost(CSpell* PSpell) { if(PSpell == NULL) { ShowWarning("CMagicState::CalculateMPCost Spell is NULL\n"); return 0; } // ninja tools or bard song if(!PSpell->hasMPCost()) { return 0; } bool applyArts = true; uint16 base = PSpell->getMPCost(); if (PSpell->getID() == 478 || PSpell->getID() == 502) //Embrava/Kaustra { base = m_PEntity->health.maxmp * 0.2; } int16 cost = base; if (PSpell->getSpellGroup() == SPELLGROUP_BLACK) { if (PSpell->getAOE() == SPELLAOE_RADIAL_MANI && m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_MANIFESTATION)) { cost *= 2; applyArts = false; } if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_PARSIMONY)) { cost /= 2; applyArts = false; } else if (applyArts) { cost += base * (m_PEntity->getMod(MOD_BLACK_MAGIC_COST)/100.0f); } } else if (PSpell->getSpellGroup() == SPELLGROUP_WHITE) { if (PSpell->getAOE() == SPELLAOE_RADIAL_ACCE && m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ACCESSION)) { cost *= 2; applyArts = false; } if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_PENURY)) { cost /= 2; applyArts = false; } else if (applyArts) { cost += base * (m_PEntity->getMod(MOD_WHITE_MAGIC_COST)/100.0f); } } return dsp_cap(cost, 0, 9999); }
void CEnmityContainer::LowerEnmityByPercent(CBattleEntity* PEntity, uint8 percent, CBattleEntity* HateReceiver) { EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if (PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { float mod = ((float)(percent) / 100.0f); int32 CEValue = (float)(PEnmity->second->CE * mod); PEnmity->second->CE -= (CEValue < 0 ? 0 : CEValue); int32 VEValue = (float)(PEnmity->second->VE * mod); PEnmity->second->VE -= (VEValue < 0 ? 0 : VEValue); // transfer hate if HateReceiver not nullptr if (HateReceiver != nullptr) { UpdateEnmity(HateReceiver, 0, 0); EnmityList_t::iterator PEnmityReceiver = m_EnmityList.lower_bound(HateReceiver->id); PEnmityReceiver->second->CE = dsp_cap(PEnmityReceiver->second->CE + CEValue,1,10000); PEnmityReceiver->second->VE = dsp_cap(PEnmityReceiver->second->VE + VEValue,0,10000); } } // highest enmity holder after this update CBattleEntity* NewEntity = GetHighestEnmity(); // PEntity is now the target, face the target if (OldEntity != NewEntity && !m_EnmityHolder->isAsleep()) { if ((m_EnmityHolder->objtype == TYPE_MOB && !(((CMobEntity*)m_EnmityHolder)->m_Behaviour & BEHAVIOUR_NO_TURN)) || m_EnmityHolder->objtype != TYPE_MOB) { uint8 angle = getangle(m_EnmityHolder->loc.p, NewEntity->loc.p); m_EnmityHolder->loc.p.rotation = angle; m_EnmityHolder->loc.zone->PushPacket(m_EnmityHolder, CHAR_INRANGE, new CEntityUpdatePacket(m_EnmityHolder, ENTITY_UPDATE, UPDATE_POS)); } } }
float CEnmityContainer::CalculateEnmityBonus(CBattleEntity* PEntity){ int8 enmityBonus = 0; if (PEntity->objtype & TYPE_PC) { enmityBonus = ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_INCREASE, (CCharEntity*)PEntity) - ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_DECREASE, (CCharEntity*)PEntity); } float bonus = (100.0f + dsp_cap(PEntity->getMod(Mod::ENMITY) + enmityBonus, -50, 100)) / 100.0f; return bonus; }
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; }
void CEnmityContainer::UpdateEnmityFromCure(CBattleEntity* PEntity, uint16 level, uint16 CureAmount, bool isCureV) { if (!IsWithinEnmityRange(PEntity)) return; int16 CE; int16 VE; float bonus = CalculateEnmityBonus(PEntity); float tranquilHeartReduction = 1.f - battleutils::HandleTranquilHeart(PEntity); if (isCureV) { CE = 400 * bonus * tranquilHeartReduction; VE = 700 * bonus * tranquilHeartReduction; } else { CureAmount = (CureAmount < 1 ? 1 : CureAmount); uint16 mod = battleutils::GetEnmityModCure(level); CE = 40. / mod * CureAmount * bonus * tranquilHeartReduction; VE = 240. / mod * CureAmount * bonus * tranquilHeartReduction; } 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); enmity_obj->second.VE = dsp_cap(enmity_obj->second.VE + VE, 0, 10000); enmity_obj->second.active = true; } else m_EnmityList.emplace(PEntity->id, EnmityObject_t{ PEntity, dsp_cap(CE, 0, 10000), dsp_cap(VE, 0, 10000), true, 0 }); }
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); } }
uint8 GetTotalSlots(CCharEntity* PChar) { uint8 level = 0; if (PChar->GetMJob() == JOB_BLU) { level = PChar->GetMLevel(); } else if (PChar->GetSJob() == JOB_BLU) { level = PChar->GetSLevel(); } if (level == 0) return 0; else return dsp_cap(((level - 1)/10)*2 + 6, 6, 20); }
std::pair<uint16, uint16> CGuild::getDailyGPItem(CCharEntity* PChar) { uint8 rank = PChar->RealSkills.rank[m_id + 48]; rank = dsp_cap(rank, 3, 9); auto GPItem = m_GPItems[rank - 3]; int32 curPoints = charutils::GetVar(PChar, "[GUILD]daily_points"); if (curPoints == -1) { return std::make_pair(GPItem[0].item->getID(), 0); } else { return std::make_pair(GPItem[0].item->getID(), GPItem[0].maxpoints - curPoints); } }
CCharStatsPacket::CCharStatsPacket(CCharEntity * PChar) { this->type = 0x61; this->size = 0x30; WBUFL(data,(0x04)) = PChar->GetMaxHP(); WBUFL(data,(0x08)) = PChar->GetMaxMP(); WBUFB(data,(0x0C)) = PChar->GetMJob(); WBUFB(data,(0x0D)) = PChar->GetMLevel(); WBUFB(data,(0x0E)) = PChar->GetSJob(); WBUFB(data,(0x0F)) = PChar->GetSLevel(); WBUFW(data,(0x10)) = PChar->jobs.exp[PChar->GetMJob()]; WBUFW(data,(0x12)) = charutils::GetExpNEXTLevel(PChar->jobs.job[PChar->GetMJob()]); memcpy(data+(0x14), &PChar->stats, 14); // TODO: с merits это не прокатит WBUFW(data,(0x22)) = dsp_cap(PChar->getMod(MOD_STR), -999 + PChar->stats.STR, 999 - PChar->stats.STR); WBUFW(data,(0x24)) = dsp_cap(PChar->getMod(MOD_DEX), -999 + PChar->stats.DEX, 999 - PChar->stats.DEX); WBUFW(data,(0x26)) = dsp_cap(PChar->getMod(MOD_VIT), -999 + PChar->stats.VIT, 999 - PChar->stats.VIT); WBUFW(data,(0x28)) = dsp_cap(PChar->getMod(MOD_AGI), -999 + PChar->stats.AGI, 999 - PChar->stats.AGI); WBUFW(data,(0x2A)) = dsp_cap(PChar->getMod(MOD_INT), -999 + PChar->stats.INT, 999 - PChar->stats.INT); WBUFW(data,(0x2C)) = dsp_cap(PChar->getMod(MOD_MND), -999 + PChar->stats.MND, 999 - PChar->stats.MND); WBUFW(data,(0x2E)) = dsp_cap(PChar->getMod(MOD_CHR), -999 + PChar->stats.CHR, 999 - PChar->stats.CHR); WBUFW(data,(0x30)) = PChar->ATT(); WBUFW(data,(0x32)) = PChar->DEF(); WBUFW(data,(0x34)) = PChar->getMod(MOD_FIRERES); WBUFW(data,(0x36)) = PChar->getMod(MOD_ICERES); WBUFW(data,(0x38)) = PChar->getMod(MOD_WINDRES); WBUFW(data,(0x3A)) = PChar->getMod(MOD_EARTHRES); WBUFW(data,(0x3C)) = PChar->getMod(MOD_THUNDERRES); WBUFW(data,(0x3E)) = PChar->getMod(MOD_WATERRES); WBUFW(data,(0x40)) = PChar->getMod(MOD_LIGHTRES); WBUFW(data,(0x42)) = PChar->getMod(MOD_DARKRES); WBUFW(data,(0x44)) = PChar->profile.title; WBUFB(data,(0x46)) = PChar->profile.rank[PChar->profile.nation]; WBUFW(data,(0x48)) = PChar->profile.rankpoints; WBUFW(data,(0x4A)) = PChar->profile.home_point.destination; WBUFB(data,(0x50)) = PChar->profile.nation; //0x52 = superior level (1 or 2) //0x54 = maximum item level //0x55 = itemlevel over 99 //0x56 = main weapon item level }
uint16 CBattleEntity::addTP(float tp) { float TPMulti = 1.0; if(objtype == TYPE_PC) { TPMulti = map_config.player_tp_multiplier; } else if(objtype == TYPE_MOB) { TPMulti = map_config.mob_tp_multiplier; } else if(objtype == TYPE_PET) { TPMulti = map_config.mob_tp_multiplier * 3; } float cap = dsp_cap(health.tp + (tp * TPMulti), 0, 300); tp = health.tp - cap; health.tp = cap; return abs(tp); }
uint32 CTaskMgr::DoTimer(uint32 tick) { int32 diff = 1000; while( !m_TaskList.empty() ) { CTask * PTask = m_TaskList.top(); diff = PTask->m_tick - tick; if( diff > 0 ) break; // no more expired timers to process m_TaskList.pop(); if( PTask->m_func ) { PTask->m_func(( diff < -1000 ? tick : PTask->m_tick),PTask); } switch( PTask->m_type ) { case TASK_INTERVAL: { PTask->m_tick = PTask->m_interval + (diff < - 1000 ? tick : PTask->m_tick); m_TaskList.push(PTask); } break; case TASK_ONCE: case TASK_REMOVE: default: { delete PTask; // suppose that all tasks were allocated by new } break; } diff = dsp_cap(diff, 50, 1000); } return diff; }
/************************************************************************ * * * Creates zanshin attacks. * * * ************************************************************************/ void CAttackRound::CreateZanshinAttacks() { // Zanshin effects from gear, food or buffs do not require the job trait to be enabled. if (m_attacker->objtype == TYPE_PC && !m_zanshinOccured && !m_doubleAttackOccured && !m_tripleAttackOccured && !m_quadAttackOccured && m_attackSwings.at(0)->GetAttackType() != ZANSHIN_ATTACK) { uint8 zanshinChance = m_attacker->getMod(MOD_ZANSHIN) + ((CCharEntity*)m_attacker)->PMeritPoints->GetMeritValue(MERIT_ZASHIN_ATTACK_RATE, (CCharEntity*)m_attacker); zanshinChance = dsp_cap(zanshinChance, 0, 100); if (rand()%100 < zanshinChance) { // Flag this attack to repeat m_zanshinOccured = true; } else { m_zanshinOccured = false; } } }
/************************************************************************ * * * 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); }
uint32 CMagicState::CalculateRecastTime(CSpell* PSpell) { if(PSpell == NULL) { return 0; } bool applyArts = true; uint32 base = PSpell->getRecastTime(); uint32 recast = base; //apply Fast Cast recast *= ((100.0f-dsp_cap((float)m_PEntity->getMod(MOD_FASTCAST)/2.0f,0.0f,25.0f))/100.0f); int16 haste = m_PEntity->getMod(MOD_HASTE_MAGIC) + m_PEntity->getMod(MOD_HASTE_GEAR); recast *= ((float)(1024-haste)/1024); recast = dsp_max(recast, base * 0.2f); if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_COMPOSURE)) { recast *= 1.25; } if (PSpell->getSpellGroup() == SPELLGROUP_BLACK) { if (PSpell->getAOE() == SPELLAOE_RADIAL_MANI && m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_MANIFESTATION)) { if (m_PEntity->GetMJob() == JOB_SCH) { recast *= 2; } else { recast *= 3; } applyArts = false; } if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ALACRITY)) { uint16 bonus = 0; //Only apply Alacrity/celerity mod if the spell element matches the weather. if (battleutils::WeatherMatchesElement(battleutils::GetWeather(m_PEntity,false), PSpell->getElement())) { bonus = m_PEntity->getMod(MOD_ALACRITY_CELERITY_EFFECT); } recast *= ((50 - bonus) / 100.0f); applyArts = false; } if (applyArts) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_DARK_ARTS) || m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ADDENDUM_BLACK)) { // Add any "Grimoire: Reduces spellcasting time" bonuses recast *= (1.0f + (m_PEntity->getMod(MOD_BLACK_MAGIC_RECAST)+m_PEntity->getMod(MOD_GRIMOIRE_SPELLCASTING))/100.0f); } else { recast *= (1.0f + m_PEntity->getMod(MOD_BLACK_MAGIC_RECAST)/100.0f); } } } else if (PSpell->getSpellGroup() == SPELLGROUP_WHITE) { if (PSpell->getAOE() == SPELLAOE_RADIAL_ACCE && m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ACCESSION)) { if (m_PEntity->GetMJob() == JOB_SCH) { recast *= 2; } else { recast *= 3; } applyArts = false; } if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_CELERITY)) { uint16 bonus = 0; //Only apply Alacrity/celerity mod if the spell element matches the weather. if (battleutils::WeatherMatchesElement(battleutils::GetWeather(m_PEntity, true), PSpell->getElement())) { bonus = m_PEntity->getMod(MOD_ALACRITY_CELERITY_EFFECT); } recast *= ((50 - bonus) / 100.0f); applyArts = false; } if (applyArts) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_LIGHT_ARTS) || m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ADDENDUM_WHITE)) { // Add any "Grimoire: Reduces spellcasting time" bonuses recast *= (1.0f + (m_PEntity->getMod(MOD_WHITE_MAGIC_RECAST)+m_PEntity->getMod(MOD_GRIMOIRE_SPELLCASTING))/100.0f); } else { recast *= (1.0f + m_PEntity->getMod(MOD_WHITE_MAGIC_RECAST)/100.0f); } } } else if (PSpell->getSpellGroup() == SPELLGROUP_SONG) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_NIGHTINGALE)) { recast *= 0.5f; } } return recast; }
uint32 CMagicState::CalculateCastTime(CSpell* PSpell) { if(PSpell == NULL) { return 0; } bool applyArts = true; uint32 base = PSpell->getCastTime(); uint32 cast = base; if (PSpell->getSpellGroup() == SPELLGROUP_BLACK) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ALACRITY)) { uint16 bonus = 0; //Only apply Alacrity/celerity mod if the spell element matches the weather. if(battleutils::WeatherMatchesElement(battleutils::GetWeather(m_PEntity,false),PSpell->getElement())) { bonus = m_PEntity->getMod(MOD_ALACRITY_CELERITY_EFFECT); } cast -= base * ((100 - (50 + bonus)) / 100.0f); applyArts = false; } else if (applyArts) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_DARK_ARTS) || m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ADDENDUM_BLACK)) { // Add any "Grimoire: Reduces spellcasting time" bonuses cast = cast * (1.0f + (m_PEntity->getMod(MOD_BLACK_MAGIC_CAST)+m_PEntity->getMod(MOD_GRIMOIRE_SPELLCASTING))/100.0f); } else { cast = cast * (1.0f + m_PEntity->getMod(MOD_BLACK_MAGIC_CAST)/100.0f); } } } else if (PSpell->getSpellGroup() == SPELLGROUP_WHITE) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_CELERITY)) { uint16 bonus = 0; //Only apply Alacrity/celerity mod if the spell element matches the weather. if(battleutils::WeatherMatchesElement(battleutils::GetWeather(m_PEntity,false),PSpell->getElement())) { bonus = m_PEntity->getMod(MOD_ALACRITY_CELERITY_EFFECT); } cast -= base * ((100 - (50 + bonus)) / 100.0f); applyArts = false; } else if (applyArts) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_LIGHT_ARTS) || m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_ADDENDUM_WHITE)) { // Add any "Grimoire: Reduces spellcasting time" bonuses cast = cast * (1.0f + (m_PEntity->getMod(MOD_WHITE_MAGIC_CAST)+m_PEntity->getMod(MOD_GRIMOIRE_SPELLCASTING))/100.0f); } else { cast = cast * (1.0f + m_PEntity->getMod(MOD_WHITE_MAGIC_CAST)/100.0f); } } } else if (PSpell->getSpellGroup() == SPELLGROUP_SONG) { if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_PIANISSIMO)) { if (PSpell->getAOE() == SPELLAOE_PIANISSIMO) { cast = base / 2; } } if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_NIGHTINGALE)) { if (m_PEntity->objtype == TYPE_PC && rand() % 100 < ((CCharEntity*)m_PEntity)->PMeritPoints->GetMeritValue(MERIT_TROUBADOUR, (CCharEntity*)m_PEntity) - 25) { return 0; } cast = cast * 0.5f; } if (m_PEntity->StatusEffectContainer->HasStatusEffect(EFFECT_TROUBADOUR)) { cast = cast * 1.5f; } uint16 songcasting = m_PEntity->getMod(MOD_SONG_SPELLCASTING_TIME); cast = cast * (1.0f - ((songcasting > 50 ? 50 : songcasting) / 100.0f)); } int16 fastCast = dsp_cap(m_PEntity->getMod(MOD_FASTCAST),-100,50); int16 uncappedFastCast = dsp_cap(m_PEntity->getMod(MOD_UFASTCAST),-100,100); float sumFastCast = dsp_cap(fastCast + uncappedFastCast, -100, 100); return cast * ((100.0f - sumFastCast)/100.0f); }
/************************************************************************ * * * Creates up to many attacks for a particular hand. * * * ************************************************************************/ void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction) { uint8 num = 1; // Checking the players weapon hit count if (PWeapon->getReqLvl() <= m_attacker->GetMLevel()) { num = PWeapon->getHitCount(); } AddAttackSwing(ATTACK_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 (m_attacker->objtype == TYPE_PC) { 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(ATTACK_NORMAL, direction, shadows); } else if (num == 1 && dsprand::GetRandomNumber(100) < quadAttack) AddAttackSwing(QUAD_ATTACK, direction, 3); else if (num == 1 && dsprand::GetRandomNumber(100) < tripleAttack) AddAttackSwing(TRIPLE_ATTACK, direction, 2); else if (num == 1 && dsprand::GetRandomNumber(100) < doubleAttack) AddAttackSwing(DOUBLE_ATTACK, direction, 1); // Ammo extra swing - players only if (m_attacker->objtype == TYPE_PC && m_attacker->getMod(MOD_AMMO_SWING) > 0) { // Check for ammo CCharEntity* PChar = (CCharEntity*)m_attacker; CItemArmor* PAmmo = PChar->getEquip(SLOT_AMMO); uint8 slot = PChar->equip[SLOT_AMMO]; uint8 loc = PChar->equipLoc[SLOT_AMMO]; if (dsprand::GetRandomNumber(100) < m_attacker->getMod(MOD_AMMO_SWING)) { // Add swing, then subtract an ammo item, unequip if there's one left. AddAttackSwing(ATTACK_NORMAL, direction, 1); if (PAmmo->getQuantity() == 1) { charutils::UnequipItem(PChar, SLOT_AMMO); charutils::SaveCharEquip(PChar); } charutils::UpdateItem(PChar, loc, slot, -1); 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(ATTACK_NORMAL, RIGHTATTACK, 1); }
void LoadAvatarStats(CPetEntity* PChar) { // Объявление переменных, нужных для рассчета. float raceStat = 0; // конечное число HP для уровня на основе расы. float jobStat = 0; // конечное число HP для уровня на основе первичной профессии. float sJobStat = 0; // коенчное число HP для уровня на основе вторичной профессии. int32 bonusStat = 0; // бонусное число HP которое добавляется при соблюдении некоторых условий. int32 baseValueColumn = 0; // номер колонки с базовым количеством HP int32 scaleTo60Column = 1; // номер колонки с модификатором до 60 уровня int32 scaleOver30Column = 2; // номер колонки с модификатором после 30 уровня int32 scaleOver60Column = 3; // номер колонки с модификатором после 60 уровня int32 scaleOver75Column = 4; // номер колонки с модификатором после 75 уровня int32 scaleOver60 = 2; // номер колонки с модификатором для расчета MP после 60 уровня int32 scaleOver75 = 3; // номер колонки с модификатором для расчета Статов после 75-го уровня uint8 grade; uint8 mlvl = PChar->GetMLevel(); JOBTYPE mjob = PChar->GetMJob(); uint8 race = 3; //Tarutaru // Расчет прироста HP от main job int32 mainLevelOver30 = dsp_cap(mlvl - 30, 0, 30); // Расчет условия +1HP каждый лвл после 30 уровня int32 mainLevelUpTo60 = (mlvl < 60 ? mlvl - 1 : 59 ); // Первый режим рассчета до 60 уровня (Используется так же и для MP) int32 mainLevelOver60To75 = dsp_cap(mlvl - 60, 0, 15); // Второй режим расчета после 60 уровня int32 mainLevelOver75 = (mlvl < 75 ? 0 : mlvl - 75); // Третий режим расчета после 75 уровня //Расчет бонусного количества HP int32 mainLevelOver10 = (mlvl < 10 ? 0 : mlvl - 10); // +2HP на каждом уровне после 10 int32 mainLevelOver50andUnder60 = dsp_cap(mlvl - 50, 0, 10); // +2HP на каждом уровне в промежутке от 50 до 60 уровня int32 mainLevelOver60 = (mlvl < 60 ? 0 : mlvl - 60); // Расчет raceStat jobStat bonusStat sJobStat // Расчет по расе grade = grade::GetRaceGrades(race,0); raceStat = grade::GetHPScale(grade,baseValueColumn) + (grade::GetHPScale(grade,scaleTo60Column) * mainLevelUpTo60) + (grade::GetHPScale(grade,scaleOver30Column) * mainLevelOver30) + (grade::GetHPScale(grade,scaleOver60Column) * mainLevelOver60To75) + (grade::GetHPScale(grade,scaleOver75Column) * mainLevelOver75); // raceStat = (int32)(statScale[grade][baseValueColumn] + statScale[grade][scaleTo60Column] * (mlvl - 1)); // Расчет по main job grade = grade::GetJobGrade(mjob,0); jobStat = grade::GetHPScale(grade,baseValueColumn) + (grade::GetHPScale(grade,scaleTo60Column) * mainLevelUpTo60) + (grade::GetHPScale(grade,scaleOver30Column) * mainLevelOver30) + (grade::GetHPScale(grade,scaleOver60Column) * mainLevelOver60To75) + (grade::GetHPScale(grade,scaleOver75Column) * mainLevelOver75); // Расчет бонусных HP bonusStat = (mainLevelOver10 + mainLevelOver50andUnder60) * 2; PChar->health.maxhp = (int16)(raceStat + jobStat + bonusStat + sJobStat); PChar->health.hp = PChar->health.maxhp; //Начало расчера MP raceStat = 0; jobStat = 0; sJobStat = 0; // Расчет MP расе. grade = grade::GetRaceGrades(race,1); //Если у main job нет МП рейтинга, расчитиваем расовый бонус на основе уровня subjob уровня(при условии, что у него есть МП рейтинг) if (grade::GetJobGrade(mjob,1) == 0) { }else{ //Расчет нормального расового бонуса raceStat = grade::GetMPScale(grade,0) + grade::GetMPScale(grade,scaleTo60Column) * mainLevelUpTo60 + grade::GetMPScale(grade,scaleOver60) * mainLevelOver60; } //Для главной профессии grade = grade::GetJobGrade(mjob,1); if (grade > 0) { jobStat = grade::GetMPScale(grade,0) + grade::GetMPScale(grade,scaleTo60Column) * mainLevelUpTo60 + grade::GetMPScale(grade,scaleOver60) * mainLevelOver60; } PChar->health.maxmp = (int16)(raceStat + jobStat + sJobStat); // результат расчета MP //add in evasion from skill int16 evaskill = PChar->GetSkill(SKILL_EVA); int16 eva = evaskill; if(evaskill>200){ //Evasion skill is 0.9 evasion post-200 eva = 200 + (evaskill-200)*0.9; } PChar->setModifier(MOD_EVA,eva); //Начало расчета характеристик uint8 counter = 0; for (uint8 StatIndex = 2; StatIndex <=8; ++StatIndex) { // расчет по расе grade = grade::GetRaceGrades(race,StatIndex); raceStat = grade::GetStatScale(grade,0) + grade::GetStatScale(grade,scaleTo60Column) * mainLevelUpTo60; if (mainLevelOver60 > 0) { raceStat += grade::GetStatScale(grade,scaleOver60) * mainLevelOver60; if (mainLevelOver75 > 0) { raceStat += grade::GetStatScale(grade,scaleOver75) * mainLevelOver75 - (mlvl >= 75 ? 0.01f : 0); } } // расчет по профессии grade = grade::GetJobGrade(mjob,StatIndex); jobStat = grade::GetStatScale(grade,0) + grade::GetStatScale(grade,scaleTo60Column) * mainLevelUpTo60; if (mainLevelOver60 > 0) { jobStat += grade::GetStatScale(grade,scaleOver60) * mainLevelOver60; if (mainLevelOver75 > 0) { jobStat += grade::GetStatScale(grade,scaleOver75) * mainLevelOver75 - (mlvl >= 75 ? 0.01f : 0); } } jobStat = jobStat * 1.5; //stats from subjob (assuming BLM/BLM for avatars) // Вывод значения WBUFW(&PChar->stats,counter) = (uint16)(raceStat + jobStat); counter += 2; } }
void CEnmityContainer::UpdateEnmity(CBattleEntity* PEntity, int16 CE, int16 VE, bool withMaster) { // you're too far away so i'm ignoring you if(!IsWithinEnmityRange(PEntity)) { CE = 0; VE = 0; } // Crash fix, PEntity was in ACTION_FALL if (PEntity->PBattleAI->GetCurrentAction() == ACTION_FALL) return; EnmityList_t::iterator PEnmity = m_EnmityList.lower_bound(PEntity->id); // current highest enmity before this update CBattleEntity* OldEntity = GetHighestEnmity(); if( PEnmity != m_EnmityList.end() && !m_EnmityList.key_comp()(PEntity->id, PEnmity->first)) { int8 enmityBonus = 0; if (PEntity->objtype & TYPE_PC) { enmityBonus = ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_INCREASE, (CCharEntity*)PEntity) - ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_DECREASE, (CCharEntity*)PEntity); } float bonus = (100.0f + dsp_cap(PEntity->getMod(MOD_ENMITY)+enmityBonus, -50, 100)) / 100.0f; PEnmity->second->CE += CE * bonus; PEnmity->second->VE += VE * bonus; //Check for cap limit PEnmity->second->CE = dsp_cap(PEnmity->second->CE, 1, 10000); PEnmity->second->VE = dsp_cap(PEnmity->second->VE, 1, 10000); } else { EnmityObject_t* PEnmityObject = new EnmityObject_t; int8 enmityBonus = 0; if (PEntity->objtype & TYPE_PC) { enmityBonus = ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_INCREASE, (CCharEntity*)PEntity) - ((CCharEntity*)PEntity)->PMeritPoints->GetMeritValue(MERIT_ENMITY_DECREASE, (CCharEntity*)PEntity); } float bonus = (100.0f + dsp_cap(PEntity->getMod(MOD_ENMITY)+enmityBonus, -50, 100)) / 100.0f; PEnmityObject->CE = CE * bonus; PEnmityObject->VE = VE * bonus; PEnmityObject->PEnmityOwner = PEntity; m_EnmityList.insert(PEnmity, EnmityList_t::value_type(PEntity->id, PEnmityObject)); if(withMaster && PEntity->PMaster != NULL) { //add master to the enmity list //add master to the enmity list (charmed mob) if(PEntity->objtype == TYPE_PET || PEntity->objtype == TYPE_MOB && PEntity->PMaster!=NULL && PEntity->PMaster->objtype == TYPE_PC) { UpdateEnmity(PEntity->PMaster, 0, 0); } } } }
void CCharEntity::SetName(int8* name) { this->name.insert(0, name, dsp_cap(strlen((const int8*)name), 0, 15)); }
int32 map_config_read(const int8* cfgName) { int8 line[1024], w1[1024], w2[1024]; FILE* fp; fp = fopen(cfgName, "r"); if (fp == nullptr) { ShowError("Map configuration file not found at: %s\n", cfgName); return 1; } while (fgets(line, sizeof(line), fp)) { int8* ptr; if (line[0] == '#') { continue; } if (sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2) { continue; } //Strip trailing spaces ptr = w2 + strlen(w2); while (--ptr >= w2 && *ptr == ' '); ptr++; *ptr = '\0'; if (strcmpi(w1, "timestamp_format") == 0) { strncpy(timestamp_format, w2, 20); } else if (strcmpi(w1, "stdout_with_ansisequence") == 0) { stdout_with_ansisequence = config_switch(w2); } else if (strcmpi(w1, "console_silent") == 0) { ShowInfo("Console Silent Setting: %d", atoi(w2)); msg_silent = atoi(w2); } else if (strcmpi(w1, "map_port") == 0) { map_config.usMapPort = (atoi(w2)); } else if (strcmp(w1, "buff_maxsize") == 0) { map_config.buffer_size = atoi(w2); } else if (strcmp(w1, "max_time_lastupdate") == 0) { map_config.max_time_lastupdate = atoi(w2); } else if (strcmp(w1, "vanadiel_time_offset") == 0) { map_config.vanadiel_time_offset = atoi(w2); } else if (strcmp(w1, "lightluggage_block") == 0) { map_config.lightluggage_block = atoi(w2); } else if (strcmp(w1, "exp_rate") == 0) { map_config.exp_rate = atof(w2); } else if (strcmp(w1, "exp_loss_rate") == 0) { map_config.exp_loss_rate = atof(w2); } else if (strcmp(w1, "exp_party_gap_penalties") == 0) { map_config.exp_party_gap_penalties = atof(w2); } else if (strcmp(w1, "fov_party_gap_penalties") == 0) { map_config.fov_party_gap_penalties = atof(w2); } else if (strcmp(w1, "fov_allow_alliance") == 0) { map_config.fov_allow_alliance = atof(w2); } else if (strcmp(w1, "mob_tp_multiplier") == 0) { map_config.mob_tp_multiplier = atof(w2); } else if (strcmp(w1, "player_tp_multiplier") == 0) { map_config.player_tp_multiplier = atof(w2); } else if (strcmp(w1, "nm_hp_multiplier") == 0) { map_config.nm_hp_multiplier = atof(w2); } else if (strcmp(w1, "mob_hp_multiplier") == 0) { map_config.mob_hp_multiplier = atof(w2); } else if (strcmp(w1, "player_hp_multiplier") == 0) { map_config.player_hp_multiplier = atof(w2); } else if (strcmp(w1, "nm_mp_multiplier") == 0) { map_config.nm_mp_multiplier = atof(w2); } else if (strcmp(w1, "mob_mp_multiplier") == 0) { map_config.mob_mp_multiplier = atof(w2); } else if (strcmp(w1, "player_mp_multiplier") == 0) { map_config.player_mp_multiplier = atof(w2); } else if (strcmp(w1, "sj_mp_divisor") == 0) { map_config.sj_mp_divisor = atof(w2); } else if (strcmp(w1, "nm_stat_multiplier") == 0) { map_config.nm_stat_multiplier = atof(w2); } else if (strcmp(w1, "mob_stat_multiplier") == 0) { map_config.mob_stat_multiplier = atof(w2); } else if (strcmp(w1, "player_stat_multiplier") == 0) { map_config.player_stat_multiplier = atof(w2); } else if (strcmp(w1, "drop_rate_multiplier") == 0) { map_config.drop_rate_multiplier = atof(w2); } else if (strcmp(w1, "all_mobs_gil_bonus") == 0) { map_config.all_mobs_gil_bonus = atoi(w2); } else if (strcmp(w1, "max_gil_bonus") == 0) { map_config.max_gil_bonus = atoi(w2); } else if (strcmp(w1, "exp_retain") == 0) { map_config.exp_retain = dsp_cap(atof(w2), 0.0f, 1.0f); } else if (strcmp(w1, "exp_loss_level") == 0) { map_config.exp_loss_level = atoi(w2); } else if (strcmp(w1, "level_sync_enable") == 0) { map_config.level_sync_enable = atoi(w2); } else if (strcmp(w1, "all_jobs_widescan") == 0) { map_config.all_jobs_widescan = atoi(w2); } else if (strcmp(w1, "speed_mod") == 0) { map_config.speed_mod = atoi(w2); } else if (strcmp(w1, "mob_speed_mod") == 0) { map_config.mob_speed_mod = atoi(w2); } else if (strcmp(w1, "skillup_chance_multiplier") == 0) { map_config.skillup_chance_multiplier = atof(w2); } else if (strcmp(w1, "craft_chance_multiplier") == 0) { map_config.craft_chance_multiplier = atof(w2); } else if (strcmp(w1, "skillup_amount_multiplier") == 0) { map_config.skillup_amount_multiplier = atof(w2); } else if (strcmp(w1, "craft_amount_multiplier") == 0) { map_config.craft_amount_multiplier = atof(w2); } else if (strcmp(w1, "craft_day_matters") == 0) { map_config.craft_day_matters = atof(w2); } else if (strcmp(w1, "craft_moonphase_matters") == 0) { map_config.craft_moonphase_matters = atof(w2); } else if (strcmp(w1, "craft_direction_matters") == 0) { map_config.craft_direction_matters = atof(w2); } else if (strcmp(w1, "mysql_host") == 0) { map_config.mysql_host = aStrdup(w2); } else if (strcmp(w1, "mysql_login") == 0) { map_config.mysql_login = aStrdup(w2); } else if (strcmp(w1, "mysql_password") == 0) { map_config.mysql_password = aStrdup(w2); } else if (strcmp(w1, "mysql_port") == 0) { map_config.mysql_port = atoi(w2); } else if (strcmp(w1, "mysql_database") == 0) { map_config.mysql_database = aStrdup(w2); } else if (strcmpi(w1, "import") == 0) { map_config_read(w2); } else if (strcmpi(w1, "newstyle_skillups") == 0) { map_config.newstyle_skillups = atoi(w2); } else if (strcmp(w1, "Battle_cap_tweak") == 0) { map_config.Battle_cap_tweak = atoi(w2); } else if (strcmp(w1, "CoP_Battle_cap") == 0) { map_config.CoP_Battle_cap = atoi(w2); } else if (strcmp(w1, "max_merit_points") == 0) { map_config.max_merit_points = atoi(w2); } else if (strcmp(w1, "yell_cooldown") == 0) { map_config.yell_cooldown = atoi(w2); } else if (strcmp(w1, "audit_chat") == 0) { map_config.audit_chat = atoi(w2); } else if (strcmp(w1, "audit_say") == 0) { map_config.audit_say = atoi(w2); } else if (strcmp(w1, "audit_shout") == 0) { map_config.audit_shout = atoi(w2); } else if (strcmp(w1, "audit_tell") == 0) { map_config.audit_tell = atoi(w2); } else if (strcmp(w1, "audit_yell") == 0) { map_config.audit_yell = atoi(w2); } else if (strcmp(w1, "audit_linkshell") == 0) { map_config.audit_linkshell = atoi(w2); } else if (strcmp(w1, "audit_party") == 0) { map_config.audit_party = atoi(w2); } else if (strcmp(w1, "msg_server_port") == 0) { map_config.msg_server_port = atoi(w2); } else if (strcmp(w1, "msg_server_ip") == 0) { map_config.msg_server_ip = aStrdup(w2); } else { ShowWarning(CL_YELLOW"Unknown setting '%s' in file %s\n" CL_RESET, w1, cfgName); } } fclose(fp); // Load the English server message.. fp = fopen("./conf/server_message.conf", "rb"); if (fp == nullptr) { ShowError("Could not read English server message from: ./conf/server_message.conf\n"); return 1; } while (fgets(line, sizeof(line), fp)) { string_t sline(line); map_config.server_message += sline; } fclose(fp); // Load the French server message.. fp = fopen("./conf/server_message_fr.conf", "rb"); if (fp == nullptr) { ShowError("Could not read English server message from: ./conf/server_message_fr.conf\n"); return 1; } while (fgets(line, sizeof(line), fp)) { string_t sline(line); map_config.server_message_fr += sline; } fclose(fp); // Ensure both messages have nullptr terminates.. if (map_config.server_message.at(map_config.server_message.length() - 1) != 0x00) { map_config.server_message += (char)0x00; } if (map_config.server_message_fr.at(map_config.server_message_fr.length() - 1) != 0x00) { map_config.server_message_fr += (char)0x00; } return 0; }