void SpriteMonsterMgr::CreateCacheMonster(int typeId)
{
	//CCLOG("create monster cache typeId: %d", typeId);
	SpriteMonster * monster = NULL;

	MonsterInitInfo info;
	info.typeId = typeId;

	monster = new SpriteMonster(info);
	if (monster)
	{
		monster->createTexture(typeId);
		if (cacheMonsters.find(typeId) == cacheMonsters.end())
		{
			set<SpriteMonster*> monsterSet;
			monsterSet.insert(monster);
			cacheMonsters[typeId] = monsterSet;
		}
		else
		{
			cacheMonsters[typeId].insert(monster);
		}
	}
	else
	{
		CC_SAFE_DELETE(monster);
	}
}
float GetNearestMonster( SpriteSeer* pRole )
{
    float fret = 0.0f;
    SpriteMonster* pRet = NULL;

    float minDis = 100000.0f;

    minDis *= minDis;

    const map<int, SpriteMonster*>& allMonster = SpriteMonsterMgr::Get()->GetAllMonster();
    for(map<int, SpriteMonster*>::const_iterator iter = allMonster.begin(); iter != allMonster.end(); iter++)
    {
        float dis = ccpDistanceSQ(iter->second->getPosition(), pRole->getPosition());
        if( dis <= minDis)
        {
            pRet = iter->second;
            minDis = dis;

        }
    }

    if(pRet)
    {
        fret = ccpDistance(pRet->getPosition(), pRole->getPosition());
    }
    return fret;
}
void BaseLevelBuilder::showMonsterOrNot(bool bShow)
{
	if (m_level)
	{
		std::map<uint32_t, SpriteMonster*>::iterator iter = m_level->m_MonsterInfo.begin();
		while(iter != m_level->m_MonsterInfo.end())
		{
			SpriteMonster* pMonster = (*iter).second;
			if (pMonster)
			{
				pMonster->getRoot()->setVisible(bShow);
			}

			iter ++;
		}
	}
}
void NormalMonsterHPLayer::SetEnemyHpLable(float currentHp,bool isAnim,PLAYER_ID enemyId,unsigned int monsterType)
{
	SpriteMonster* monster = SpriteMonsterMgr::Get()->GetMonster(enemyId.getID());
	if(monster == NULL)
	{
		return;
	}

	float totalHp = monster->getTotalBlood();
	float scale = UIManager::sharedManager()->getScaleFactor();
	float percent= scale;
	if(totalHp != 0)
	{
		percent *= currentHp / totalHp;
	}
	if(m_hpPic)
	{
		m_hpPic->stopAllActions();
		if(isAnim)
		{
			CCActionInterval* actionScale = CCScaleTo::create(0.2f,percent,scale);
			m_hpPic->runAction(actionScale);
		}
		else
		{
			m_hpPic->setScaleX(percent);
		}
	}

	if(m_targetMonsterId != enemyId.getID())
	{
		const char* mosterNameIndex = LuaTinkerManager::Get()->getLuaConfig<const char *>("MonsterBasicInfomation", "MonsterBasicInfomation", monsterType, "Name");
		CCAssert(mosterNameIndex,"monster name index is null");
		const char* monsterName = Localizatioin::getLocalization(mosterNameIndex);
		CCAssert(monsterName,"monster name is null");
		m_nameLabel->setString(monsterName);

		char levelStr[20];
		sprintf(levelStr,"Lv%d",monster->getLevel());
		m_levelLabel->setString(levelStr);
	}

	b_checkMonster = true;
	m_targetMonsterId = enemyId.getID();
}
//----------------------------------------------------------------------------------------
//			others function means other players'
//----------------------------------------------------------------------------------------
void BaseLevelBuilder::addMonster(MonsterInitInfo info)
{
	std::map<uint32_t, SpriteMonster*>::iterator itor = m_level->m_MonsterInfo.find(info.uid);
	if (itor == m_level->m_MonsterInfo.end())
	{
		//add monster
		ASSERT(m_level->m_levelDataReference->mapFilePointer != NULL, "map file is empty");
		SpriteMonster* monster = LevelObjectCreator::sCreateSpriteMonster(info);

		monster->SetID(info.uid);
		monster->setTag(MAP_TAG_MONSTER);
		monster->setPosition(info.pos);

		//printf("addMonster %f, %f\n", info.pos.x, info.pos.y);

		//添加阴影
		/*ASprite* pAsprite = AspriteManager::getInstance()->getAsprite("spriteBin/shadow.bin");
		if(pAsprite != NULL)
		{
			CCPoint cp;
			CCSprite* pCSprite = pAsprite->getSpriteFromFrame(0, 0, cp);
			if(pCSprite != NULL)
			{
				pCSprite->setPosition(ccp(0, 0));
				pCSprite->setTag(SHADOW_TAG);
				monster->addChildToRoot(pCSprite);
			}
		}*/

		CATLObjectLayer* pObjLayer = dynamic_cast<CATLObjectLayer*>(m_level->m_pObjectsLayer);
		if(pObjLayer)
		{
			pObjLayer->AddRoleShadow(monster);
		}

		//为精英怪添加特效
		if(info.isElite)
		{
			EffectSprite * eliteEffect = ParticleManager::Get()->createEffectSprite(206,"");
			eliteEffect->SetAnim(kType_Play, 1, true);
			eliteEffect->setTag(ELITE_TAG);
			monster->addChildToRoot(eliteEffect);
		}

		if (m_level->m_pObjectsLayer)
		{
			m_level->m_pObjectsLayer->addChild(monster, LevelLayer::sCalcZorder(monster->getPosition()));			
		}

		m_level->m_MonsterInfo.insert(std::pair<uint32_t, SpriteMonster*>(info.uid, monster));
	}
	else
	{
		CCLog("error, the player has add before");
	}
}
SpriteMonster * SpriteMonsterMgr::getNearestMonster()
{
	SpriteMonster * nearestMonster = NULL;
	float distance = 10000.0f;
	SpriteSeer * hero = GameManager::Get()->getHero();
	if (!hero || m_tabMonsters.size() == 0)
	{
		return NULL;
	}

	map<int, SpriteMonster*>::iterator it = m_tabMonsters.begin();

	SpriteMonster * firstMonster = it->second;

	//能被锁定的怪物才记入数据,隐身不计入
	if (firstMonster->getCanBeFocus() && !firstMonster->getIsAlliance())
	{
		distance = ccpDistance(firstMonster->getPosition(), hero->getPosition());
		nearestMonster = firstMonster;
	}	

	for(; it != m_tabMonsters.end(); it++ )
	{
		SpriteMonster* monster = it->second;
		if (!monster->getCanBeFocus() || monster->getIsAlliance())
		{
			continue;
		}

		float dis = ccpDistance(monster->getPosition(), hero->getPosition());
		if (dis < distance && monster->fsm_rule.IsRunning())
		{
			distance = dis;
			nearestMonster = monster;
		}	
	}

	return nearestMonster;
}
SpriteMonster* SpriteMonsterMgr::CreateMonster(MonsterInitInfo info)
{
	SpriteMonster * monster = NULL;

	
	do
	{
		//try to use cache , if failed create a new one
		if (info.useCache)
		{
			if (cacheMonsters.find(info.typeId) == cacheMonsters.end())
			{
				CCLOG("can't find cache monster type : %d", info.typeId);
				break;
			}

			set<SpriteMonster*> monsterSet = cacheMonsters[info.typeId];
			if (monsterSet.size() == 0)
			{
				CCLOG("cache monster count none : type : %d", info.typeId);
				break;
			}

			set<SpriteMonster*>::iterator iter = monsterSet.begin();
			monster = *iter;
			if (monster->initWithInfoAndShow(info))
			{
				if (Add(monster) == false)
				{
					CCLOG("create monster id:%d failed, it's already existed" , info.uid);
					break;
				}
				cacheMonsters[info.typeId].erase(*iter);
				//CCLOG("use cache monster type : %d", info.typeId);
				return monster;
			}
		}
	} while (0);



	monster = new SpriteMonster(info);

	do
	{
		if (!monster)
		{
			break;
		}
		monster->autorelease();

		if (monster->createTexture(info.typeId) && monster->initWithInfoAndShow(info))
		{
			if (Add(monster) == false)
			{
				CCLOG("create monster id:%d failed, it's already existed" , info.uid);
				CC_SAFE_DELETE(monster);
				monster = NULL;
			}
			return  monster;
		}
		else
		{
			break;
		}
	} while (0);

	CC_SAFE_DELETE(monster);
	return NULL;
}
//type : 1 世界boss 2 勇者试炼 3 主城防守
void SpriteMonsterMgr::updateSpecialMonsterHPLayer(int id, int nowHp, int totalHp, int type)
{
	UILayout * layout = UIManager::sharedManager()->getUILayout("WorldBossHPUI");
	SpriteMonster * monster = NULL;
	if (m_tabMonsters.find(id) != m_tabMonsters.end())
	{
		monster = m_tabMonsters[id];
	}
	if (layout && monster)
	{		
		if (!specialMonsterHpInited)
		{			
			const char* mosterNameIndex = LuaTinkerManager::Get()->getLuaConfig<const char *>("MonsterBasicInfomation", "MonsterBasicInfomation", monster->GetTypeId(), "Name");
			const char* monsterName = Localizatioin::getLocalization(mosterNameIndex);

			CCSprite * monsterHPBarNode = NULL;

			if (type != 3)
			{
				layout->FindChildObjectByName<UILabel>("bossName")->setString(monsterName);

				stringstream bossLevelStream;
				bossLevelStream << "Lv." << monster->getLevel();
				string bossLevel = bossLevelStream.str();

				//layout->FindChildObjectByName<UILabel>("bossLevel")->setString(bossLevel.c_str());
				layout->FindChildObjectByName<UILabel>("bossLevel")->setString("");

				monsterHPBarNode = (CCSprite *)layout->FindChildObjectByName<UIPicture>("bossHPBar")->getCurrentNode();
				
			}
			else
			{
				layout->FindChildObjectByName<UILabel>("cityName")->setString(monsterName);

				monsterHPBarNode = (CCSprite *)layout->FindChildObjectByName<UIPicture>("cityHPBar")->getCurrentNode();
			}



			monsterHPBarNode->setAnchorPoint(ccp(0, 0.5f));

			CCPoint oldPos = monsterHPBarNode->getPosition();
			float scale = UIManager::sharedManager()->getScaleFactor();
			monsterHPBarNode->setPosition(ccp(oldPos.x-scale * monsterHPBarNode->getContentSize().width/2, oldPos.y));

			specialMonsterHpInited = true;
		}

		stringstream hpStream;
		hpStream << nowHp << "/" << totalHp;
		string hpStr = hpStream.str();


		switch (type)
		{
		case 1:
			//layout->FindChildObjectByName<UILabel>("bossHPNum")->setString(hpStr.c_str());
			layout->FindChildObjectByName<UILabel>("bossHPNum")->setString(Localizatioin::getLocalization("M_WORLDBOSS_HP"));
			break;

		case 2:
			layout->FindChildObjectByName<UILabel>("bossHPNum")->setString("");
			break;

		default:
			break;
		}

		
		CCSprite * monsterHPBarNode = NULL;
		if (type != 3)
		{
			monsterHPBarNode = (CCSprite *)layout->FindChildObjectByName<UIPicture>("bossHPBar")->getCurrentNode();
		}
		else
		{
			monsterHPBarNode = (CCSprite *)layout->FindChildObjectByName<UIPicture>("cityHPBar")->getCurrentNode();
		}
		
		float scale = UIManager::sharedManager()->getScaleFactor();
		float percent= scale;
		if(totalHp != 0)
		{
			percent *= nowHp * 1.0f / totalHp;
		}

		CCActionInterval* actionScale = CCScaleTo::create(0.2f,percent,scale);
		monsterHPBarNode->runAction(actionScale);
	}
}
void SpriteMonsterMgr::Update(float dt)
{
	map<int, SpriteMonster*>::iterator it = m_tabMonsters.begin();
	for(; it != m_tabMonsters.end(); )
	{
		SpriteMonster* monster = it->second;
		bool bDeleteSelf = false;
		bool isDead = false;
		monster->Update(dt, bDeleteSelf, isDead);
		
		//死亡检测是否为最后一个boss
		if (isDead && !inSlow && !hasSlowed)
		{
			if (isLastBoss(monster))
			{
				inSlow = true;
				hasSlowed = true;
				CCDirector::sharedDirector()->getScheduler()->setTimeScale(0.2f);
			}
		}

		if (inSlow && isLastBoss(monster) && monster->selfScheduleTimer >= 0)
		{
			CCDirector::sharedDirector()->getScheduler()->setTimeScale(1.0f);
			inSlow = false;
		}

		if (bDeleteSelf)
		{
			m_tabMonsters.erase(it++);
			monster->removeFromParentAndCleanup(true);			
		}
		else
		{
			it++;
		}
	}

	//检测播放声音
	if (isPlayingDieSound)
	{
		//该接口在Android失效,如果效果不好考虑用CD控制
		isPlayingDieSound = GameAudioManager::sharedManager()->isEffectIsPlaying(nowPlayingSoundId);
	}


	map<int , SkillSoundInfo>::iterator iter = skillSoundMap.begin();
	for (; iter != skillSoundMap.end(); iter++)
	{
		//首先刷新延迟时间
		if (iter->second.delayTime >= 0)
		{
			iter->second.delayTime -= dt;
		}		

		//尚未播放的声音,检测延迟时间是否已到
		if (iter->second.waitingForPlay == true)
		{
			if (iter->second.delayTime <= 0)
			{
				//延迟时间已到,可以播放
				GameAudioManager::sharedManager()->playEffect(iter->second.soundId, iter->second.isLoop);
				iter->second.waitingForPlay = false;
			}
		}
		else
		{
			//启动持续时间计时
			if (iter->second.continueTime >= 0)
			{
				iter->second.continueTime -= dt;
			}

			//终止后持续调用保证停止
			if (iter->second.continueTime <= 0 && iter->second.isLoop)
			{
				GameAudioManager::sharedManager()->stopEffect(iter->second.soundId);
			}
		}
	}
}
cocos2d::CCPoint ElfAimDirectionHandler::GetAimDirection()
{
	CCPoint ret = m_pElf->getDirectionVector();
	CCPoint rolePos = m_pElf->getPosition();

	
	if(LevelManager::sShareInstance()->isCurrentPVPLevel())
	{
		if(LevelManager::sShareInstance()->getCurrentLevelLayer())
		{
			float minDis = m_pSkill->longDistanceAttackRange;

			if(minDis <= 0.0f)
				minDis = 320.0f;

			minDis *= minDis;

			SpriteSeer* pNearestHero = NULL;

			std::map<unsigned int, OthersPlayerInfo>& otherPlayer = LevelManager::sShareInstance()->getCurrentLevelLayer()->m_othersPlayerInfo;

			for(std::map<unsigned int, OthersPlayerInfo>::const_iterator iter = otherPlayer.begin(); iter != otherPlayer.end(); iter++)
			{
				SpriteSeer* pOhterHero = iter->second.seer; 
				if(m_pRole == pOhterHero || pOhterHero == NULL)
					continue;

				float dis = ccpDistanceSQ(pOhterHero->getPosition(), m_pElf->getPosition());
				if( dis <= minDis)
				{
					pNearestHero = pOhterHero;
					minDis = dis;

				}
			}

			if(pNearestHero)
			{
				m_bAimMonster = true;
				m_nearestMonsterPos = pNearestHero->getPosition();
				ret = ccpSub(m_nearestMonsterPos, rolePos);
			}
		}
	}
	else
	{
		SpriteMonster* pNearestMonster = GetNearestMonster();

		if(pNearestMonster)
		{
			m_bAimMonster = true;
			m_nearestMonsterPos = pNearestMonster->getPosition();
			ret = ccpSub(m_nearestMonsterPos, rolePos);

		}
	}

	

	ret = ccpNormalize(ret);

	return ret;
}