forked from metin-server/m2dev-client-src
@@ -10,7 +10,10 @@ This repository contains the source code necessary to compile the game client ex
|
||||
|
||||
---
|
||||
|
||||
## Changelog 📋
|
||||
## 📋 Changelog
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
* **Realtime Character Level Updates:** Implemented the reversed fix (credits to Mali) for updating character level in real-time across game view and all windows (such as Guild window) for all viewing players.
|
||||
* **Shaman Mounted Combat:** Fixed a bug that wrongly calculated Shaman characters mounted hits that didn't collide with the target to cause damage when attack speed was had an extremely high value.
|
||||
* **Invisibility VFX Logic:** Fixed an issue where skill visual effects remained visible to the character while under the `AFFECT_INVISIBLE` state.
|
||||
* **Buff Effects Visibility Recovery:** Fixed an issue where buff skill visual effects remained invisible if the skill was cast while the character was under the `AFFECT_INVISIBLE` state.
|
||||
* **Casting Speed Cooldowns:** Fixed an issue where Casting Speed was not properly calculated in skill cooldowns. The system now supports real-time calculation updates whenever the bonus value changes.
|
||||
|
||||
@@ -270,6 +270,7 @@ void CEffectInstance::Clear()
|
||||
void CEffectInstance::__Initialize()
|
||||
{
|
||||
ReleaseAlwaysHidden();
|
||||
|
||||
m_isAlive = FALSE;
|
||||
m_dwFrame = 0;
|
||||
m_pSoundInstanceVector = NULL;
|
||||
|
||||
@@ -484,15 +484,18 @@ DWORD CEffectManager::GetSelectedEffectDataCRC() const
|
||||
return 0;
|
||||
|
||||
CEffectData* pData = m_pSelectedEffectInstance->GetEffectDataPointer();
|
||||
|
||||
if (!pData)
|
||||
return 0;
|
||||
|
||||
const char* cszFile = pData->GetFileName();
|
||||
|
||||
if (!cszFile || !cszFile[0])
|
||||
return 0;
|
||||
|
||||
std::string str;
|
||||
StringPath(cszFile, str);
|
||||
|
||||
return GetCaseCRC32(str.c_str(), (int)str.length());
|
||||
}
|
||||
|
||||
|
||||
@@ -285,9 +285,7 @@ void CGraphicObjectInstance::Initialize()
|
||||
m_isVisible = TRUE;
|
||||
|
||||
m_BlockCamera = false;
|
||||
|
||||
m_isAlwaysHidden = false;
|
||||
|
||||
|
||||
m_v3Position.x = m_v3Position.y = m_v3Position.z = 0.0f;
|
||||
m_v3Scale.x = m_v3Scale.y = m_v3Scale.z = 1.0f;
|
||||
|
||||
@@ -60,7 +60,6 @@ class CGraphicObjectInstance : public CGraphicCollisionObject
|
||||
void ApplyAlwaysHidden();
|
||||
void ReleaseAlwaysHidden();
|
||||
|
||||
|
||||
// Camera Block
|
||||
void BlockCamera(bool bBlock) {m_BlockCamera = bBlock;}
|
||||
bool BlockCamera() { return m_BlockCamera; }
|
||||
|
||||
@@ -362,6 +362,7 @@ class CActorInstance : public IActorInstance, public IFlyTargetableObject
|
||||
BOOL IsActEmotion();
|
||||
DWORD GetComboIndex();
|
||||
float GetAttackingElapsedTime();
|
||||
|
||||
void SetBlendingPosition(const TPixelPosition & c_rPosition, float fBlendingTime = 1.0f);
|
||||
void ResetBlendingPosition();
|
||||
void GetBlendingPosition(TPixelPosition * pPosition);
|
||||
@@ -607,6 +608,9 @@ class CActorInstance : public IActorInstance, public IFlyTargetableObject
|
||||
void __ProcessMotionEventAttackSuccess(DWORD dwMotionKey, BYTE byEventIndex, CActorInstance & rVictim);
|
||||
void __ProcessMotionAttackSuccess(DWORD dwMotionKey, CActorInstance & rVictim);
|
||||
|
||||
// MR-3: Shaman on-mount hitting fix
|
||||
float __GetInvisibleTimeAdjust(const UINT uiSkill, const NRaceData::TAttackData& c_rAttackData);
|
||||
// MR-3: -- END OF -- Shaman on-mount hitting fix
|
||||
|
||||
void __HitStone(CActorInstance& rVictim);
|
||||
void __HitGood(CActorInstance& rVictim);
|
||||
|
||||
@@ -620,19 +620,21 @@ void CActorInstance::__ProcessDataAttackSuccess(const NRaceData::TAttackData & c
|
||||
// VICTIM_COLLISION_TEST_END
|
||||
}
|
||||
|
||||
// MR-3: Shaman on-mount hitting fix
|
||||
// Invisible Time
|
||||
if (IS_PARTY_HUNTING_RACE(rVictim.GetRace()))
|
||||
{
|
||||
if (uiSkill) // 파티 사냥 몬스터라도 스킬이면 무적시간 적용
|
||||
rVictim.m_fInvisibleTime = CTimer::Instance().GetCurrentSecond() + c_rAttackData.fInvisibleTime;
|
||||
rVictim.m_fInvisibleTime = CTimer::Instance().GetCurrentSecond() + (c_rAttackData.fInvisibleTime - __GetInvisibleTimeAdjust(uiSkill, c_rAttackData));
|
||||
|
||||
if (m_isMain) // #0000794: [M2KR] 폴리모프 - 밸런싱 문제 타인 공격에 의한 무적 타임은 고려하지 않고 자신 공격에 의한것만 체크한다
|
||||
rVictim.m_fInvisibleTime = CTimer::Instance().GetCurrentSecond() + c_rAttackData.fInvisibleTime;
|
||||
rVictim.m_fInvisibleTime = CTimer::Instance().GetCurrentSecond() + (c_rAttackData.fInvisibleTime - __GetInvisibleTimeAdjust(uiSkill, c_rAttackData));
|
||||
}
|
||||
else // 파티 사냥 몬스터가 아닐 경우만 적용
|
||||
{
|
||||
rVictim.m_fInvisibleTime = CTimer::Instance().GetCurrentSecond() + c_rAttackData.fInvisibleTime;
|
||||
rVictim.m_fInvisibleTime = CTimer::Instance().GetCurrentSecond() + (c_rAttackData.fInvisibleTime - __GetInvisibleTimeAdjust(uiSkill, c_rAttackData));
|
||||
}
|
||||
// MR-3: -- END OF -- Shaman on-mount hitting fix
|
||||
|
||||
// Stiffen Time
|
||||
rVictim.InsertDelay(c_rAttackData.fStiffenTime);
|
||||
@@ -964,3 +966,19 @@ void CActorInstance::__SetFallingDirection(float fx, float fy)
|
||||
{
|
||||
m_PhysicsObject.SetDirection(D3DXVECTOR3(fx, fy, 0.0f));
|
||||
}
|
||||
|
||||
// MR-3: Shaman on-mount hitting fix
|
||||
float CActorInstance::__GetInvisibleTimeAdjust(const UINT uiSkill, const NRaceData::TAttackData& c_rAttackData) {
|
||||
|
||||
static const int shamanw = 3, shamanm = 7;
|
||||
|
||||
if ((GetRace() != shamanw && GetRace() != shamanm) ||
|
||||
uiSkill != 0 ||
|
||||
m_fAtkSpd < 1.3)
|
||||
return 0.0f;
|
||||
|
||||
const auto scale = (m_fAtkSpd - 1.3) / 1.3;
|
||||
const auto inv = c_rAttackData.fInvisibleTime * 0.5;
|
||||
return inv * scale;
|
||||
}
|
||||
// MR-3: -- END OF -- Shaman on-mount hitting fix
|
||||
|
||||
@@ -1978,9 +1978,10 @@ void CInstanceBase::Render()
|
||||
|
||||
if (pkInstEach)
|
||||
{
|
||||
// MR-3: Invisibility fix
|
||||
if (pkInstEach->IsAffect(AFFECT_INVISIBILITY) || pkInstEach->IsAffect(AFFECT_EUNHYEONG) || pkInstEach->IsAffect(AFFECT_REVIVE_INVISIBILITY))
|
||||
{
|
||||
if (CPythonPlayer::Instance().IsMainCharacterIndex(pkInstEach->GetVirtualID()))
|
||||
if (CPythonPlayer::Instance().IsMainCharacterIndex(pkInstEach->GetVirtualID()) && !pkInstEach->IsAffect(AFFECT_INVISIBILITY))
|
||||
continue;
|
||||
|
||||
if (pkInstEach->IsAffect(AFFECT_EUNHYEONG) && !pkInstEach->IsAffect(AFFECT_INVISIBILITY) && !pkInstEach->IsAffect(AFFECT_REVIVE_INVISIBILITY))
|
||||
@@ -1988,6 +1989,11 @@ void CInstanceBase::Render()
|
||||
else
|
||||
pkInstEach->m_GraphicThingInstance.HideAllAttachingEffect();
|
||||
}
|
||||
else
|
||||
{
|
||||
pkInstEach->m_GraphicThingInstance.ShowAllAttachingEffect();
|
||||
}
|
||||
// MR-3: -- END OF -- Invisibility fix
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1662,18 +1662,36 @@ PyObject * skillGetSkillAffectDescription(PyObject * poSelf, PyObject * poArgs)
|
||||
PyObject * skillGetSkillCoolTime(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
int iSkillIndex;
|
||||
|
||||
if (!PyTuple_GetInteger(poArgs, 0, &iSkillIndex))
|
||||
return Py_BadArgument();
|
||||
|
||||
float fSkillPoint;
|
||||
|
||||
if (!PyTuple_GetFloat(poArgs, 1, &fSkillPoint))
|
||||
return Py_BadArgument();
|
||||
|
||||
CPythonSkill::SSkillData * c_pSkillData;
|
||||
|
||||
if (!CPythonSkill::Instance().GetSkillData(iSkillIndex, &c_pSkillData))
|
||||
return Py_BuildException("skill.GetSkillCoolTime - Failed to find skill by %d", iSkillIndex);
|
||||
|
||||
return Py_BuildValue("i", c_pSkillData->GetSkillCoolTime(fSkillPoint));
|
||||
// MR-3: Calculate casting speed bonus on skill cool time
|
||||
DWORD dwSkillCoolTime = c_pSkillData->GetSkillCoolTime(fSkillPoint);
|
||||
int iCastingSpeed = CPythonPlayer::Instance().GetStatus(POINT_CASTING_SPEED);
|
||||
|
||||
int iSpd = 100 - iCastingSpeed;
|
||||
if (iSpd > 0)
|
||||
iSpd = 100 + iSpd;
|
||||
else if (iSpd < 0)
|
||||
iSpd = 10000 / (100 - iSpd);
|
||||
else
|
||||
iSpd = 100;
|
||||
|
||||
dwSkillCoolTime = dwSkillCoolTime * iSpd / 100;
|
||||
|
||||
return Py_BuildValue("i", dwSkillCoolTime);
|
||||
// MR-3: -- END OF -- Calculate casting speed bonus on skill cool time
|
||||
}
|
||||
|
||||
PyObject * skillGetSkillNeedSP(PyObject * poSelf, PyObject * poArgs)
|
||||
|
||||
Reference in New Issue
Block a user