Files
Client/Server/RylServerProject/RylGameLibrary/Creature/Monster/MonsterShout.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

320 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "stdafx.h"
#include "MonsterShout.h"
#include "MonsterMgr.h"
#include "ScriptEngine/ScriptEngine.h"
#include <Network/Packet/ChatPacket.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Dispatch/Chat/ChatDispatch.h>
#include <Map/FieldMap/Cell.h>
#include <Utility/Math/Math.h>
#include <Creature/CreatureManager.h>
#include <Creature/Monster/Monster.h>
const char* CMonsterShout::ms_DefaultFileName = "./Script/Game/MonsterChat.gsf";
CMonsterShout& CMonsterShout::GetInstance()
{
static CMonsterShout monsterShout;
return monsterShout;
}
CMonsterShout::CMonsterShout()
{
}
CMonsterShout::~CMonsterShout()
{
ShoutMap::iterator pos = m_ShoutMap.begin();
ShoutMap::iterator end = m_ShoutMap.end();
for(; pos != end; ++pos)
{
ShoutInfo& shoutInfo = pos->second;
ChatNode* lpNode = shoutInfo.m_lpNextNode;
ChatNode* lpDeleteNode = lpNode;
while(0 != lpNode)
{
lpDeleteNode = lpNode;
lpNode = lpNode->m_lpNextNode;
delete lpDeleteNode;
}
}
}
void SetShoutText(int nKID, int nBehavior, int nSkill_ID,
int nChatType, int nPercentage, const char* szMessage)
{
CMonsterShout::ShoutInfo shoutInfo;
CMonsterShout::ChatNode chatNode;
memset(&shoutInfo, 0, sizeof(CMonsterShout::ShoutInfo));
memset(&chatNode, 0, sizeof(CMonsterShout::ChatNode));
shoutInfo.m_nKID = nKID;
shoutInfo.m_nBehavior = nBehavior;
shoutInfo.m_nSkill_ID = nSkill_ID;
shoutInfo.m_nChatType = nChatType;
chatNode.m_nPercentage = nPercentage;
const CMonsterMgr::MonsterProtoType* lpMonsterProtoType =
CMonsterMgr::GetInstance().GetMonsterProtoType(nKID);
if(0 != szMessage && 0 != lpMonsterProtoType)
{
if(shoutInfo.m_nBehavior != CMonsterShout::RESPAWN)
{
_snprintf(chatNode.m_szMonsterChat, MAX_PATH - 1, "%s : %s",
lpMonsterProtoType->m_MonsterInfo.m_strName, szMessage);
}
else
{
_snprintf(chatNode.m_szMonsterChat, MAX_PATH - 1, "%s", szMessage);
}
chatNode.m_szMonsterChat[MAX_PATH - 1] = 0;
chatNode.m_usChatLength =
static_cast<unsigned short>(strlen(chatNode.m_szMonsterChat)) + 1;
CMonsterShout::GetInstance().AddMonsterShout(shoutInfo, chatNode);
}
}
bool CMonsterShout::LoadScript(const char* szFileName)
{
SCRIPT Script = _SE_Create(szFileName);
if (NULL == Script)
{
return false;
}
_SE_RegisterFunction(Script, SetShoutText, T_VOID,
"MonsterChat", T_INT, T_INT, T_INT, T_INT, T_INT, T_STRING, 0);
_SE_Execute(Script);
_SE_Destroy(Script);
return true;
}
void CMonsterShout::Shout(unsigned long dwMonsterCID, unsigned long nKID,
unsigned short usXPos, unsigned short usZPos,
Behavior eBehavior, const char* szName, unsigned short usSkill_ID)
{
// KID<49><44> <20>˻<EFBFBD><CBBB>Ѵ<EFBFBD>.
// Ȯ<><C8AE> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˻<EFBFBD><CBBB>Ѵ<EFBFBD>.
std::pair<ShoutMap::iterator, ShoutMap::iterator> result = m_ShoutMap.equal_range(nKID);
std::vector<int> shoutedList;
for(; result.first != result.second; ++result.first)
{
ShoutInfo& shoutInfo = result.first->second;
bool bChatSend = false;
if(shoutInfo.m_nBehavior == eBehavior)
{
if(SKILL_ATTACK == eBehavior || SKILL_ATTACKED == eBehavior)
{
// <20><>ų<EFBFBD><C5B3> <20><><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ų Ÿ<>Ե<EFBFBD> Ȯ<><C8AE><EFBFBD>ؾ<EFBFBD> <20>Ѵ<EFBFBD>.
if(shoutInfo.m_nSkill_ID == 0xFFFF || shoutInfo.m_nSkill_ID == usSkill_ID)
{
bChatSend = true;
}
}
else
{
bChatSend = true;
}
// <20>̹<EFBFBD> <20><>ģ ChatType<70≯<EFBFBD> <20><>ġ<EFBFBD><C4A1> <20>ʴ´<CAB4>.
if(shoutedList.end() !=
std::find(shoutedList.begin(), shoutedList.end(), shoutInfo.m_nChatType))
{
bChatSend = false;
}
int nRand = Math::Random::ComplexRandom(100, 1);
if(bChatSend && (nRand < shoutInfo.m_nTotalPercentage))
{
// <20><><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD>߿<EFBFBD><DFBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int nPercentage = 0;
ChatNode* lpNode = shoutInfo.m_lpNextNode;
while(0 != lpNode)
{
if(nPercentage <= nRand && nRand <= nPercentage + lpNode->m_nPercentage)
{
// <20><><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ȿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Break;
break;
}
nPercentage += lpNode->m_nPercentage;
lpNode = lpNode->m_lpNextNode;
}
if(0 != lpNode)
{
shoutedList.push_back(shoutInfo.m_nChatType);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ä<><C3A4><EFBFBD><EFBFBD> ä<>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. usState<74><65> X<><58>ǥ, usError<6F><72> Z<><5A>ǥ<EFBFBD>̴<EFBFBD>.
// <20><><EFBFBD><EFBFBD> ä<><C3A4><EFBFBD>϶<EFBFBD><CFB6><EFBFBD> <20><>ǥ<EFBFBD><C7A5> <20>ǹ̰<C7B9> <20>ִ<EFBFBD>.
char szChatBuffer[PktChat::PktChatMaxSize * 2];
char szNameBuffer[PktChat::PktChatMaxSize];
szChatBuffer[0] = 0;
szNameBuffer[0] = 0;
if(0 != szName)
{
// <20≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>..
_snprintf(szNameBuffer, PktChat::PktChatMaxSize - 1, "%s", szName);
szNameBuffer[PktChat::PktChatMaxSize - 1];
}
const char* szTarget = 0;
char* szTargetPos = 0;
size_t nTargetLen = 0;
char* szMessageResult = 0;
size_t nMessageLen = 0;
switch(shoutInfo.m_nBehavior)
{
case NORMAL_ATTACK:
case SKILL_ATTACK:
case CRITICAL_ATTACK:
szTarget = "$DEFNAME$";
break;
case NORMAL_ATTACKED:
case SKILL_ATTACKED:
case CRITICAL_ATTACKED:
szTarget = "$ATTNAME$";
break;
case DEAD:
szTarget = "$KILLERNAME$";
break;
}
if(0 != szTarget && (szTargetPos = strstr(lpNode->m_szMonsterChat, szTarget)))
{
// ġȯ<C4A1>ؼ<EFBFBD> <20><><EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD>.
nTargetLen = strlen(szTarget);
const char* szLastMessage = szTargetPos + nTargetLen;
size_t nPreMessageLen = szTargetPos - lpNode->m_szMonsterChat;
memcpy(szChatBuffer, lpNode->m_szMonsterChat, nPreMessageLen);
nMessageLen = _snprintf(szChatBuffer + nPreMessageLen,
PktChat::PktChatMaxSize * 2 - 1, "%s%s", szNameBuffer, szLastMessage);
szMessageResult = szChatBuffer;
nMessageLen += nPreMessageLen;
}
else
{
szMessageResult = lpNode->m_szMonsterChat;
nMessageLen = lpNode->m_usChatLength;
}
PktChat::PktChatCmd eChatCmd = static_cast<PktChat::PktChatCmd>(shoutInfo.m_nChatType);
CChatPacket chatPacket(szMessageResult, dwMonsterCID, eChatCmd, 0);
if(chatPacket.IsValid())
{
// ê Ÿ<><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>/<2F>Ϲ<EFBFBD>/<2F><>ġ<EFBFBD><C4A1> <20><><EFBFBD>̴<EFBFBD>.
switch(eChatCmd)
{
case PktChat::SHOUT:
case PktChat::NOTICE:
// <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
CCreatureManager::GetInstance().SendAllCharacter(
chatPacket.GetCompressedPacket(),
chatPacket.GetCompressedSize(), CmdCharChat);
break;
case PktChat::NORMAL:
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֺ<EFBFBD> 8<><38> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
CMonster* lpMonster =
CCreatureManager::GetInstance().GetMonster(dwMonsterCID);
CCell* lpCell = 0;
if(0 != lpMonster && 0 != (lpCell = lpMonster->GetCellPos().m_lpCell))
{
lpCell->SendAllNearCellCharacter(
chatPacket.GetPacketData(),
chatPacket.GetPacketSize(), CmdCharChat);
}
}
break;
}
}
}
}
}
};
}
void CMonsterShout::AddMonsterShout(ShoutInfo& shoutInfo, ChatNode& chatNode)
{
std::pair<ShoutMap::iterator, ShoutMap::iterator> result = m_ShoutMap.equal_range(shoutInfo.m_nKID);
for(; result.first != result.second; ++result.first)
{
ShoutInfo& foundShoutInfo = result.first->second;
if(foundShoutInfo.m_nKID == shoutInfo.m_nKID &&
foundShoutInfo.m_nBehavior == shoutInfo.m_nBehavior &&
foundShoutInfo.m_nSkill_ID == shoutInfo.m_nSkill_ID &&
foundShoutInfo.m_nChatType == shoutInfo.m_nChatType)
{
foundShoutInfo.m_nTotalPercentage += chatNode.m_nPercentage;
ChatNode* lpNode = foundShoutInfo.m_lpNextNode;
while(0 != lpNode && 0 != lpNode->m_lpNextNode)
{
lpNode = lpNode->m_lpNextNode;
}
if(0 != lpNode && 0 == lpNode->m_lpNextNode)
{
lpNode->m_lpNextNode = new ChatNode(chatNode);
}
break;
}
}
if(result.first == result.second)
{
shoutInfo.m_lpNextNode = new ChatNode(chatNode);
shoutInfo.m_nTotalPercentage = chatNode.m_nPercentage;
m_ShoutMap.insert(std::make_pair(shoutInfo.m_nKID, shoutInfo));
}
}