mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-26 06:27:45 +00:00
Merge pull request #65 from itsmaru/master
Basic battle-related calculation class; Cast interrupt;
This commit is contained in:
commit
488070a53f
19 changed files with 287 additions and 93 deletions
|
@ -10,7 +10,7 @@ class skillDef_119Def
|
||||||
|
|
||||||
def onFinish( player, target )
|
def onFinish( player, target )
|
||||||
{
|
{
|
||||||
player.handleScriptSkill( STD_DAMAGE, 119, 30, 0, target );
|
player.handleScriptSkill( STD_DAMAGE, 119, 140, 0, target );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
// Skill Name: Sprint
|
// Skill Name: Cure
|
||||||
// Skill ID: 3
|
// Skill ID: 120
|
||||||
|
|
||||||
class skillDef_120Def
|
class skillDef_120Def
|
||||||
{
|
{
|
||||||
|
@ -10,7 +10,7 @@ class skillDef_120Def
|
||||||
|
|
||||||
def onFinish( player, target )
|
def onFinish( player, target )
|
||||||
{
|
{
|
||||||
player.handleScriptSkill( STD_HEAL, 120, 1000, 0, target );
|
player.handleScriptSkill( STD_HEAL, 120, 450, 0, target );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
// Skill Name: Sprint
|
// Skill Name: Aero
|
||||||
// Skill ID: 3
|
// Skill ID: 121
|
||||||
|
|
||||||
class skillDef_121Def
|
class skillDef_121Def
|
||||||
{
|
{
|
|
@ -1,5 +1,5 @@
|
||||||
// Skill Name: Sprint
|
// Skill Name: Stone II
|
||||||
// Skill ID: 3
|
// Skill ID: 127
|
||||||
|
|
||||||
class skillDef_127Def
|
class skillDef_127Def
|
||||||
{
|
{
|
||||||
|
@ -10,7 +10,7 @@ class skillDef_127Def
|
||||||
|
|
||||||
def onFinish( player, target )
|
def onFinish( player, target )
|
||||||
{
|
{
|
||||||
player.handleScriptSkill( STD_DAMAGE, 127, 1000, 0, target );
|
player.handleScriptSkill( STD_DAMAGE, 127, 200, 0, target );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
18
bin/scripts/chai/skill/cnj/skillDef_128.chai
Normal file
18
bin/scripts/chai/skill/cnj/skillDef_128.chai
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Skill Name: Repose
|
||||||
|
// Skill ID: 128
|
||||||
|
|
||||||
|
class skillDef_128Def
|
||||||
|
{
|
||||||
|
def skillDef_128Def()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def onFinish( player, target )
|
||||||
|
{
|
||||||
|
target.addStatusEffectByIdIfNotExist(3, 30000, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL skillDef_128 = skillDef_128Def();
|
18
bin/scripts/chai/skill/pgl/skillDef_53.chai
Normal file
18
bin/scripts/chai/skill/pgl/skillDef_53.chai
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Skill Name: Bootshine
|
||||||
|
// Skill ID: 53
|
||||||
|
|
||||||
|
class skillDef_53Def
|
||||||
|
{
|
||||||
|
def skillDef_53Def()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def onFinish( player, target )
|
||||||
|
{
|
||||||
|
player.handleScriptSkill( STD_DAMAGE, 53, 140, 0, target );
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL skillDef_53 = skillDef_53Def();
|
|
@ -1,5 +1,5 @@
|
||||||
// Skill Name: Sprint
|
// Skill Name: Return
|
||||||
// Skill ID: 3
|
// Skill ID: 6
|
||||||
|
|
||||||
class skillDef_6Def
|
class skillDef_6Def
|
||||||
{
|
{
|
||||||
|
|
|
@ -253,13 +253,13 @@ namespace Core {
|
||||||
JOB_WARRIOR = 21, // warrior
|
JOB_WARRIOR = 21, // warrior
|
||||||
JOB_DRAGON = 22, // dragoon
|
JOB_DRAGON = 22, // dragoon
|
||||||
JOB_BARD = 23, // bard
|
JOB_BARD = 23, // bard
|
||||||
JOB_WHITE = 24, // white mage
|
JOB_WHITEMAGE = 24, // white mage
|
||||||
JOB_BLACK = 25, // black mage
|
JOB_BLACKMAGE = 25, // black mage
|
||||||
CLASS_ARCANIST = 26, // arcanist
|
CLASS_ARCANIST = 26, // arcanist
|
||||||
JOB_SUMMONER = 27, // summoner
|
JOB_SUMMONER = 27, // summoner
|
||||||
JOB_SCHOLAR = 28, // scholar
|
JOB_SCHOLAR = 28, // scholar
|
||||||
CLASS_ROGUE = 29,
|
CLASS_ROGUE = 29, // rogue
|
||||||
JOB_NINJA = 30,
|
JOB_NINJA = 30, // ninja
|
||||||
JOB_MACHINIST = 31, // machinist
|
JOB_MACHINIST = 31, // machinist
|
||||||
JOB_DARKKNIGHT = 32, // darknight
|
JOB_DARKKNIGHT = 32, // darknight
|
||||||
JOB_ASTROLOGIAN = 33, // astro
|
JOB_ASTROLOGIAN = 33, // astro
|
||||||
|
|
|
@ -236,11 +236,11 @@ bool Core::Data::ExdData::loadParamGrowInfo()
|
||||||
uint32_t id = row.first;
|
uint32_t id = row.first;
|
||||||
info.level = id;
|
info.level = id;
|
||||||
info.needed_exp = getField< int32_t >( fields, 0 );
|
info.needed_exp = getField< int32_t >( fields, 0 );
|
||||||
info.piety_scalar = getField< uint16_t >( fields, 3 ); // 3
|
info.mp_mod = getField< uint16_t >( fields, 3 ); // 3
|
||||||
info.mp_const = getField< int32_t >( fields, 4 ); // 4
|
info.mp_const = getField< int32_t >( fields, 4 ); // 4
|
||||||
info.base_secondary = getField< int32_t >( fields, 5 );// 5
|
info.base_secondary = getField< int32_t >( fields, 5 );// 5
|
||||||
info.hp_mod = getField< uint16_t >( fields, 8 ); // 8
|
|
||||||
info.quest_exp_mod = getField< uint8_t >( fields, 7 ); // 7
|
info.quest_exp_mod = getField< uint8_t >( fields, 7 ); // 7
|
||||||
|
info.hp_mod = getField< uint16_t >(fields, 8); // 8
|
||||||
|
|
||||||
|
|
||||||
m_paramGrowthInfoMap[id] = info;
|
m_paramGrowthInfoMap[id] = info;
|
||||||
|
@ -426,6 +426,7 @@ boost::shared_ptr< Core::Data::ItemInfo >
|
||||||
info->model_primary = getField< uint64_t >( row, 45 );
|
info->model_primary = getField< uint64_t >( row, 45 );
|
||||||
info->model_secondary = getField< uint64_t >( row, 46 );
|
info->model_secondary = getField< uint64_t >( row, 46 );
|
||||||
info->physical_damage = getField< uint16_t >( row, 49 );
|
info->physical_damage = getField< uint16_t >( row, 49 );
|
||||||
|
info->magical_damage = getField< uint16_t >( row, 50 );
|
||||||
info->delayMs = getField< uint16_t >( row, 51 );
|
info->delayMs = getField< uint16_t >( row, 51 );
|
||||||
info->is_unique = getField< int16_t >( row, 64 ) != 0 ? true : false;
|
info->is_unique = getField< int16_t >( row, 64 ) != 0 ? true : false;
|
||||||
info->is_untradeable = getField< uint8_t >( row, 65 ) != 0 ? true : false;
|
info->is_untradeable = getField< uint8_t >( row, 65 ) != 0 ? true : false;
|
||||||
|
|
|
@ -116,7 +116,7 @@ namespace Core {
|
||||||
uint32_t needed_exp;
|
uint32_t needed_exp;
|
||||||
int16_t hp_mod;
|
int16_t hp_mod;
|
||||||
int32_t mp_const;
|
int32_t mp_const;
|
||||||
int16_t piety_scalar;
|
int16_t mp_mod;
|
||||||
int32_t base_secondary;
|
int32_t base_secondary;
|
||||||
uint16_t quest_exp_mod;
|
uint16_t quest_exp_mod;
|
||||||
};
|
};
|
||||||
|
@ -211,8 +211,9 @@ namespace Core {
|
||||||
uint64_t model_primary; //28
|
uint64_t model_primary; //28
|
||||||
uint64_t model_secondary; //29
|
uint64_t model_secondary; //29
|
||||||
uint16_t physical_damage; //49
|
uint16_t physical_damage; //49
|
||||||
|
uint16_t magical_damage; //50
|
||||||
|
uint16_t delayMs; //51
|
||||||
uint32_t class_job_requirement; //58
|
uint32_t class_job_requirement; //58
|
||||||
uint16_t delayMs; //59
|
|
||||||
bool is_unique; //72
|
bool is_unique; //72
|
||||||
bool is_untradeable; //73
|
bool is_untradeable; //73
|
||||||
uint32_t class_job_index; //86
|
uint32_t class_job_index; //86
|
||||||
|
|
|
@ -79,6 +79,12 @@ Core::Entity::Actor::Stance Core::Entity::Actor::getStance() const
|
||||||
return m_currentStance;
|
return m_currentStance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \return actor stats */
|
||||||
|
Core::Entity::Actor::ActorStats Core::Entity::Actor::getStats() const
|
||||||
|
{
|
||||||
|
return m_baseStats;
|
||||||
|
}
|
||||||
|
|
||||||
/*! \return current HP */
|
/*! \return current HP */
|
||||||
uint32_t Core::Entity::Actor::getHp() const
|
uint32_t Core::Entity::Actor::getHp() const
|
||||||
{
|
{
|
||||||
|
@ -207,11 +213,8 @@ void Core::Entity::Actor::die()
|
||||||
// fire onDeath event
|
// fire onDeath event
|
||||||
onDeath();
|
onDeath();
|
||||||
|
|
||||||
bool selfNeedsUpdate = false;
|
|
||||||
|
|
||||||
// if the actor is a player, the update needs to be send to himself too
|
// if the actor is a player, the update needs to be send to himself too
|
||||||
if( isPlayer() )
|
bool selfNeedsUpdate = isPlayer();
|
||||||
selfNeedsUpdate = true;
|
|
||||||
|
|
||||||
sendToInRangeSet( ActorControlPacket142( m_id, SetStatus, static_cast< uint8_t>( ActorStatus::Dead ) ), selfNeedsUpdate );
|
sendToInRangeSet( ActorControlPacket142( m_id, SetStatus, static_cast< uint8_t>( ActorStatus::Dead ) ), selfNeedsUpdate );
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,51 @@ public:
|
||||||
SMachine = 0x08
|
SMachine = 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ActorStats
|
||||||
|
{
|
||||||
|
uint32_t max_mp = 0;
|
||||||
|
uint32_t max_hp = 0;
|
||||||
|
|
||||||
|
uint32_t str = 0;
|
||||||
|
uint32_t dex = 0;
|
||||||
|
uint32_t vit = 0;
|
||||||
|
uint32_t inte = 0;
|
||||||
|
uint32_t mnd = 0;
|
||||||
|
uint32_t pie = 0;
|
||||||
|
|
||||||
|
uint32_t parry = 0;
|
||||||
|
uint32_t attack = 0;
|
||||||
|
uint32_t defense = 0;
|
||||||
|
uint32_t accuracy = 0;
|
||||||
|
uint32_t spellSpeed = 0;
|
||||||
|
uint32_t magicDefense = 0;
|
||||||
|
uint32_t critHitRate = 0;
|
||||||
|
uint32_t resistSlash = 0;
|
||||||
|
uint32_t resistPierce = 0;
|
||||||
|
uint32_t resistBlunt = 0;
|
||||||
|
uint32_t attackPotMagic = 0;
|
||||||
|
uint32_t healingPotMagic = 0;
|
||||||
|
uint32_t determination = 0;
|
||||||
|
uint32_t skillSpeed = 0;
|
||||||
|
|
||||||
|
uint32_t resistSlow = 0;
|
||||||
|
uint32_t resistSilence = 0;
|
||||||
|
uint32_t resistBlind = 0;
|
||||||
|
uint32_t resistPoison = 0;
|
||||||
|
uint32_t resistStun = 0;
|
||||||
|
uint32_t resistSleep = 0;
|
||||||
|
uint32_t resistBind = 0;
|
||||||
|
uint32_t resistHeavy = 0;
|
||||||
|
|
||||||
|
uint32_t resistFire = 0;
|
||||||
|
uint32_t resistIce = 0;
|
||||||
|
uint32_t resistWind = 0;
|
||||||
|
uint32_t resistEarth = 0;
|
||||||
|
uint32_t resistLightning = 0;
|
||||||
|
uint32_t resistWater = 0;
|
||||||
|
|
||||||
|
} m_baseStats;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// TODO: The position class should probably be abolished and
|
// TODO: The position class should probably be abolished and
|
||||||
// the FFXIV_POS struct used instead ( the functions in there
|
// the FFXIV_POS struct used instead ( the functions in there
|
||||||
|
@ -106,51 +151,6 @@ protected:
|
||||||
/*! Container for status effects */
|
/*! Container for status effects */
|
||||||
StatusEffect::StatusEffectContainerPtr m_pStatusEffectContainer;
|
StatusEffect::StatusEffectContainerPtr m_pStatusEffectContainer;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t max_mp = 0;
|
|
||||||
uint32_t max_hp = 0;
|
|
||||||
|
|
||||||
uint32_t str = 0;
|
|
||||||
uint32_t dex = 0;
|
|
||||||
uint32_t vit = 0;
|
|
||||||
uint32_t inte = 0;
|
|
||||||
uint32_t mnd = 0;
|
|
||||||
uint32_t pie = 0;
|
|
||||||
|
|
||||||
uint32_t parry = 0;
|
|
||||||
uint32_t attack = 0;
|
|
||||||
uint32_t defense = 0;
|
|
||||||
uint32_t accuracy = 0;
|
|
||||||
uint32_t spellSpeed = 0;
|
|
||||||
uint32_t magicDefense = 0;
|
|
||||||
uint32_t critHitRate = 0;
|
|
||||||
uint32_t resistSlash = 0;
|
|
||||||
uint32_t resistPierce = 0;
|
|
||||||
uint32_t resistBlunt = 0;
|
|
||||||
uint32_t attackPotMagic = 0;
|
|
||||||
uint32_t healingPotMagic = 0;
|
|
||||||
uint32_t determination = 0;
|
|
||||||
uint32_t skillSpeed = 0;
|
|
||||||
|
|
||||||
uint32_t resistSlow = 0;
|
|
||||||
uint32_t resistSilence = 0;
|
|
||||||
uint32_t resistBlind = 0;
|
|
||||||
uint32_t resistPoison = 0;
|
|
||||||
uint32_t resistStun = 0;
|
|
||||||
uint32_t resistSleep = 0;
|
|
||||||
uint32_t resistBind = 0;
|
|
||||||
uint32_t resistHeavy = 0;
|
|
||||||
|
|
||||||
uint32_t resistFire = 0;
|
|
||||||
uint32_t resistIce = 0;
|
|
||||||
uint32_t resistWind = 0;
|
|
||||||
uint32_t resistEarth = 0;
|
|
||||||
uint32_t resistLightning = 0;
|
|
||||||
uint32_t resistWater = 0;
|
|
||||||
|
|
||||||
} m_baseStats;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Actor();
|
Actor();
|
||||||
|
|
||||||
|
@ -189,6 +189,8 @@ public:
|
||||||
|
|
||||||
void setStance( Stance stance );
|
void setStance( Stance stance );
|
||||||
|
|
||||||
|
ActorStats getStats() const;
|
||||||
|
|
||||||
uint32_t getHp() const;
|
uint32_t getHp() const;
|
||||||
|
|
||||||
uint32_t getMp() const;
|
uint32_t getMp() const;
|
||||||
|
|
107
src/servers/Server_Zone/Actor/CalcBattle.cpp
Normal file
107
src/servers/Server_Zone/Actor/CalcBattle.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#include <src/servers/Server_Common/Exd/ExdData.h>
|
||||||
|
|
||||||
|
#include "CalcBattle.h"
|
||||||
|
#include "Actor.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
using namespace Core::Entity;
|
||||||
|
|
||||||
|
extern Core::Data::ExdData g_exdData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Class used for battle-related formulas and calculations.
|
||||||
|
Big thanks to the Theoryjerks group!
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
Formulas here shouldn't be considered final. It's possible that the formula it was based on is correct but
|
||||||
|
wasn't implemented correctly here, or approximated things due to limited knowledge of how things work in retail.
|
||||||
|
It's also possible that we're using formulas that were correct for previous patches, but not the current version.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
Base HP val modifier. I can only find values for levels 50~70.
|
||||||
|
Attack power (and healing power). Need more researchg on this.
|
||||||
|
Damage outgoing calculations. This includes auto-attacks, etc.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Don't know too much about this formula, but seems to work for some of the levels tested.
|
||||||
|
// Originally from Player.cpp, calculateStats().
|
||||||
|
|
||||||
|
uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer )
|
||||||
|
{
|
||||||
|
float base = 0.0f;
|
||||||
|
uint8_t level = pPlayer->getLevel();
|
||||||
|
|
||||||
|
if (level < 51)
|
||||||
|
base = static_cast<uint32_t>( 0.053f * ( level * level ) + (1.022f * level) - 0.907f + 20 );
|
||||||
|
else
|
||||||
|
base = static_cast<uint32_t>( 1.627f * level + 120.773f );
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leggerless' HP Formula
|
||||||
|
// ROUNDDOWN(JobModHP * (BaseHP / 100)) + ROUNDDOWN(VitHPMod / 100 * (VIT - BaseDET))
|
||||||
|
|
||||||
|
uint32_t CalcBattle::calculateMaxHp( PlayerPtr pPlayer )
|
||||||
|
{
|
||||||
|
// TODO: Replace ApproxBaseHP with something that can get us a BaseHP reliably.
|
||||||
|
// Is there any way to pull BaseHP without having to manually use a pet for every level, and using the values from a table?
|
||||||
|
|
||||||
|
auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
|
||||||
|
auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );
|
||||||
|
|
||||||
|
float baseStat = calculateBaseStat( pPlayer );
|
||||||
|
uint16_t vit = pPlayer->getStats().vit;
|
||||||
|
uint16_t hp_mod = paramGrowthInfoIt->second.hp_mod;
|
||||||
|
uint16_t jobModHp = classInfoIt->second.mod_hp;
|
||||||
|
uint16_t approxBaseHp = 0; // Read above
|
||||||
|
|
||||||
|
// These values are not precise.
|
||||||
|
if ( pPlayer->getLevel() > 50 )
|
||||||
|
approxBaseHp = 0.1452f * paramGrowthInfoIt->second.mp_const + 1356.6f;
|
||||||
|
else
|
||||||
|
approxBaseHp = paramGrowthInfoIt->second.mp_const * 0.525f;
|
||||||
|
|
||||||
|
uint16_t result = floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hp_mod / 100.0f * ( vit - baseStat ) );
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leggerless' MP Formula
|
||||||
|
// ROUNDDOWN(((ROUNDDOWN(((PIE - BaseDET) * PieMPMod/100),0) + BaseMP) * JobModMP / 100),0)
|
||||||
|
|
||||||
|
uint32_t CalcBattle::calculateMaxMp( PlayerPtr pPlayer )
|
||||||
|
{
|
||||||
|
auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
|
||||||
|
auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );
|
||||||
|
|
||||||
|
float baseStat = calculateBaseStat( pPlayer );
|
||||||
|
uint16_t piety = pPlayer->getStats().pie;
|
||||||
|
uint16_t piety_scalar = paramGrowthInfoIt->second.mp_mod;
|
||||||
|
uint16_t jobModMp = classInfoIt->second.mod_mpcpgp;
|
||||||
|
uint16_t baseMp = paramGrowthInfoIt->second.mp_const;
|
||||||
|
|
||||||
|
uint16_t result = floor( floor( piety - baseStat ) * ( piety_scalar / 100 ) + baseMp ) * jobModMp / 100;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t CalcBattle::calculateHealValue( PlayerPtr pPlayer, uint32_t potency )
|
||||||
|
{
|
||||||
|
auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
|
||||||
|
auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );
|
||||||
|
|
||||||
|
if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
|
||||||
|
paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
auto jobModVal = classInfoIt->second;
|
||||||
|
|
||||||
|
// consider 3% variation
|
||||||
|
return potency / 10;
|
||||||
|
}
|
27
src/servers/Server_Zone/Actor/CalcBattle.h
Normal file
27
src/servers/Server_Zone/Actor/CalcBattle.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef _CALCBATTLE_H
|
||||||
|
#define _CALCBATTLE_H
|
||||||
|
|
||||||
|
#include <src/servers/Server_Common/Common.h>
|
||||||
|
|
||||||
|
#include "Actor.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
namespace Entity {
|
||||||
|
|
||||||
|
class CalcBattle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static uint32_t calculateBaseStat( PlayerPtr pPlayer );
|
||||||
|
static uint32_t calculateMaxMp( PlayerPtr pPlayer );
|
||||||
|
static uint32_t calculateMaxHp( PlayerPtr pPlayer );
|
||||||
|
static uint32_t calculateHealValue( PlayerPtr pPlayer, uint32_t potency );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -44,6 +44,7 @@
|
||||||
#include "src/servers/Server_Zone/Action/EventAction.h"
|
#include "src/servers/Server_Zone/Action/EventAction.h"
|
||||||
#include "src/servers/Server_Zone/Action/EventItemAction.h"
|
#include "src/servers/Server_Zone/Action/EventItemAction.h"
|
||||||
#include "src/servers/Server_Zone/Zone/ZonePosition.h"
|
#include "src/servers/Server_Zone/Zone/ZonePosition.h"
|
||||||
|
#include "src/servers/Server_Zone/Actor/CalcBattle.h"
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
extern Core::Logger g_log;
|
extern Core::Logger g_log;
|
||||||
|
@ -203,12 +204,7 @@ void Core::Entity::Player::calculateStats()
|
||||||
auto paramGrowthInfo = paramGrowthInfoIt->second;
|
auto paramGrowthInfo = paramGrowthInfoIt->second;
|
||||||
|
|
||||||
// TODO: put formula somewhere else...
|
// TODO: put formula somewhere else...
|
||||||
float base = 0.0f;
|
float base = CalcBattle::calculateBaseStat( getAsPlayer() );
|
||||||
|
|
||||||
if( level < 51 )
|
|
||||||
base = 0.053f * ( level * level ) + ( 1.022f * level ) - 0.907f + 20;
|
|
||||||
else
|
|
||||||
base = 1.627f * level + 120.773f;
|
|
||||||
|
|
||||||
m_baseStats.str = base * ( static_cast< float >( classInfo.mod_str ) / 100 ) + tribeInfo.mod_str;
|
m_baseStats.str = base * ( static_cast< float >( classInfo.mod_str ) / 100 ) + tribeInfo.mod_str;
|
||||||
m_baseStats.dex = base * ( static_cast< float >( classInfo.mod_dex ) / 100 ) + tribeInfo.mod_dex;
|
m_baseStats.dex = base * ( static_cast< float >( classInfo.mod_dex ) / 100 ) + tribeInfo.mod_dex;
|
||||||
|
@ -224,15 +220,9 @@ void Core::Entity::Player::calculateStats()
|
||||||
m_baseStats.attackPotMagic = paramGrowthInfo.base_secondary;
|
m_baseStats.attackPotMagic = paramGrowthInfo.base_secondary;
|
||||||
m_baseStats.healingPotMagic = paramGrowthInfo.base_secondary;
|
m_baseStats.healingPotMagic = paramGrowthInfo.base_secondary;
|
||||||
|
|
||||||
m_baseStats.max_mp = floor(
|
m_baseStats.max_mp = CalcBattle::calculateMaxMp( getAsPlayer() );
|
||||||
floor(
|
|
||||||
( ( m_baseStats.pie - base ) * ( static_cast< float >( paramGrowthInfo.piety_scalar ) / 100 ) ) + paramGrowthInfo.mp_const ) * ( static_cast< float >( classInfo.mod_mpcpgp ) / 100 )
|
|
||||||
);
|
|
||||||
|
|
||||||
m_baseStats.max_hp = floor(
|
m_baseStats.max_hp = CalcBattle::calculateMaxHp( getAsPlayer() );
|
||||||
floor(
|
|
||||||
( ( m_baseStats.vit - base ) * ( ( static_cast< float >( paramGrowthInfo.piety_scalar ) ) / 100 ) ) + paramGrowthInfo.hp_mod ) * ( static_cast< float >( classInfo.mod_hp * 0.9f ) / 100 ) * 15
|
|
||||||
);
|
|
||||||
|
|
||||||
if( m_mp > m_baseStats.max_mp )
|
if( m_mp > m_baseStats.max_mp )
|
||||||
m_mp = m_baseStats.max_mp;
|
m_mp = m_baseStats.max_mp;
|
||||||
|
@ -1451,10 +1441,12 @@ void Core::Entity::Player::autoAttack( ActorPtr pTarget )
|
||||||
//uint64_t tick = Util::getTimeMs();
|
//uint64_t tick = Util::getTimeMs();
|
||||||
//srand(static_cast< uint32_t >(tick));
|
//srand(static_cast< uint32_t >(tick));
|
||||||
|
|
||||||
uint32_t damage = mainWeap->getAutoAttackDmg() + rand() % 12;
|
uint32_t damage = mainWeap->getAutoAttackDmg();
|
||||||
uint32_t variation = 0 + rand() % 3;
|
uint32_t variation = 0 + rand() % 3;
|
||||||
|
|
||||||
if( getClass() == 5 || getClass() == 23 || getClass() == 31 )
|
if (getClass() == JOB_MACHINIST ||
|
||||||
|
getClass() == JOB_BARD ||
|
||||||
|
getClass() == CLASS_ARCHER)
|
||||||
{
|
{
|
||||||
GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket(getId());
|
GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket(getId());
|
||||||
effectPacket.data().targetId = pTarget->getId();
|
effectPacket.data().targetId = pTarget->getId();
|
||||||
|
@ -1533,7 +1525,10 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId,
|
||||||
|
|
||||||
case Core::Common::HandleSkillType::StdHeal:
|
case Core::Common::HandleSkillType::StdHeal:
|
||||||
{
|
{
|
||||||
|
uint32_t calculatedHeal = CalcBattle::calculateHealValue( getAsPlayer(), param1 );
|
||||||
|
|
||||||
sendDebug( "STD_HEAL" );
|
sendDebug( "STD_HEAL" );
|
||||||
|
|
||||||
GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket( getId() );
|
GamePacketNew< FFXIVIpcEffect, ServerZoneIpcType > effectPacket( getId() );
|
||||||
effectPacket.data().targetId = pTarget.getId();
|
effectPacket.data().targetId = pTarget.getId();
|
||||||
effectPacket.data().actionAnimationId = actionId;
|
effectPacket.data().actionAnimationId = actionId;
|
||||||
|
@ -1543,14 +1538,14 @@ void Core::Entity::Player::handleScriptSkill( uint32_t type, uint32_t actionId,
|
||||||
effectPacket.data().numEffects = 1;
|
effectPacket.data().numEffects = 1;
|
||||||
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() );
|
effectPacket.data().rotation = Math::Util::floatToUInt16Rot( getRotation() );
|
||||||
effectPacket.data().effectTarget = pTarget.getId();
|
effectPacket.data().effectTarget = pTarget.getId();
|
||||||
effectPacket.data().effects[0].param1 = param1;
|
effectPacket.data().effects[0].param1 = calculatedHeal;
|
||||||
effectPacket.data().effects[0].unknown_1 = 4;
|
effectPacket.data().effects[0].unknown_1 = 4;
|
||||||
effectPacket.data().effects[0].unknown_2 = 1;
|
effectPacket.data().effects[0].unknown_2 = 1;
|
||||||
effectPacket.data().effects[0].unknown_3 = 7;
|
effectPacket.data().effects[0].unknown_3 = 7;
|
||||||
|
|
||||||
sendToInRangeSet( effectPacket, true );
|
sendToInRangeSet( effectPacket, true );
|
||||||
|
|
||||||
pTarget.heal( param1 );
|
pTarget.heal( calculatedHeal );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,13 +56,13 @@ void Core::Entity::Player::equipWeapon( Core::ItemPtr pItem )
|
||||||
case ItemCategory::ThmWep:
|
case ItemCategory::ThmWep:
|
||||||
case ItemCategory::Thm2Wep:
|
case ItemCategory::Thm2Wep:
|
||||||
if( currentClass != ClassJob::CLASS_THAUMATURGE &&
|
if( currentClass != ClassJob::CLASS_THAUMATURGE &&
|
||||||
currentClass != ClassJob::JOB_BLACK )
|
currentClass != ClassJob::JOB_BLACKMAGE )
|
||||||
setClassJob( ClassJob::CLASS_THAUMATURGE );
|
setClassJob( ClassJob::CLASS_THAUMATURGE );
|
||||||
break;
|
break;
|
||||||
case ItemCategory::CnjWep:
|
case ItemCategory::CnjWep:
|
||||||
case ItemCategory::Cnj2Wep:
|
case ItemCategory::Cnj2Wep:
|
||||||
if( currentClass != ClassJob::CLASS_CONJURER &&
|
if( currentClass != ClassJob::CLASS_CONJURER &&
|
||||||
currentClass != ClassJob::JOB_WHITE )
|
currentClass != ClassJob::JOB_WHITEMAGE )
|
||||||
setClassJob( ClassJob::CLASS_CONJURER );
|
setClassJob( ClassJob::CLASS_CONJURER );
|
||||||
break;
|
break;
|
||||||
case ItemCategory::ArnWep:
|
case ItemCategory::ArnWep:
|
||||||
|
|
|
@ -27,7 +27,9 @@ Core::Item::Item( uint64_t uId, uint32_t catalogId, uint64_t model1, uint64_t mo
|
||||||
auto itemInfo = g_exdData.getItemInfo( catalogId );
|
auto itemInfo = g_exdData.getItemInfo( catalogId );
|
||||||
m_delayMs = itemInfo->delayMs;
|
m_delayMs = itemInfo->delayMs;
|
||||||
m_physicalDmg = itemInfo->physical_damage;
|
m_physicalDmg = itemInfo->physical_damage;
|
||||||
m_autoAttackDmg = float( m_physicalDmg * m_delayMs ) / 3000;
|
m_magicalDmg = itemInfo->magical_damage;
|
||||||
|
m_weaponDmg = ( m_physicalDmg != 0 ) ? m_physicalDmg : m_magicalDmg;
|
||||||
|
m_autoAttackDmg = static_cast< float >( m_weaponDmg * m_delayMs ) / 3000;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Item::~Item()
|
Core::Item::~Item()
|
||||||
|
@ -50,6 +52,16 @@ uint16_t Core::Item::getPhysicalDmg() const
|
||||||
return m_physicalDmg;
|
return m_physicalDmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Core::Item::getMagicalDmg() const
|
||||||
|
{
|
||||||
|
return m_magicalDmg;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Core::Item::getWeaponDmg() const
|
||||||
|
{
|
||||||
|
return m_weaponDmg;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Core::Item::getId() const
|
uint32_t Core::Item::getId() const
|
||||||
{
|
{
|
||||||
return m_id;
|
return m_id;
|
||||||
|
|
|
@ -44,6 +44,10 @@ public:
|
||||||
|
|
||||||
uint16_t getPhysicalDmg() const;
|
uint16_t getPhysicalDmg() const;
|
||||||
|
|
||||||
|
uint16_t getMagicalDmg() const;
|
||||||
|
|
||||||
|
uint16_t getWeaponDmg() const;
|
||||||
|
|
||||||
float getAutoAttackDmg() const;
|
float getAutoAttackDmg() const;
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +68,8 @@ protected:
|
||||||
|
|
||||||
uint16_t m_delayMs;
|
uint16_t m_delayMs;
|
||||||
uint16_t m_physicalDmg;
|
uint16_t m_physicalDmg;
|
||||||
|
uint16_t m_magicalDmg;
|
||||||
|
uint16_t m_weaponDmg;
|
||||||
float m_autoAttackDmg;
|
float m_autoAttackDmg;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,7 +106,11 @@ void Core::Network::GameConnection::actionHandler( const Packets::GamePacket& in
|
||||||
pPlayer->changeTarget( targetId );
|
pPlayer->changeTarget( targetId );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0x69: // Cancel cast
|
||||||
|
{
|
||||||
|
pPlayer->getCurrentAction()->setInterrupted();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0x133: // Update howtos seen
|
case 0x133: // Update howtos seen
|
||||||
{
|
{
|
||||||
uint32_t howToId = static_cast< uint32_t >( param1 );
|
uint32_t howToId = static_cast< uint32_t >( param1 );
|
||||||
|
|
Loading…
Add table
Reference in a new issue