随机活动分析
随机活动是一种全局系统,全局系统都采取了单例模式。
活动类型
每一个活动都有一个活动类型,它们统一定义在activitydef.h文件中。随机活动定义在枚举RAND_ACTIVITY_TYPE
中。在设计一个活动之前,首先需要定义一个活动类型。
随机活动类都有一个基类RandActivity
,它们被统一管理到RandActivityManager
的容器当中。基类提供了一些虚函数,它们大多是一些事件处理函数,比如当玩家登陆、登出。
一个随机活动类的定义如:
class RandActivitySome : public RandActivity{public: RandActivitySome(RandActivityManager *act_mgr) : RandActivity(act_mgr, RAND_ACTIVITY_TYPE_SOME) {}};
活动状态切换
活动的状态有三种:关闭,准备,开启,它们定义在枚举ACTIVITY_STATUS
中。
但是随机活动只有两种状态:关闭,开启。我们通过两种方式修改活动的状态:
-
通过配置调整活动时间,这个配置是S-随机活动开启配置.xls,对应的类型是RandActivityOpenCfg
-
通过GM命令强制切换活动状态,这个命令是:
/gm activitynextstate:activity_type
强制切换状态后活动的时间会被调整,比较蛋疼的是,这个时间是通过读取了dynamic_cfg.xml来调整的。
关于活动时间计算的已由基类RandActivity实现好了,因此我们在写代码的时候基本是不需要考虑的。如果我们需要对活动状态改变编写相关逻辑,只要在活动状态切换时,覆盖接口
RandActivity::OnSpecialActivityStatusChange
即可。
正确覆盖虚函数
当我们覆盖虚函数以实现派生类的逻辑时,要考虑到基类有没有相关的实现,如果有,我们很可能要调用一下基类的实现。比如:
void RandActivitySome::OnSpecialActivityStatusChange(int from_status, int to_status){ RandActivity::OnSpecialActivityStatusChange(from_status, to_status); // derived class logic...}
如果我们在这里忘记调用基类的实现,具体会出现什么问题?请结合项目实际代码分析。
随机活动数据存储
全局数据存储
随机活动拥有一块存储结构RandActivityParam
,它存储在worldstatus表的rand_activity_data字段里。对于每一个随机活动,它也拥有一块固定的存储结构RandActivityData
,我们可以往里面存放少量的随机活动数据,比如对于一个充值活动,可能需要记录活动开始到现在充值了的玩家数。
如果我们需要存储数据,还必须编写相关的代码才行。一个比较常规的解决方法是:
class RandActivitySome : public RandActivity{public: // other member functions... virtual void Init(const RandActivityData &data) { RandActivity::Init(data); UNSTD_STATIC_CHECK(sizeof(m_data_param) <= sizeof(data.data)); m_data_param = *((ActivityDataParam *)data.data); } virtual void GetInitParam(RandActivityDataParam *data) { RandActivity::GetInitParam(data); UNSTD_STATIC_CHECK(sizeof(m_data_param) <= sizeof(data->data)); *((ActivityDataParam *)data->data) = m_data_param; }private: struct ActivityDataParam { ActivityDataParam() {} // some data }; ActivityDataParam m_data_param;};
玩家数据存储
我们肯定还需要保存玩家的随机活动数据,这一块数据统一放到了RoleActivityParam
里。
除了常规地在Reset函数中对数据成员进行初始化外,玩家还需要在活动开始后,首次参与活动前初始化一次数据。这个工作统一交给了函数RoleActivity::CheckInitRandActivity
。
- 我们必须在恰当的位置调用
RoleActivity::CheckInitRandActivity
,这些地方极可能有: - 当玩家登陆时:RoleActivity::RandActivityOnRoleLogin
- 当玩家发起一个随机活动请求时