游戏场景服务器概况

5658cf3a9b5eba8535a6e556dbe7da34.png

指令对应的处理handle的文件:SSBattleMgr.cpp

创建战场

  • 指令: eMsgToSSFromCS_CreateBattle
  • GC服务器发往SS fromCS 收到中心服务器CS创建站场的指令,在函数INT32 CSSBattleMgr::OnMsgFromCS_CreateBattle(const char* pData, int n32DataLength)中创建站场成功后,加入到战场管理器中:
m_cAllBattleMap[pBattle->GetBattleID()] = pBattle;

发送创建结果给CS服务器

CSSWorkThreadMgr::GetInstance().PostMsgToCS(sMsg, sMsg.mgsid());

发送可以进入战场的消息给客户端

CSSWorkThreadMgr::GetInstance().PostMsgToGCLIULU((*iter)->GetUserNetInfo(), sMsgBattle, sMsgBattle.msgid());

英雄移动

  • 指令:eMsgToGSToSSFromGC_AskMoveDir,eMsgToGSToSSFromGC_AskStopMove
  • GSToSS: 客户端发往SS,fromGC 收到客户端发来的移动信息, GCToSS::MoveDir, 转化为服务器能识别的参数 CVector3D, 开始计算客户端移动的位置
CVector3D pcDir(pMoveDir->dir().x(), 0, pMoveDir->dir().z());
m_pMsgBattle->AskMoveDir(m_pMsgUser, pcDir);

开始按照方向移动:

bool CSSMoveMgr::AskStartMoveDir(ISSMoveObject* pMObject, ColVector dir) 
{<!-- -->
...
        //计算下一个100毫秒后的位置
		pMObject->CalculateStepMoveTarget(now + 100);
                //检查是否会直接撞墙
		if(FALSE == TestNextStepMove(pMObject)){<!-- -->
			if(FALSE == TryTurnDir(pMObject)){<!-- -->
				pMObject->Stop(now,FALSE);
				return FALSE;
			}
		}
		pMObject->OnStartMove(pMObject->GetDir());
}
INT32 CSSGameUnit::BeginAction_Move(const CVector3D &crsDir, bool bIfNotifyGC){<!-- -->}

同步移动状态到客户端

pcCurBattle->SyncState(this);
...
SendMsgToAllWatcher(*sMsg, msgid, pcGO); 
...
CSSWorkThreadMgr::GetInstance().PostMsgToGCLIULU(watcherArray[i]->GetUserNetInfo(), sMsg, n32MsgID);
INT32	CSSBattle::SyncState(CSSGameUnit *pcGO, bool spot){<!-- -->}
void CSSBattle::SendMsgToAllWatcher(google::protobuf::Message& sMsg, int n32MsgID, CSSGameUnit* pGU){<!-- -->}

英雄技能

  • 指令:eMsgToGSToSSFromGC_AskBuyGoods- GSToSS:客户端发往SS,fromGC SS服务器接收到请求释放技能的指令eMsgToGSToSSFromGC_AskBuyGoods, 转化数据为GCToSS::UseSkill格式 :
boost::shared_ptr<GCToSS::UseSkill> pUseSkill = ParseProtoMsgWithNewMemory<GCToSS::UseSkill>(pData, n32DataLength);
INT32 nret = m_pMsgBattle->AskUseSkill(m_pMsgUser, pUseSkill->skillid());

请求释放技能:

INT32 CSSAI_Hero::AskUseSkill(UINT32 un32SkillID) {<!-- -->}
//检查是否是不能操作状态
//检查是否被沉默了
//检查是否在吸附中,如果是,不能使用技能
//获取并检查技能是否存在
//检查技能是否符合可用条件
//检查是否是正在运行的技能

开始使用技能

pSkill->Start();
```cpp
准备技能的配置
```cpp
void CSSSkill::MakeSkillEffect(TIME_MILSEC	tUTCMilsec){
...
	pcCurBattle->GetEffectMgr()->AddEffectsFromCfg((SSNextSkillEffectCfg*)cpsCfg->asSkillModelList, pcMasterGU.get(), pcTarGU.get(), cPos, pcMasterGU->GetCurDir(), this, tUTCMilsec);

}

从配置中添加技能

INT32 CSSEffectMgr::AddEffectsFromCfg(SSNextSkillEffectCfg* pEffectCfg, CSSGameUnit* pMaster, CSSGameUnit* pTarget, CVector3D cPos, CVector3D cDir
	,  CSSSkill* pSkill, TIME_MILSEC beginTime, CSSGameUnit* pStartSkillGU){<!-- -->
...
AddEffect(pEffect); 
}

添加效果到管理器中

INT32 CSSEffectMgr::AddEffect(CSSSkillEffect* pEffect) {<!-- -->
...
        //尝试使用效果的启动方法。如果启动成功,将其加入正在运行的技能列表中
		if(eNormal == pEffect->Begin()){<!-- -->
			//if (FALSE == pEffect->m_pCfg->bIsCanMove){<!-- -->
				pEffect->AddSelfToUsingList();
			//}
			m_UpdateEffectMap[pEffect->m_un32UniqueID] = pEffect;
		}
		//如果效果启动失败,检查其是否会开始计算技能CD,然后结束技能。
		else{<!-- -->
			pEffect->CheckCooldown();
			pEffect->End();
			DestroyAFreeSkillEffect(pEffect);
			return eEC_AddEffectFailed;
		}
...
}
//正在运行的效果列表
m_UpdateEffectMap

对应的技能在如下图所示的文件中
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uoAAHV02-1609600677855)(https://s3.ax1x.com/2021/01/02/spS5KH.png)]

  • SSSkillEffect_Buf.cpp: 附加的buff技能
  • SSSkillEffect_Fly.cpp: 飞行技能

装备买卖

  • 买装备指令:eMsgToGSToSSFromGC_AskBuyGoods
  • 卖商品指令:eMsgToGSToSSFromGC_AskSellGoods
  • 释放装备技能:eMsgToGSToSSFromGC_AskUseGoods
  • GSToSS: 客户端发往SS,fromGC

商品配置

目录:

  • 商品组合:CSBattleMgr/CombineCfg.xml
  • 商品描述:CSBattleMgr/ItemCfg.xml

商品配置描述: |attributeKeyList / attributeValList|描述 |—— |5 / 10|+10 物理攻击 |6 / 35|+35点魔法攻击 |7 / 20|+20 点物理防御 |8 / 25|+25点魔法防御 |9 / 60|+60点移动速度 |10 / 200|+200生命值 |11 / 200|+200生命值 |12 / 150|+150魔法值 |13 / 2000|+2点/秒生命回复

  • attributeKeyLi: 占位
  • attributeValList: 值
  • n32CPCost: 金币

举例

	<info un32GoodsID="30038">
		<sNameID>spe_item_HP</sNameID>
		<sNameCh>神果</sNameCh>
		<un8TypeID>3</un8TypeID>
		<attributeKeyList>6</attributeKeyList>
		<attributeValList>65</attributeValList>
		<attributePerList>0</attributePerList>
		<un8UseTimes>0</un8UseTimes>
		<bDestroyAfterUsed>0</bDestroyAfterUsed>
		<un32SkillID>0</un32SkillID>
		<un32PassSkillID>0</un32PassSkillID>
		<bIsCanDeathToBuy>1</bIsCanDeathToBuy>
		<bUsedAfterBuyed>0</bUsedAfterBuyed>
		<sIcon>Dicon038</sIcon>
		<un32CdTime>0</un32CdTime>
		<bUniqueID>0</bUniqueID>
		<un8OverlapTimes>1</un8OverlapTimes>
		<un8CPCostType>1</un8CPCostType>
		<n32CPCost>800</n32CPCost>
		<n32CombineCPCost>200</n32CombineCPCost>
		<un8FunctionType>0</un8FunctionType>
		<un32UniqueTypeID>0</un32UniqueTypeID>
		<sDescribe>+65点魔法攻击</sDescribe>
		<un32UseSoundID>0</un32UseSoundID>
	</info>

神果+65点魔法攻击, 售价是800金币。

整个服务器的心跳

心跳的作用:

  • 检查掉线时间。如果玩家掉线超过30秒,则将其AI替换为机器人AI
  • 技能心跳- 移动心跳- NPC和hero的心跳
void	CSSBattle::DoPlayHeartBeat(TIME_MILSEC tUTCMilsec, TIME_TICK tTickSpan){<!-- -->
...
    //移动心跳
    m_pMoveMgr->OnHeartBeat(tUTCMilsec, tTickSpan);
    for (GameObjectMap::iterator iterObj = m_cGameObjectMap.begin(); iterObj != m_cGameObjectMap.end(); ++iterObj){<!-- -->
            //NPC和hero的心跳
    		iterObj->second->OnHeartBeat(tUTCMilsec, tTickSpan);
    }
...
    //技能心跳
    m_pEffectMgr->OnHeartBeat(tUTCMilsec, tTickSpan);
    m_pPassiveSkillMgr->OnHeartBeat(tUTCMilsec, tTickSpan);
    m_pSightMgr->OnHeartBeat(tUTCMilsec, tTickSpan);
...
}

--完--