Files
Sun1602/Server/GameServer/ChangeMonsterAbility.cpp
2022-10-26 12:25:11 +08:00

132 lines
4.2 KiB
C++

#include "StdAfx.h"
#include "ChangeMonsterAbility.h"
#include "GameZone.h"
#include "Monster.h"
#include "GameCHuntingRoom.h"
#include "CHuntingManager.h"
#include "CharacterFormula.h"
#include "Map.h"
ChangeMonsterAbility g_ChangeMonsterAbility;
VOID
ChangeMonsterAbility::UpdateMonster(GameZone* pZone, NPC* pNPC)
{
if(pZone == 0)
return;
sPOLICY_ZONE& Policyment = pZone->Policyment;
if(Policyment.FIELD & Policyment.ENABLE_CHANGE_MOB_ABILITY)
{
const BYTE player_count = GetPlayerNum(pZone);
if(!player_count)
return;
pNPC->SetHPAttackPowerAsParty(player_count);
}
}
VOID
ChangeMonsterAbility::UpdateAllMonster(GameZone* pZone)
{
if(pZone == 0)
return;
sPOLICY_ZONE& Policyment = pZone->Policyment;
if(Policyment.FIELD & Policyment.ENABLE_CHANGE_MOB_ABILITY)
{
const BYTE player_number = GetPlayerNum(pZone, TRUE);
if(player_number == 0)
return;
// 변경된 HP 비율을 존에 알린다.
const FLOAT fIncreaseRatio = CalcHPIncreaseRatioAsParty(player_number);
MSG_CG_STATUS_CHANGE_MONSTER_ABILITY msg;
msg.m_fHPRatio = fIncreaseRatio;
pZone->SendPacketToAll(&msg, sizeof(msg));
// Zone의 모든 필드에 적용한다.
const _GAMEFIELD_HASH& rFields = pZone->GetFieldHash();
FOREACH_CONTAINER(const _GAMEFIELD_HASH::value_type& rField, rFields, _GAMEFIELD_HASH)
{
GameField* const pField = rField.second;
typedef GameField::_NPC_HASH _NPC_HASH;
const _NPC_HASH& rMobs = pField->GetRefNPCList();
FOREACH_CONTAINER(const _NPC_HASH::value_type& rMob, rMobs, _NPC_HASH)
{
NPC* const pNPC = rMob.second;
//#ifdef _NA_004126_20120111_CHANGE_GAME_SERVER_OBJECT_FACTORY
if (pNPC != NULL && pNPC->IsDeleted())
{
const Object::Key key = pNPC->GetObjectKey();
SUNLOG(
eCRITICAL_LOG,
_T("|%s|%d|Object is already deleted.|ObjectKey = %d|"),
__FUNCTION__,
__LINE__,
key
);
continue;
}
//#endif
pNPC->SetHPAttackPowerAsParty(player_number);
}
}
}
}
void
ChangeMonsterAbility::NotifyChangeAbility(GameZone* pZone, Player* pPlayer)
{
BYTE number_of_players = GetPlayerNum(pZone);
if(number_of_players == 0)
return;
// 변경된 HP 비율을 알린다.
MSG_CG_STATUS_CHANGE_MONSTER_ABILITY msg;
msg.m_fHPRatio = CalcHPIncreaseRatioAsParty(number_of_players);
pPlayer->SendPacket(&msg, sizeof(msg));
}
BYTE
ChangeMonsterAbility::GetPlayerNum(GameZone* pZone, BOOLEAN bRefresh)
{
const DWORD AcceptMask = (1 << eZONETYPE_MISSION)
| (1 << eZONETYPE_HUNTING)
| (1 << eZONETYPE_CHUNTING)
| (1 << eZONETYPE_INSTANCE);
DWORD zone_type_flag = pZone->GetZoneType();
zone_type_flag = 1 << zone_type_flag;
if((AcceptMask & zone_type_flag) == 0)
return 0; // 이 값이면 Default이므로, 1과 결과가 동일할 것이다.
WORD number_of_expected_players = 0;
if(bRefresh == 0)
number_of_expected_players = pZone->GetNumberOfExpectedPlayers();
else if(pZone->UpdateNumberOfExpectedPlayers(&number_of_expected_players) == 0)
return 0;
//DWORD number_of_expected_players = pZone->GetNumberOfExpectedPlayers();
//const BOOLEAN assert_cond =
// !!FlowControl::FCAssert(SAFE_NUMERIC_TYPECAST(DWORD, number_of_expected_players, BYTE));
//if(assert_cond == 0)
// number_of_expected_players = pZone->GetPlayerNum();
if((1 << eZONETYPE_CHUNTING) & zone_type_flag)
{
CHuntingManager* pHuntingManager = static_cast<GameCHuntingRoom*>(pZone)->GetCHuntingManager();
if(pHuntingManager == 0)
return 0; //null인 경우가 있으면... 안 되는 뎅...
if(pHuntingManager->GetCompetitionState() != eCOMPETITION_NONE)
number_of_expected_players = number_of_expected_players >> 1;
}
return BYTE(max(1, number_of_expected_players));
}