bool FightStateNormal::SearchSkill(CMonster *monster, long dis) { if (monster == NULL) { LogError(AI_MODULE, "monster object is null."); return false; } // 选择周期技能 if(SearchSkill(SKILLTYPE_CYCLE, monster, dis)) { return true; } unsigned long thisTime = timeGetTime(); if(thisTime > m_NormalSkillTimeStamp) { m_NormalSkillTimeStamp = thisTime + monster->GetSkillSpace(); int proportion = monster->GetSkillProportion(); if(random(100) < proportion) { // 选择普通技能 if(SearchSkill(SKILLTYPE_NORMAL, monster, dis)) { return true; } } } // 选择基本技能 return SearchSkill(SKILLTYPE_BASE, monster, dis); }
INT CFixedPositionArcher::Tracing(CMoveShape*pTarget) { SearchSkill(pTarget); CBaseModule* basemodule=0; stStaticModuParam* moduparam=0; BOOL HasSkill=TRUE; INT MinAtkDistance=0; INT MaxAtkDistance=0; if (HasChoiceSkill()) { basemodule=dynamic_cast<CMonster*>(m_pOwner)->GetActiveSkill(0);//GetSearchedSkillKey() } else { Stand(dynamic_cast<CMonster*>(m_pOwner)->GetStopFrame()); WhenLoseTarget(); return TRACE_RESULT_TRACE; } if (basemodule!=NULL) { moduparam=basemodule->GetStaticParam(); MinAtkDistance=moduparam->lMinAtkDistance; MaxAtkDistance=moduparam->lMaxAtkDistance; } else { Stand(dynamic_cast<CMonster*>(m_pOwner)->GetStopFrame()); WhenLoseTarget(); return TRACE_RESULT_TRACE; } //##合乎距离要求。 LONG lDistance = m_pOwner -> RealDistance( pTarget ); //如果在技能的距离内, 则使用技能 if(lDistance >= MinAtkDistance && lDistance <= MaxAtkDistance ) { if (HasSkill) { return TRACE_RESULT_SUCCESS; } else { Stand(dynamic_cast<CMonster*>(m_pOwner)->GetStopFrame()); WhenLoseTarget(); return TRACE_RESULT_TRACE; } } //##如果依然在追击范围内,就开始跟随玩家。 else { Stand(dynamic_cast<CMonster*>(m_pOwner)->GetStopFrame()); return TRACE_RESULT_TRACE; } }
void FightStateNormal::Attack(BaseType::EntityType *entity, CMoveShape *target) { if (entity == NULL) { LogError(AI_MODULE, "Attack entity object is null."); return; } if (target == NULL) { LogError(AI_MODULE, "Target to be attacked is null."); return; } CMonster *monster= static_cast<CMonster*>(entity->GetOwner()); long targetDis = monster->RealDistance(target); if(m_SelSkill.id == 0) { // search one skill to attack if(!SearchSkill(monster, targetDis)) { entity->Resume(OPER_FAILED_TIME); return ; } } // we assume we have one skill to attack the target if(!GetInst(SkillAttribute).IsExist(m_SelSkill.id , m_SelSkill.level)) { // error entity->Resume(OPER_FAILED_TIME); ClearSelSkill(); return ; } float minAtkDis = (float)monster->GetSkillValue(m_SelSkill.id , m_SelSkill.level , "MinAtkDistance"); float maxAtkDis = (float)monster->GetSkillValue(m_SelSkill.id , m_SelSkill.level , "MaxAtkDistance"); bool used = false; // we assume the target is still in the track range. if(targetDis > maxAtkDis) { entity->Move(target->GetTileX(), target->GetTileY()); } else if(targetDis < minAtkDis) { long dir = GetLineDir(target->GetTileX(), target->GetTileY(), monster->GetTileX(), monster->GetTileY()); entity->Move(dir); } else { // in the attack range if(static_cast<MonsterAI*>(entity)->BeginSkill(m_SelSkill.id, m_SelSkill.level, target->GetTileX(), target->GetTileY(), target)) { // use this skill ok, clear the selection. OnSkillUsed(monster); used = true; } } // clear the selected skill if it's not a cycle skill if(!used && m_SelSkill.type != SKILLTYPE_CYCLE) { ClearSelSkill(); } }