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

368 lines
11 KiB
C++

#include "StdAfx.h"
#ifdef _NA_1419_20100121_ACCUMULATE_POINT
#include ".\AccumulatePoint.h"
#include ".\Player.h"
#include <AccumulatePointParser.h>
#include <AccumulatePointData.h>
#define ONE_SECOND 1000
class TempTimer : public util::Timer
{
public:
TempTimer(uint interval_time)
{
SetTimer(interval_time);
}
~TempTimer() {}
uint Update()
{
uint progress_time = GetProcessTime() / GetIntervalTime();
IsExpired(TRUE);
return progress_time;
}
};
struct GlobalData
{
GlobalData():
year(0),
dayofweek(0),
increase_second(0),
event_time(false)
{
}
ushort year;
ushort dayofweek;
bool event_time;
uint increase_second;
};
GlobalData global_data;
void AccumulatePoint::SyncMatchDate(ushort year, ushort dayofweek, uint secondofday)
{
global_data.year = year;
global_data.dayofweek = dayofweek;
global_data.event_time = false;
#ifdef _NA_0_20100528_ACCUMULATE_POINT_EVENT
const AccumulatePointParser::RewardGroup& reward_group =
AccumulatePointParser::Instance()->get_reward_group(global_data.dayofweek);
const AccumulatePointParser::RewardGroup::RewardEvent& reward_event = reward_group.reward_event;
if ((reward_event.start_time == 0) && (reward_event.end_time == 0))
{
global_data.event_time = false;
}
else
{
uint second = secondofday;
if ((reward_event.start_time <= second) && (reward_event.end_time > second))
global_data.event_time = true;
else
global_data.event_time = false;
}
#endif
}
// 현재 년도 및 플레이어의 게임 플레이 증가 시간(초 단위)을 설정 한다.
// 서버가 실행되는 동안 해당 년도가 바뀔 수 있기 때문에 Update 동안 호출한다.
// 년도 및 플레이어의 증가 시간은 여러 AccumulatePoint 객체가 공통으로 사용 하기에 전역으로 선언한다.
// 매 Update마다 틱 카운트를 누적해 1초 이상인 경우 AccumulatePoint::increase_second_에 설정.
// 각 플레이어의 시간 계산을 전역적으로 1번만 하기 위한 방편이다.
void AccumulatePoint::Calculate_Current_Year(uint delta_tick_count)
{
static TempTimer second_timer(ONE_SECOND);
// 누적된 초값을 전역적으로 저장해놓는다. 플레이어 당 매번 계산하는 것 보다 어느 정도의 오차를
// 허용하므로 전역적으로 계산을 1번 하는게 낫다.
global_data.increase_second = second_timer.Update();
}
AccumulatePoint::AccumulatePoint(Player* player) :
player_(player),
playerinfo_(NULL)
{
ASSERT(player_);
}
AccumulatePoint::~AccumulatePoint()
{
}
// Player 메모리 풀에서 생성자및 소멸자를 호출이 일어나지 않아 초기화 부분을 정의함.
void AccumulatePoint::Init(Player* player)
{
ASSERT(player);
if (player == NULL)
return;
ASSERT(player->GetCharInfo());
if (player->GetCharInfo() == NULL)
return;
const AccumulatePointParser::RewardGroup& reward_group =
AccumulatePointParser::Instance()->get_reward_group(global_data.dayofweek);
player_ = player;
playerinfo_ = player->GetCharInfo();
generated_ = false;
reserved_data_.dayofweek = global_data.dayofweek;
reserved_data_.event_time = global_data.event_time;
reserved_data_.require_point = reward_group.require_point;
reserved_data_.reward_code = 0;
current_data_ = reserved_data_;
}
void AccumulatePoint::Release()
{
player_ = NULL;
playerinfo_ = NULL;
}
// Player::Update() 내부에서 호출된다.
// Player의 접속시간을 (초 단위)로 증가 시키며, 특정 시간 마다 마일리지 코인을 1 증가 시킨다.
// 만약, 매년 1월 1일(즉 해당 연도가 바뀔 경우)일때 적립시간을 초기화 시키며 코인은 그대로 유지한다.
void AccumulatePoint::Update()
{
// 플레이어가 ZONE 에 존재 하지 않는 경우 Update()를 실행하지 않는다.
// ZONE 에 존재 유무 판별은 class PlayerManager::Update() 에서 체크하고있다.
// 만약, ZONE의 판별을 직접처리 해야할 경우 아래의 구문을 사용한다.
//GameZone* pEnterZone = NULL;
//MAPCODE EnterFieldCode = 0;
//const eZONE_STATE eRoomState = pPlayer->GetGameZone( pEnterZone, EnterFieldCode );
//if ( !(eRoomState & ePRS_AT_ZONE) )
// return;
// 아직 EnterField 전이면 Update를 실행하지 않는다.
// EnterField 판별문은 class Player::Update() 시작시 체크하고있다.
// 만약, EnterField의 판별을 직접처리 해야할 경우 아래의 구문을 사용한다.
//GameField* pField = player_pointer_->GetField();
//if ( !(pField && pField->IsReady()) )
// return;
ASSERT(player_ && playerinfo_);
if (player_ == NULL || playerinfo_ == NULL)
return;
static MSG_CG_CHARINFO_ACCUMULATE_POINT_CMD send_message;
// 초 단위로 증가된 값이 존재할때만 체크한다.
if (global_data.increase_second == 0)
return;
const AccumulatePointParser::RewardGroup& reward_group =
AccumulatePointParser::Instance()->get_reward_group(global_data.dayofweek);
// 0으로 나누기 오류 피하기
// 해당 값을 0으로 세팅하는 국가에 대량으로 로그가 남는 경우가 존재하여 주석 처리함.
// ASSERT(reward_group.generate_time);
if (reward_group.generate_time == 0)
return;
// 년도가 바뀐경우 적립시간을 초기화 시킨다.
if (global_data.year != playerinfo_->m_wAccumulateYear)
{
playerinfo_->m_wAccumulateYear = global_data.year;
playerinfo_->m_dwAccumulateTime = 0;
GAMELOG->LogAccumulatePoint(ACCUM_CHANGE_YEAR, player_, 0, 0);
send_message.m_dwReason = RC::RC_ACCUMULATE_POINT_INITIALIZE;
send_message.m_dwAccumulateTime = playerinfo_->m_dwAccumulateTime;
send_message.m_wAccumulatePoint = playerinfo_->m_wAccumulatePoint;
send_message.m_byRequirePoint = reward_group.require_point;
player_->SendPacket(&send_message, sizeof(send_message));
}
// 보상에 필요한 요구 코인이 변경된 경우.
if (reward_group.require_point != reserved_data_.require_point)
{
reserved_data_.require_point = reward_group.require_point;
send_message.m_dwReason = RC::RC_ACCUMULATE_POINT_CHANGE_REQUIRE_POINT;
send_message.m_dwAccumulateTime = playerinfo_->m_dwAccumulateTime;
send_message.m_wAccumulatePoint = playerinfo_->m_wAccumulatePoint;
send_message.m_byRequirePoint = reward_group.require_point;
player_->SendPacket(&send_message, sizeof(send_message));
}
// 현재의 요일이 변경된 경우
reserved_data_.dayofweek = global_data.dayofweek;
// 이벤트 시간이 변경된 경우
reserved_data_.event_time = global_data.event_time;
// 마일리지 시간을 누적시킨다.(초 단위)
// 시간 변화 : 증가 전 시간 - 증가 후 시간
int before_second = playerinfo_->m_dwAccumulateTime / reward_group.generate_time;
playerinfo_->m_dwAccumulateTime += global_data.increase_second;
if ((playerinfo_->m_dwAccumulateTime / reward_group.generate_time) - before_second)
{
if (PlusAccumulatePoint(reward_group.generate_point))
{
GAMELOG->LogAccumulatePoint(ACCUM_ACQUISITION_TIME, player_, reward_group.generate_point, 0);
send_message.m_dwReason = RC::RC_ACCUMULATE_POINT_SUCCESS;
send_message.m_dwAccumulateTime = playerinfo_->m_dwAccumulateTime;
send_message.m_wAccumulatePoint = playerinfo_->m_wAccumulatePoint;
send_message.m_byRequirePoint = reward_group.require_point;
player_->SendPacket(&send_message, sizeof(send_message));
}
}
}
bool AccumulatePoint::GenerateReward(bool first)
{
bool change_data = false;
// 이벤트가 변경되었을 경우.
if (current_data_.event_time != reserved_data_.event_time)
change_data = true;
// 요일이 변경되었을 경우.
if (current_data_.dayofweek != reserved_data_.dayofweek)
change_data = true;
if (first)
{
if (!generated_)
change_data = true;
}
if (change_data)
{
current_data_ = reserved_data_;
generated_ = false;
}
if (!generated_)
{
const AccumulatePointParser::RewardGroup& reward_group =
AccumulatePointParser::Instance()->get_reward_group(current_data_.dayofweek);
#ifdef _NA_0_20100528_ACCUMULATE_POINT_EVENT
if (current_data_.event_time)
{
current_data_.reward_code = reward_group.reward_event.reward_code;
current_data_.require_point = reward_group.require_point;
}
else
#endif
{
uint seed = random(0, (AccumulatePointParser::RewardGroup::Max_Reward - 1));
current_data_.reward_code = reward_group.reward_array[seed].reward_code;
current_data_.require_point = reward_group.require_point;
}
}
generated_ = ((current_data_.reward_code > 0) && (current_data_.require_point > 0)) ? true : false;
return generated_;
}
void AccumulatePoint::ResetReward()
{
generated_ = false;
}
void AccumulatePoint::SendPacketAccumulatePoint()
{
ASSERT(player_ && playerinfo_);
if (player_ == NULL || playerinfo_ == NULL)
return;
MSG_CG_CHARINFO_ACCUMULATE_POINT_CMD send_message;
send_message.m_dwReason = RC::RC_ACCUMULATE_POINT_SUCCESS;
send_message.m_dwAccumulateTime = playerinfo_->m_dwAccumulateTime;
send_message.m_wAccumulatePoint = playerinfo_->m_wAccumulatePoint;
send_message.m_byRequirePoint = current_data_.require_point;
player_->SendPacket(&send_message, sizeof(send_message));
}
bool AccumulatePoint::PlusAccumulatePoint(ushort accumulate_point)
{
ASSERT(player_ && playerinfo_);
if (player_ == NULL || playerinfo_ == NULL)
return false;
uint max_point = 65000;
uint next_point = playerinfo_->m_wAccumulatePoint + accumulate_point;
#ifdef _NA_0_20101011_ACCUMULATE_POINT_LIMIT_OPTION
const AccumulatePointParser::RewardGroup& reward_group =
AccumulatePointParser::Instance()->get_reward_group(global_data.dayofweek);
// 적립포인트를 받기위한 최소 레벨보다 작은 경우( 0인 경우 최소 레벨 제한없음)
if ((reward_group.limit_option.receptible_min_level != 0) && (playerinfo_->m_LV < reward_group.limit_option.receptible_min_level))
return false;
// 적립포인트를 받기위한 최대 레벨보다 작은 경우( 0인 경우 최대 레벨 제한없음)
if ((reward_group.limit_option.receptible_max_level != 0) && (playerinfo_->m_LV > reward_group.limit_option.receptible_max_level))
return false;
// 적립포인트 최대치 설정
if (reward_group.limit_option.limit_max_point != 0)
max_point = reward_group.limit_option.limit_max_point;
#endif
playerinfo_->m_wAccumulatePoint = min(next_point, max_point);
return (next_point <= max_point) ? true : false;
}
void AccumulatePoint::MinusAccumulatePoint(ushort accumulate_point)
{
ASSERT(player_ && playerinfo_);
if (player_ == NULL || playerinfo_ == NULL)
return;
playerinfo_->m_wAccumulatePoint = max((playerinfo_->m_wAccumulatePoint - accumulate_point), 0);
}
ushort AccumulatePoint::get_accumulate_point() const
{
ASSERT(player_ && playerinfo_);
if (player_ == NULL || playerinfo_ == NULL)
return 0;
return playerinfo_->m_wAccumulatePoint;
}
uint AccumulatePoint::get_accumulate_time() const
{
ASSERT(player_ && playerinfo_);
if (player_ == NULL || playerinfo_ == NULL)
return 0;
return playerinfo_->m_dwAccumulateTime;
}
#endif //_NA_1419_20100121_ACCUMULATE_POINT