MRMJ-1: Messenger & Skills fixes

This commit is contained in:
Mind Rapist
2025-12-14 05:12:39 +02:00
parent 436db01a80
commit 7b08687023
46 changed files with 1258 additions and 60 deletions

View File

@@ -1,6 +1,7 @@
#pragma once
#include "AbstractSingleton.h"
#include "GameType.h"
class CInstanceBase;

View File

@@ -448,7 +448,11 @@ BOOL CInstanceBase::IsMovieMode()
BOOL CInstanceBase::IsInvisibility()
{
#ifdef __ENABLE_STEALTH_FIX__
if (IsAffect(AFFECT_INVISIBILITY) || IsAffect(AFFECT_EUNHYEONG) || IsAffect(AFFECT_REVIVE_INVISIBILITY))
#else
if (IsAffect(AFFECT_INVISIBILITY))
#endif
return true;
return false;
@@ -1556,7 +1560,11 @@ void CInstanceBase::StateProcess()
SetAdvancingRotation(fRotDst);
SetRotation(fRotDst);
#ifdef FIX_POS_SYNC
NEW_UseSkill(1, eFunc& FUNC_SKILL - 1, uArg & 0x0f, (uArg >> 4) ? true : false);
#else
NEW_UseSkill(0, eFunc & 0x7f, uArg&0x0f, (uArg>>4) ? true : false);
#endif
//Tracen("가깝기 때문에 워프 공격");
}
}
@@ -1734,7 +1742,11 @@ void CInstanceBase::MovementProcess()
{
SetAdvancingRotation(m_fDstRot);
BlendRotation(m_fDstRot);
#ifdef FIX_POS_SYNC
NEW_UseSkill(1, m_kMovAfterFunc.eFunc& FUNC_SKILL - 1, m_kMovAfterFunc.uArg & 0x0f, (m_kMovAfterFunc.uArg >> 4) ? true : false);
#else
NEW_UseSkill(0, m_kMovAfterFunc.eFunc & 0x7f, m_kMovAfterFunc.uArg&0x0f, (m_kMovAfterFunc.uArg>>4) ? true : false);
#endif
}
else
{
@@ -1790,7 +1802,11 @@ void CInstanceBase::MovementProcess()
m_GraphicThingInstance.SetRotation(fRotation);
}
#ifdef __ENABLE_STEALTH_FIX__
if (__IsInDustRange() && !IsAffect(AFFECT_INVISIBILITY) && !IsAffect(AFFECT_EUNHYEONG) && !IsAffect(AFFECT_REVIVE_INVISIBILITY))
#else
if (__IsInDustRange())
#endif
{
float fDustDistance = NEW_GetDistanceFromDestPixelPosition(m_kPPosDust);
if (IsMountingHorse())
@@ -1906,7 +1922,7 @@ void CInstanceBase::Update()
}
__ComboProcess();
ProcessDamage();
}
@@ -1968,7 +1984,30 @@ void CInstanceBase::Render()
++ms_dwRenderCounter;
m_kHorse.Render();
m_GraphicThingInstance.Render();
m_GraphicThingInstance.Render();
#ifdef __ENABLE_STEALTH_FIX__
CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance();
for (auto ptr = rkChrMgr.CharacterInstanceBegin(); ptr != rkChrMgr.CharacterInstanceEnd(); ++ptr)
{
CInstanceBase* pkInstEach = *ptr;
if (pkInstEach)
{
if (pkInstEach->IsAffect(AFFECT_INVISIBILITY) || pkInstEach->IsAffect(AFFECT_EUNHYEONG) || pkInstEach->IsAffect(AFFECT_REVIVE_INVISIBILITY))
{
if (CPythonPlayer::Instance().IsMainCharacterIndex(pkInstEach->GetVirtualID()))
continue;
if (pkInstEach->IsAffect(AFFECT_EUNHYEONG) && !pkInstEach->IsAffect(AFFECT_INVISIBILITY) && !pkInstEach->IsAffect(AFFECT_REVIVE_INVISIBILITY))
pkInstEach->m_GraphicThingInstance.HideAllAttachingEffectForEunhyeong();
else
pkInstEach->m_GraphicThingInstance.HideAllAttachingEffect();
}
}
}
#endif
if (CActorInstance::IsDirLine())
{

View File

@@ -3,6 +3,7 @@
#include "GameLib/RaceData.h"
#include "GameLib/ActorInstance.h"
#include "StdAfx.h"
#include "AffectFlagContainer.h"
class CInstanceBase
@@ -632,6 +633,11 @@ class CInstanceBase
bool NEW_AttackToDestInstanceDirection(CInstanceBase& rkInstDst, IFlyEventHandler* pkFlyHandler);
bool NEW_AttackToDestInstanceDirection(CInstanceBase& rkInstDst);
#ifdef FIX_POS_SYNC
void ServerAttack(DWORD dwVID);
bool ProcessingClientAttack(DWORD dwVID);
#endif
bool NEW_MoveToDestPixelPositionDirection(const TPixelPosition& c_rkPPosDst);
void NEW_MoveToDestInstanceDirection(CInstanceBase& rkInstDst);
void NEW_MoveToDirection(float fDirRot);

View File

@@ -410,6 +410,18 @@ bool CInstanceBase::NEW_AttackToDestInstanceDirection(CInstanceBase& rkInstDst)
return true;
}
#ifdef FIX_POS_SYNC
void CInstanceBase::ServerAttack(DWORD dwVID)
{
m_GraphicThingInstance.ServerAttack(dwVID);
}
bool CInstanceBase::ProcessingClientAttack(DWORD dwVID)
{
return m_GraphicThingInstance.ProcessingClientAttack(dwVID);
}
#endif
void CInstanceBase::AttackProcess()
{
if (!m_GraphicThingInstance.CanCheckAttacking())

View File

@@ -84,7 +84,7 @@ const D3DXCOLOR& CInstanceBase::GetIndexedNameColor(UINT eNameColor)
return g_akD3DXClrName[eNameColor];
}
void CInstanceBase::AddDamageEffect(DWORD damage,BYTE flag,BOOL bSelf,BOOL bTarget)
void CInstanceBase::AddDamageEffect(DWORD damage, BYTE flag, BOOL bSelf, BOOL bTarget)
{
if(CPythonSystem::Instance().IsShowDamage())
{
@@ -149,19 +149,26 @@ void CInstanceBase::ProcessDamage()
else
*/
{
if(bSelf)
if (bSelf)
{
strDamageType = "damage_";
if(m_bDamageEffectType==0)
if (m_bDamageEffectType == 0)
rdwCRCEft = EFFECT_DAMAGE_SELFDAMAGE;
else
rdwCRCEft = EFFECT_DAMAGE_SELFDAMAGE2;
m_bDamageEffectType = !m_bDamageEffectType;
}
else if(bTarget == false)
#ifdef __ENABLE_STEALTH_FIX__ //EXP
else if (!bTarget || ((IsAffect(AFFECT_INVISIBILITY) || IsAffect(AFFECT_EUNHYEONG)) && bTarget))
#else
else if (bTarget == false)
#endif
{
strDamageType = "nontarget_";
rdwCRCEft = EFFECT_DAMAGE_NOT_TARGET;
return;//현재 적용 안됨.
}
else
@@ -174,34 +181,41 @@ void CInstanceBase::ProcessDamage()
DWORD index = 0;
DWORD num = 0;
std::vector<std::string> textures;
while(damage>0)
while (damage > 0)
{
if(index > 7)
if (index > 7)
{
TraceError("ProcessDamage무한루프 가능성");
break;
}
num = damage%10;
damage /= 10;
char numBuf[MAX_PATH];
sprintf(numBuf,"%d.dds",num);
textures.push_back("d:/ymir work/effect/affect/damagevalue/"+strDamageType+numBuf);
sprintf(numBuf, "%d.dds", num);
textures.push_back("d:/ymir work/effect/affect/damagevalue/" +strDamageType + numBuf);
rkEftMgr.SetEffectTextures(ms_adwCRCAffectEffect[rdwCRCEft],textures);
D3DXMATRIX matrix,matTrans;
D3DXMATRIX matrix, matTrans;
D3DXMatrixIdentity(&matrix);
matrix._41 = v3Pos.x;
matrix._42 = v3Pos.y;
matrix._43 = v3Pos.z;
D3DXMatrixTranslation(&matrix,v3Pos.x,v3Pos.y,v3Pos.z);
D3DXMatrixMultiply(&matrix,&pCamera->GetInverseViewMatrix(),&matrix);
D3DXMatrixTranslation(&matTrans,FONT_WIDTH*index,0,0);
D3DXMatrixTranslation(&matrix, v3Pos.x, v3Pos.y, v3Pos.z);
D3DXMatrixMultiply(&matrix, &pCamera->GetInverseViewMatrix(), &matrix);
D3DXMatrixTranslation(&matTrans, FONT_WIDTH * index, 0, 0);
matTrans._41 = -matTrans._41;
matrix = matTrans*matrix;
D3DXMatrixMultiply(&matrix,&pCamera->GetViewMatrix(),&matrix);
D3DXMatrixMultiply(&matrix, &pCamera->GetViewMatrix(), &matrix);
rkEftMgr.CreateEffect(ms_adwCRCAffectEffect[rdwCRCEft],D3DXVECTOR3(matrix._41,matrix._42,matrix._43)
rkEftMgr.CreateEffect(ms_adwCRCAffectEffect[rdwCRCEft], D3DXVECTOR3(matrix._41, matrix._42, matrix._43)
,v3Rot);
textures.clear();
@@ -784,11 +798,31 @@ void CInstanceBase::__SetReviveInvisibilityAffect(bool isVisible)
if (IsWearingDress())
return;
m_GraphicThingInstance.BlendAlphaValue(0.5f, 1.0f);
#ifdef __ENABLE_STEALTH_FIX__
if (__IsMainInstance() || __MainCanSeeHiddenThing())
{
#endif
m_GraphicThingInstance.BlendAlphaValue(0.5f, 1.0f);
#ifdef __ENABLE_STEALTH_FIX__
}
else
{
m_GraphicThingInstance.BlendAlphaValue(0.0f, 1.0f);
m_GraphicThingInstance.HideAllAttachingEffect();
}
#endif
}
else
{
m_GraphicThingInstance.BlendAlphaValue(1.0f, 1.0f);
#ifdef __ENABLE_STEALTH_FIX__
if (!IsAffect(AFFECT_EUNHYEONG) && !IsAffect(AFFECT_INVISIBILITY))
{
#endif
m_GraphicThingInstance.BlendAlphaValue(1.0f, 1.0f);
#ifdef __ENABLE_STEALTH_FIX__
m_GraphicThingInstance.ShowAllAttachingEffect();
}
#endif
}
}
@@ -808,13 +842,26 @@ void CInstanceBase::__Assassin_SetEunhyeongAffect(bool isVisible)
{
// 2004.10.16.myevan.은형법 완전 투명
m_GraphicThingInstance.BlendAlphaValue(0.0f, 1.0f);
m_GraphicThingInstance.HideAllAttachingEffect();
#ifdef __ENABLE_STEALTH_FIX__ //EXP
if (!IsAffect(AFFECT_INVISIBILITY) && !IsAffect(AFFECT_REVIVE_INVISIBILITY))
m_GraphicThingInstance.HideAllAttachingEffectForEunhyeong();
else
#endif
m_GraphicThingInstance.HideAllAttachingEffect();
}
}
else
{
m_GraphicThingInstance.BlendAlphaValue(1.0f, 1.0f);
m_GraphicThingInstance.ShowAllAttachingEffect();
#ifdef __ENABLE_STEALTH_FIX__
if (!IsAffect(AFFECT_REVIVE_INVISIBILITY) && !IsAffect(AFFECT_INVISIBILITY))
{
#endif
m_GraphicThingInstance.BlendAlphaValue(1.0f, 1.0f);
m_GraphicThingInstance.ShowAllAttachingEffect();
#ifdef __ENABLE_STEALTH_FIX__
ProcessDamage();
}
#endif
}
}
@@ -823,8 +870,6 @@ void CInstanceBase::__Shaman_SetParalysis(bool isParalysis)
m_GraphicThingInstance.SetParalysis(isParalysis);
}
void CInstanceBase::__Warrior_SetGeomgyeongAffect(bool isVisible)
{
if (isVisible)
@@ -895,7 +940,11 @@ void CInstanceBase::__SetAffect(UINT eAffect, bool isVisible)
return;
break;
case AFFECT_REVIVE_INVISIBILITY:
#ifdef __ENABLE_STEALTH_FIX__
__SetReviveInvisibilityAffect(isVisible);
#else
__Assassin_SetEunhyeongAffect(isVisible);
#endif
break;
case AFFECT_EUNHYEONG:
__Assassin_SetEunhyeongAffect(isVisible);
@@ -911,15 +960,28 @@ void CInstanceBase::__SetAffect(UINT eAffect, bool isVisible)
// 2004.07.17.levites.isShow를 ViewFrustumCheck로 변경
if (isVisible)
{
#ifndef __ENABLE_STEALTH_FIX__
m_GraphicThingInstance.ClearAttachingEffect();
__EffectContainer_Destroy();
DetachTextTail();
#else
m_GraphicThingInstance.HideAllAttachingEffect();
#endif
}
else
{
#ifdef __ENABLE_STEALTH_FIX__
if (!IsAffect(AFFECT_EUNHYEONG) && !IsAffect(AFFECT_REVIVE_INVISIBILITY))
{
m_GraphicThingInstance.BlendAlphaValue(1.0f, 1.0f);
m_GraphicThingInstance.ShowAllAttachingEffect();
ProcessDamage();
}
#else
m_GraphicThingInstance.BlendAlphaValue(1.0f, 1.0f);
AttachTextTail();
RefreshTextTail();
#endif
}
return;
break;

View File

@@ -259,8 +259,8 @@ struct SLOCALEDATA
const char* szSecurityKey;
} gs_stLocaleData[] = {
{ LSS_YMIR, "ymir", 949, "testtesttesttest" }, // Korea
{ LSS_EUROPE, "de", 1252, "1234abcd5678efgh" }, // GameForge (Germany)
{ LSS_EUROPE, "en", 1252, "1234abcd5678efgh" }, // GameForge (United Kingdom)
{ LSS_EUROPE, "de", 1252, "1234abcd5678efgh" }, // GameForge (Germany)
{ LSS_EUROPE, "us", 1252, "1234abcd5678efgh" }, // GameForge (USA)
{ LSS_EUROPE, "es", 1252, "1234abcd5678efgh" }, // GameForge (Spain)
{ LSS_EUROPE, "it", 1252, "1234abcd5678efgh" }, // GameForge (Italy)

View File

@@ -6,3 +6,14 @@
#define ENABLE_DRAGON_SOUL_SYSTEM
#define ENABLE_NEW_EQUIPMENT_SYSTEM
//#define ENABLE_DISCORD_RPC
// Fixes
#define FIX_MESSENGER_ACTION_SYNC
#define FIX_REFRESH_SKILL_COOLDOWN
#define FIX_SEQ_254
#define CHAR_SELECT_STATS_IMPROVEMENT // Improve stats values in character select screen
#define __ENABLE_STEALTH_FIX__
//#define FIX_POS_SYNC
// Python-only
#define FIX_HORSE_SKILLS_TAB

View File

@@ -536,6 +536,41 @@ void CNetworkActorManager::MoveActor(const SNetworkMoveActorData& c_rkNetMoveAct
rkNetActorData.m_fRot=c_rkNetMoveActorData.m_fRot;
}
#ifdef FIX_POS_SYNC
void CNetworkActorManager::AttackActor(DWORD dwVID, DWORD dwAttacakerVID, LONG lDestPosX, LONG lDestPosY, const TPixelPosition& k_pSyncPos, DWORD dwBlendDuration)
{
std::map<DWORD, SNetworkActorData>::iterator f = m_kNetActorDict.find(dwVID);
if (m_kNetActorDict.end() == f)
{
return;
}
SNetworkActorData& rkNetActorData = f->second;
if (k_pSyncPos.x && k_pSyncPos.y) {
CInstanceBase* pkInstFind = __FindActor(rkNetActorData);
if (pkInstFind)
{
const bool bProcessingClientAttack = pkInstFind->ProcessingClientAttack(dwAttacakerVID);
pkInstFind->ServerAttack(dwAttacakerVID);
// if already blending, update
if (bProcessingClientAttack && pkInstFind->IsPushing() && pkInstFind->GetBlendingRemainTime() > 0.15) {
pkInstFind->SetBlendingPosition(k_pSyncPos, pkInstFind->GetBlendingRemainTime());
}
else {
// otherwise sync
//pkInstFind->SCRIPT_SetPixelPosition(k_pSyncPos.x, k_pSyncPos.y);
pkInstFind->NEW_SyncPixelPosition(k_pSyncPos, dwBlendDuration);
}
}
rkNetActorData.SetPosition(long(k_pSyncPos.x), long(k_pSyncPos.y));
}
}
#endif
void CNetworkActorManager::SyncActor(DWORD dwVID, LONG lPosX, LONG lPosY)
{
std::map<DWORD, SNetworkActorData>::iterator f=m_kNetActorDict.find(dwVID);

View File

@@ -127,6 +127,10 @@ class CNetworkActorManager : public CReferenceObject
void UpdateActor(const SNetworkUpdateActorData& c_rkNetUpdateActorData);
void MoveActor(const SNetworkMoveActorData& c_rkNetMoveActorData);
#ifdef FIX_POS_SYNC
void AttackActor(DWORD dwVID, DWORD dwAttacakerVID, LONG lDestPosX, LONG lDestPosY, const TPixelPosition& k_pSyncPos, DWORD dwBlendDuration);
#endif
void SyncActor(DWORD dwVID, LONG lPosX, LONG lPosY);
void SetActorOwner(DWORD dwOwnerVID, DWORD dwVictimVID);

View File

@@ -1,5 +1,10 @@
#pragma once
#include "Gamelib/RaceData.h"
#include "StdAfx.h"
#ifdef FIX_REFRESH_SKILL_COOLDOWN
#include "GameType.h"
#endif
typedef uint8_t TPacketHeader;
@@ -511,6 +516,18 @@ typedef struct command_attack
uint32_t dwVictimVID; // 적 VID
uint8_t bCRCMagicCubeProcPiece;
uint8_t bCRCMagicCubeFilePiece;
#ifdef FIX_POS_SYNC
BOOL bPacket;
LONG lSX;
LONG lSY;
LONG lX;
LONG lY;
float fSyncDestX;
float fSyncDestY;
DWORD dwBlendDuration;
DWORD dwComboMotion;
DWORD dwTime;
#endif
} TPacketCGAttack;
typedef struct command_chat
@@ -730,6 +747,9 @@ enum
MESSENGER_SUBHEADER_GC_LOGOUT,
MESSENGER_SUBHEADER_GC_INVITE,
MESSENGER_SUBHEADER_GC_MOBILE,
#ifdef FIX_MESSENGER_ACTION_SYNC
MESSENGER_SUBHEADER_GC_REMOVE_FRIEND
#endif
};
typedef struct packet_messenger
@@ -1862,6 +1882,16 @@ typedef struct packet_attack
uint32_t dwVID;
uint32_t dwVictimVID; // 적 VID
uint8_t bType; // 공격 유형
#ifdef FIX_POS_SYNC
BOOL bPacket;
LONG lSX;
LONG lSY;
LONG lX;
LONG lY;
float fSyncDestX;
float fSyncDestY;
DWORD dwBlendDuration;
#endif
} TPacketGCAttack;
typedef struct packet_c2c

View File

@@ -1305,7 +1305,6 @@ void initapp()
{ "OnLogoRender", appLogoRender, METH_VARARGS },
{ "OnLogoOpen", appLogoOpen, METH_VARARGS },
{ "OnLogoClose", appLogoClose, METH_VARARGS },
{ NULL, NULL },
};
@@ -1490,4 +1489,22 @@ void initapp()
#else
PyModule_AddIntConstant(poModule, "ENABLE_NEW_EQUIPMENT_SYSTEM", 0);
#endif
#ifdef FIX_MESSENGER_ACTION_SYNC
PyModule_AddIntConstant(poModule, "FIX_MESSENGER_ACTION_SYNC", 1);
#else
PyModule_AddIntConstant(poModule, "FIX_MESSENGER_ACTION_SYNC", 0);
#endif
#ifdef FIX_REFRESH_SKILL_COOLDOWN
PyModule_AddIntConstant(poModule, "FIX_REFRESH_SKILL_COOLDOWN", 1);
#else
PyModule_AddIntConstant(poModule, "FIX_REFRESH_SKILL_COOLDOWN", 0);
#endif
#ifdef FIX_HORSE_SKILLS_TAB
PyModule_AddIntConstant(poModule, "FIX_HORSE_SKILLS_TAB", 1);
#else
PyModule_AddIntConstant(poModule, "FIX_HORSE_SKILLS_TAB", 0);
#endif
}

View File

@@ -4,6 +4,11 @@
void CPythonMessenger::RemoveFriend(const char * c_szKey)
{
m_FriendNameMap.erase(c_szKey);
#ifdef FIX_MESSENGER_ACTION_SYNC
if (m_poMessengerHandler)
PyCallClassMemberFunc(m_poMessengerHandler, "OnRemoveList", Py_BuildValue("(is)", MESSENGER_GRUOP_INDEX_FRIEND, c_szKey));
#endif
}
void CPythonMessenger::OnFriendLogin(const char * c_szKey/*, const char * c_szName*/)
@@ -161,6 +166,7 @@ void initMessenger()
{ "Destroy", messengerDestroy, METH_VARARGS },
{ "RefreshGuildMember", messengerRefreshGuildMember, METH_VARARGS },
{ "SetMessengerHandler", messengerSetMessengerHandler, METH_VARARGS },
{ NULL, NULL, NULL },
};

View File

@@ -1,5 +1,7 @@
#pragma once
#include <set>
class CPythonMessenger : public CSingleton<CPythonMessenger>
{
public:

View File

@@ -662,10 +662,14 @@ bool CPythonNetworkStream::RecvPingPacket()
if (!Send(sizeof(TPacketCGPong), &kPacketPong))
return false;
#ifdef FIX_SEQ_254
return SendSequence();
#else
if (IsSecurityMode())
return SendSequence();
else
return true;
#endif
}
bool CPythonNetworkStream::RecvDefaultPacket(int header)

View File

@@ -8,6 +8,10 @@
#include "packet.h"
#ifdef FIX_POS_SYNC
#include <GameLib/ActorInstance.h>
#endif
class CInstanceBase;
class CNetworkActorManager;
struct SNetworkActorData;
@@ -136,7 +140,11 @@ class CPythonNetworkStream : public CNetworkStream, public CSingleton<CPythonNet
bool SendSyncPositionElementPacket(DWORD dwVictimVID, DWORD dwVictimX, DWORD dwVictimY);
#ifdef FIX_POS_SYNC
bool SendAttackPacket(UINT uMotAttack, DWORD dwVIDVictim, BOOL bPacket, CActorInstance::BlendingPosition& sBlending);
#else
bool SendAttackPacket(UINT uMotAttack, DWORD dwVIDVictim);
#endif
bool SendCharacterStatePacket(const TPixelPosition& c_rkPPosDst, float fDstRot, UINT eFunc, UINT uArg);
bool SendUseSkillPacket(DWORD dwSkillIndex, DWORD dwTargetVID=0);
bool SendTargetPacket(DWORD dwVID);
@@ -478,6 +486,9 @@ class CPythonNetworkStream : public CNetworkStream, public CSingleton<CPythonNet
bool RecvTargetPacket();
bool RecvViewEquipPacket();
bool RecvDamageInfoPacket();
#ifdef FIX_POS_SYNC
bool RecvCharacterAttackPacket();
#endif
// Mount
bool RecvMountPacket();

View File

@@ -1495,7 +1495,18 @@ bool CPythonNetworkStream::RecvPointChange()
case POINT_STAT_RESET_COUNT:
__RefreshStatus();
break;
#ifdef CHAR_SELECT_STATS_IMPROVEMENT
case POINT_PLAYTIME:
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].dwPlayMinutes = PointChange.value;
break;
case POINT_LEVEL:
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointChange.value;
__RefreshStatus();
__RefreshSkillWindow();
break;
#else
case POINT_LEVEL:
#endif
case POINT_ST:
case POINT_DX:
case POINT_HT:
@@ -2332,16 +2343,19 @@ bool CPythonNetworkStream::RecvSkillCoolTimeEnd()
bool CPythonNetworkStream::RecvSkillLevel()
{
assert(!"CPythonNetworkStream::RecvSkillLevel - 사용하지 않는 함수");
TPacketGCSkillLevel packet;
if (!Recv(sizeof(TPacketGCSkillLevel), &packet))
{
Tracen("CPythonNetworkStream::RecvSkillLevel - RecvError");
return false;
}
DWORD dwSlotIndex;
CPythonPlayer& rkPlayer = CPythonPlayer::Instance();
CPythonPlayer& rkPlayer=CPythonPlayer::Instance();
for (int i = 0; i < SKILL_MAX_NUM; ++i)
{
if (rkPlayer.GetSkillSlotIndex(i, &dwSlotIndex))
@@ -2350,7 +2364,9 @@ bool CPythonNetworkStream::RecvSkillLevel()
__RefreshSkillWindow();
__RefreshStatus();
Tracef(" >> RecvSkillLevel\n");
return true;
}
@@ -2364,7 +2380,7 @@ bool CPythonNetworkStream::RecvSkillLevelNew()
return false;
}
CPythonPlayer& rkPlayer=CPythonPlayer::Instance();
CPythonPlayer& rkPlayer = CPythonPlayer::Instance();
rkPlayer.SetSkill(7, 0);
rkPlayer.SetSkill(8, 0);
@@ -2412,6 +2428,31 @@ bool CPythonNetworkStream::RecvDamageInfoPacket()
return true;
}
#ifdef FIX_POS_SYNC
bool CPythonNetworkStream::RecvCharacterAttackPacket()
{
TPacketGCAttack kPacket;
if (!Recv(sizeof(TPacketGCAttack), &kPacket))
{
Tracen("CPythonNetworkStream::RecvCharacterAttackPacket - PACKET READ ERROR");
return false;
}
if (kPacket.lX && kPacket.lY) {
__GlobalPositionToLocalPosition(kPacket.lX, kPacket.lY);
}
__GlobalPositionToLocalPosition(kPacket.lSX, kPacket.lSY);
TPixelPosition tSyncPosition = TPixelPosition{ kPacket.fSyncDestX, kPacket.fSyncDestY, 0 };
m_rokNetActorMgr->AttackActor(kPacket.dwVID, kPacket.dwVictimVID, kPacket.lX, kPacket.lY, tSyncPosition, kPacket.dwBlendDuration);
return true;
}
#endif
bool CPythonNetworkStream::RecvTargetPacket()
{
TPacketGCTarget TargetPacket;
@@ -2503,11 +2544,20 @@ bool CPythonNetworkStream::RecvChangeSpeedPacket()
///////////////////////////////////////////////////////////////////////////////////////////////////
// Recv
#ifdef FIX_POS_SYNC
bool CPythonNetworkStream::SendAttackPacket(UINT uMotAttack, DWORD dwVIDVictim, BOOL bPacket, CActorInstance::BlendingPosition& sBlending)
#else
bool CPythonNetworkStream::SendAttackPacket(UINT uMotAttack, DWORD dwVIDVictim)
#endif
{
if (!__CanActMainInstance())
return true;
#ifdef FIX_POS_SYNC
CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance();
CInstanceBase* pkInstMain = rkChrMgr.GetMainInstancePtr();
#endif
#ifdef ATTACK_TIME_LOG
static DWORD prevTime = timeGetTime();
DWORD curTime = timeGetTime();
@@ -2520,6 +2570,25 @@ bool CPythonNetworkStream::SendAttackPacket(UINT uMotAttack, DWORD dwVIDVictim)
kPacketAtk.header = HEADER_CG_ATTACK;
kPacketAtk.bType = uMotAttack;
kPacketAtk.dwVictimVID = dwVIDVictim;
#ifdef FIX_POS_SYNC
kPacketAtk.bPacket = bPacket;
kPacketAtk.lX = (long)sBlending.dest.x;
kPacketAtk.lY = (long)sBlending.dest.y;
kPacketAtk.lSX = (long)sBlending.source.x;
kPacketAtk.lSY = (long)sBlending.source.y;
kPacketAtk.fSyncDestX = sBlending.dest.x;
// sources and dest are normalized with both coordinates positive
// since fSync are ment to be broadcasted to other clients, the Y has to preserve the negative coord
kPacketAtk.fSyncDestY = -sBlending.dest.y;
kPacketAtk.dwBlendDuration = (unsigned int)(sBlending.duration * 1000);
kPacketAtk.dwComboMotion = pkInstMain->GetComboMotion();
kPacketAtk.dwTime = ELTimer_GetServerMSec();
if (kPacketAtk.lX && kPacketAtk.lY)
__LocalPositionToGlobalPosition(kPacketAtk.lX, kPacketAtk.lY);
__LocalPositionToGlobalPosition(kPacketAtk.lSX, kPacketAtk.lSY);
#endif
if (!SendSpecial(sizeof(kPacketAtk), &kPacketAtk))
{
@@ -2814,6 +2883,26 @@ bool CPythonNetworkStream::RecvMessenger()
CPythonMessenger::Instance().SetMobile(char_name, byState);
break;
}
#ifdef FIX_MESSENGER_ACTION_SYNC
case MESSENGER_SUBHEADER_GC_REMOVE_FRIEND:
{
BYTE bLength;
if (!Recv(sizeof(bLength), &bLength))
return false;
if (!Recv(bLength, char_name))
return false;
char_name[bLength] = 0;
CPythonMessenger::Instance().RemoveFriend(char_name);
__RefreshTargetBoardByName(char_name);
break;
}
#endif
}
return true;
}
@@ -3984,6 +4073,7 @@ bool CPythonNetworkStream::RecvWalkModePacket()
bool CPythonNetworkStream::RecvChangeSkillGroupPacket()
{
TPacketGCChangeSkillGroup ChangeSkillGroup;
if (!Recv(sizeof(ChangeSkillGroup), &ChangeSkillGroup))
return false;
@@ -3991,6 +4081,7 @@ bool CPythonNetworkStream::RecvChangeSkillGroupPacket()
CPythonPlayer::Instance().NEW_ClearSkillData();
__RefreshCharacterWindow();
return true;
}

View File

@@ -324,6 +324,10 @@ void CPythonNetworkStream::__RecvCharacterUpdatePacket(SNetworkUpdateActorData *
__RefreshAlignmentWindow();
__RefreshEquipmentWindow();
__RefreshInventoryWindow();
#ifdef CHAR_SELECT_STATS_IMPROVEMENT
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].wHairPart = pkNetUpdateActorData->m_dwHair;
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].wMainPart = pkNetUpdateActorData->m_dwArmor;
#endif
}
else
{

View File

@@ -326,7 +326,21 @@ bool CPythonNetworkStream::__RecvPlayerPoints()
return false;
for (DWORD i = 0; i < POINT_MAX_NUM; ++i)
{
CPythonPlayer::Instance().SetStatus(i, PointsPacket.points[i]);
#ifdef CHAR_SELECT_STATS_IMPROVEMENT
if (i == POINT_LEVEL)
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byLevel = PointsPacket.points[i];
else if (i == POINT_ST)
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byST = PointsPacket.points[i];
else if (i == POINT_HT)
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byHT = PointsPacket.points[i];
else if (i == POINT_DX)
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byDX = PointsPacket.points[i];
else if (i == POINT_IQ)
m_akSimplePlayerInfo[m_dwSelectedCharacterIndex].byIQ = PointsPacket.points[i];
#endif
}
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "RefreshStatus", Py_BuildValue("()"));
return true;

View File

@@ -532,6 +532,74 @@ void CPythonPlayer::NotifyChangePKMode()
PyCallClassMemberFunc(m_ppyGameWindow, "OnChangePKMode", Py_BuildValue("()"));
}
#ifdef FIX_REFRESH_SKILL_COOLDOWN
void CPythonPlayer::ResetSkillCoolTimes()
{
for (int i = 0; i < SKILL_MAX_NUM; ++i)
ResetSkillCoolTimeForSlot(i);
}
void CPythonPlayer::ResetSkillCoolTimeForSlot(DWORD dwSlotIndex)
{
if (dwSlotIndex >= SKILL_MAX_NUM)
return;
TSkillInstance& rkSkillInst = m_playerStatus.aSkill[dwSlotIndex];
// If this skill is a toggle and currently active, deactivate it so UI/state is consistent.
// __DeactivateSkillSlot is a private/protected helper on this class.
if (IsToggleSkill(dwSlotIndex) && IsSkillActive(dwSlotIndex))
__DeactivateSkillSlot(dwSlotIndex);
// If nothing to clear, skip
if (!rkSkillInst.fLastUsedTime && !rkSkillInst.fCoolTime)
return;
// Clear cooldown timers
rkSkillInst.fLastUsedTime = rkSkillInst.fCoolTime = 0.0f;
// Get the actual skill type to clear cooldowns from the correct storage
DWORD dwSkillType = CPythonSkill::SKILL_TYPE_ACTIVE; // default
DWORD dwSkillIndex = rkSkillInst.dwIndex;
CPythonSkill::TSkillData* pSkillData = NULL;
if (dwSkillIndex != 0 && CPythonSkill::Instance().GetSkillData(dwSkillIndex, &pSkillData))
{
dwSkillType = pSkillData->byType;
}
if (dwSkillType == CPythonSkill::SKILL_TYPE_ACTIVE)
{
for (int iGrade = 0; iGrade < CPythonSkill::SKILL_GRADE_COUNT; ++iGrade)
{
UI::CWindowManager::Instance().ClearStoredSlotCoolTimeInAllSlotWindows(
dwSkillType,
dwSlotIndex + iGrade * CPythonSkill::SKILL_GRADE_STEP_COUNT);
}
}
else
{
UI::CWindowManager::Instance().ClearStoredSlotCoolTimeInAllSlotWindows(dwSkillType, dwSlotIndex);
}
// Inform Python/UI which slot was cleared
PyCallClassMemberFunc(m_ppyGameWindow, "SkillClearCoolTime", Py_BuildValue("(i)", (int)dwSlotIndex));
}
void CPythonPlayer::ResetHorseSkillCoolTime(DWORD dwSkillIndex, DWORD dwVisualSlotIndex)
{
// Clear both the source slot (137-140) and the visual slot (0-3)
// so RestoreSlotCoolTime won't have anything to restore
UI::CWindowManager::Instance().ClearStoredSlotCoolTimeInAllSlotWindows(
CPythonSkill::SKILL_TYPE_HORSE,
dwSkillIndex);
UI::CWindowManager::Instance().ClearStoredSlotCoolTimeInAllSlotWindows(
CPythonSkill::SKILL_TYPE_HORSE,
dwVisualSlotIndex);
}
#endif
void CPythonPlayer::MoveItemData(TItemPos SrcCell, TItemPos DstCell)
{
@@ -993,6 +1061,7 @@ void CPythonPlayer::SetSkillLevel(DWORD dwSlotIndex, DWORD dwSkillLevel)
void CPythonPlayer::SetSkillLevel_(DWORD dwSkillIndex, DWORD dwSkillGrade, DWORD dwSkillLevel)
{
DWORD dwSlotIndex;
if (!GetSkillSlotIndex(dwSkillIndex, &dwSlotIndex))
return;
@@ -1004,39 +1073,46 @@ void CPythonPlayer::SetSkillLevel_(DWORD dwSkillIndex, DWORD dwSkillGrade, DWORD
case 0:
m_playerStatus.aSkill[dwSlotIndex].iGrade = dwSkillGrade;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel;
break;
case 1:
m_playerStatus.aSkill[dwSlotIndex].iGrade = dwSkillGrade;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel-20+1;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel - 20 + 1;
break;
case 2:
m_playerStatus.aSkill[dwSlotIndex].iGrade = dwSkillGrade;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel-30+1;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel - 30 + 1;
break;
case 3:
m_playerStatus.aSkill[dwSlotIndex].iGrade = dwSkillGrade;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel-40+1;
m_playerStatus.aSkill[dwSlotIndex].iLevel = dwSkillLevel - 40 + 1;
break;
}
const DWORD SKILL_MAX_LEVEL = 40;
if (dwSkillLevel>SKILL_MAX_LEVEL)
if (dwSkillLevel > SKILL_MAX_LEVEL)
{
m_playerStatus.aSkill[dwSlotIndex].fcurEfficientPercentage = 0.0f;
m_playerStatus.aSkill[dwSlotIndex].fnextEfficientPercentage = 0.0f;
TraceError("CPythonPlayer::SetSkillLevel(SlotIndex=%d, SkillLevel=%d)", dwSlotIndex, dwSkillLevel);
return;
}
m_playerStatus.aSkill[dwSlotIndex].fcurEfficientPercentage = LocaleService_GetSkillPower(dwSkillLevel)/100.0f;
m_playerStatus.aSkill[dwSlotIndex].fnextEfficientPercentage = LocaleService_GetSkillPower(dwSkillLevel+1)/100.0f;
#ifdef FIX_REFRESH_SKILL_COOLDOWN
if (m_playerStatus.aSkill[dwSlotIndex].iLevel <= 0)
{
ResetSkillCoolTimeForSlot(dwSlotIndex);
}
#endif
m_playerStatus.aSkill[dwSlotIndex].fcurEfficientPercentage = LocaleService_GetSkillPower(dwSkillLevel) / 100.0f;
m_playerStatus.aSkill[dwSlotIndex].fnextEfficientPercentage = LocaleService_GetSkillPower(dwSkillLevel + 1) / 100.0f;
}
void CPythonPlayer::SetSkillCoolTime(DWORD dwSkillIndex)
@@ -1568,7 +1644,19 @@ void CPythonPlayer::NEW_ClearSkillData(bool bAll)
for (it = m_skillSlotDict.begin(); it != m_skillSlotDict.end();)
{
#ifdef FIX_REFRESH_SKILL_COOLDOWN
CPythonSkill::TSkillData* data = nullptr;
if (!CPythonSkill::Instance().GetSkillData(it->first, &data))
{
++it;
continue;
}
if (bAll || (data->byType != CPythonSkill::SKILL_TYPE_SUPPORT && data->byType != CPythonSkill::SKILL_TYPE_HORSE && data->byType != CPythonSkill::SKILL_TYPE_GUILD))
#else
if (bAll || __GetSkillType(it->first) == CPythonSkill::SKILL_TYPE_ACTIVE)
#endif
it = m_skillSlotDict.erase(it);
else
++it;
@@ -1576,6 +1664,24 @@ void CPythonPlayer::NEW_ClearSkillData(bool bAll)
for (int i = 0; i < SKILL_MAX_NUM; ++i)
{
#ifdef FIX_REFRESH_SKILL_COOLDOWN
DWORD dwSkillIndex = m_playerStatus.aSkill[i].dwIndex;
CPythonSkill::TSkillData* pSkillData = NULL;
// Skip empty slots
if (dwSkillIndex == 0)
continue;
if (!CPythonSkill::Instance().GetSkillData(dwSkillIndex, &pSkillData))
continue;
// If not clearing all, skip persistent skill types (SUPPORT, HORSE, GUILD)
if (!bAll && (pSkillData->byType == CPythonSkill::SKILL_TYPE_SUPPORT ||
pSkillData->byType == CPythonSkill::SKILL_TYPE_HORSE ||
pSkillData->byType == CPythonSkill::SKILL_TYPE_GUILD))
continue;
#endif
ZeroMemory(&m_playerStatus.aSkill[i], sizeof(TSkillInstance));
}
@@ -1583,8 +1689,22 @@ void CPythonPlayer::NEW_ClearSkillData(bool bAll)
{
// 2004.09.30.myevan.스킬갱신시 스킬 포인트업[+] 버튼이 안나와 처리
m_playerStatus.aSkill[j].iGrade = 0;
m_playerStatus.aSkill[j].fcurEfficientPercentage=0.0f;
m_playerStatus.aSkill[j].fnextEfficientPercentage=0.05f;
m_playerStatus.aSkill[j].fcurEfficientPercentage = 0.0f;
m_playerStatus.aSkill[j].fnextEfficientPercentage = 0.05f;
#ifdef FIX_REFRESH_SKILL_COOLDOWN
m_playerStatus.aSkill[j].isCoolTime = false;
m_playerStatus.aSkill[j].fCoolTime = 0.0f;
m_playerStatus.aSkill[j].fLastUsedTime = 0.0f;
//ResetSkillCoolTimeForSlot(j);
for (int iGrade = 0; iGrade < CPythonSkill::SKILL_GRADE_COUNT; ++iGrade)
{
UI::CWindowManager::Instance().ClearStoredSlotCoolTimeInAllSlotWindows(
CPythonSkill::SKILL_TYPE_ACTIVE,
j + iGrade * CPythonSkill::SKILL_GRADE_STEP_COUNT);
}
#endif
}
if (m_ppyGameWindow)

View File

@@ -262,6 +262,11 @@ class CPythonPlayer : public CSingleton<CPythonPlayer>, public IAbstractPlayer
void NotifyCharacterUpdate(DWORD dwVID);
void NotifyDeadMainCharacter();
void NotifyChangePKMode();
#ifdef FIX_REFRESH_SKILL_COOLDOWN
void ResetSkillCoolTimes();
void ResetSkillCoolTimeForSlot(DWORD dwSlotIndex);
void ResetHorseSkillCoolTime(DWORD dwSkillIndex, DWORD dwVisualSlotIndex);
#endif
// Player Status

View File

@@ -132,10 +132,26 @@ void CPythonPlayerEventHandler::OnChangeShape()
CPythonPlayer::Instance().NEW_Stop();
}
#ifdef FIX_POS_SYNC
void CPythonPlayerEventHandler::OnHit(UINT uSkill, CActorInstance& rkActorVictim, BOOL isSendPacket, CActorInstance::BlendingPosition* sBlending)
#else
void CPythonPlayerEventHandler::OnHit(UINT uSkill, CActorInstance& rkActorVictim, BOOL isSendPacket)
#endif
{
DWORD dwVIDVictim=rkActorVictim.GetVirtualID();
#ifdef FIX_POS_SYNC
CPythonCharacterManager::Instance().AdjustCollisionWithOtherObjects(&rkActorVictim);
CActorInstance::BlendingPosition kBlendingPacket;
memset(&kBlendingPacket, 0, sizeof(kBlendingPacket));
kBlendingPacket.source = rkActorVictim.NEW_GetCurPixelPositionRef();
if (rkActorVictim.IsPushing()) {
kBlendingPacket.dest = rkActorVictim.NEW_GetLastPixelPositionRef();
kBlendingPacket.duration = sBlending->duration;
}
#endif
// Update Target
CPythonPlayer::Instance().SetTarget(dwVIDVictim, FALSE);
// Update Target
@@ -165,7 +181,11 @@ void CPythonPlayerEventHandler::OnHit(UINT uSkill, CActorInstance& rkActorVictim
s_prevTimed[dwVIDVictim] = curTime;
#endif
CPythonNetworkStream& rkStream=CPythonNetworkStream::Instance();
#ifdef FIX_POS_SYNC
rkStream.SendAttackPacket(uSkill, dwVIDVictim, isSendPacket, kBlendingPacket);
#else
rkStream.SendAttackPacket(uSkill, dwVIDVictim);
#endif
}
if (!rkActorVictim.IsPushing())

View File

@@ -27,7 +27,11 @@ class CPythonPlayerEventHandler : public CActorInstance::IEventHandler
virtual void OnUseSkill(const SState& c_rkState, UINT uMotSkill, UINT uArg);
virtual void OnUpdate();
virtual void OnChangeShape();
#ifdef FIX_POS_SYNC
virtual void OnHit(UINT uSkill, CActorInstance& rkActorVictim, BOOL isSendPacket, CActorInstance::BlendingPosition* sBlending);
#else
virtual void OnHit(UINT uSkill, CActorInstance& rkActorVictim, BOOL isSendPacket);
#endif
void FlushVictimList();

View File

@@ -543,6 +543,31 @@ PyObject * playerGetSkillCoolTime(PyObject* poSelf, PyObject* poArgs)
return Py_BuildValue("ff", fCoolTime, fElapsedCoolTime);
}
#ifdef FIX_REFRESH_SKILL_COOLDOWN
PyObject * playerResetSkillCoolTimeForSlot(PyObject* poSelf, PyObject* poArgs)
{
int iSlotIndex;
if (!PyTuple_GetInteger(poArgs, 0, &iSlotIndex))
return Py_BuildException();
CPythonPlayer::Instance().ResetSkillCoolTimeForSlot(iSlotIndex);
return Py_BuildNone();
}
PyObject* playerResetHorseSkillCoolTime(PyObject* poSelf, PyObject* poArgs)
{
DWORD dwSkillIndex;
DWORD dwVisualSlotIndex;
if (!PyArg_ParseTuple(poArgs, "ii", &dwSkillIndex, &dwVisualSlotIndex))
return Py_BuildException();
CPythonPlayer::Instance().ResetHorseSkillCoolTime(dwSkillIndex, dwVisualSlotIndex);
Py_RETURN_NONE;
}
#endif
PyObject * playerIsSkillActive(PyObject* poSelf, PyObject* poArgs)
{
int iSlotIndex;
@@ -2233,6 +2258,10 @@ void initPlayer()
{ "IsSkillCoolTime", playerIsSkillCoolTime, METH_VARARGS },
{ "GetSkillCoolTime", playerGetSkillCoolTime, METH_VARARGS },
#ifdef FIX_REFRESH_SKILL_COOLDOWN
{ "ResetSkillCoolTimeForSlot", playerResetSkillCoolTimeForSlot, METH_VARARGS },
{ "ResetHorseSkillCoolTime", playerResetHorseSkillCoolTime, METH_VARARGS },
#endif
{ "IsSkillActive", playerIsSkillActive, METH_VARARGS },
{ "UseGuildSkill", playerUseGuildSkill, METH_VARARGS },
{ "AffectIndexToSkillIndex", playerAffectIndexToSkillIndex, METH_VARARGS },