Beispiel #1
0
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);
            }
        }
    }
}
Beispiel #2
0
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));
        }
    }
}
Beispiel #3
0
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);
}
Beispiel #4
0
/************************************************************************
*                                                                       *
*  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);
	}
}
Beispiel #5
0
int32 CBattleEntity::addMP(int32 mp)
{
    int32 cap = dsp_cap(health.mp + mp, 0, GetMaxMP());
    mp = health.mp - cap;
    health.mp = cap;
    return abs(mp);
}
Beispiel #6
0
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);
}
Beispiel #7
0
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;
}
Beispiel #8
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
/************************************************************************
*                                                                       *
*  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);
        }
    }
}
Beispiel #11
0
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));
        }
    }
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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 });
}
Beispiel #16
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);
    }
}
Beispiel #17
0
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);
}
Beispiel #18
0
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);
    }
}
Beispiel #19
0
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
}
Beispiel #20
0
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);
}
Beispiel #21
0
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;
}
Beispiel #22
0
/************************************************************************
*                                                                       *
*  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;
		}
	}
}
Beispiel #23
0
/************************************************************************
*                                                                       *
*  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);

}
Beispiel #24
0
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;
}
Beispiel #25
0
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);
}
Beispiel #26
0
/************************************************************************
*                                                                       *
*  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);

}
Beispiel #27
0
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));
}
Beispiel #30
0
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;
}