Files
mir_server/server/LogicServer/skill/SkillResult.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

2720 lines
85 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 "SkillResult.h"
#include <algorithm>
#include "config/HallowsConfig.h"
//CSkillResult::SkillResultMgr *CSkillResult::s_skillResultMgr = new CSkillResult::SkillResultMgr;
//Buff计算属性的时候比率的计算规则
#define BUFF_RATE_TYPE_PHYSICAL_ATTACK 0 //物理攻击
#define BUFF_RATE_TYPE_MAGIC_ATTACK 1 //魔法攻击
#define BUFF_RATE_TYPE_WIZARD_ATTACK 2 //道术攻击
#define BUFF_RATE_TYPE_LEVEL 3 //基于等级的
#ifdef _DEBUG
std::string s_HurtValueMsg;
char s_HurtValueBuff[100];
#endif
//增加技能效果请在enSkillResultID中对应增加
const CSkillResult::SkillResultFunc CSkillResult::Handlers[]=
{
&CSkillResult::IsError, // 0 占位
&CSkillResult::PhysicAttack, // 1 物理攻击
&CSkillResult::MagicAttack, // 2 魔法攻击
&CSkillResult::WizardAttack, // 3 道术攻击
&CSkillResult::AddBuff, // 4 增加buff
&CSkillResult::DefBuff, // 5 删除buff
&CSkillResult::CatchMonster, // 6 抓怪
&CSkillResult::BeatBack, // 7 击退效果
&CSkillResult::MobFire, // 8 召唤火墙
&CSkillResult::MobPet, // 9 召唤宠物
&CSkillResult::GoAhead, // 10 往前跑若干格
&CSkillResult::GoBack, // 11 向后退若干格
&CSkillResult::LastSafeAreaRTransfer, // 12 上一个安全区随机传送
&CSkillResult::IsError, // 13 被动技能
&CSkillResult::Cure, // 14 瞬间治疗
&CSkillResult::HolyAttack, // 15 神圣攻击
&CSkillResult::MoveToTarget, // 16 瞬移到目标旁
&CSkillResult::MoveBackHome, // 17 瞬移回巢
&CSkillResult::Transfer, // 18 指定场景地点传送
&CSkillResult::SceneTransfer, // 19 本场景随机传送
&CSkillResult::LastSafeAreaTransfer, // 20 上一个安全区传送
///////////////////////// 以下暫無用
&CSkillResult::DeleteEffect, // 21 删除特效
&CSkillResult::IgnoreDefence, // 22 忽略目标的防御
&CSkillResult::CatchTarget, // 23 把目标抓到自己身边
&CSkillResult::SetAttackTarget, // 24 设置攻击目标
&CSkillResult::MobEntity, // 25 刷怪
&CSkillResult::RapidMove, // 26 冲锋
&CSkillResult::SelfHpCureTarget, // 27 自身的HP的百分比治疗目标
&CSkillResult::LostTarget, // 28 丢弃目标
&CSkillResult::ChangEquipDua, // 29 改变装备的耐久
&CSkillResult::DropMonsterItem, // 30 按怪物的掉率掉落东西
&CSkillResult::ScreenShake, // 31 震屏
&CSkillResult::IsError, // 32
&CSkillResult::ChangeModel, // 33 换个模型
&CSkillResult::RateChangeProperty, // 34 百分比改属性
&CSkillResult::SelfDelSkillCd, // 35 删除技能的CD
&CSkillResult::GiveAward, // 36 给奖励
&CSkillResult::BeatFly, // 20 击飞效果
&CSkillResult::PlayGuide, // 38 客户端播放引导性特
&CSkillResult::IgnoreMaxDropHp, // 39 忽略每次最大伤害限制
&CSkillResult::PointMove, // 40 把目标移动到地图一个点
&CSkillResult::SelfPointMove, // 41 自己移动到范围内的鼠标指定的点
&CSkillResult::TargetRapidMove, // 42 向某目标冲撞
&CSkillResult::RemovePet, // 43 删除宠物
&CSkillResult::ChangeMonsterAttacked, // 44 改变怪物是否能被攻击
&CSkillResult::FastSelfCurHp, // 45 瞬回血
&CSkillResult::TargetPointMove, // 46 把目标移动到范围内的鼠标指定的点
&CSkillResult::CatchAll, // 47 抓取所有符合条件对象
&CSkillResult::MonsterMove, // 48 怪物移动
&CSkillResult::Shout, // 49 怪物喊话
};
void CSkillResult::DoResult( PSKILLRESULTPARAM pParam,bool bNoDelay)
{
if( pParam->pTargetEntity)
{
if( pParam->pTargetEntity->GetType() == enNpc) return; //Npc不能受到所有技能的影响
}
//技能在2,3,4步 距离误差的时候命中的概率
static int s_nSkill2StepRate = GetLogicServer()->GetDataProvider()->GetGlobalConfig().n2StepSkillHitRate;
static int s_nSkill3StepRate = GetLogicServer()->GetDataProvider()->GetGlobalConfig().n3StepSkillHitRate;
static int s_nSkill4StepRate = GetLogicServer()->GetDataProvider()->GetGlobalConfig().n3StepSkillHitRate;
INT_PTR nCmdID = pParam->pSkillResult->nResultType;
if( nCmdID >=0 && nCmdID <ArrayCount(Handlers) )
{
if(bNoDelay || pParam->pSkillResult->nDelay ==0)
{
int nPosX,nPosY;
if(pParam->pTargetEntity && pParam->pTargetEntity !=pParam->pSrcEntity )
{
if(pParam->pTargetEntity->IsInited() ==false) return;
//不在同1个场景不执行
//if(pParam->pTargetEntity->GetScene() != pParam->pSrcEntity->GetScene()) return;
//技能在2,3,4步 距离误差的时候命中的概率
pParam->pTargetEntity->GetPosition(nPosX,nPosY);
if(pParam->nTargetPosX && pParam->nTargetPosY )
{
int nDisX = abs(nPosX -pParam->nTargetPosX);
int nDisY = abs(nPosY -pParam->nTargetPosY);
int nDis = __max(nDisX,nDisY); //取2个的最大值
if( !pParam->pSkillResult->ignoreTargetDis && nDis >=2) //如果距离大于2格以上
{
//怪物维持原来的,只有玩家,宠物,和狗维持原来的
if(pParam->pSrcEntity && pParam->pSrcEntity->GetType() == enMonster )
{
return ;
}
int nRand =wrand(10000); //取1万之间的随机数
bool isHit =false;
//根据技能和当前的点之间的距离按概率计算是否命中23,4格有一定概率命中1格直接命中5格以上直接不命中了
switch(nDis)
{
case 2:
if( nRand <= s_nSkill2StepRate )
{
isHit =true;
}
break;
case 3:
if( nRand <= s_nSkill3StepRate )
{
isHit =true;
}
break;
case 4:
if( nRand <= s_nSkill4StepRate )
{
isHit =true;
}
break;
default:
break;
}
if(!isHit) return; //没有命中
}
}
}
( this->*CSkillResult::Handlers[nCmdID] )(pParam);
}
else
{
INT_PTR nDelay;
//取施法者的攻击速度
if(pParam->pSkillResult->nDelay <0)
{
//倍率
nDelay =- pParam->pSkillResult->nDelay *
pParam->pSrcEntity->GetProperty<unsigned int>(PROP_CREATURE_ATTACK_SPEED);
}
else
{
nDelay = pParam->pSkillResult->nDelay;
}
CAnimal * pEntity = pParam->pTargetEntity;
if(pEntity ==NULL)
{
pEntity = pParam->pSrcEntity;
}
if(pEntity)
{
CEntityMsg msg(CEntityMsg::emSkillResult, pParam->pSrcEntity->GetHandle());
msg.dwDelay = nDelay;
msg.nParam1 =pParam->nSkillID;
msg.nParam2 = pParam->nTargetPosX;
msg.nParam3= pParam->nTargetPosY;
msg.nParam4= pParam->btIgnoreDefence;
msg.nParam5= pParam->btIgnoreMaxDropHp;
msg.nParam5 = pParam->pSkillResult->nValue;
msg.nParam6 = pParam->pSkillResult->nId;
msg.nParam7 = pParam->pSkillResult->nResultType;
//msg.nParam8 = pParam->wCriticalDamgeAdd;
//msg.nParam9 = pParam->wHitRateAdd;
pEntity->PostEntityMsg(msg);
}
}
}
}
int CSkillResult::GetAttackValByType(CAnimal * pSrcActor, int nType, int nParam )
{
int nAbility = 0;
switch(nType)
{
case BUFF_RATE_TYPE_PHYSICAL_ATTACK :
nAbility = pSrcActor->GetAttackValue(TYPE_PHYSICAL_ATTACK) ;
break;
case BUFF_RATE_TYPE_MAGIC_ATTACK:
nAbility = pSrcActor->GetAttackValue(TYPE_MAGIC_ATTACK) ;
break;
case BUFF_RATE_TYPE_WIZARD_ATTACK:
nAbility = pSrcActor->GetAttackValue(TYPE_WIZARD_ATTACK) ;
break;
case BUFF_RATE_TYPE_LEVEL:
nAbility = pSrcActor->GetProperty<int>(PROP_CREATURE_LEVEL) ;
break;
default:
break;
}
return nAbility;
}
void CSkillResult::AddBufProcess(PSKILLRESULTPARAM pParam, float fTimeDesc)
{
CBuffProvider::BUFFCONFIG * pBuffCfg = GetLogicServer()->GetDataProvider()->GetBuffProvider().GetBuff(pParam->pSkillResult->nId);
if (pBuffCfg == NULL)
{
return;
}
GAMEATTRVALUE gameValue;
memset(&gameValue, 0, sizeof(gameValue));
int nAbility = 0;
if(pParam->pSkillResult->nParam1)
{
if (!(pParam->pSkillResult->nParam1 >= wrand(10000)))
{
return;
}
}
if (AttrDataTypes[pBuffCfg->nType] == adFloat)
{
gameValue.fValue += (float)pBuffCfg->dValue;
}
else
{
gameValue.nValue += (int)pBuffCfg->dValue;
}
if(pParam->pTargetEntity ==NULL) return;
CDynamicBuff dyBuff;
dyBuff.wBuffId = pParam->pSkillResult->nId;
dyBuff.value = gameValue;
dyBuff.dwTwice = pBuffCfg->nTimes;
dyBuff.wActWait = pBuffCfg->nInterval;
dyBuff.pConfig = pBuffCfg;
if (pParam->pSrcEntity != NULL)
{
dyBuff.mGiver = pParam->pSrcEntity->GetHandle();
}
pParam->pTargetEntity->GetBuffSystem()->Append(dyBuff.wBuffId, &dyBuff);
//雷霆一击--致残特效、高级致残特效
if ( pParam->pSkillResult->nId == 324 || pParam->pSkillResult->nId == 325 )
{
CEntityMsg msg(CEntityMsg::emShowEntityEffect, pParam->pSrcEntity->GetHandle());
switch ( pParam->pSkillResult->nId )
{
case 324: //雷霆一击--致残
msg.nParam1 = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nCrippleEffectId;
break;
case 325: //雷霆一击--高级致残
msg.nParam1 = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nAdvancedCrippleEffectId;
break;
default:
break;
}
pParam->pTargetEntity->PostEntityMsg(msg);
}
}
//添加buff
inline void CSkillResult::AddBuff(PSKILLRESULTPARAM pParam)
{
AddBufProcess(pParam,0.0);
}
//删除buff
void CSkillResult::DefBuff(PSKILLRESULTPARAM pParam)
{
if(pParam->pTargetEntity && pParam->pTargetEntity->IsInited() && pParam->pTargetEntity->isAnimal())
{
pParam->pTargetEntity->GetBuffSystem()->RemoveById(pParam->pSkillResult->nId);
}
}
//抓怪
void CSkillResult::CatchMonster(PSKILLRESULTPARAM pParam)
{
if(pParam->pTargetEntity && pParam->pTargetEntity->IsInited() && pParam->pTargetEntity->isAnimal())
{
if (pParam->pTargetEntity->GetType() != enMonster) return;
if (pParam->pTargetEntity->GetAttriFlag().DenyBeCatch == true) return;
if(!(pParam->pSrcEntity)) return ;
CActor *pActor = ((CActor *)(pParam->pSrcEntity));
if (pActor->GetType()!=enActor) { return ;}
INT_PTR nSkillLevel = pActor->GetSkillSystem().GetSkillLevel(pParam->nSkillID);
const SKILLONELEVEL * pLevel = GetLogicServer()->GetDataProvider()->GetSkillProvider()->GetSkillLevelData(pParam->nSkillID,nSkillLevel);
unsigned int nPetNum = pActor->GetPetSystem().GetPetCount(); //当前宠物数量
if(pLevel->nMaxPet >=1)
{ //配置了技能等级相关的宠物数量限制
if( nPetNum >= pLevel->nMaxPet )
{
pActor->SendTipmsgFormatWithId(tmCannotCatchPetMore, tstUI);
return ;
}
}
int nCatchRate = rand() % 10000;
if(pParam->pSkillResult->nId > nCatchRate)
{
INT_PTR nEntityId = pParam->pTargetEntity->GetProperty<unsigned int>(PROP_ENTITY_ID);
INT_PTR nLevel = pParam->pTargetEntity->GetProperty<unsigned int>(PROP_CREATURE_LEVEL);
int nPosX = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSX);
int nPosY = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSY);
CEntityManager* em = GetGlobalLogicEngine()->GetEntityMgr();
em->DestroyEntity(pParam->pTargetEntity->GetHandle());
int nAiId = pParam->pSkillResult->nParam1;
int nLiveSecs = pParam->pSkillResult->nValue;
pActor->GetPetSystem().AddPet(nEntityId, nLevel, nAiId, nLiveSecs, 0, 0, nPosX, nPosY);
}
}
}
bool CSkillResult::isHit( PSKILLRESULTPARAM pParam ,INT_PTR nAttackType )
{
//延时作用,有可能人物已下线了
if (!pParam->pSrcEntity || !pParam->pTargetEntity)
{
return false;
}
if(pParam->pSrcEntity ==pParam->pTargetEntity ) return true;
/*
情况一:攻击者准确>目标的敏捷100%命中
情况二:攻击者准确<=目标的敏捷,闪避率公式=(敏捷-准确+1/(敏捷+1
注意,无论是物理还是魔法都要通过这个判断才能命中目标
*/
bool isHit =false;
unsigned int HitValue = pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_HITVALUE); //准确
unsigned int nDogValue = pParam->pTargetEntity->GetProperty<int>(PROP_CREATURE_DODVALUE); //敏捷
if(HitValue ==0) return false; //准确为0就没法名字了
if(HitValue > nDogValue )
{
isHit =true;
}
else
{
if( HitValue >= (unsigned int)( wrand (nDogValue+1) +1) )
{
isHit =true;
}
}
/*
注意:先判断准确与敏捷是否能够命中,如果命中,再判断魔法的闪避
魔法命中几率 = 1 - (魔法命中-魔法闪避)
中毒命中几率 = 1 - (魔法命中-毒物闪避)
*/
/*
如果是法师或者道士的攻击,需要根据攻击类型判断命中,
道士和法师的攻击分为的魔法攻击和读物攻击
魔法命中几率 = 1 - (魔法命中-魔法闪避)
中毒命中几率 = 1 - (魔法命中-毒物闪避)
*/
if(!isHit || nAttackType == TYPE_PHYSICAL_ATTACK || nAttackType == TYPE_HOLY_ATTACK) //这里没有命中的话,那么就直接不命中了
{
return isHit;
}
int nRate;
if(nAttackType == TYPE_MAGIC_ATTACK || nAttackType == TYPE_WIZARD_ATTACK) //如果是魔法攻击的话
{
nRate= 10000+ pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_MAGIC_HITRATE) -
pParam->pTargetEntity->GetProperty<int>(PROP_CREATURE_MAGIC_DOGERATE) ;
}
// unsigned int nRate = (unsigned int)(fRate * 10000);
isHit = nRate <= 0 ? false : wrand(10000) < nRate; //这里躲闪超过
if (!isHit)
return isHit; //这里没有命中的话,那么就直接不命中了
//火墙伤害判定防火率
if (pParam->pSkillResult->btHitType == htFire)
{
WORD nDefenseRate = pParam->pTargetEntity->m_nFireDefenseRate;
if (nDefenseRate > 0 && nDefenseRate <= 10000) //超过1W就就找策划吧
{
isHit = wrand(10000) < (unsigned int)(10000 - nDefenseRate);
}
else
{
isHit = true;
}
}
return isHit;
}
//内功攻击
void CSkillResult::PhysicAttack(PSKILLRESULTPARAM pParam)
{
NormalAttack(pParam,TYPE_PHYSICAL_ATTACK);
}
void CSkillResult::HolyAttack(PSKILLRESULTPARAM pParam)
{
NormalAttack(pParam,TYPE_HOLY_ATTACK);
}
void CSkillResult::MoveToTarget(PSKILLRESULTPARAM pParam)
{
if(!pParam->pSrcEntity || !pParam->pTargetEntity)
{
return;
}
unsigned int nSceneID = pParam->pSrcEntity->GetSceneID();
unsigned int nTargetSceneId = pParam->pTargetEntity->GetSceneID();
if (nSceneID != nTargetSceneId)
{
return;
}
CScene* pScene = pParam->pSrcEntity->GetScene();
if (!pScene) return;
INT_PTR nEntityType = pParam->pSrcEntity->GetType();
INT_PTR nDist = 1;//pParam->pSkillResult->nId;
INT_PTR nMovePosX,nMovePosY;
INT_PTR nTarPosX,nTarPosY;
pParam->pSrcEntity->GetPosition(nTarPosX,nTarPosY);
pParam->pTargetEntity->GetPosition(nMovePosX,nMovePosY);
INT_PTR nDir = CEntity::GetDir(nTarPosX,nTarPosY,nMovePosX,nMovePosY);
CEntityGrid::NewPosition(nMovePosX,nMovePosY,(nDir+4)%DIR_STOP,1);
if (pScene->CanCross(nEntityType,nMovePosX,nMovePosY,true))
{
pParam->pTargetEntity->GetPosition(nTarPosX,nTarPosY);
nDir = CEntity::GetDir(nMovePosX,nMovePosY,nTarPosX,nTarPosY);
//pParam->pSrcEntity->SetDir(nDir);//GetAttriFlag().DenySetDir
pParam->pSrcEntity->SetProperty<unsigned int>(PROP_ENTITY_DIR,(unsigned int)nDir);
}
else
{
pParam->pTargetEntity->GetPosition(nTarPosX,nTarPosY);
int nLeftRight[2] = { nTarPosX - nDist, nTarPosX + nDist };
int nTopDown[2] = { nTarPosY - nDist, nTarPosY + nDist };
bool flag = false;
// 左右两边
for (nTarPosX = nLeftRight[0]; nTarPosX <= nLeftRight[1] && !flag; nTarPosX++)
{
for (int i = 0; i < 2 && !flag; i++)
{
nTarPosY = nTopDown[i];
if(pScene->CanCross(nEntityType,nTarPosX,nTarPosY,true))
{
flag = true;
break;
}
}
}
// 上下两边
for (nTarPosY = nTopDown[0]; nTarPosY <= nTopDown[1] && !flag; nTarPosY++)
{
for (int i = 0; i < 2 && !flag; i++)
{
nTarPosX = nLeftRight[i];
if(pScene->CanCross(nEntityType,nTarPosX,nTarPosY,true))
{
flag = true;
break;
}
}
}
if (flag)
{
nMovePosX = nTarPosX;
nMovePosY = nTarPosY;
pParam->pTargetEntity->GetPosition(nTarPosX,nTarPosY);
nDir = CEntity::GetDir(nMovePosX,nMovePosY,nTarPosX,nTarPosY);
pParam->pSrcEntity->SetProperty<unsigned int>(PROP_ENTITY_DIR,(unsigned int)nDir);
}
else
{
pParam->pTargetEntity->GetPosition(nMovePosX,nMovePosY);
}
}
//CFuBen* hFb = pParam->pSrcEntity->GetFuBen();
//GetGlobalLogicEngine()->GetFuBenMgr()->EnterFuBen(pParam->pSrcEntity,hFb,nSceneID,nMovePosX,nMovePosY);
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
((CAnimal*)pParam->pSrcEntity)->GetMoveSystem()->InstantMove(nMovePosX,nMovePosY,1,enDefaultTelePort,nEffId);
}
void CSkillResult::MoveBackHome(PSKILLRESULTPARAM pParam)
{
if(!pParam->pSrcEntity || pParam->pSrcEntity->GetType() != enMonster)
{
return;
}
unsigned int nSceneID = pParam->pSrcEntity->GetSceneID();
INT_PTR nTargetPosX,nTargetPosY;
((CMonster*)pParam->pSrcEntity)->GetBornPoint(nTargetPosX,nTargetPosY);
CFuBen* hFb = pParam->pSrcEntity->GetFuBen();
//GetGlobalLogicEngine()->GetFuBenMgr()->EnterFuBen(pParam->pSrcEntity,hFb,nSceneID,nTargetPosX,nTargetPosY);
if (pParam->pSrcEntity->GetAttriFlag().DenySetDir)
{
unsigned int nMonsterId = pParam->pSrcEntity->GetProperty<unsigned int>(PROP_ENTITY_ID);
PMONSTERCONFIG pMonsterConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(nMonsterId);
if (pMonsterConfig)
{
if (pMonsterConfig->btDir >= 0 && pMonsterConfig->btDir <=7)
{
pParam->pSrcEntity->SetProperty<unsigned int>(PROP_ENTITY_DIR,(unsigned int)pMonsterConfig->btDir);
}
}
}
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
((CAnimal*)pParam->pSrcEntity)->GetMoveSystem()->InstantMove(nTargetPosX,nTargetPosY,1,enDefaultTelePort,nEffId);
}
void CSkillResult::OnDodge(CEntity * pSrcEntity,CEntity * pTargetEntity)
{
Uint64 uTargetHandle = (Uint64)pTargetEntity->GetHandle();
if(pSrcEntity&& pSrcEntity->GetType() == enActor)
{
CActorPacket pack;
CDataPacket & data = ((CActor*)pSrcEntity)->AllocPacket(pack);
data << (BYTE)enDefaultEntitySystemID << (BYTE)sDoDge << uTargetHandle;
pack.flush();
}
if(pTargetEntity && pTargetEntity->GetType() == enActor)
{
CActorPacket pack;
CDataPacket & data = ((CActor*)pTargetEntity)->AllocPacket(pack);
data << (BYTE)enDefaultEntitySystemID << (BYTE)sDoDge << uTargetHandle;
pack.flush();
}
}
//魔法攻击
void CSkillResult::MagicAttack(PSKILLRESULTPARAM pParam)
{
NormalAttack(pParam,TYPE_MAGIC_ATTACK);
}
//设定攻击目标
void CSkillResult::SetAttackTarget(PSKILLRESULTPARAM pParam)
{
if(pParam->pTargetEntity == NULL || pParam->pSrcEntity == NULL) return;
if(pParam->pTargetEntity == pParam->pSrcEntity) return;
if(pParam->pTargetEntity->GetAI() == NULL) return;
pParam->pTargetEntity->GetAI()->AttackStart( pParam->pSrcEntity);
}
//把目标抓到自己身边
void CSkillResult::CatchTarget(PSKILLRESULTPARAM pParam)
{
CEntity * pEntity = GetEntityFromHandle(pParam->pSrcEntity->GetTarget());
if(pEntity && pEntity->isAnimal() )
{
if(pEntity->GetAttriFlag().DenyBeMove) return; //如果不能移动的话就不能抓取
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
((CAnimal*)pEntity)->GetMoveSystem()->InstantMove(pParam->nTargetPosX,pParam->nTargetPosY,1,enDefaultTelePort,nEffId); //瞬间移动
}
}
//瞬间回血
void CSkillResult::Cure(PSKILLRESULTPARAM pParam)
{
if(pParam->pTargetEntity ==NULL || pParam->pSrcEntity ==NULL) return;
if(pParam->pTargetEntity->IsDeath()) return; //死亡的不能加血
// 回血量
int nValue = pParam->pSrcEntity->GetAttackValue(TYPE_WIZARD_ATTACK);
nValue = (float)pParam->pSkillResult->nId/10000 * nValue + pParam->pSkillResult->nValue;
// 回复上限
if( pParam->pSkillResult->nParam1 && pParam->pSkillResult->nParam1 > nValue)
{
nValue = pParam->pSkillResult->nParam1;
}
// 加血
pParam->pTargetEntity->ChangeHP(nValue);
}
//冲锋
void CSkillResult::RapidMove(PSKILLRESULTPARAM pParam)
{
INT_PTR nStep = pParam->pSkillResult->nId; //跳跃的距离
if(nStep ==0) return;
pParam->pSrcEntity->GetMoveSystem()->RapidMove((int)nStep);
}
void CSkillResult::LostTarget(PSKILLRESULTPARAM pParam)
{
if( NULL == pParam->pTargetEntity ) return ;
if( pParam->pTargetEntity->GetType() ==enActor)
{
CActorPacket pack;
((CActor*)pParam->pTargetEntity)->AllocPacket(pack);
pack <<(BYTE) enDefaultEntitySystemID << (BYTE) sLostTarget << Uint64(pParam->pTargetEntity->GetTarget());
pack.flush();
}
pParam->pTargetEntity->SetTarget(EntityHandle(0));
}
//删除特效
void CSkillResult::DeleteEffect(PSKILLRESULTPARAM pParam)
{
if( NULL == pParam->pTargetEntity ) return ;
if( pParam->pTargetEntity->isAnimal())
{
((CAnimal*)pParam->pTargetEntity)->GetEffectSystem().DelEffect(pParam->pSkillResult->nValue,
pParam->pSkillResult->nId);
}
}
//刷怪
void CSkillResult::MobEntity(PSKILLRESULTPARAM pParam)
{
if(pParam->nTargetPosX ==0 || pParam->nTargetPosY ==0) return;
if(pParam->pTargetEntity ==NULL) return;
CScene * pScene = pParam->pTargetEntity->GetScene();
if(pScene ==NULL )return;
INT_PTR nPosX = (INT_PTR)pParam->nTargetPosX ;
INT_PTR nPosY = (INT_PTR)pParam->nTargetPosY;
INT_PTR nEntityType = pParam->pSkillResult->nParam1; //实体的类型
if(nEntityType == enActor || nEntityType == enNpc)return;
INT_PTR nTotalCount = pParam->pSkillResult->nValue; //刷出怪的数量
//x,y,如果策划配置了点,那就在策划的点上刷
int nConfigX = pParam->pSkillResult->nParam2;
int nConfigY = pParam->pSkillResult->nParam3;
if(nConfigX && nConfigY )
{
nPosX = nConfigX;
nPosY = nConfigY;
}
for(INT_PTR i = 0; i < nTotalCount;i ++)
{
bool flag = false;
if( pParam->pSkillResult->nParam4 >0) //在一个范围里随机
{
unsigned int nTwoR =2* pParam->pSkillResult->nParam4 +1; //这个半径
int nR = pParam->pSkillResult->nParam4;
INT_PTR nCenterX = nPosX;
INT_PTR nCenterY = nPosY;
for(INT_PTR j=0; j< 10000; j++)
{
INT_PTR x = (INT_PTR)wrand(nTwoR) - nR + nPosX;
INT_PTR y =(INT_PTR)wrand(nTwoR) - nR + nPosY;
if(pScene->canEntityMove((int)x,(int)y, (int)nEntityType,0,0,0))
{
nPosX = x;
nPosY = y;
flag = true;
break;
}
}
}
else
{
if(nConfigX && nConfigY)
{
flag = pScene->GetGrid().GetMoveablePoint(NULL,pScene,nConfigX,nConfigY,nPosX,nPosY,false,nEntityType);
if(flag ==false)
{
if( pScene->CanMove(nConfigX,nConfigY))
{
nPosX = nConfigX;
nPosY = nConfigY;
flag =true;
}
}
}
else
{
flag = true;
}
}
if(flag ==false)
{
OutputMsg(rmError,_T("Skill MobEntity Error,position error,skillid=%d,mid=%d,sid=%d,x=%d,y=%d"),
(int)pParam->nSkillID,pParam->pSkillResult->nId,pScene->GetSceneId(),(int)nPosX,(int)nPosY);
continue;
}
if(nEntityType == enMonster || nEntityType == enGatherMonster)
{
int nInitPercent = pParam->pSkillResult->nParam6;
if (nInitPercent == 0)
{
nInitPercent = 100;
}
CEntity* pEntity = pScene->CreateEntityAndEnterScene(pParam->pSkillResult->nId,
nEntityType,nPosX ,nPosY,-1,NULL, pParam->pSkillResult->nParam5,0,NULL,0,nInitPercent);
if (pEntity == NULL)
{
OutputMsg(rmError,_T("Skill MobEntity Error,create entity error,skillid=%d,mid=%d,sid=%d,x=%d,y=%d"),
(int)pParam->nSkillID,pParam->pSkillResult->nId,pScene->GetSceneId(),(int)nPosX,(int)nPosY);
}
}
}
}
void CSkillResult::ScreenShake(PSKILLRESULTPARAM pParam)
{
if(pParam->pTargetEntity ==NULL )return;
if(pParam->pTargetEntity->GetType() != enActor) return;
CActorPacket pack;
((CActor*)pParam->pTargetEntity)->AllocPacket(pack);
pack <<(BYTE) enDefaultEntitySystemID << (BYTE) sScreenShake << (WORD) pParam->pSkillResult->nId;
pack << (WORD) pParam->pSkillResult->nValue;
pack.flush();
}
//自身的HP的比例治疗目标
void CSkillResult::SelfHpCureTarget(PSKILLRESULTPARAM pParam)
{
if(pParam->pSrcEntity == pParam->pTargetEntity ) return; //自己不能治疗自己,否则就是白费
if(pParam->pSrcEntity->IsDeath() || pParam->pTargetEntity->IsDeath()) return ; //有一方死了都不行
//如果对方的血是满的话,那么就不浪费自己的血
if(pParam->pTargetEntity->GetProperty<int>(PROP_CREATURE_HP) == pParam->pTargetEntity->GetProperty<int>(PROP_CREATURE_MAXHP))
{
return ;
}
if(pParam->pSkillResult->nId <=0) return;
float rate = (float)pParam->pSkillResult->nId /10000; //牺牲自己的血量
float addRate = (float)pParam->pSkillResult->nValue /10000; //给别人加的血量
int nHpAdd =(int) ( pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_HP) *rate);
pParam->pSrcEntity->ChangeHP(-nHpAdd);
nHpAdd = (int) (nHpAdd * addRate); //按比例给对方
pParam->pTargetEntity->ChangeHP(nHpAdd);
}
//删除技能的CD
void CSkillResult::SelfDelSkillCd(PSKILLRESULTPARAM pParam)
{
if(pParam->pSrcEntity ==NULL) return;
int nSkillId = pParam->pSkillResult->nId;
if(nSkillId <=0) return ; //配置不合法
pParam->pSrcEntity->GetSkillSystem().DelSkillCdTemporary(nSkillId);
}
//击飞
void CSkillResult::BeatFly(PSKILLRESULTPARAM pParam)
{
INT_PTR nStep = pParam->pSkillResult->nId;
if(nStep ==0) return;
INT_PTR nTargetPosX = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nTargetPosY = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSY);
//如果怪物自己把自己击退的话,就往后退几格
CEntity *pSrc = pParam->pSrcEntity ;
if(pParam->pSrcEntity ==pParam->pTargetEntity )
{
pSrc =GetEntityFromHandle(pParam->pSrcEntity->GetTarget());
}
if(pSrc ==NULL) return;
//当前的坐标
INT_PTR nCurrentPosx = pSrc->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nCurrentPosy = pSrc->GetProperty<int>(PROP_ENTITY_POSY);
//如果坐标不变的话
if(nCurrentPosx == nTargetPosX && nCurrentPosy == nTargetPosY) return;
INT_PTR nDir = CEntity::GetDir(nCurrentPosx,nCurrentPosy,nTargetPosX,nTargetPosY);
pParam->pTargetEntity->GetMoveSystem()->BeatBack(nDir,nStep,false);
}
//击退
void CSkillResult::BeatBack(PSKILLRESULTPARAM pParam)
{
INT_PTR nStep = pParam->pSkillResult->nId; //跳跃的距离
if(nStep ==0) return;
INT_PTR nTargetPosX = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nTargetPosY = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSY);
// 非怪物,在安全区不能弹出去
INT_PTR entityType = pParam->pTargetEntity->GetType();
if (entityType != enMonster)
{
CScene* pActorScene = pParam->pTargetEntity->GetScene();
if (pActorScene && pActorScene->HasMapAttribute(nTargetPosX,nTargetPosY,aaSaft))
{
return;
}
}
//如果怪物自己把自己击退的话,就往后退几格
CEntity *pSrc = pParam->pSrcEntity ;
if(pParam->pSrcEntity ==pParam->pTargetEntity )
{
pSrc =GetEntityFromHandle(pParam->pSrcEntity->GetTarget());
}
if(pSrc ==NULL) return;
//当前的坐标
INT_PTR nCurrentPosx = pSrc->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nCurrentPosy = pSrc->GetProperty<int>(PROP_ENTITY_POSY);
//如果坐标不变的话
if(nCurrentPosx == nTargetPosX && nCurrentPosy == nTargetPosY) return;
INT_PTR nDir = CEntity::GetDir(nCurrentPosx,nCurrentPosy,nTargetPosX,nTargetPosY);
pParam->pTargetEntity->SetDir((nDir +4) %DIR_STOP); //取相反的方向
pParam->pTargetEntity->GetMoveSystem()->BeatBack(nDir,nStep,true);
}
inline void CSkillResult::NormalAttack(PSKILLRESULTPARAM pParam, int nAttackType)
{
//某些怪物只能被特定技能伤害
if (pParam->pSrcEntity && pParam->pSrcEntity->GetType() == enActor && pParam->pTargetEntity && pParam->pTargetEntity->GetType() == enMonster)
{
PMONSTERCONFIG pMonsterConfig = GetLogicServer()->GetDataProvider()->GetMonsterConfig().GetMonsterData(pParam->pTargetEntity->GetId());
if ( pMonsterConfig->wDamageSkill > 0 && pMonsterConfig->wDamageSkill != pParam->nSkillID)
{
LPCSTR sSkillName = GetLogicServer()->GetDataProvider()->GetSkillProvider()->GetSkillNameById(pMonsterConfig->wDamageSkill);
if (sSkillName != NULL)
{
((CActor*)pParam->pSrcEntity)->SendOldTipmsgFormatWithId(tpNotDamageBySkill, ttFlyTip, sSkillName);
}
return;
}
}
bool isMonster = bool(pParam->pSrcEntity? (pParam->pSrcEntity->GetType() == enMonster) : false);
bool isActor = bool(pParam->pSrcEntity? (pParam->pSrcEntity->GetType() == enActor) : false);
//命中
if(isHit(pParam, nAttackType))
{
//职业攻击
int nValue = pParam->pSrcEntity->GetAttackValue(nAttackType);
if ((nValue >= 10000) && isMonster)
{
int nScene = pParam->pSrcEntity->GetSceneID();
int nEntityId= pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_ID);
if (nEntityId != 171)
{
int nX= pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_POSX);
int nY= pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_POSY);
int nPhysAttackMax= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MIN);
int nPhysAttackMin= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MAX);
int nMagicAttackMax= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MAX);
int nMagicAttackMin= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MIN);
OutputMsg(rmError,_T("[Monster Attack1] 怪物攻击过高ID:%d Atk:%d 技能参数SId:%d, AtkType:%d 坐标(%d,%d,%d 物理(%d,%d 魔法(%d,%d"),
nEntityId,nValue,
pParam->nSkillID,nAttackType,
nScene,nX,nY,
nPhysAttackMin,nPhysAttackMin,
nMagicAttackMax,nMagicAttackMin);
}
}
#ifdef _DEBUG
// S1
s_HurtValueMsg.clear();
SNPRINTFA(s_HurtValueBuff,100,"S1::%d",nValue);
s_HurtValueMsg += s_HurtValueBuff;
#endif
//伤害值
float fValue = 0;
//技能攻击上限和下限
if(pParam->pSkillResult->nParam1 && pParam->pSkillResult->nParam1 >pParam->pSkillResult->nValue)
{
int nAddValue = pParam->pSkillResult->nValue + wrand(pParam->pSkillResult->nParam1 - pParam->pSkillResult->nValue +1);
fValue = (float)pParam->pSkillResult->nId/10000 * nValue + nAddValue;
}
else
{
fValue = (float)pParam->pSkillResult->nId/10000 * nValue + pParam->pSkillResult->nValue;
}
//兵魂-霜之哀伤
if ((nAttackType == TYPE_PHYSICAL_ATTACK || nAttackType == TYPE_MAGIC_ATTACK || nAttackType == TYPE_WIZARD_ATTACK ))
{
if( pParam->pSkillResult->btHitType != htFire )
{
if(isActor)
{
HallowsLorderInfo *pHallowsLorderInfo = ((CActor*)pParam->pSrcEntity)->GetHallowsSystem().GetHallowsLoderv(0, eHallowsSSC_SZAS);
if(pParam->pSrcEntity->m_nFrozenStrength > 0 && pHallowsLorderInfo && pHallowsLorderInfo->nLv > 0)
{
int nFrozenRate = 0;
//触发几率:施法者冰冻强度 - 目标冰冻强度(施法者冰冻强度与目标冰冻强度 相等时,施法者增加冰冻强度(万分比))最高几率8%
if(pParam->pSrcEntity->m_nFrozenStrength >= pParam->pTargetEntity->m_nFrozenStrength)
{
nFrozenRate = std::max(pParam->pSrcEntity->m_nFrozenStrength - pParam->pTargetEntity->m_nFrozenStrength, GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nFrozenAddValue);
nFrozenRate = std::min(nFrozenRate, GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nMaxFrozen);
if(wrand(10000) < nFrozenRate)
{
//目标为怪物时,怪物攻击降低10%,
if(pParam->pTargetEntity->GetType() == enMonster)
{
std::vector<int>::iterator iter = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vReduceAttackMon.begin();
for(; iter != GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vReduceAttackMon.end(); ++iter)
{
pParam->pTargetEntity->GetBuffSystem()->Append(*iter);
}
}
//已处于冰冻效果时不可再次被冰冻
static int nFrozenBuffId = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nFrozenBuffId;
CBuffProvider::BUFFCONFIG * pBUFFCONFIG = GetLogicServer()->GetDataProvider()->GetBuffProvider().GetBuff(nFrozenBuffId);
if (pBUFFCONFIG)
{
CDynamicBuff *pDynamicBuff = pParam->pTargetEntity->GetBuffSystem()->GetBuff((GAMEATTRTYPE)pBUFFCONFIG->nType, pBUFFCONFIG->nGroup);
if(!pDynamicBuff)
{
pParam->pTargetEntity->GetBuffSystem()->Append(nFrozenBuffId);
//触发冰冻时额外扣除与施法者冰冻值相等的额外伤害
int nFrozenTimes = 5;
if ( GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nFrozenTimes > 0 )
{
nFrozenTimes = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.nFrozenTimes;
}
pParam->pTargetEntity->m_nSZASAttckValue = pParam->pSrcEntity->m_nFrozenStrength * nFrozenTimes;
}
}
}
}
}
}
}
}
// 这里将法/道的职业的普攻速万分比加到伤害增益上
if (isActor && (nAttackType == TYPE_MAGIC_ATTACK || nAttackType == TYPE_WIZARD_ATTACK))
{
// 必须属性伤害增益万分比有值, 普攻增速万分比才有效
if (pParam->pSkillResult->nId > 0)
{
float atk_acc = pParam->pSrcEntity->GetProperty<int>(PROP_ACTOR_NORMAL_ATK_ACC);
fValue = fValue + (atk_acc/10000 * nValue);
}
}
//兵魂-剧毒裁决
if ((nAttackType == TYPE_PHYSICAL_ATTACK || nAttackType == TYPE_MAGIC_ATTACK || nAttackType == TYPE_WIZARD_ATTACK ))
{
if( pParam->pSkillResult->btHitType != htFire )
{
if(isActor)
{
HallowsLorderInfo* pHallowsLorderInfo = ((CActor*)pParam->pSrcEntity)->GetHallowsSystem().GetHallowsLoderv(0, eHallowsSSC_JDCJ);
if(pHallowsLorderInfo && pHallowsLorderInfo->nLv > 0)
{
//触发几率
if(wrand(10000) < pParam->pSrcEntity->m_nToxicRate)
{
//触发效果:额外绝对值伤害
pParam->pTargetEntity->m_nToxicAttckValue = pParam->pSrcEntity->m_nToxicDamage;
std::vector<int>::iterator iter = GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vPoisonBuff.begin();
for(; iter < GetLogicServer()->GetDataProvider()->GetHallowthen().m_HallowsSSCMainInfo.vPoisonBuff.end(); ++iter)
{
pParam->pTargetEntity->GetBuffSystem()->Append(*iter);
}
}
}
}
}
}
//内功
if ( isActor )
{
bool isInternalWork = false;
switch (pParam->nSkillID)
{
case enInternalWorkSkillsId_HalfMoon: //半月弯刀
case enInternalWorkSkillsId_Fire: //烈火剑法
case enInternalWorkSkillsId_DayByDay: //逐日剑法
case enInternalWorkSkillsId_Thunder: //雷电术
case enInternalWorkSkillsId_IceStorm: //冰咆哮
case enInternalWorkSkillsId_RainFlowSpark: //流星火雨
case enInternalWorkSkillsId_SoulFireSign: //灵魂火符
case enInternalWorkSkillsId_BloodBite: //嗜血术
isInternalWork = true;
break;
default:
break;
}
if ( isInternalWork )
{
if (pParam->pTargetEntity->GetType() == enActor)
{
fValue = fValue + pParam->pSrcEntity->GetProperty<unsigned int>(InternalWorkIncreaseDamageMap[pParam->nSkillID]) - pParam->pTargetEntity->GetProperty<unsigned int>(InternalWorkReduceDamageMap[pParam->nSkillID]);
} else {
fValue = fValue + pParam->pSrcEntity->GetProperty<unsigned int>(InternalWorkIncreaseDamageMap[pParam->nSkillID]);
}
}
}
#ifdef _DEBUG
// S2
SNPRINTFA(s_HurtValueBuff,100," //S2::%d",(int)fValue);
s_HurtValueMsg += s_HurtValueBuff;
#endif
if ((fValue >= 10000.0f) && isMonster)
{
int nScene = pParam->pSrcEntity->GetSceneID();
int nEntityId= pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_ID);
if (nEntityId != 171)
{
int nX= pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_POSX);
int nY= pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_POSY);
int nPhysAttackMax= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MIN);
int nPhysAttackMin= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_PHYSICAL_ATTACK_MAX);
int nMagicAttackMax= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MAX);
int nMagicAttackMin= pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MIN);
OutputMsg(rmError,_T("[Monster Attack2] 怪物攻击过高ID:%d Atk:%f 技能参数SId:%d, AtkType:%d 坐标(%d,%d,%d 物理(%d,%d 魔法(%d,%d"),
nEntityId,fValue,
pParam->nSkillID,nAttackType,
nScene,nX,nY,
nPhysAttackMin,nPhysAttackMin,
nMagicAttackMax,nMagicAttackMin);
}
}
//触发附加效果(麻痹)
if ((nAttackType == TYPE_PHYSICAL_ATTACK || nAttackType == TYPE_MAGIC_ATTACK || nAttackType == TYPE_WIZARD_ATTACK ))
{
//概率触发麻痹逻辑 --对方如果是麻痹中这不触发麻痹
if(!((CAnimal*)pParam->pTargetEntity)->GetDizzyState() &&pParam->pSrcEntity->m_nDizzyValue >0) {
if( pParam->pSkillResult->btHitType != htFire /*&& pParam->pSrcEntity->m_nDizzyBuffInterval <= GetGlobalLogicEngine()->getMiniDateTime() */) {
//M1=((麻痹几率-抗麻几率)/10000)*职业麻痹系数
//M1=Min{M1,30%}
//M2=(麻痹时长增加-麻痹时长减免)
//M2=Min{M2,7000}
int nCoefficient = 10000;
if(pParam->pSrcEntity->GetType() == enActor) {
CActor* pActor = (CActor*)pParam->pSrcEntity;
if(pActor) {
nCoefficient = GetLogicServer()->GetDataProvider()->GetGlobalConfig().GetJobDizzyRate(pActor->GetJob()-1);
}
}
int nDizzyRate = (pParam->pSrcEntity->m_nDizzyValue - pParam->pTargetEntity->m_nDeductDizzyValue)/* nCoefficient/10000.0*/;
int nDizzyBuffMaxRate = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nDizzyBuffMaxRate;
nDizzyRate = std::min(nDizzyRate, nDizzyBuffMaxRate);
//麻痹命中了
if( nDizzyRate >= 0 && wrand(10000) <= nDizzyRate) {
int nDizzyTime = pParam->pSrcEntity->m_nDizzyTimeAdd - pParam->pTargetEntity->m_nDizzyTimeAbsorbAdd;
int nDizzyBuffMaxTime = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nDizzyBuffMaxTime;
nDizzyTime = std::min(nDizzyTime, nDizzyBuffMaxTime);
if(nDizzyTime > 0) {
((CAnimal*)pParam->pTargetEntity)->SetDizzyTime(nDizzyTime);
if(pParam->pSrcEntity && pParam->pTargetEntity) {
static int nParalyEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nParalyEffId;
if(nParalyEffId > 0 ) {
CEntityMsg msg(CEntityMsg::emShowEntityEffect, pParam->pSrcEntity->GetHandle());
msg.nParam1 = nParalyEffId;
pParam->pTargetEntity->PostEntityMsg(msg);
}
}
}
// if (pParam->pSrcEntity->GetType() == enActor)
// {
// ((CActor *)(pParam->pSrcEntity))->SendOldTipmsgWithId(tpDizzyActive, ttChatWindow);
// }
}
}
}
}
if (nAttackType == TYPE_HOLY_ATTACK)
{
//神圣攻击
((CCreature *)pParam->pTargetEntity)->ChangeHP(-1 * fValue, pParam->pSrcEntity, true, false, true);
}
else
{
CalculateDamage( pParam->nSkillID, pParam->pSrcEntity, pParam->pTargetEntity, pParam, fValue, nAttackType);
}
#ifdef _DEBUG
if (GetGlobalLogicEngine()->IsPrintDamageInfo() && (pParam->pSrcEntity->GetType() == enActor))
{
s_HurtValueMsg += ";;";
CActor *pActor = ((CActor*)pParam->pSrcEntity);
CActorPacket pack;
CDataPacket &data = pActor->AllocPacket(pack);
data << (BYTE)enChatSystemID << (BYTE)sSendChat << (BYTE)1;
data.writeString(pParam->pTargetEntity->GetShowName());
data.writeString(s_HurtValueMsg.c_str());
data << pActor->GetLevel();
data << Uint64(pActor->GetHandle());
data <<(unsigned int)(0);
data << (BYTE)0;
pack.flush();
}
#endif
}
//无命中
else OnDodge(pParam->pSrcEntity,pParam->pTargetEntity);
}
inline void CSkillResult::WizardAttack(PSKILLRESULTPARAM pParam)
{
NormalAttack(pParam,TYPE_WIZARD_ATTACK);
}
//忽略防御
inline void CSkillResult::IgnoreDefence(PSKILLRESULTPARAM pParam)
{
pParam->btIgnoreDefence =1; //忽略目标的防御
}
//召唤火出来
inline void CSkillResult::MobFire(PSKILLRESULTPARAM pParam)
{
if(pParam->pSkillResult->nValue <=0) return;
if ( !pParam->pSrcEntity )
{
return;
}
int nCurPosX,nCurPosY;
pParam->pSrcEntity->GetPosition(nCurPosX,nCurPosY);
if (abs(nCurPosX - pParam->nTargetPosX) >MOVE_GRID_ROW_RADIO || abs(nCurPosY - pParam->nTargetPosY) > MIN_MOVE_GRID_COL_RADIO)
{
return;
}
float rate = (float)pParam->pSkillResult->nParam2 /10000;
float addValue = (float)(pParam->pSkillResult->nParam3 * 1000);
//火墙的存活时间单位ms
int nLiveTime =(int) ( (int)(pParam->pSrcEntity->GetProperty<int>(PROP_CREATURE_MAGIC_ATTACK_MAX) *rate) + addValue );
/*
*
* 2021-08-20 火墙 暂时性修改
// 清除上一次召唤的火墙
std::deque<EntityHandle>& LastFireSkillEntitys = ((CActor*)pParam->pSrcEntity)->m_deqLastFireSkillEntity;
for ( ;LastFireSkillEntitys.size() > 0; LastFireSkillEntitys.pop_front() )
{
EntityHandle hLastFireEntity = LastFireSkillEntitys.front();
CFire* pFire = (CFire*)GetGlobalLogicEngine()->GetEntityMgr()->GetEntity(hLastFireEntity);
CActor* pMaster = NULL;
if (pFire && (pMaster = (CActor*)pFire->GetMasterPtr()))
{
if (pParam->pSrcEntity->GetHandle() == pMaster->GetHandle())
{
GetGlobalLogicEngine()->GetEntityMgr()->DestroyEntity(hLastFireEntity,false);
}
}
}
*/
// 创建9个火的位置
static int s_matrix[][2] =
{
{-1,-1}, {0,-1}, {1,-1},
{-1,0}, {0,0}, {1,0},
{-1,1}, {0,1}, {1,1}
};
for(INT_PTR j=0; j< ArrayCount(s_matrix); j++)
{
int x = s_matrix[j][0];
int y = s_matrix[j][1];
//创建法师的火
CFire * pFire = CFire::CreateFire(pParam->pSrcEntity->GetScene(),pParam->nTargetPosX + x,pParam->nTargetPosY + y,pParam->pSrcEntity,
pParam->pSkillResult->nId,
nLiveTime,
pParam->pSkillResult->nValue,
pParam->pSkillResult->nParam1);
/*
*
* 2021-08-20 火墙 暂时性修改
//记录火
if (pFire)
{
((CActor*)pParam->pSrcEntity)->m_deqLastFireSkillEntity.push_back(pFire->GetHandle());
} else
{
((CActor*)pParam->pSrcEntity)->m_deqLastFireSkillEntity.push_back(0);
}
*/
}
}
//召唤宠物
inline void CSkillResult::MobPet(PSKILLRESULTPARAM pParam)
{
int nPetId = pParam->pSkillResult->nId;
int nLevel = pParam->pSkillResult->nValue;
int nAiId = pParam->pSkillResult->nParam1;
int nInheritPercent = pParam->pSkillResult->nParam2;
if(nPetId <=0 || nLevel<=0) return;
if( pParam->pSrcEntity ==NULL) return;
if(pParam->pSrcEntity->GetType() != enActor) return;
CActor *pActor = (CActor*)pParam->pSrcEntity;
pActor->GetPetSystem().AddPet(nPetId,nLevel, nAiId, 0, nInheritPercent,pParam->nSkillID);
}
//删除自身宠物
inline void CSkillResult::RemovePet(PSKILLRESULTPARAM pParam)
{
int nPetId = pParam->pSkillResult->nId;
if (nPetId <=0) return;
if (pParam->pSrcEntity ==NULL) return;
if (pParam->pSrcEntity->GetType() != enActor) return;
((CActor*)pParam->pSrcEntity)->GetPetSystem().RemoveAllPetByConfigId(nPetId);
}
//自己往前方走一格
void CSkillResult::GoAhead(PSKILLRESULTPARAM pParam)
{
int nStep = pParam->pSkillResult->nValue;
int nDir = pParam->pSrcEntity->GetProperty<int>(PROP_ENTITY_DIR); //按当前的方向往前面走
int nInterval =pParam->pSkillResult->nParam1; //表示移动一格的速度(单位ms)
int nSimulateReboundSpeed = 1; //如果是1表示需要失败模拟
CScene *pScene = pParam->pSrcEntity->GetScene();
if(pScene ==NULL) return;
CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
// 当前点
int nCurrentPosx ,nCurrentPosy;
pParam->pSrcEntity->GetPosition(nCurrentPosx,nCurrentPosy);
int nCurPosX = nCurrentPosx, nCurPosY = nCurrentPosy;
//bool hasEntityBlock =false;
int nRealStep = 0;
for (size_t i = 0; i < nStep; i++)
{
// 新的点
INT_PTR nNewPox = nCurPosX;
INT_PTR nNewPoy = nCurPosY;
CEntityGrid::NewPosition(nNewPox,nNewPoy,nDir,1);
// //是否有传送门
// bool hasTransPoint =false;
// if(pScene->IsTelePort(nNewPox,nNewPoy))
// {
// hasTransPoint = true;
// }
//不能穿过实体
bool hasEntityBlock = false;
const MapEntityGrid *pGrid=pScene->GetMapEntityGrid((int)nNewPox);
#ifndef GRID_USE_STL_MAP
for(INT_PTR i=0; i< pGrid->m_entitys.count(); i++)
{
if(pGrid->m_entitys[i].pos != nNewPoy) continue;
EntityHandle& hHandle = pGrid->m_entitys[i].hd;
#else
const EntityPosVector& entitys = pGrid->m_entitys;
typedef typename EntityPosVector::const_iterator Iter;
Iter it = entitys.begin(), end = entitys.end();
for (; it != end; it++)
{
if((*it).second != nNewPoy) continue;
const EntityHandle& hHandle = (*it).first;
#endif
switch(hHandle.GetType())
{
case enActor:
case enMonster:
case enNpc:
case enPet:
case enHero:
CEntity* pEntity = pEntityMgr->GetEntity(hHandle);
if (pEntity && !pEntity->IsDeath())
hasEntityBlock = true;
break;
}
}
if(hasEntityBlock || !pScene->CanMove(nNewPox,nNewPoy)) break;
nRealStep++;
nCurPosX = nNewPox;
nCurPosY = nNewPoy;
}
pParam->pSrcEntity->GetMoveSystem()->Move(nDir,nCurrentPosx,nCurrentPosy,nRealStep,0,true,nInterval,sMoveAhead,0,nSimulateReboundSpeed);
}
//往后走若干格
void CSkillResult::GoBack(PSKILLRESULTPARAM pParam)
{
INT_PTR nStep = pParam->pSkillResult->nValue;
int nInterval =pParam->pSkillResult->nParam1;
if(nStep ==0)
{
return;
}
INT_PTR nTargetPosX = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nTargetPosY = pParam->pTargetEntity->GetProperty<int>(PROP_ENTITY_POSY);
// 非怪物,在安全区不能弹出去
INT_PTR entityType = pParam->pTargetEntity->GetType();
if (entityType != enMonster)
{
CScene* pActorScene = pParam->pTargetEntity->GetScene();
if (pActorScene && pActorScene->HasMapAttribute(nTargetPosX,nTargetPosY,aaSaft))
{
return;
}
}
int nId = pParam->pSkillResult->nId; //如果失败了添加值为id的技能标记
int nTime = pParam->pSkillResult->nParam2; //技能标记的时间
//如果怪物自己把自己击退的话,就往后退几格
CEntity *pSrc = pParam->pSrcEntity ;
if(pParam->pSrcEntity ==pParam->pTargetEntity )
{
return ;
}
if(pSrc ==NULL)
{
return;
}
//当前的坐标
INT_PTR nCurrentPosx = pSrc->GetProperty<int>(PROP_ENTITY_POSX);
INT_PTR nCurrentPosy = pSrc->GetProperty<int>(PROP_ENTITY_POSY);
//如果坐标不变的话
if(nCurrentPosx == nTargetPosX && nCurrentPosy == nTargetPosY)
{
return;
}
INT_PTR nDir = CEntity::GetDir(nCurrentPosx,nCurrentPosy,nTargetPosX,nTargetPosY);
CScene *pScene = pParam->pTargetEntity->GetScene();
if(pScene ==NULL) return;
CEntityManager* pEntityMgr = GetGlobalLogicEngine()->GetEntityMgr();
// INT_PTR nNewPox=nTargetPosX ;
// INT_PTR nNewPoy=nTargetPosY;
// CEntityGrid::NewPosition(nNewPox,nNewPoy,nDir,nStep);
// if(pScene->IsTelePort(nNewPox,nNewPoy)) //如果目标点有传送门则不可以推出去
// {
// return;
// }
// pParam->pTargetEntity->SetDir((nDir +4) %DIR_STOP); //取相反的方向
// pParam->pTargetEntity->GetMoveSystem()->Move(nDir,nTargetPosX,nTargetPosY,nStep,0,true,nInterval,sMoveBack);
// 当前点
int nTarPosX = nTargetPosX, nTarPosY = nTargetPosY;
int nRealStep = 0;
for (size_t i = 0; i < nStep; i++)
{
// 新的点
INT_PTR nNewPox = nTarPosX;
INT_PTR nNewPoy = nTarPosY;
CEntityGrid::NewPosition(nNewPox,nNewPoy,nDir,1);
//如果目标点有传送门则不可以推出去
if(pScene->IsTelePort(nNewPox,nNewPoy))
{
return;
}
//不能穿过实体
bool hasEntityBlock = false;
const MapEntityGrid *pGrid=pScene->GetMapEntityGrid((int)nNewPox);
#ifndef GRID_USE_STL_MAP
for(INT_PTR i=0; i< pGrid->m_entitys.count(); i++)
{
if(pGrid->m_entitys[i].pos != nNewPoy) continue;
EntityHandle& hHandle = pGrid->m_entitys[i].hd;
#else
const EntityPosVector& entitys = pGrid->m_entitys;
typedef typename EntityPosVector::const_iterator Iter;
Iter it = entitys.begin(), end = entitys.end();
for (; it != end; it++)
{
if((*it).second != nNewPoy) continue;
const EntityHandle& hHandle = (*it).first;
#endif
switch(hHandle.GetType())
{
case enActor:
case enMonster:
case enNpc:
case enPet:
case enHero:
CEntity* pEntity = pEntityMgr->GetEntity(hHandle);
if (pEntity && !pEntity->IsDeath())
hasEntityBlock = true;
break;
}
}
if(hasEntityBlock || !pScene->CanMove(nNewPox,nNewPoy)) break;
nRealStep++;
nTarPosX = nNewPox;
nTarPosY = nNewPoy;
}
pParam->pTargetEntity->SetDir((nDir +4) %DIR_STOP); //取相反的方向
pParam->pTargetEntity->GetMoveSystem()->Move(nDir,nTargetPosX,nTargetPosY,nRealStep,0,true,nInterval,sMoveBack);
}
void CSkillResult::RandTransfer(CFuBen *pFb,CScene *pScene,CEntity *pEntity)
{
if(pScene ==NULL) return;
int nWidth=0,nHeight=0; //长宽
int nSceneId = pScene->GetSceneId();
pScene->GetMapSize(nWidth,nHeight);
if(nWidth <=0 || nHeight <=0) return; //场景非法
int nPosX,nPosY;
CFuBenManager* pMgr = GetGlobalLogicEngine()->GetFuBenMgr();
int nCurrentPosX,nCurrentPosY;
pEntity->GetPosition(nCurrentPosX,nCurrentPosY);
//尝试一万次,在这个地方找到一个点可以传送过去,找个点传送过去
for(INT_PTR i=0; i< 10000; i++)
{
nPosX = wrand(nWidth);
nPosY = wrand(nHeight);
if(pScene->CanMove(nPosX,nPosY) )
{
//自己当前的点不算
if(nCurrentPosX == nPosX &&nCurrentPosY == nPosY)
{
continue;
}
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
if( pMgr->EnterFuBen(pEntity,pFb,nSceneId,nPosX,nPosY,enDefaultTelePort,nEffId))
{
char broadcastBuff[64];
CDataPacket broadcastPack(broadcastBuff, sizeof(broadcastBuff)); //下发的数据包
broadcastPack << (BYTE) enDefaultEntitySystemID <<(BYTE)sEnterSceneEffect;
broadcastPack << (Uint64)pEntity->GetHandle();
broadcastPack << (unsigned short)(nEffId);
CObserverSystem * pSystem = ((CAnimal*)pEntity)->GetObserverSystem();
pSystem->BroadCast(broadcastPack.getMemoryPtr(),broadcastPack.getPosition(),false);
break;
}
}
}
}
void CSkillResult::FixTransfer(CFuBen *pFb,CScene *pScene,CEntity *pEntity, int nPosX,int nPosY)
{
if(pScene ==NULL) return;
int nWidth=0,nHeight=0; //长宽
int nSceneId = pScene->GetSceneId();
pScene->GetMapSize(nWidth,nHeight);
if(nWidth <=0 || nHeight <=0) return; //场景非法
CFuBenManager* pMgr = GetGlobalLogicEngine()->GetFuBenMgr();
int nCurrentPosX,nCurrentPosY;
pEntity->GetPosition(nCurrentPosX,nCurrentPosY);
if(pScene->CanMove(nPosX,nPosY) )
{
//自己当前的点不算
if(nCurrentPosX == nPosX &&nCurrentPosY == nPosY)
{
return ;
}
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
bool bEnterResult = false;
int nPkValue = pEntity->GetProperty<unsigned int>(PROP_ACTOR_PK_VALUE);
if (pEntity->GetScene() == pScene && GetLogicServer()->GetDataProvider()->GetPkConfig().redName > nPkValue)
{
bEnterResult = ((CAnimal*)pEntity)->GetMoveSystem()->InstantMove(nPosX,nPosY,1,enDefaultTelePort,nEffId);
}
else
{
bEnterResult = pFb->Enter(pEntity,nSceneId,nPosX,nPosY,0,0,enDefaultTelePort,nEffId);
}
if(bEnterResult)
{
char broadcastBuff[64];
CDataPacket broadcastPack(broadcastBuff, sizeof(broadcastBuff)); //下发的数据包
broadcastPack << (BYTE) enDefaultEntitySystemID <<(BYTE)sEnterSceneEffect;
broadcastPack << (Uint64)pEntity->GetHandle();
broadcastPack << (unsigned short)(nEffId);
CObserverSystem * pSystem = ((CAnimal*)pEntity)->GetObserverSystem();
pSystem->BroadCast(broadcastPack.getMemoryPtr(),broadcastPack.getPosition(),false);
}
}
}
void CSkillResult::PostponeMoveTime(PSKILLRESULTPARAM pParam)
{
if( pParam->pTargetEntity ==NULL) return;
pParam->pTargetEntity->GetMoveSystem()->PostponeMoveTime(pParam->pSkillResult->nValue);
}
void CSkillResult::LastSafeAreaRTransfer(PSKILLRESULTPARAM pParam)
{
if(pParam->pSrcEntity ==NULL) return;
if(pParam->pSrcEntity->GetType() != enActor) return; //只有玩家才有
CActor *pActor = (CActor*)pParam->pSrcEntity; //玩家的指针
if( !pActor->IsInRawServer() ) return; //不在跨服里是没法使用的
if (wrand(10000) <= pParam->pSkillResult->nId)
{
int nSceneId = pActor->GetCitySceneId();
if(nSceneId ==0)
{
nSceneId = pActor->GetSceneID();
}
CFuBen * pFb=GetGlobalLogicEngine()->GetFuBenMgr()->GetFbStaticDataPtr(0);
if(pFb ==NULL) return;
CScene *pScene= pFb->GetScene(nSceneId);
RandTransfer(NULL,pScene,pActor);
}
}
//指定场景地点传送
void CSkillResult::Transfer(PSKILLRESULTPARAM pParam)
{
if(pParam->pSrcEntity ==NULL) return;
if(pParam->pSrcEntity->GetType() != enActor) return; //只有玩家才有
CActor *pActor = (CActor*)pParam->pSrcEntity; //玩家的指针
CFuBenManager *pFBMgr = GetGlobalLogicEngine()->GetFuBenMgr();
if( !pActor->IsInRawServer() ) return; //不在跨服里是没法使用的
int nSceneId = pParam->pSkillResult->nId;
int nX = pParam->pSkillResult->nParam1;
int nY = pParam->pSkillResult->nParam2;
CFuBen* pFb = GetGlobalLogicEngine()->GetFuBenMgr()->GetFbStaticDataPtr(0);
if (pFb)
{
CScene *pScene= pFb->GetScene(nSceneId);
FixTransfer(pFb, pScene,pParam->pSrcEntity,nX,nY);
// if (pScene && pScene->CanMove(nX,nY))
// {
// if (pActor->GetScene() == pScene)
// {
// ((CAnimal*)pParam->pSrcEntity)->GetMoveSystem()->InstantMove(nX,nY);
// }
// else
// {
// pFb->Enter(pParam->pSrcEntity,nSceneId,nX,nY,0,0);
// }
// }
}
}
//本场景随机传送
void CSkillResult::SceneTransfer(PSKILLRESULTPARAM pParam)
{
//往这里随机传送
if(pParam->pSrcEntity ==NULL) return;
//CScene *pScene= pParam->pSrcEntity->GetScene();
CEntity *pEntity = (CEntity*) pParam->pSrcEntity;
CFuBen * pFb = pEntity->GetFuBen();
int nSceneId = pEntity->GetSceneID();
if(nSceneId ==0) return; //别传送进了测试场景
if(pEntity ==NULL || pEntity->GetScene() ==NULL) return;
if(pEntity->GetType() != enActor)
{
OutputMsg(rmTip,"Skill SceneTransfer ,name=[%s],scene=[%s]",pEntity->GetEntityName(), pEntity->GetScene()->GetSceneName());
}
RandTransfer(pFb,pEntity->GetScene(),pEntity);
}
//最后一个安全区域传送
void CSkillResult::LastSafeAreaTransfer(PSKILLRESULTPARAM pParam)
{
if(pParam->pSrcEntity ==NULL) return;
if(pParam->pSrcEntity->GetType() != enActor) return; //只有玩家才有
CActor *pActor = (CActor*)pParam->pSrcEntity; //玩家的指针
WORD nSceneId, nX, nY;
// if( !pActor->IsInRawServer() ) return; //不在跨服里是没法使用的
pActor->GetCityPoint(nSceneId,nX,nY);
if(nSceneId==0)
{
nSceneId = pActor->GetSceneID();
}
int nPkValue = pParam->pSrcEntity->GetProperty<unsigned int>(PROP_ACTOR_PK_VALUE);
if (GetLogicServer()->GetDataProvider()->GetPkConfig().redName <= nPkValue)
{
nSceneId = GetLogicServer()->GetDataProvider()->GetPkConfig().m_nPrisonSceneId;//红名地图
nX = GetLogicServer()->GetDataProvider()->GetPkConfig().m_nPrisonPosX;
nY = GetLogicServer()->GetDataProvider()->GetPkConfig().m_nPrisonPosY;
//nWeight = GetLogicServer()->GetDataProvider()->GetPkConfig().m_nPrisonWeight;
//nHeight = GetLogicServer()->GetDataProvider()->GetPkConfig().m_nPrisonHeight;
}
CFuBen * pFb=GetGlobalLogicEngine()->GetFuBenMgr()->GetFbStaticDataPtr(0);
if(pFb == NULL) return;
CScene *pScene= pFb->GetScene(nSceneId);
int nDiffX,nDiffY;
for(INT_PTR i=0; i< 50; i++)
{
nDiffX = (int)wrand(6) - 3;
nDiffY = (int)wrand(6) - 3;
if(pScene->CanMove(nX+nDiffX, nY+nDiffY) )
{
FixTransfer(pFb, pScene, pParam->pSrcEntity,nX+nDiffX,nY+nDiffY);
return;
}
}
FixTransfer(pFb, pScene, pParam->pSrcEntity,nX,nY);
}
void CSkillResult::ChangEquipDua(PSKILLRESULTPARAM pParam)
{
if(pParam->pSrcEntity ==NULL) return;
if(pParam->pSrcEntity->GetType() != enActor)
{
return ;
}
CUserEquipment& equips= ((CActor *) pParam->pSrcEntity)->GetEquipmentSystem();
//获取武器的指针
CUserItem *pUserItem =equips.GetItemByType(pParam->pSkillResult->nId);
if(pUserItem ==NULL )return ;
equips.ChangeEquipDua(pUserItem,pParam->pSkillResult->nValue);
}
//怪物掉落东西
void CSkillResult::DropMonsterItem(PSKILLRESULTPARAM pParam)
{
CActor * pActor = NULL;
if(pParam->pTargetEntity != NULL )
{
if(pParam->pTargetEntity->GetType() == enPet)
{
pActor = ((CPet*)pParam->pTargetEntity)->GetMaster();
}
else if(pParam->pTargetEntity->GetType() == enHero)
{
pActor = ((CHero*)pParam->pTargetEntity)->GetMaster();
}
else if(pParam->pTargetEntity->GetType() == enActor)
{
pActor = (CActor*)pParam->pTargetEntity;
}
}
CMonster::RealDropItemExp(pParam->pSkillResult->nId,pActor,pParam->pSrcEntity->GetScene(),pParam->nTargetPosX,pParam->nTargetPosY);
}
void CSkillResult::ChangeModel(PSKILLRESULTPARAM pParam)
{
if( pParam->pSrcEntity == NULL ) return;
pParam->pSrcEntity->SetProperty<int>(PROP_ENTITY_MODELID, pParam->pSkillResult->nId);
}
//按百分比扣属性,rate表示扩除的万分比1000表示10%id=1表示扣血1表示扣蓝
void CSkillResult::RateChangeProperty(PSKILLRESULTPARAM pParam)
{
if( pParam->pTargetEntity == NULL || !pParam->pTargetEntity->isAnimal()) return;
INT_PTR nEntityType = pParam->pTargetEntity->GetType();
int nType = pParam->pSkillResult->nId;
int nRate = pParam->pSkillResult->nValue;
float fRate= (float)nRate/10000;
int nValue =0;
switch (nType)
{
case 1: //最大血
{
nValue = pParam->pTargetEntity->GetProperty< int>(PROP_CREATURE_MAXHP);
nValue = (int )(fRate * nValue);
if (nValue < 0 && pParam->pTargetEntity->GetProperty<unsigned int>(PROP_CREATURE_HP) == 0) //如果挂了就没血可扣了
{
return;
}
pParam->pTargetEntity->ChangeHP(nValue);
if (nValue < 0 && pParam->pTargetEntity->GetProperty<unsigned int>(PROP_CREATURE_HP) == 0)
{
pParam->pTargetEntity->OnKilledByEntity(pParam->pSrcEntity);
}
}
break;
case 2: //最大蓝
{
nValue = pParam->pTargetEntity->GetProperty< int>(PROP_CREATURE_MAXMP);
nValue = (int )(fRate * nValue);
pParam->pTargetEntity->ChangeMP(nValue);
}
break;
case 3: //最大基本血
{
if (nEntityType == enActor)
{
nValue = ((CActor *)(pParam->pTargetEntity))->m_nBase_MaxHp;
}
else if (nEntityType == enHero)
{
const CHeroSystem::HERODATA *pData = ((CHero *)(pParam->pTargetEntity))->GetHeroPtr();
if (pData)
{
nValue = pData->nBaseMaxHp;
}
}
else
nValue = pParam->pTargetEntity->GetProperty< int>(PROP_CREATURE_MAXHP);
nValue = (int )(fRate * nValue);
if (nValue < 0 && pParam->pTargetEntity->GetProperty<unsigned int>(PROP_CREATURE_HP) == 0) //如果挂了就没血可扣了
{
return;
}
pParam->pTargetEntity->ChangeHP(nValue);
if (nValue < 0 && pParam->pTargetEntity->GetProperty<unsigned int>(PROP_CREATURE_HP) == 0)
{
pParam->pTargetEntity->OnKilledByEntity(pParam->pSrcEntity);
}
}
break;
case 4: //最大基本蓝
{
if (nEntityType == enActor)
{
nValue = ((CActor *)(pParam->pTargetEntity))->m_nBase_MaxMp;
}
else if (nEntityType == enHero)
{
const CHeroSystem::HERODATA *pData = ((CHero *)(pParam->pTargetEntity))->GetHeroPtr();
if (pData)
{
nValue = pData->nBaseMaxMp;
}
}
else
nValue = pParam->pTargetEntity->GetProperty< int>(PROP_CREATURE_MAXMP);
nValue = (int )(fRate * nValue);
pParam->pTargetEntity->ChangeMP(nValue);
}
break;
default:
break;
}
}
void CSkillResult::GiveAward(PSKILLRESULTPARAM pParam)
{
if( pParam->pTargetEntity == NULL || pParam->pTargetEntity->GetType() != enActor) return;
CActor *pActor = (CActor*)pParam->pTargetEntity;
pActor->GiveAward(pParam->pSkillResult->nParam1,pParam->pSkillResult->nId,pParam->pSkillResult->nValue,0,0,pParam->pSkillResult->nParam2,0,GameLog::clSkillResultGiveAward,"Skill");
}
void CSkillResult::NoticeRemMasterAsset( LPCTSTR sName, bool boItems, int nItemId, int nCount)
{
char sText[1024] = {0};
if (boItems)
{
if (nCount > 0)
{
const CStdItem * pItemConfig = GetLogicServer()->GetDataProvider()->GetStdItemProvider().GetStdItem(nItemId);
if (pItemConfig != NULL)
{
LPCTSTR sFormat = GetLogicServer()->GetDataProvider()->GetOldTipmsgConfig().GetTipmsg(tpPetDropMasterItems);
sprintf_s(sText, sizeof(sText), sFormat, sName, pItemConfig->m_sName, nCount);
}
}
else
{
LPCTSTR sFormat = GetLogicServer()->GetDataProvider()->GetOldTipmsgConfig().GetTipmsg(tpPetNotDropMstItems);
sprintf_s(sText, sizeof(sText), sFormat, sName, nCount);
}
}
else
{
if (nCount > 0)
{
LPCTSTR sFormat = GetLogicServer()->GetDataProvider()->GetOldTipmsgConfig().GetTipmsg(tpPetDropMasterMoney);
sprintf_s(sText, sizeof(sText), sFormat, sName, nCount);
}
else
{
LPCTSTR sFormat = GetLogicServer()->GetDataProvider()->GetOldTipmsgConfig().GetTipmsg(tpPetNotDropMstMoney);
sprintf_s(sText, sizeof(sText), sFormat, sName);
}
}
GetGlobalLogicEngine()->GetEntityMgr()->BroadcastTipmsg(sText, ttChatWindow + ttScreenCenter);
}
//客户端播放引导性特效
void CSkillResult::PlayGuide(PSKILLRESULTPARAM pParam)
{
if (NULL == pParam->pTargetEntity) return;
if (pParam->pTargetEntity->GetType() == enActor)
{
CActorPacket pack;
CDataPacket &data = ((CActor*)pParam->pTargetEntity)->AllocPacket(pack);
data << (BYTE)enSkillSystemID << (BYTE)sPlayGuide;
data << (unsigned)pParam->pSkillResult->nId;
data << (unsigned)pParam->pSkillResult->nValue;
pack.flush();
}
}
//忽略每次最大伤害限制
void CSkillResult::IgnoreMaxDropHp(PSKILLRESULTPARAM pParam)
{
pParam->btIgnoreMaxDropHp =1; //忽略每次最大伤害限制
}
//丢到一个点移动
void CSkillResult::PointMove(PSKILLRESULTPARAM pParam)
{
if(pParam->pTargetEntity ==NULL) return;
int nPosX,nPosY;
nPosX = pParam->pSkillResult->nId ; //x,y
nPosY = pParam->pSkillResult->nValue;
if(nPosX >0 && nPosY >0)
{
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
pParam->pTargetEntity->GetMoveSystem()->InstantMove(nPosX,nPosY,1,enDefaultTelePort,nEffId); //瞬间移动
}
else
{
//如果坐标没有配置则随机传
CFuBen *pFb = pParam->pTargetEntity->GetFuBen();
CScene *pScene =pParam->pTargetEntity->GetScene();
RandTransfer(pFb,pScene,pParam->pTargetEntity);
}
}
//自己移动到范围内的一个点
void CSkillResult::SelfPointMove(PSKILLRESULTPARAM pParam)
{
/*
if (pParam->pSrcEntity ==NULL) return;
int nPosX,nPosY,nMaxDis,isUseRand,isUseLine;
nPosX = pParam->nTargetPosX; //x,y
nPosY = pParam->nTargetPosY;
nMaxDis = pParam->pSkillResult->nValue;
isUseRand = pParam->pSkillResult->nId; //是否使用回字查找
isUseLine = pParam->pSkillResult->nParam1; //是否优先选择距离与玩家原来所在地较近的位置
if (nPosX >0 && nPosY >0 && isUseLine)
{
//点不可移动时,是否优先选择距离与玩家原来所在地较近的位置
CScene *pScene = pParam->pSrcEntity->GetScene();
if (pScene)
{
int nStartX, nStartY;
pParam->pSrcEntity->GetPosition(nStartX, nStartY);
//距离的平方
INT_PTR nDisSquare = CMovementSystem::GetDisSqare(nStartX,nStartY, nPosX,nPosY);
//获取方向
INT_PTR nDir = CEntity::GetDir(nPosX,nPosY,nStartX,nStartY);
INT_PTR nNewPosX = nPosX;
INT_PTR nNewPosY = nPosY;
INT_PTR nStep = ((int)sqrt((double)nDisSquare));
for (INT_PTR i = 0; i < nStep; i++)
{
if (!pParam->pSrcEntity->GetMoveSystem()->CanJumpTo(pScene,nNewPosX,nNewPosY))
{
CEntityGrid::NewPosition(nNewPosX, nNewPosY, nDir, 1);
continue;
}
if (nMaxDis > 0) //限制一下移动最大的距离
{
nDisSquare = CMovementSystem::GetDisSqare(nStartX,nStartY, nNewPosX,nNewPosY);
if (nDisSquare > (nMaxDis * nMaxDis))
{
CEntityGrid::NewPosition(nNewPosX, nNewPosY, nDir, 1);
continue;
}
}
//找到了,如果一直找不到会在InstantMove()再进行回字查找
nPosX = (int)nNewPosX;
nPosY = (int)nNewPosY;
break;
}
}
}
pParam->pSrcEntity->GetMoveSystem()->InstantMove(nPosX,nPosY,isUseRand); //瞬间移动
*/
if (pParam->pSrcEntity ==NULL) return;
int nPosX,nPosY,nMaxDis,isUseRand,isUseLine;
nPosX = pParam->nTargetPosX; //x,y
nPosY = pParam->nTargetPosY;
nMaxDis = pParam->pSkillResult->nValue;
isUseRand = pParam->pSkillResult->nId; //是否使用回字查找
isUseLine = pParam->pSkillResult->nParam1; //是否优先选择距离与玩家原来所在地较近的位置
if (nPosX >0 && nPosY >0 && isUseLine)
{
CScene *pScene = pParam->pSrcEntity->GetScene();
if (pScene)
{
int nStartX, nStartY;
pParam->pSrcEntity->GetPosition(nStartX, nStartY);
//距离的平方
INT_PTR nDisSquare = CMovementSystem::GetDisSqare(nStartX,nStartY, nPosX,nPosY);
//获取方向
INT_PTR nDir = CEntity::GetDir(nStartX,nStartY,nPosX,nPosY);
INT_PTR nNewPosX = nPosX;
INT_PTR nNewPosY = nPosY;
if (nDisSquare > nMaxDis * nMaxDis)
{
nDisSquare = nMaxDis * nMaxDis;
nNewPosX = nStartX;
nNewPosY = nStartY;
CEntityGrid::NewPosition(nNewPosX, nNewPosY, nDir, nMaxDis);
nPosX = (int)nNewPosX;
nPosY = (int)nNewPosY;
}
}
}
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
pParam->pSrcEntity->GetMoveSystem()->InstantMove(nPosX,nPosY,isUseRand,enDefaultTelePort,nEffId); //瞬间移动
}
//冲锋
void CSkillResult::TargetRapidMove(PSKILLRESULTPARAM pParam)
{
if (pParam->pTargetEntity == NULL || pParam->pSrcEntity == NULL || !pParam->pTargetEntity->isAnimal()) return;
if (pParam->pTargetEntity == pParam->pSrcEntity) return;
INT_PTR nMaxStep = pParam->pSkillResult->nValue > 0 ? pParam->pSkillResult->nValue : 30; //移动的最大步数
int nId = pParam->pSkillResult->nId; //如果失败了添加值为id的技能标记
int nTime = pParam->pSkillResult->nParam1; //timeParam表示技能标记的时间
int nSpeed = pParam->pSkillResult->nParam2; //冲锋速度
int nPosX,nPosY,nTargetPosX,nTargetPosY;
pParam->pSrcEntity->GetPosition(nPosX,nPosY); //玩家当前的位置
nTargetPosX = pParam->nTargetPosX;
nTargetPosY = pParam->nTargetPosY;
if (nTargetPosX == 0 || nTargetPosY == 0)
{
pParam->pTargetEntity->GetPosition(nTargetPosX,nTargetPosY); //目标当前的位置
}
CMovementSystem *pMoveSys = pParam->pSrcEntity->GetMoveSystem();
CScene *pScene = pParam->pSrcEntity->GetScene();
CScene *pTargetScene = pParam->pTargetEntity->GetScene();
if (pScene == NULL || pScene != pTargetScene) return;
bool hasHit = false;
INT_PTR nDir = pParam->pSrcEntity->GetProperty< int>(PROP_ENTITY_DIR);
INT_PTR nFinishStep = 0, nOneStep = 1;
INT_PTR nNewPosX = nPosX;
INT_PTR nNewPosY = nPosY;
static INT_PTR nDirTbl[3] = {0, -1, 1}; //需先判断与目标点的方向
INT_PTR nCheckDir = nDir;
if (nNewPosX == nTargetPosX && nNewPosY == nTargetPosY)
{
hasHit = true;
}
else
{
while (nFinishStep < nMaxStep) //如果还没完成
{
nDir = CEntity::GetDir(nNewPosX,nNewPosY,nTargetPosX,nTargetPosY);
//取新坐标
INT_PTR nCheckPosX = nNewPosX;
INT_PTR nCheckPosY = nNewPosY;
bool bCanMove = false;
for (INT_PTR i = 0; i < 1; i++) //判断3方向 现暂判断1方向
{
nCheckDir = (nDir + nDirTbl[i]) % DIR_STOP;
CEntityGrid::NewPosition(nCheckPosX,nCheckPosY,nCheckDir,nOneStep);
if (nCheckPosX == nTargetPosX && nCheckPosY == nTargetPosY)
{
hasHit = true;
break;
}
if (pMoveSys->CanJumpTo(pScene,nCheckPosX,nCheckPosY)) //遇到了一个传说门就不过去了
{
nNewPosX = nCheckPosX;
nNewPosY = nCheckPosY;
bCanMove = true;
break;
}
}
if (!bCanMove) //无法通过
{
break;
}
nFinishStep ++; //已经完成的步子
}
}
INT_PTR nNewDir = CEntity::GetDir(nPosX,nPosY,nNewPosX,nNewPosY);
if (nNewDir != DIR_STOP)
{
pParam->pSrcEntity->SetDir(nNewDir);
}
if (nFinishStep > 0)
{
if (pScene->MoveTo(pParam->pSrcEntity,nNewPosX,nNewPosY))
{
if (pParam->pSrcEntity->GetPosInfo().pScene == pScene)
{
char broadcasrBuff[128];
CDataPacket broadData(broadcasrBuff,sizeof(broadcasrBuff)); //广播的数据
//广播玩家的c移动
broadData << (BYTE)enDefaultEntitySystemID << (BYTE)sTargetRapidMove;
broadData << (Uint64)pParam->pSrcEntity->GetHandle() << (WORD)nPosX << (WORD)nPosY;
broadData << (WORD)nNewPosX << (WORD)nNewPosY;
broadData << (BYTE)pParam->pSrcEntity->GetProperty<unsigned int>(PROP_ENTITY_DIR);
broadData << (int)nSpeed;
CObserverSystem *pSystem = pParam->pSrcEntity->GetObserverSystem();
if (pSystem)
{
pSystem->BroadCast(broadData.getMemoryPtr(),broadData.getPosition(),true);
}
}
}
else
{
hasHit = false;
}
}
}
void CSkillResult::BroadCastHit(CAnimal * pEntity, Uint64 hTargetHandle)
{
char buff[128];
CDataPacket pack(buff,sizeof(buff));
pack << (BYTE) enDefaultEntitySystemID << (BYTE) sSkillHit;
pack << (Uint64) hTargetHandle ;
pEntity->GetObserverSystem()->BroadCast(pack.getMemoryPtr(),pack.getPosition(),true);
}
//造成伤害 = 攻击方攻击伤害 * ( 1 防守方护甲减伤比例)
// 护甲减伤比例 = 防守方防御值 * 15 / 防守方防御值 * 15 + 角色等级 * 400
// 角色等级的取值并不是固定的,当攻击方等级比防守方高时,采用防守方的等级进行计算,
// 当防守方等级比攻击方等级高时,采用攻击方的等级进行伤害减免计算,这样设定的主要目的是建立等级优势。
void CSkillResult::CalculateDamage(INT_PTR nSkillID,CAnimal * pSrcEntity,CAnimal *pTargetEntity,
PSKILLRESULTPARAM pParam,float fAttackValue,INT_PTR nAttackType)
{
if(pSrcEntity == NULL || pTargetEntity ==NULL || fAttackValue <= 0.0) return; //压根就没有伤害
unsigned int nCurrentHp = pTargetEntity->GetProperty<unsigned int>( PROP_CREATURE_HP);
if( nCurrentHp == 0) return;
GLOBALCONFIG &globalConfig = GetLogicServer()->GetDataProvider()->GetGlobalConfig();
const char * sSkillName=NULL ;
const OneSkillData *pConfig = NULL;
if(nSkillID)
{
pConfig = GetLogicServer()->GetDataProvider()->GetSkillProvider()->GetSkillData(nSkillID);
sSkillName = pConfig->sSkillName;
}
else
{
sSkillName = GetLogicServer()->GetDataProvider()->GetOldTipmsgConfig().GetTipmsg(tpNearAttackSkillName);
}
int nDefence = 0;
int nSrcType = (int)pSrcEntity->GetType();
INT_PTR nTargetType = pTargetEntity->GetType(); //获取实体的类型
if(nTargetType ==enActor)
{
if( ((CActor*)pTargetEntity)->m_isSuperman ) return; //如果是无敌状态,则不添加伤害
}
//防御值
float fDrop ; //掉血的点数
int nDrop; //整数的血的掉落
bool bIgnoreDamgeRate =false; //是否忽略伤害吸收
bool isNotFireDamage = pParam->pSkillResult->btHitType != htFire; //不是火的伤害,部分效果不计算火墙输出
if(pParam->btIgnoreDefence) //如果是忽略对方的防御那么就是0
{
nDefence =0;
bIgnoreDamgeRate =true;
}
else
{
int nMaxValue,nMinValue;
if( nAttackType == TYPE_PHYSICAL_ATTACK) //如果是物理攻击的话
{
nMaxValue = pTargetEntity->GetProperty<int>(PROP_CREATURE_PYSICAL_DEFENCE_MAX);
nMinValue = pTargetEntity->GetProperty<int>(PROP_CREATURE_PYSICAL_DEFENCE_MIN);
}
else
{
nMaxValue = pTargetEntity->GetProperty<int>(PROP_CREATURE_MAGIC_DEFENCE_MAX);
nMinValue = pTargetEntity->GetProperty<int>(PROP_CREATURE_MAGIC_DEFENCE_MIN);
}
if(nMinValue >= nMaxValue)
{
nDefence = nMaxValue;
}
else
{
nDefence = nMinValue + wrand(nMaxValue - nMinValue +1); //随机取一个防御值
}
//无视防御比例--mhl
if(isNotFireDamage && nSrcType == enActor || nSrcType == enHero ) {
CAdvanceAnimal* pAdvSrcAnimal = (CAdvanceAnimal*)pSrcEntity;
if (pAdvSrcAnimal && pAdvSrcAnimal->m_nIgnorDefenceRatio > 0)
{
int currentDef = (int)(nDefence *(pAdvSrcAnimal->m_nIgnorDefenceRatio)/10000.0);
nDefence -= currentDef;
}
}
//无视防御,如果施法方有无视防御的效果,则需要免去对方一定的防御
if(isNotFireDamage && nSrcType == enActor || nSrcType == enHero )
{
CAdvanceAnimal* pAdvSrcAnimal = (CAdvanceAnimal*)pSrcEntity;
int nRateSkill = 0;
if (pAdvSrcAnimal && pConfig && pConfig->wAttrId == aIgnorDefenceRateSkill)
{
nRateSkill = pAdvSrcAnimal->m_nIgnorDefenceRateSkill;
}
if( pAdvSrcAnimal->m_nIgnorDefenceRate + nRateSkill > 0 )
{
if(wrand(10000) < (unsigned long)(pAdvSrcAnimal->m_nIgnorDefenceRate + nRateSkill)) //触发了无视防御
{
nDefence = 0 ;
//如果实现了目标无视防御要给自己放1个特效
static int s_nIgnorDefenceEffectId = 0; //这个特效id
static int s_nIgnorDefenceEffectKeepTime = 0; //这个特效持续时间
if(s_nIgnorDefenceEffectId >0 )
{
CEntityMsg msg(CEntityMsg::emAppendEntityEffect, pSrcEntity->GetHandle());
msg.dwDelay = 0;
msg.nParam1 = 0; //肯定是个挥洒型的特效
msg.nParam2 = s_nIgnorDefenceEffectId;
msg.nParam3 = s_nIgnorDefenceEffectKeepTime;
pSrcEntity->PostEntityMsg(msg); //向目标发送消息,稍候由目标进行广播
}
}
}
}
if(nDefence <0) //防御不能小于0小于0了就当成0
{
nDefence =0;
}
}
fDrop = fAttackValue - nDefence;
#ifdef _DEBUG
// S3
SNPRINTFA(s_HurtValueBuff,100," //S3::%d",(int)fDrop);
s_HurtValueMsg += s_HurtValueBuff;
#endif
// 攻击事件
pTargetEntity->OnAttacked(pSrcEntity);
pSrcEntity->OnAttackOther(pTargetEntity);
//职业伤害减免/加成
int nDamageValueDesc =0, nDamageRateDesc=0; //职业伤害减免
int nTargetDamageValue = 0, nTargetDamageRate = 0; //职业伤害加成
{
CAdvanceAnimal* pAdvAnimal = (CAdvanceAnimal*)pTargetEntity;
CAdvanceAnimal* pAdvSrcAnimal = (CAdvanceAnimal*)pSrcEntity;
//职业伤害加成 nTargetDamageValue nTargetDamageRate
int nTargetVocation = 0;
if (nTargetType == enActor)
{
nTargetVocation = pTargetEntity->GetProperty<int>(PROP_ACTOR_VOCATION);
}
else if (nTargetType == enHero)
{
const CHeroSystem::HERODATA * pTargetHero = ((CHero *)pTargetEntity)->GetHeroPtr();
if (pTargetHero != NULL)
{
nTargetVocation = pTargetHero->data.bVocation;
}
}
else
{
nTargetVocation = enVocNone;
}
switch(nTargetVocation)
{
case enVocNone: //怪物,宠物
nTargetDamageValue += pAdvSrcAnimal->m_nMonsterTargetDamageValue;
nTargetDamageRate = pAdvSrcAnimal->m_nMonsterTargetDamageRate;
break;
case enVocWarrior:
nTargetDamageValue += pAdvSrcAnimal->m_nWarriorTargetDamageValue;
nTargetDamageRate = pAdvSrcAnimal->m_nWarriorTargetDamageRate;
break;
case enVocMagician:
nTargetDamageValue += pAdvSrcAnimal->m_nMagicianTargetDamageValue;
nTargetDamageRate = pAdvSrcAnimal->m_nMagicianTargetDamageRate;
break;
case enVocWizard:
nTargetDamageValue += pAdvSrcAnimal->m_nWizardTargetDamageValue;
nTargetDamageRate = pAdvSrcAnimal->m_nWizardTargetDamageRate;
break;
default:
break;
}
//职业伤害减免 nDamageValueDesc nDamageRateDesc
if( nTargetType == enHero || nTargetType == enActor )
{
if(nSrcType == enActor || nSrcType == enHero)
{
int nVocation = 0;
if(nSrcType == enActor)
{
nVocation = pSrcEntity->GetProperty<int>(PROP_ACTOR_VOCATION);
}
else
{
const CHeroSystem::HERODATA * pData = ((CHero*)pSrcEntity)->GetHeroPtr();
if(pData)
{
nVocation = pData->data.bVocation;
}
}
switch(nVocation)
{
case enVocWarrior:
nDamageValueDesc += pAdvAnimal->m_nWarriorDamageValueDec;
nDamageRateDesc = pAdvAnimal->m_nWarriorDamageRateDec;
break;
case enVocMagician:
nDamageValueDesc += pAdvAnimal->m_nMagicianDamageValueDec;
nDamageRateDesc = pAdvAnimal->m_nMagicianDamageRateDec;
break;
case enVocWizard:
nDamageValueDesc += pAdvAnimal->m_nWizardDamageValueDec;
nDamageRateDesc = pAdvAnimal->m_nWizardDamageRateDec;
break;
}
}
else if(nSrcType == enMonster || nSrcType == enPet) //宝宝也算怪物的减免
{
nDamageValueDesc += pAdvAnimal->m_nMonsterDamageValueDec;
nDamageRateDesc = pAdvAnimal->m_nMonsterDamageRateDec;
}
}
}
//非职业伤害减免 +nDamageValueDesc
if( nTargetType == enHero || nTargetType == enActor )
{
CAdvanceAnimal* pAdvAnimal = (CAdvanceAnimal*)pTargetEntity;
CAdvanceAnimal* pAdvSrcAnimal = (CAdvanceAnimal*)pSrcEntity;
if( isNotFireDamage && pAdvAnimal->m_nDamageReduceRate > 0 && pAdvAnimal->m_nDamageReduceValue >0)
{
if(wrand(10000) < pAdvAnimal->m_nDamageReduceRate) //触发了伤害减免
{
nDamageValueDesc += pAdvAnimal->m_nDamageReduceValue;
//如果实现了目标无视防御要给自己放1个特效
static int s_nDamageDescEffectId = 0;
static int s_nDamageDescEffectKeepTime = 0; //这个特效持续时间
if(s_nDamageDescEffectId >0 )
{
CEntityMsg msg(CEntityMsg::emAppendEntityEffect, pSrcEntity->GetHandle());
msg.dwDelay = 0;
msg.nParam1 = 0; //肯定是个挥洒型的特效
msg.nParam2 = s_nDamageDescEffectId;
msg.nParam3 = s_nDamageDescEffectKeepTime;
pTargetEntity->PostEntityMsg(msg); //向目标发送消息,稍候由目标进行广播
}
}
}
}
//非职业伤害加成 -nDamageValueDesc
if(nSrcType == enActor || nSrcType == enHero)
{
CAdvanceAnimal* pAdvSrcAnimal = (CAdvanceAnimal*)pSrcEntity;
//伤害追加
if(isNotFireDamage && pAdvSrcAnimal->m_nDamageAddRate > 0 && pAdvSrcAnimal->m_nDamageAddValue >0)
{
if(wrand(10000) < pAdvSrcAnimal->m_nDamageAddRate) //触发了伤害追加
{
nDamageValueDesc -= pAdvSrcAnimal->m_nDamageAddValue;
//如果实现了目标无视防御要给自己放1个特效
static int s_nDamageAddEffectId = 0; //这个特效id
static int s_nDamageAddEffectKeepTime = 0; //这个特效持续时间
if(s_nDamageAddEffectId >0 )
{
CEntityMsg msg(CEntityMsg::emAppendEntityEffect, pSrcEntity->GetHandle());
msg.dwDelay = 0;
msg.nParam1 = 0; //肯定是个挥洒型的特效
msg.nParam2 = s_nDamageAddEffectId;
msg.nParam3 = s_nDamageAddEffectKeepTime;
pAdvSrcAnimal->PostEntityMsg(msg); //向目标发送消息,稍候由目标进行广播
}
}
}
}
if (nTargetDamageValue > 0) fDrop += nTargetDamageValue;
if(nDamageValueDesc != 0) fDrop -= nDamageValueDesc;
#ifdef _DEBUG
// S4
SNPRINTFA(s_HurtValueBuff,100," //S4::%d",(int)fDrop);
s_HurtValueMsg += s_HurtValueBuff;
#endif
if (nTargetDamageRate > 0 || nDamageRateDesc >0)
{
float nBaseRate = ((float)(10000 + nTargetDamageRate - nDamageRateDesc))/10000;
fDrop *= nBaseRate;
}
#ifdef _DEBUG
// S5
SNPRINTFA(s_HurtValueBuff,100," //S5::%d",(int)fDrop);
s_HurtValueMsg += s_HurtValueBuff;
#endif
//新版暴击,最后计算 --火墙除外
int nCritiEffId = 0;
if(pParam->pSkillResult && pParam->pSkillResult->btHitType != htFire)
{
int nNewCriDamarate = pParam->pSrcEntity->m_nCritDamageRate - pParam->pTargetEntity->m_nDeductCritDamageRate;
if (nNewCriDamarate > 0 && (int)wrand(10000) < nNewCriDamarate)
{
fDrop *= (1 + (pParam->pSrcEntity->m_nCritDamagePower/10000.0));
fDrop += (float)pParam->pSrcEntity->m_nCritDamageValue;
pSrcEntity->SetProperty<unsigned int>(PROP_ACTOR_CRIT_DAMAGE,(int)fDrop);
if(pSrcEntity && pTargetEntity) {
// static int nCritiEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nCritiEffId;
// if(nCritiEffId > 0) {
nCritiEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nCritiEffId;
// }
}
}
}
//最终的扣血伤害
if (fDrop <= 0.0 ) fDrop = 1.0f;//return ; //压根就不掉血
nDrop = (int)fDrop;
if(nCritiEffId > 0) {
CEntityMsg msg(CEntityMsg::emShowEntityEffect, pSrcEntity->GetHandle());
msg.nParam1 = nCritiEffId;
msg.nParam3 = (int)nDrop;
pTargetEntity->PostEntityMsg(msg);
}
if(fDrop - nDrop > 0.0) nDrop ++;//向上取整不够一滴的算1滴伤害
#ifdef _DEBUG
// S6
SNPRINTFA(s_HurtValueBuff,100," //S6::%d",nDrop);
s_HurtValueMsg += s_HurtValueBuff;
#endif
//扣血
bool bIgnoreMaxDropHp = pParam->btIgnoreMaxDropHp > 0 ? true : false; //是否忽略每次最大伤害限制
///---------应策划要求暂时加一条无敌--理应是buff 怪物打玩家无敌
// if(nTargetType == enActor && (nSrcType == enMonster || nSrcType == enNpc))
// nDrop = 0;
// if(((CActor *)pTargetEntity)->GetIsWd())
// nDrop = 0;
int btHitType = htDefault;
if(pParam->pSkillResult)
btHitType = pParam->pSkillResult->btHitType;
((CCreature *)pTargetEntity)->ChangeHP(-1* nDrop,pSrcEntity,bIgnoreDamgeRate,bIgnoreMaxDropHp,true, btHitType); //掉了多少点血
//特殊buff
CDynamicBuff *pBuff = pTargetEntity->GetBuffSystem()->GetFirstBuff(aDamageDropTime);
if(pBuff)
{
pTargetEntity->GetBuffSystem()->ReduceBuffTime(pBuff,nDrop);
}
//计算反弹
if (pTargetEntity->m_nDamageReboundRate > 0 && wrand(10000) < pTargetEntity->m_nDamageReboundRate)
{
int nTargetDrop = (int)(nDrop * pTargetEntity->m_fDamageReboundPower);
if (nTargetDrop > 0)
{
pSrcEntity->ChangeHP(-nTargetDrop, pTargetEntity);
if (nSrcType == enActor)
{
((CActor*)pSrcEntity)->GetPkSystem().SendPkToClient();
}
}
}
//死亡
if( pTargetEntity->GetProperty<unsigned int>(PROP_CREATURE_HP) == 0)
{
((CAnimal*)pTargetEntity)->OnKilledByEntity(pSrcEntity);
}
//受到攻击播放后摇
else
{
//{
BroadCastHit((CAnimal*)pTargetEntity,pTargetEntity->GetHandle());
//}
}
}
void CSkillResult::ChangeMonsterAttacked( PSKILLRESULTPARAM pParam )
{
if( pParam->pTargetEntity == NULL || pParam->pTargetEntity->GetType() != enMonster) return;
EntityFlags& flag= pParam->pTargetEntity->GetAttriFlag();
if(pParam->pSkillResult->nId ==0)
{
flag.DenyBeAttack =false;
}
else
{
flag.DenyBeAttack =true;
}
}
void CSkillResult::FastSelfCurHp(PSKILLRESULTPARAM pParam)
{
if( pParam->pSrcEntity ==NULL || pParam->pSrcEntity->IsDeath() || pParam->pSkillResult == NULL) return;
int nRate = pParam->pSkillResult->nValue; //比例
int nValue = pParam->pSkillResult->nId; //类型0红1血2红和血
bool boPercent = pParam->pSkillResult->nParam1 == 0 ? true: false;
float fCureValue= (float)nRate/10000;
switch(nValue)
{
case 0:
{
if (boPercent)
{
pParam->pSrcEntity->ChangeHP((int)(fCureValue * pParam->pSrcEntity->GetProperty<unsigned int>(PROP_CREATURE_MAXHP)));
}
else
{
pParam->pSrcEntity->ChangeHP(nRate);
}
break;
}
case 1:
{
if (boPercent)
{
pParam->pSrcEntity->ChangeMP((int)(fCureValue * pParam->pSrcEntity->GetProperty<unsigned int>(PROP_CREATURE_MAXMP)));
}
else
{
pParam->pSrcEntity->ChangeMP(nRate);
}
break;
}
case 2:
{
if (boPercent)
{
pParam->pSrcEntity->ChangeHP((int)(fCureValue * pParam->pSrcEntity->GetProperty<unsigned int>(PROP_CREATURE_MAXHP)));
pParam->pSrcEntity->ChangeMP((int)(fCureValue * pParam->pSrcEntity->GetProperty<unsigned int>(PROP_CREATURE_MAXMP)));
}
else
{
pParam->pSrcEntity->ChangeHP(nRate);
pParam->pSrcEntity->ChangeMP(nRate);
}
break;
}
default:
{
break;
}
}
}
//把目标移动到范围内的鼠标指定的点
void CSkillResult::TargetPointMove(PSKILLRESULTPARAM pParam)
{
if (pParam->pTargetEntity == NULL || pParam->pSrcEntity == NULL || !pParam->pTargetEntity->isAnimal()) return;
int nPosX, nPosY,isUseRand,nMaxDis ;
nPosX = pParam->nTargetPosX;
nPosY = pParam->nTargetPosY;
isUseRand = pParam->pSkillResult->nId; //是否使用回字查找
nMaxDis = pParam->pSkillResult->nValue; //限制移动的最大距离
if (nPosX >0 && nPosY >0)
{
CScene *pScene = pParam->pTargetEntity->GetScene();
if (pScene)
{
int nStartX, nStartY;
pParam->pTargetEntity->GetPosition(nStartX, nStartY);
//距离的平方
INT_PTR nDisSquare = CMovementSystem::GetDisSqare(nStartX,nStartY, nPosX,nPosY);
//获取方向
INT_PTR nDir = CEntity::GetDir(nPosX,nPosY,nStartX,nStartY);
INT_PTR nNewPosX = nPosX;
INT_PTR nNewPosY = nPosY;
INT_PTR nStep = ((int)sqrt((double)nDisSquare));
for (INT_PTR i = 0; i < nStep; i++)
{
if (!pParam->pTargetEntity->GetMoveSystem()->CanJumpTo(pScene,nNewPosX,nNewPosY))
{
CEntityGrid::NewPosition(nNewPosX, nNewPosY, nDir, 1);
continue;
}
if (nMaxDis > 0) //限制一下移动最大的距离
{
nDisSquare = CMovementSystem::GetDisSqare(nStartX,nStartY, nNewPosX,nNewPosY);
if (nDisSquare > (nMaxDis * nMaxDis))
{
CEntityGrid::NewPosition(nNewPosX, nNewPosY, nDir, 1);
continue;
}
}
//找到了,如果一直找不到会在InstantMove()再进行回字查找
nPosX = (int)nNewPosX;
nPosY = (int)nNewPosY;
break;
}
}
}
int nEffId = GetLogicServer()->GetDataProvider()->GetGlobalConfig().nBlinkEnterEffect;
pParam->pTargetEntity->GetMoveSystem()->InstantMove(nPosX,nPosY,isUseRand,enDefaultTelePort,nEffId); //瞬间移动
}
void CSkillResult::CatchAll(PSKILLRESULTPARAM pParam)
{
if(!pParam->pSkillResult || !pParam->pTargetEntity)
{
return;
}
CEntity * pEntity = pParam->pTargetEntity;
if(pEntity->GetAttriFlag().DenyBeMove) return; //如果不能被抓取的话就不能抓取
int nPosX,nPosY;
pParam->pSrcEntity->GetPosition(nPosX,nPosY);
nPosX += pParam->pSkillResult->nId; //x坐标偏移
nPosY += pParam->pSkillResult->nValue; //Y坐标偏移
if(pEntity && pEntity->isAnimal() )
{
((CAnimal*)pEntity)->GetMoveSystem()->InstantMove(nPosX,nPosY); //瞬间移动
}
}
void CSkillResult::MonsterMove(PSKILLRESULTPARAM pParam)
{
if(!pParam->pSrcEntity || !pParam->pTargetEntity)
{
return;
}
unsigned int nSceneID = pParam->pSrcEntity->GetSceneID();
unsigned int nTargetSceneId = pParam->pTargetEntity->GetSceneID();
if (nSceneID != nTargetSceneId)
{
return;
}
int nTargetPosX,nTargetPosY;
pParam->pTargetEntity->GetPosition(nTargetPosX,nTargetPosY);
CFuBen* hFb = pParam->pSrcEntity->GetFuBen();
GetGlobalLogicEngine()->GetFuBenMgr()->EnterFuBen(pParam->pSrcEntity,hFb,nSceneID,nTargetPosX,nTargetPosY);
}
void CSkillResult::Shout(PSKILLRESULTPARAM pParam)
{
INT_PTR nShoutType = pParam->pSkillResult->bBuffType;
INT_PTR nShoutId = pParam->pSkillResult->nId;
INT_PTR nTipType = pParam->pSkillResult->nValue == 0 ? ttChatWindow : pParam->pSkillResult->nValue;
//if(nShoutId)
char * pStr = GetLogicServer()->GetDataProvider()->GetMonsterShoutConfig().GetTipmsg(nShoutId); //获取这句话
if(pStr ==NULL) return;
if(pParam->pSrcEntity ==NULL || nShoutType <= mssInvalid || nShoutType >=mssMax ) return; //参数错误
pParam->pSrcEntity->Say((MonsterSayBCType)nShoutType,pStr,(int)nTipType);
}