Files
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

1248 lines
34 KiB
C++
Raw Permalink 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 "HeroSystem.h"
#include "../base/Container.hpp"
template<> const CHeroSystem::Inherid::OnHandleSockPacket CHeroSystem::Inherid::Handlers[]=
{
&CHeroSystem::HandError, //占位
&CHeroSystem::HandGetHeroList,
&CHeroSystem::HandHeroStageUp,
&CHeroSystem::HandHeroSkillLevelUp,
&CHeroSystem::HandChangeHeroName,
&CHeroSystem::HandSetHeroState,
&CHeroSystem::HandViewHero,
&CHeroSystem::HandHeroLevelUp
};
CHeroSystem::CHeroSystem()
{
Destroy();
m_fExpRate =0.0;
}
CHeroSystem::~CHeroSystem()
{
Destroy();
}
//英雄DB数据
void CHeroSystem::OnDbRetData(INT_PTR nCmd,INT_PTR nErrorCode,CDataPacketReader & reader )
{
if(m_pEntity ==NULL)
{
OutputMsg(rmError,_T("load Hero data error,m_pEntity ==NULL"));
return ;
}
//如果DB的数据已经初始化好了再收到数据不处理
if(nCmd == jxInterSrvComm::DbServerProto::dcLoadHeroData) //装载玩家的英雄数据
{
if(HasDbDataInit() )
{
OutputMsg(rmError,_T(" Hero data has loaded"));
return ;
}
if(nErrorCode == jxInterSrvComm::DbServerProto::reSucc)
{
int nCount=0;
reader >> nCount;
if(nCount >0)
{
bool flag =true;
HERODATA Hero;
Hero.equips.clear();
Hero.skills.clear();
for ( int i=0; i< nCount; i++)
{
reader >> Hero.data;
INT_PTR nPos = GetHeroPos (Hero.data.bID );
if(nPos >=0)
{
OutputMsg(rmError,_T("add Hero error ,has same Hero id=%d"),(int)Hero.data.bID );
continue;
}
m_heros.add(Hero);
}
}
}
else
{
OutputMsg(rmError,_T("load[%s]Hero data error,actorid=%u"),((CActor*)m_pEntity)->GetEntityName(),m_pEntity->GetProperty<unsigned int>(PROP_ENTITY_ID));
}
}
else if(nCmd == jxInterSrvComm::DbServerProto::dcLoadHeroSkillData) //装载玩家的英雄技能
{
if(HasDbDataInit() )
{
OutputMsg(rmError,_T(" Hero data has loaded"));
return ;
}
if(nErrorCode == jxInterSrvComm::DbServerProto::reSucc)
{
int nCount=0;
reader >> nCount;
if(nCount >0)
{
CSkillProvider *pSkillProvider = GetLogicServer()->GetDataProvider()->GetSkillProvider(); //技能数据读取器
CStdItemProvider & itemProvider = GetLogicServer()->GetDataProvider()->GetStdItemProvider(); //物品配置器
HEROSKILLDATA data;
for ( int i=0; i< nCount; i++)
{
memset(&data,0,sizeof(data));
reader >> data;
INT_PTR nPos = GetHeroPos (data.nHeroID);
if(nPos <0)
{
OutputMsg(rmError,_T("Hero skill data errr,no Hero=%d"),data.nHeroID);
}
else
{
const SKILLONELEVEL * pLevel = pSkillProvider->GetSkillLevelData(data.nSkillID, data.nLevel);
const OneSkillData *pConfig = pSkillProvider->GetSkillData(data.nSkillID);
if(pLevel ==NULL || pConfig ==NULL) continue;
m_heros[nPos].skills.add(data);
}
}
}
((CActor*)m_pEntity)->OnFinishOneInitStep(eMSG_USR_LOGIN_DATA_HERO_SYSTEM); //完成一个步骤
OnDbInitData(); //这个时候才确定db的数据发生了修改
}
else
{
OutputMsg(rmError,_T("load[%s]Hero skill data error,actorid=%d"),((CActor*)m_pEntity)->GetEntityName(),m_pEntity->GetProperty<int>(PROP_ENTITY_ID));
}
}
}
void CHeroSystem::ProcessNetData(INT_PTR nCmd,CDataPacketReader &packet )
{
if(m_pEntity ==NULL) return;
if(nCmd >=0 && nCmd <ArrayCount(CHeroSystem::Inherid::Handlers))
{
(this->*Handlers[nCmd] )(packet);
}
}
void CHeroSystem::OnEnterGame()
{
CallbackBattleHero(false);
}
void CHeroSystem::OnEnterScene()
{
}
void CHeroSystem::Destroy()
{
CEntity * pEntity;
for(INT_PTR i=0; i< m_heros.count();i++)
{
m_heros[i].skills.clear();
m_heros[i].equips.clear();
pEntity =GetEntityFromHandle(m_heros[i].handle);
if(pEntity)
{
GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(m_heros[i].handle);
}
}
m_heros.clear();
}
void CHeroSystem::HandViewHero(CDataPacketReader &packet)
{
if(m_pEntity ==NULL) return;
if (m_pEntity->HasMapAttribute(aaCannotViewOther))
{
(m_pEntity)->SendOldTipmsgWithId(tpChatDisableOperator);
return;
}
char msg[54];
packet.readString(msg,sizeof(msg));
msg[sizeof(msg) -1] =0;
CActor * pActor = GetGlobalLogicEngine()->GetEntityMgr()->GetActorPtrByName(msg);
if(pActor && pActor->IsInited())
{
pActor->GetHeroSystem().ViewHeros(m_pEntity); //观察其他玩家的英雄
}
else
{
((CActor*)m_pEntity)->SendOldTipmsgWithId(tpChatTargetOffLine);
}
}
//查看英雄
void CHeroSystem::ViewHeros(CActor * pActor)
{
if(m_pEntity ==NULL) return;
if(pActor ==NULL || pActor->IsInited() ==false) return;
INT_PTR nCount= m_heros.count();
if(nCount <=0 )
{
pActor->SendOldTipmsgWithId(tpOtherHasNoHero,ttChatWindow );
return ;
}
//如果没有出战英雄,默认为第一个英雄
INT_PTR nHeroIndex =0;
for(INT_PTR i=0; i< nCount; i++)
{
HERODATA & HERODATA = m_heros[i];
if( HERODATA.data.bState == psStateNormal)
{
nHeroIndex = i;
break;
}
}
HERODATA &hero = m_heros[nHeroIndex];
HERODBDATA & heroData = m_heros[nHeroIndex].data;
CActorPacket actorData;
CDataPacket& data = pActor->AllocPacket(actorData);
data <<(BYTE)GetSystemID() << (BYTE)sHeroView;
data << (BYTE) heroData.bID; //id
data << (BYTE) heroData.bState; //状态
data << (BYTE) heroData.bStage; //阶
data << (BYTE) heroData.bLevel; //等级
data << (unsigned int)heroData.nExp; //当前经验
data << (int)heroData.nBodyforce; //当前体力
data << (int)heroData.nBless; //当前祝福
data.writeString(heroData.name); //名字
CVector<HEROSKILLDATA> & skills = m_heros[nHeroIndex].skills;
data <<(BYTE) skills.count();
for(INT_PTR j=0;j < skills.count(); j++)
{
HEROSKILLDATA & skill =hero.skills[j];
data << (WORD) skill.nSkillID;
data << (BYTE) skill.nLevel;
}
actorData.flush();
((CActor*)m_pEntity)->PlayerViewNotice(pActor);
}
//计算英雄的属性
void CHeroSystem::CalHeroProp(HERODATA & Hero)
{
if(m_pEntity ==NULL) return;
//英雄未出战,不计算属性
if(Hero.data.bState != psStateNormal)
return;
Hero.cal.reset();
CAttrCalc calc;
PHEROLEVEL levelCfg = GetLogicServer()->GetDataProvider()->GetHeroConfig().GetHeroLevel(Hero.data.bID, Hero.data.bLevel);
if(!levelCfg)
return;
for(int i = 0; i < levelCfg->attri.nCount ; i++)
{
calc << levelCfg->attri.pAttrs[i];
}
for(INT_PTR i=0; i< Hero.skills.count(); i++)
{
((CHero*)m_pEntity)->GetSkillSystem().CalcOneSkillAttr(Hero.skills[i].nSkillID,Hero.skills[i].nLevel,calc);
}
Hero.cal << calc;
}
//重载这个函数,初始化玩家的一些2级属性
bool CHeroSystem::Initialize(void *data,SIZE_T size)
{
if(m_pEntity ==NULL ) return false;
return true;
}
void CHeroSystem::Save(PACTORDBDATA pData)
{
if(m_pEntity ==NULL) return;
//保存英雄列表
size_t count;
int nRawServerIndex = m_pEntity->GetRawServerIndex();
int nLoginServerIndex = GetLogicServer()->GetServerIndex();
if(m_HeroBasicDataHasModifed)
{
count = m_heros.count();
CDataPacket& HeroPacket =GetLogicServer()->GetDbClient()->allocProtoPacket(jxInterSrvComm::DbServerProto::dcSaveHeroData);
HeroPacket << nRawServerIndex << nLoginServerIndex;
HeroPacket <<(unsigned int ) m_pEntity->GetId(); //玩家ID
HeroPacket << (int)count; //玩家技能的数量
for (int i=0; i< count; i ++ )
{
HERODATA &hero = m_heros[i];
HeroPacket << hero.data; //只保持db需要的那部分
}
GetLogicServer()->GetDbClient()->flushProtoPacket(HeroPacket);
SetHeroDataModifyFlag(edHeroBasicData,false);
}
//保存英雄的技能列表
if(m_heroskillHasModified)
{
count =0;
for(INT_PTR i=0; i< m_heros.count(); i++)
{
count += m_heros[i].skills.count();
}
CDataPacket& skillPack =GetLogicServer()->GetDbClient()->allocProtoPacket(jxInterSrvComm::DbServerProto::dcSaveHeroSkillData);
skillPack << nRawServerIndex << nLoginServerIndex;
skillPack << (unsigned int ) m_pEntity->GetProperty<unsigned int>(PROP_ENTITY_ID); //玩家ID
skillPack << (int)count; //玩家技能的数量
for (INT_PTR i=0; i< m_heros.count(); i ++ )
{
for(INT_PTR j=0;j < m_heros[i].skills.count(); j++)
{
skillPack << m_heros[i].skills[j]; //只保持db需要的那部分
}
}
GetLogicServer()->GetDbClient()->flushProtoPacket(skillPack);
SetHeroDataModifyFlag(edHeroSkillData,false);
}
}
void CHeroSystem::OnTimeCheck(TICKCOUNT nTickCount)
{
if(m_pEntity ==NULL) return;
INT_PTR nCount =m_heros.count();
if(nCount <=0) return;
for(INT_PTR i= nCount-1; i>-1; i--)
{
INT_PTR nState = m_heros[i].data.bState;
if(nState ==psStateNormal)
{
CEntity *pHero = GetEntityFromHandle(m_heros[i].handle);
if(pHero )
{
bool hasHpMpChange =false; //HP,MP是否发生了改变
unsigned int nHp = pHero->GetProperty<unsigned int>(PROP_CREATURE_HP);
unsigned int nMp = pHero->GetProperty<unsigned int>(PROP_CREATURE_MP);
if(nHp >0)
{
if(m_heros[i].data.nHp != nHp)
{
m_heros[i].data.nHp = nHp;
hasHpMpChange = true;
}
}
if(m_heros[i].data.nMp != nMp)
{
m_heros[i].data.nMp = nMp;
hasHpMpChange =true;
}
//数据发生了改变
if(hasHpMpChange)
{
SetHeroDataModifyFlag(edHeroBasicData,true);
}
}
}
}
}
//英雄属性附加到人物
CAttrCalc & CHeroSystem::CalcAttributes(CAttrCalc &cal)
{
for(INT_PTR i=0; i< m_heros.count(); i++)
{
if ( m_heros[i].data.bState == psStateMerge) //附体属性
{
cal << m_heros[i].mergeCal; //附体
}
}
return cal;
}
//是否能增加英雄
bool CHeroSystem::CanAddHero(bool bWithTipmsg)
{
if(m_pEntity ==NULL) return false;
int nMaxCount = GetLogicServer()->GetDataProvider()->GetHeroConfig().GetHeroMaxCount();
bool flag= m_heros.count() < nMaxCount;
if(!flag && bWithTipmsg)
{
m_pEntity->SendOldTipmsgWithId(tpHeroCanNotGetMore,ttChatWindow);
}
return flag;
}
//添加英雄
int CHeroSystem::AddHero(int nHeroId, int nStage, int nLevel)
{
if(m_pEntity ==NULL) return -1;
if(!CanAddHero() || GetHeroPos(nHeroId) >= 0)
return -1;
PHEROCONFIG HeroCfg = GetLogicServer()->GetDataProvider()->GetHeroConfig().GetHeroData(nHeroId);
PHEROSTAGE StageCfg = GetLogicServer()->GetDataProvider()->GetHeroConfig().GetHeroStage(nHeroId, nStage);
if(!HeroCfg || !StageCfg)
return - 1;
HERODATA hero;
HERODBDATA &heroData =hero.data;
int nOldCount = (int)m_heros.count();
heroData.bStage = (BYTE)__max(nStage,1);
heroData.bLevel = (BYTE)__max(nLevel,1);
heroData.bID = nHeroId;
heroData.bVocation = enVocWarrior; //默认为战士
heroData.nModel = StageCfg->nModel;
heroData.nWeaponAppear = StageCfg->nWeapon;
heroData.nBodyforce = StageCfg->nGiveForce; //创建时系统给于的体力值
strncpy(heroData.name, HeroCfg->name,sizeof(heroData.name));
m_heros.add(hero);
SendHeroData(hero);
SetHeroDataModifyFlag(edHeroBasicData,true);
LogHero(GameLog::clHeroAdd, (int)heroData.bID, (int)nOldCount, m_heros.count());
ResetAllHeroProperty();
return heroData.bID;
}
//下发英雄数据
void CHeroSystem::HandGetHeroList(CDataPacketReader &packet)
{
if(m_pEntity ==NULL) return;
CActorPacket pack;
CDataPacket & data = ((CActor*)m_pEntity)->AllocPacket(pack);
data << (BYTE)GetSystemID() << (BYTE)sHeroList;
INT_PTR nCount= m_heros.count();
data << (BYTE)nCount;
for(INT_PTR i=0; i< nCount; i++)
{
HERODBDATA & heroData = m_heros[i].data;
HERODATA &hero = m_heros[i];
data << (BYTE) heroData.bID; //id
data << (BYTE) heroData.bState; //状态
data << (BYTE) heroData.bStage; //阶
data << (BYTE) heroData.bLevel; //等级
data << (unsigned int)heroData.nExp; //经验
data << (int)heroData.nBodyforce; //体力
data << (int)heroData.nBless; //祝福
data.writeString(heroData.name); //名字
}
pack.flush();
SendAllSkills();
}
//下发英雄的技能
void CHeroSystem::SendAllSkills()
{
if(m_pEntity ==NULL) return;
INT_PTR nCount=0;
for(INT_PTR i=0;i < m_heros.count(); i++)
{
nCount += m_heros[i].skills.count();
}
CActorPacket pack;
CDataPacket & data = ((CActor*)m_pEntity)->AllocPacket(pack);
data << (BYTE)GetSystemID() << (BYTE)sHeroSkillList;
data << (BYTE)nCount;
for(INT_PTR i=0;i < m_heros.count(); i++)
{
for(INT_PTR j=0;j < m_heros[i].skills.count(); j++)
{
HEROSKILLDATA & skill = m_heros[i].skills[j];
pack << (BYTE) skill.nHeroID;
pack << (WORD) skill.nSkillID;
pack << (BYTE) skill.nLevel;
}
}
pack.flush();
}
//获取战斗中的英雄
CHero * CHeroSystem::GetBattleHeroPtr()
{
for(INT_PTR i=0 ;i < m_heros.count(); i++)
{
if(m_heros[i].data.bState ==psStateNormal)
{
return (CHero*) GetEntityFromHandle(m_heros[i].handle);
}
}
return NULL;
}
//获取战斗中的英雄ID
int CHeroSystem::GetBattleHeroId()
{
for(INT_PTR i=0;i <m_heros.count();i ++ )
{
HERODBDATA &data =m_heros[i].data;
if(data.bState == psStateNormal)
{
if(GetEntityFromHandle(m_heros[i].handle))
{
return data.bID;
}
}
}
return -1;
}
//获取英雄位置
INT_PTR CHeroSystem::GetHeroPos(INT_PTR nHeroId)
{
for(INT_PTR i=0; i< m_heros.count();i ++)
{
if(m_heros[i].data.bID == (BYTE)nHeroId)
{
return i;
}
}
return -1;
}
//日志
void CHeroSystem::LogHero(const INT_PTR nLogIdent, const INT_PTR nHeroId, const INT_PTR nParam1, const INT_PTR nParam2)
{
if (m_pEntity == NULL) return;
INT_PTR nPos = GetHeroPos(nHeroId);
if(nPos <0) return;
HERODATA& Hero = m_heros[nPos];
char sData[24];
sprintf(sData,"%d_%d_%d",Hero.data.bID,Hero.data.bStage,Hero.data.bLevel);
}
//英雄改名
void CHeroSystem::HandChangeHeroName(CDataPacketReader &packet)
{
if(m_pEntity ==NULL) return;
BYTE bHeroID=0;
packet >> bHeroID ;
INT_PTR nPos = GetHeroPos(bHeroID) ;
if(nPos <0) return ;
char name[32];
packet.readString(name,sizeof(name));
if( GetGlobalLogicEngine()->GetChatMgr().Filter(name) >0)
{
m_pEntity->SendOldTipmsgWithId(tpInputIsForbid,ttFlyTip);
return;
}
ChangeHeroName(nPos,name);
}
void CHeroSystem::ChangeHeroName(INT_PTR nPos,char * name)
{
if(m_pEntity ==NULL) return;
HERODATA &Hero = m_heros[nPos];
HERODBDATA &data = Hero.data;
if(strcmp(name,data.name) ==0 ) return ;
if(strlen(name) == 0)
{
m_pEntity->SendOldTipmsgWithId(tpHeroNameIsEmpty,ttFlyTip);
return;
}
for (int i=0; i < strlen(name); i++)
{
if (name[i] == '"' || name[i] == '\\' || name[i] == '\''|| name[i] == '\''|| name[i] == '\''|| name[i] == '\'')
{
m_pEntity->SendOldTipmsgWithId(tpInputIsForbid,ttFlyTip);
return;
}
}
strncpy(data.name,name,sizeof(data.name));
SendHeroData(Hero);
//如果英雄已出战
if(data.bState ==psStateNormal)
{
CHero *pHero =(CHero*) GetEntityFromHandle(m_heros[nPos].handle);
if(pHero )
{
char sName[50];
sprintf_s(sName,sizeof(sName),"%s\\%s",name, m_pEntity->GetEntityName());
pHero->SetEntityName(data.name);
pHero->SetShowName(sName);
pHero->ChangeName(sName);
}
}
LogHero(GameLog::clHeroChangeName, data.bID, 0, 0);
SetHeroDataModifyFlag(edHeroBasicData,true);
m_pEntity->SendOldTipmsgWithId(tpHeroChangeNameSuccess,ttFlyTip);
}
//英雄事件
void CHeroSystem::TriggerEvent(INT_PTR nSubEvent,INT_PTR nParam1,INT_PTR nParam2,INT_PTR nParam3,INT_PTR nParam4)
{
if(m_pEntity ==NULL) return;
CScriptValueList paramList;
//((CActor*)m_pEntity)->InitEventScriptVaueList(paramList,aeHero);
paramList << (int)nSubEvent;
if(nParam1 >=0)
{
paramList << (int)nParam1;
if(nParam2 >=0)
{
paramList << (int)nParam2;
if(nParam3 >=0)
{
paramList << (int)nParam3;
if(nParam4 >=0)
{
paramList << (int)nParam4;
}
}
}
}
((CActor*)m_pEntity)->OnEvent(aeHero,paramList,paramList);
}
//英雄学习技能
bool CHeroSystem::LearnSkill(int nHeroID, int nSkillID)
{
if(m_pEntity ==NULL) return false;
INT_PTR nPos = GetHeroPos(nHeroID) ;
if(nPos <0) return false ;
HERODATA &Hero = m_heros[nPos];
if(GetSkillLevel(nHeroID,nSkillID) > 0 )
{
return false;
}
HEROSKILLDATA data;
data.nHeroID = nHeroID;
data.nSkillID = nSkillID;
data.nLevel =1;
CSkillProvider *pSkillProvider = GetLogicServer()->GetDataProvider()->GetSkillProvider();
const SKILLONELEVEL * pLevel = pSkillProvider->GetSkillLevelData(data.nSkillID, data.nLevel);
const OneSkillData *pConfig = pSkillProvider->GetSkillData(data.nSkillID);
if(pLevel ==NULL || pConfig ==NULL) return false;
Hero.skills.add(data);
CActorPacket pack;
CDataPacket & dataPack = ((CActor*)m_pEntity)->AllocPacket(pack);
dataPack << (BYTE)GetSystemID() << (BYTE)sHeroSkillUpdate;
dataPack << (BYTE)nHeroID; //英雄的ID
dataPack << (WORD)nSkillID; //技能的ID
dataPack << (BYTE)data.nLevel; //技能的等级
pack.flush();
//如果处于战斗状态的话,英雄立即学习技能
if(Hero.data.bState == psStateNormal)
{
CHero *pHero = (CHero*)GetEntityFromHandle(Hero.handle);
if(pHero)
{
//if(!pConfig->bIsDelete)
//{
pHero->GetSkillSystem().LearnSkill(nSkillID,1,false,true,true);
pHero->GetAI()->RefreshSkillDis();
//}
TriggerEvent(OpHeroBattle,nHeroID,nSkillID, 1); //script run
ResetProperty(nPos);
}
}
//记录日志
LogHero(GameLog::clHeroLearnSkill, nHeroID,nSkillID,1);
SetHeroDataModifyFlag(edHeroSkillData,true);
return true;
}
//英雄技能升级
void CHeroSystem::HandHeroSkillLevelUp(CDataPacketReader &packet)
{
if(m_pEntity ==NULL) return;
BYTE bHeroID=0;
WORD wSkillId =0;
packet >> bHeroID >> wSkillId ;
INT_PTR nPos = GetHeroPos(bHeroID) ;
if(nPos <0) return ;
int nLevel = GetSkillLevel(bHeroID,wSkillId);
if(nLevel <=0 )
{
m_pEntity->SendOldTipmsgFormatWithId(tpHeroSkillNotActivate, ttFlyTip);
return;
}
CSkillProvider *pSkillProvider = GetLogicServer()->GetDataProvider()->GetSkillProvider();
const SKILLONELEVEL * pLevel = pSkillProvider->GetSkillLevelData(wSkillId, nLevel+1);
if(pLevel == NULL )
{
m_pEntity->SendOldTipmsgFormatWithId(tpHeroSkillLevelFull, ttFlyTip);
return;
}
TriggerEvent(OpHeroUpSkill,bHeroID,wSkillId,nLevel); //script run
}
bool CHeroSystem::SkillLevelUp(int nHeroId,int nSkillId)
{
if(m_pEntity ==NULL) return false;
INT_PTR nPos = GetHeroPos(nHeroId) ;
if(nPos <0) return false ;
int nSkillLevel = GetSkillLevel(nHeroId,nSkillId);
if(nSkillLevel <= 0) return false;
nSkillLevel = nSkillLevel + 1;
//已达到最高技能等级
CSkillProvider *pSkillProvider = GetLogicServer()->GetDataProvider()->GetSkillProvider();
const OneSkillData *pConfig = pSkillProvider->GetSkillData(nSkillId);
const SKILLONELEVEL * pLevel = pSkillProvider->GetSkillLevelData(nSkillId, nSkillLevel);
if(pConfig ==NULL || pLevel ==NULL ) return false;
HERODATA &Hero = m_heros[nPos];
CVector<HEROSKILLDATA> &skills = Hero.skills;
for(INT_PTR i=0;i < skills.count(); i++)
{
if(skills[i].nSkillID == nSkillId)
{
skills[i].nLevel += 1;
//记录日志
LogHero(GameLog::clHeroSkillLevelUp, nHeroId, nSkillId, skills[i].nLevel);
break;
}
}
CActorPacket pack;
CDataPacket & dataPack = ((CActor*)m_pEntity)->AllocPacket(pack);
dataPack << (BYTE)GetSystemID() << (BYTE)sHeroSkillUpdate ;
dataPack << (BYTE)nHeroId;
dataPack << (WORD)nSkillId;
dataPack << (BYTE)nSkillLevel;
pack.flush();
//如果处于战斗状态的话,英雄立即学习技能
if(Hero.data.bState == psStateNormal)
{
CHero *pHero = (CHero*)GetEntityFromHandle(Hero.handle);
if(pHero)
{
//if(!pConfig->bIsDelete)
//{
pHero->GetSkillSystem().LearnSkill(nSkillId,nSkillLevel,false,true,true);
pHero->GetAI()->RefreshSkillDis();
//}
TriggerEvent(OpHeroBattle,nHeroId,nSkillId, nSkillLevel); //script run
ResetProperty(nPos); //重置属性
}
}
SetHeroDataModifyFlag(edHeroSkillData,true);
m_pEntity->SendOldTipmsgFormatWithId(tpHeroSkillLevelUp,ttTipmsgWindow,Hero.data.name,
GetLogicServer()->GetDataProvider()->GetSkillProvider()->GetSkillNameById(nSkillId),
nSkillLevel);
return true;
}
//获取英雄等级
int CHeroSystem::GetSkillLevel(int nHeroId, int nSkillId)
{
INT_PTR nPos = GetHeroPos(nHeroId) ;
if(nPos <0) return -1 ;
HERODATA &Hero = m_heros[nPos];
CVector<HEROSKILLDATA> &skills = Hero.skills;
for(INT_PTR i=0;i < skills.count(); i++)
{
if(skills[i].nSkillID == nSkillId)
{
return skills[i].nLevel;
}
}
return -1 ;
}
//英雄升级
void CHeroSystem::HandHeroLevelUp(CDataPacketReader &packet)
{
TriggerEvent(OpHeroLevelUp);
}
//英雄升阶
void CHeroSystem::HandHeroStageUp(CDataPacketReader &packet)
{
BYTE bHeroID=0;
BYTE bCount =0;
packet >> bHeroID >> bCount;
INT_PTR nPos = GetHeroPos(bHeroID) ;
if(nPos <0) return ;
HERODATA &Hero = m_heros[nPos];
TriggerEvent(OpHeroUpStage,bHeroID,Hero.data.bStage,Hero.data.nBless,bCount); //script run
}
bool CHeroSystem::StageUp(int nHeroId, int nStage, int nBless)
{
if(m_pEntity ==NULL) return false;
INT_PTR nPos = GetHeroPos(nHeroId) ;
if(nPos <0) return false;
HERODATA &Hero = m_heros[nPos];
int nOldStage = Hero.data.bStage;
CHeroProvider &provider = GetLogicServer()->GetDataProvider()->GetHeroConfig();
PHEROCONFIG heroCfg = provider.GetHeroData(nHeroId);
PHEROSTAGE stageCfg = provider.GetHeroStage(nHeroId,nStage);
if(!heroCfg || !stageCfg) return false;
Hero.data.bStage = nStage;
if(nBless > stageCfg->nMaxBless)
{
Hero.data.nBless = stageCfg->nMaxBless;
}else
{
Hero.data.nBless = nBless;
}
Hero.data.nModel = stageCfg->nModel; //升阶改变英雄模型
Hero.data.nWeaponAppear = stageCfg->nWeapon;
SendHeroData(Hero);
ResetProperty(nPos,false,true);
SetHeroDataModifyFlag(edHeroBasicData,true);
LogHero(GameLog::clHeroStageUp, (int)Hero.data.bID, nOldStage, nStage);
ResetAllHeroProperty();
return true;
}
//下发英雄数据(创建&&更新)
void CHeroSystem::SendHeroData(HERODATA &Hero)
{
if(m_pEntity ==NULL) return;
CActorPacket pack;
CDataPacket & data = ((CActor*)m_pEntity)->AllocPacket(pack);
data << (BYTE)GetSystemID() << (BYTE)sHeroUpdate;
data << (BYTE) Hero.data.bID; //id
data << (BYTE) Hero.data.bState; //状态
data << (BYTE) Hero.data.bStage; //阶
data << (BYTE) Hero.data.bLevel; //等级
data << (unsigned int)Hero.data.nExp; //当前经验
data << (int)Hero.data.nBodyforce; //当前体力
data << (int)Hero.data.nBless; //当前祝福
data.writeString(Hero.data.name); //名字
pack.flush();
}
//收回英雄
bool CHeroSystem::SetHeroSleep(INT_PTR nHeroId,bool bClient)
{
if(m_pEntity ==NULL) return false;
INT_PTR nPos = GetHeroPos(nHeroId);
if(nPos <0) return false;
HERODATA & Hero = m_heros[nPos];
INT_PTR nCurrentState = Hero.data.bState;
if( nCurrentState== psStateNormal) //战斗状态
{
GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(Hero.handle);
Hero.handle =0;
m_pEntity->CollectOperate(CEntityOPCollector::coRefAbility); //重新刷能力,玩家的属性发生了改变
}
else if(nCurrentState == psStateMerge) //如果当前是合体状态的话
{
m_pEntity->CollectOperate(CEntityOPCollector::coRefAbility); //重新刷能力,玩家的属性发生了改变
m_pEntity->RemoveState(esStateHeroMerge); //去除附体状态
}
Hero.data.bState = psStateSleep;
if(bClient)
{
SendHeroStateChange(nPos);
}
SetHeroDataModifyFlag(edHeroBasicData,true);
return true;
}
//玩家Death时英雄的处理
void CHeroSystem::OnDeath()
{
for(INT_PTR i=0;i < m_heros.count();i ++)
{
if(m_heros[i].data.bState == psStateNormal)
{
SetHeroSleep(m_heros[i].data.bID,true);
}
}
}
//下发英雄经验
void CHeroSystem::SetClientHeroExp(HERODATA &Hero)
{
if(m_pEntity ==NULL) return;
CActorPacket pack;
CDataPacket & dataPack = ((CActor*)m_pEntity)->AllocPacket(pack);
dataPack << (BYTE)GetSystemID() << (BYTE)sHeroExpChange ;
dataPack << (BYTE)Hero.data.bID << (unsigned int) Hero.data.nExp;
pack.flush();
}
//下发英雄状态
void CHeroSystem::SendHeroStateChange(INT_PTR nPos)
{
if(m_pEntity ==NULL) return;
if(nPos <0 || nPos >= m_heros.count()) return;
HERODBDATA &data = m_heros[nPos].data;
CActorPacket pack;
CDataPacket & dataPack = ((CActor*)m_pEntity)->AllocPacket(pack);
dataPack << (BYTE)GetSystemID() << (BYTE)sHeroStateChange ;
dataPack << (BYTE)data.bID << (BYTE) data.bState;
pack.flush();
SetHeroDataModifyFlag(edHeroBasicData,true);
}
//英雄被攻击
void CHeroSystem::OnAttacked(CAnimal *pEntity)
{
CHero * pHero;
for(INT_PTR i=0; i< m_heros.count(); i++)
{
if(m_heros[i].data.bState ==psStateNormal)
{
pHero= (CHero*)GetEntityFromHandle(m_heros[i].handle);
if(pHero &&pHero->GetAI())
{
pHero->GetAI()->AttackedBy(pEntity);
}
}
}
}
//英雄攻击
void CHeroSystem::OnAttackOther(CAnimal * pEntity)
{
CHero * pHero;
for(INT_PTR i=0; i< m_heros.count(); i++)
{
if(m_heros[i].data.bState ==psStateNormal)
{
pHero= (CHero*)GetEntityFromHandle(m_heros[i].handle);
if(pHero &&pHero->GetAI())
{
pHero->GetAI()->AttackedBy(pEntity);
}
}
}
}
//英雄跟随
void CHeroSystem::FollowEntity(CAnimal *pActor)
{
CHero * pHero;
for(INT_PTR i=0; i< m_heros.count(); i++)
{
if(m_heros[i].data.bState ==psStateNormal)
{
pHero= (CHero*)GetEntityFromHandle(m_heros[i].handle);
if(pHero &&pHero->GetAI())
{
if (pHero->GetMoveSystem()->GetMotionType() == CMovementSystem::mtMotionTypeChase)
{
pHero->GetMoveSystem()->PopCurrentMotionState();
}
pHero->GetAI()->EnterEvadeMode();//退出战斗
pHero->GetMoveSystem()->MoveFollow(pActor);
}
}
}
}
//英雄获得打怪经验
void CHeroSystem::OnAddExp(unsigned int nExp,bool boRate, int nHeroId)
{
for(INT_PTR i=0;i <m_heros.count();i ++ )
{
HERODATA &Hero = m_heros[i];
HERODBDATA &data = Hero.data;
if(data.bState == psStateNormal || ((i + 1) == nHeroId ))
{
if(boRate)
{
unsigned int nAddExp = (unsigned int) ( (nExp * Hero.fExpRate) * (1 + m_fExpRate));
RealChangeExp(i,nAddExp);
}else
{
RealChangeExp(i,nExp);
}
}
}
}
bool CHeroSystem::RealChangeExp(INT_PTR nPos,unsigned int nAddExp)
{
if(m_pEntity ==NULL) return false;
if(nPos < 0 || nPos >= m_heros.count())
return false;
HERODATA &Hero= m_heros[nPos];
HERODBDATA &data = Hero.data;
int nHeroId = data.bID;
int nStage = data.bStage;
int nLevel = data.bLevel;
CHeroProvider &provider = GetLogicServer()->GetDataProvider()->GetHeroConfig();
PHEROSTAGE stageCfg = provider.GetHeroStage(nHeroId,nStage);
PHEROLEVEL levelCfg = provider.GetHeroLevel(nHeroId, nLevel);
BOOL boLevelUp = false;
unsigned int nRealAddExp = 0;
if(nAddExp > 0 && stageCfg && levelCfg)
{
bool boLoop = true;
while (boLoop)
{
levelCfg = provider.GetHeroLevel(nHeroId, data.bLevel);
if(!levelCfg)
{
boLoop = false;
break;
}
//已达本阶最高级
if(data.bLevel >= stageCfg->nMaxLevel)
{
boLoop = false;
if( (data.nExp + nAddExp) > levelCfg->nLevelUpExp)
{
nRealAddExp += levelCfg->nLevelUpExp - (unsigned int)data.nExp;
data.nExp = levelCfg->nLevelUpExp;
}else
{
nRealAddExp += nAddExp;
data.nExp += nAddExp;
}
break;
}else
{
//可以升级了
if((data.nExp + nAddExp) >= (unsigned int)levelCfg->nLevelUpExp)
{
BYTE nNewLevel = data.bLevel + 1;
PHEROLEVEL nextLevelCfg = provider.GetHeroLevel(nHeroId, nNewLevel);
if(nextLevelCfg)
{
boLevelUp = true;
data.bLevel = nNewLevel;
int nDecExp = (unsigned int)levelCfg->nLevelUpExp - (unsigned int)data.nExp;
data.nExp = 0; //升级后经验需要归0
nRealAddExp += nDecExp;
nAddExp -= nDecExp;
}else
{
boLoop = false;
}
}else
{
data.nExp += nAddExp;
nRealAddExp += nAddExp;
boLoop = false;
}
}
}
if(nRealAddExp > 0)
{
if(m_fExpRate > 0.0)
{
int nRateValue = (int)( (nRealAddExp / (1 + m_fExpRate)) * m_fExpRate );
m_pEntity->SendOldTipmsgFormatWithId(tpHeroGetExpRate, ttTipmsgWindow,nRealAddExp,nRateValue);
}else
{
m_pEntity->SendOldTipmsgFormatWithId(tpHeroGetExp, ttTipmsgWindow,nRealAddExp);
}
}
if(boLevelUp)
{
CHero *pHero = (CHero*)GetEntityFromHandle(Hero.handle);
if (pHero)
{
pHero->SetLevel(data.bLevel);
}
ResetProperty(nPos);
SendHeroData(Hero);
LogHero(GameLog::clHeroUpgrade, data.bID, nLevel, data.bLevel);
}
SetHeroDataModifyFlag(edHeroBasicData,true);
SetClientHeroExp(Hero);
return true;
}
return false;
}
//重置所有英雄属性
void CHeroSystem::ResetAllHeroProperty(bool bNewHero,bool bRefeshAppear)
{
for(INT_PTR i=0; i < m_heros.count();i ++)
{
ResetProperty(i, bNewHero, bRefeshAppear);
}
}
//重置英雄属性
void CHeroSystem::ResetProperty(INT_PTR nHeroPos,bool boNewHero ,bool boRefAppear)
{
if (nHeroPos < 0 || nHeroPos >= m_heros.count())
return;
HERODATA &Hero = m_heros[nHeroPos];
CalHeroProp(Hero);
if(Hero.data.bState == psStateNormal) //如果处于出战状态,需要刷新属性
{
CHero * pHero = (CHero*)(GetEntityFromHandle(Hero.handle));
if(pHero)
{
//最大hp, mp
unsigned int nMaxHp = (unsigned int)Hero.cal.m_AttrValues[aMaxHpAdd].nValue; //最大hp
unsigned int nMaxMp = (unsigned int)Hero.cal.m_AttrValues[aMaxMpAdd].nValue; //最大mp
pHero->SetProperty<unsigned int>(PROP_CREATURE_MAXHP, nMaxHp);
pHero->SetProperty<unsigned int>(PROP_CREATURE_MAXMP, nMaxMp);
pHero->CollectOperate(CEntityOPCollector::coRefAbility);
pHero->SetLevel(Hero.data.bLevel);
pHero->GetAI()->RefreshSkillDis();
if(boRefAppear)
{
pHero->SetProperty<unsigned int>(PROP_ENTITY_MODELID,Hero.data.nModel);
pHero->SetProperty<unsigned int>(PROP_ACTOR_WEAPONAPPEARANCE,Hero.data.nWeaponAppear);
}
}
}
}
//英雄出战
bool CHeroSystem::SetHeroBattle(INT_PTR nHeroId,bool boClient)
{
if(m_pEntity ==NULL) return false;
INT_PTR nPos = GetHeroPos(nHeroId);
if(nPos <0) return false;
HERODATA & Hero = m_heros[nPos];
PHEROCONFIG HeroCfg = GetLogicServer()->GetDataProvider()->GetHeroConfig().GetHeroData((int)nHeroId);
PHEROLEVEL LevelCfg = GetLogicServer()->GetDataProvider()->GetHeroConfig().GetHeroLevel(Hero.data.bID, Hero.data.bLevel);
if(!HeroCfg && !LevelCfg)
return false;
//已出战的其他英雄收回
CallbackBattleHero(boClient);
HERODBDATA & data= Hero.data;
CScene *pScene = m_pEntity->GetScene();
if(pScene ==NULL) return false;
int nPosX,nPosY;
m_pEntity->GetPosition(nPosX,nPosY);
//已经放出了一个英雄
CEntity* pEntity =GetEntityFromHandle(Hero.handle);
if(pEntity != NULL)
{
return false;
}
//创建一个英雄
int nNewPosX = 0, nNewPosY = 0;
pScene->GetEntityAppearPos(nPosX, nPosY, 4,nNewPosX, nNewPosY);
if(nNewPosX > 0 && nNewPosY > 0)
{
pEntity = pScene->CreateEntityAndEnterScene(nHeroId,enHero,nNewPosX,nNewPosY,data.bLevel,m_pEntity);
}else
{
pEntity = pScene->CreateEntityAndEnterScene(nHeroId,enHero,nPosX,nPosY,data.bLevel,m_pEntity);
}
if(pEntity ==NULL) return false;
CHero *pHero = (CHero*) pEntity;
Hero.data.bState = psStateNormal;
Hero.handle = pEntity->GetHandle();
//计算英雄属性
CalHeroProp(Hero);
char sAllName[512];
sprintf_s(sAllName,sizeof(sAllName),"%s\\%s",data.name, m_pEntity->GetEntityName());
pHero->SetEntityName(data.name);
pHero->SetShowName(sAllName);
//设置模型hp,mp(用属性值的填充)
pEntity->SetProperty<int>(PROP_ENTITY_MODELID,data.nModel);
pEntity->SetProperty<unsigned int>(PROP_ACTOR_WEAPONAPPEARANCE,data.nWeaponAppear);
CAttrCalc &cal = Hero.cal;
unsigned int nMaxHp = (unsigned int)cal.m_AttrValues[aMaxHpAdd].nValue; //最大hp
unsigned int nMaxMp = (unsigned int)cal.m_AttrValues[aMaxMpAdd].nValue; //最大mp
pEntity->SetProperty<unsigned int>(PROP_CREATURE_MAXHP, nMaxHp);
pEntity->SetProperty<unsigned int>(PROP_CREATURE_HP, nMaxHp);
pEntity->SetProperty<unsigned int>(PROP_CREATURE_MP,nMaxMp);
pEntity->SetProperty<unsigned int>(PROP_CREATURE_MAXMP,nMaxMp);
Hero.nBaseMaxHp = nMaxHp;
Hero.nBaseMaxMp = nMaxMp;
Hero.fExpRate = HeroCfg->fExpRate;
pHero->InitAi();
if( pHero->GetAI() ==NULL)
{
OutputMsg(rmError,"hero InitAi fail, hero id = %d",data.bID);
return false;
}
int nAttackSpd = pHero->GetProperty<int>(PROP_CREATURE_ATTACK_SPEED);
if(nAttackSpd > 0)
{
pHero->SetAttackInterval(nAttackSpd);
}
pEntity->SetInitFlag(true);
//立即学习技能
for(INT_PTR i=0;i < Hero.skills.count(); i++)
{
int nSkillId = Hero.skills[i].nSkillID;
int nSkillLevel = Hero.skills[i].nLevel;
CSkillProvider *pSkillProvider = GetLogicServer()->GetDataProvider()->GetSkillProvider();
const OneSkillData *pConfig = pSkillProvider->GetSkillData(nSkillId);
//if(!pConfig->bIsDelete)
//{
pHero->GetSkillSystem().LearnSkill(nSkillId,nSkillLevel,false,true,true);
//}
TriggerEvent(OpHeroBattle,nHeroId,nSkillId, nSkillLevel); //script run
}
pHero->GetAI()->RefreshSkillDis(); //重新刷新技能
pHero->GetAttriFlag().DenyAutoAddHp = false; //允许回血
pHero->GetAttriFlag().DenyAutoAddMp = false; //允许回蓝
pHero->GetAttriFlag().DenyUseNearAttack =false; //支持肉搏
if(boClient)
{
SendHeroStateChange(nPos);
}
return true;
}
void CHeroSystem::HandSetHeroState(CDataPacketReader &packet)
{
if(m_pEntity ==NULL) return;
BYTE bHeroId=0,bState =0;
packet >> bHeroId >> bState ;
INT_PTR nPos = GetHeroPos(bHeroId) ;
if(nPos <0) return ;
HERODATA &Hero = m_heros[nPos];
HERODBDATA &data = Hero.data;
if(data.bState == bState)return;
if(bState == psStateNormal)
{
CScene *pScene = m_pEntity->GetScene();
int x, y;
m_pEntity->GetPosition(x,y);
if (pScene && pScene->HasMapAttribute(x, y, aaNotCallHero))
{
m_pEntity->SendOldTipmsgFormatWithId(tpCannotCallHeroInTheArea, ttFlyTip);
return;
}
CHeroProvider &provider = GetLogicServer()->GetDataProvider()->GetHeroConfig();
PHEROCONFIG HeroCfg = provider.GetHeroData(bHeroId);
if(HeroCfg)
{
if(data.nBodyforce < HeroCfg->nBattleForce)
{
m_pEntity->SendOldTipmsgFormatWithId(tpHeroBattleForceLacking, ttFlyTip);
return;
}
data.nBodyforce = data.nBodyforce - HeroCfg->nBattleForce;
SetHeroDataModifyFlag(edHeroBasicData,true);
SendHeroData(Hero);
SetHeroBattle(bHeroId);
}
}
else if(bState == psStateSleep)
{
SetHeroSleep(bHeroId);
}
ResetAllHeroProperty();
}
//收回所有出战英雄
void CHeroSystem::CallbackBattleHero(bool boClient)
{
for(int i = 0; i < m_heros.count(); i++)
{
if(m_heros[i].data.bState ==psStateNormal)
{
SetHeroSleep(m_heros[i].data.bID,boClient);
}
}
}
//跨天清除祝福值
void CHeroSystem::EveryDayClearBless()
{
for(int i= 0; i < m_heros.count(); i++)
{
HERODATA &Hero = m_heros[i];
CHeroProvider &provider = GetLogicServer()->GetDataProvider()->GetHeroConfig();
PHEROSTAGE stage = provider.GetHeroStage(Hero.data.bID, Hero.data.bStage);
if(stage && stage->boEveryDayClearBless)
{
Hero.data.nBless = 0;
SetHeroDataModifyFlag(edHeroBasicData,true);
SendHeroData(Hero);
}
}
}
//英雄 合体
bool CHeroSystem::SetHeroMerge(INT_PTR nHeroId,bool bClient)
{
return true;
}