| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package BaseAttack  | 
| # @todo: ¹¥»÷Âß¼µ÷¶ÈÆ÷  | 
| #  | 
| # @author: eggxp  | 
| # @date 2011-10-09  | 
| # @version 1.0  | 
| #  | 
| # @note: ´¦ÀíËùÓеĹ¥»÷Âß¼  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| #"""Version = 2016-12-30 20:00"""  | 
| #---------------------------------------------------------------------  | 
| import AttackCommon  | 
| import GameWorld  | 
| import IPY_GameWorld  | 
| import PlayerControl  | 
| import NPCCommon  | 
| import ChConfig  | 
| import ChEquip  | 
| import SkillCommon  | 
| import AttackLogic  | 
| import ItemControler  | 
| import ItemCommon  | 
| import BuffSkill  | 
| import FBLogic  | 
| import SkillShell  | 
| import EventShell  | 
| import PetControl  | 
| import random  | 
| import OperControlManager  | 
| import DataRecordPack  | 
| import ChItem  | 
| import ReadChConfig  | 
| import GameObj  | 
| import ChPyNetSendPack  | 
| import ChNetSendPack  | 
| import NetPackCommon  | 
| import PassiveBuffEffMng  | 
| import PlayerGeTui  | 
| #---------------------------------------------------------------------  | 
| g_skillHurtList = IPY_GameWorld.IPY_HurtList()  | 
|   | 
| #É˺¦½á¹¹Ìå  | 
| #hurtTypeIndance = None  | 
| #---------------------------------------------------------------------  | 
| #µ¼ÈëËùÓеĹ¥»÷Ä£¿é  | 
| GameWorld.ImportAll("Script\\Attack\\", "AttackLogic")  | 
| GameWorld.ImportAll("Script\\Attack\\", "")  | 
| #---------------------------------------------------------------------  | 
| ## ÖØÐ¶ÁÈ¡ËùÓй¥»÷Âß¼  | 
| #  @param tick µ±Ç°tick  | 
| #  @return ·µ»ØNone  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def ReloadAttack(tick):  | 
|     scriptPath = ChConfig.GetAppPath() + "Script\\Attack\\AttackLogic"  | 
|     GameWorld.ReloadScript(scriptPath, "AttackLogic")  | 
|       | 
|     scriptPath = ChConfig.GetAppPath() + "Script\\Attack"  | 
|     GameWorld.ReloadScript(scriptPath, "")  | 
|     return  | 
|   | 
| #------------------------------------------------------------------  | 
| ### ÉèÖÃÉ˺¦½á¹¹Ìå  | 
| ##  @param indance É˺¦½á¹¹Ìå  | 
| ##  @return ·µ»ØÖµËµÃ÷  | 
| ##  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| #def __SetHurtIndance(indance):  | 
| #    global hurtTypeIndance  | 
| #    hurtTypeIndance = indance  | 
| #  | 
| ### »ñµÃ±¾´Î¹¥»÷ÊÇ·ñÊÇÖÂÃüÒ»»÷  | 
| ##  @param ÎÞ²ÎÊý  | 
| ##  @return True or False  | 
| ##  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| #def GetIsSuperHit():  | 
| #    #Òì³£  | 
| #    if hurtTypeIndance == None:  | 
| #        #GameWorld.Log("»ñȡȫ¾Ö±äÁ¿hurttypeʧ°Ü")  | 
| #        return ChConfig.Def_HurtType_Normal  | 
| #      | 
| #    return hurtTypeIndance.HurtType == ChConfig.Def_HurtType_SuperHit  | 
| #  | 
| ### »ñµÃ±¾´Î¹¥»÷ÊÇ·ñÊÇMiss  | 
| ##  @param ÎÞ²ÎÊý  | 
| ##  @return True or False  | 
| ##  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| #def GetIsMiss():  | 
| #    #Òì³£  | 
| #    if hurtTypeIndance == None:  | 
| #        #GameWorld.Log("»ñȡȫ¾Ö±äÁ¿hurttypeʧ°Ü")  | 
| #        return ChConfig.Def_HurtType_Normal  | 
| #      | 
| #    return hurtTypeIndance.HurtType == ChConfig.Def_HurtType_Miss  | 
| #  | 
| ### »ñµÃ±¾´Î¹¥»÷É˺¦µÄѪ  | 
| ##  @param ÎÞ²ÎÊý  | 
| ##  @return ÉËѪֵ  | 
| ##  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| #def GetLostHP():  | 
| #    #Òì³£  | 
| #    if hurtTypeIndance == None:  | 
| #        #GameWorld.Log("»ñȡȫ¾Ö±äÁ¿hurttypeʧ°Ü")  | 
| #        return 0  | 
| #      | 
| #    return hurtTypeIndance.HurtHP  | 
|   | 
| #------------------------------------------------------------------  | 
| ## »ñµÃ¹¥»÷·½Ãû×Ö(²ÎÊý -> µ±Ç°¶ÔÏó)              | 
| #  @param obj IPY_GameObj  | 
| #  @return ObjÀàÐÍ strÐÍ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GetObjAttackName(obj):  | 
|     curObjType = obj.GetGameObjType()  | 
|     result = "Unknown"  | 
|       | 
|     if curObjType == IPY_GameWorld.gotPlayer:  | 
|         result = "Player"  | 
|           | 
|     elif curObjType == IPY_GameWorld.gotNPC:  | 
|         npcObjType = obj.GetGameNPCObjType()  | 
|         npcType = obj.GetType()  | 
|           | 
|         if npcType == IPY_GameWorld.ntGuard:   #ÊØÎÀ, GetType()ÊÇÈ¡µÃ±íÖеÄtype  | 
|             result = "Guard"  | 
|               | 
|         elif npcType == IPY_GameWorld.ntFunctionNPC: #¹¦ÄÜNPC  | 
|             result = "FuncNPC"  | 
|               | 
|         elif npcType == IPY_GameWorld.ntDeer:         #¹  | 
|             result = "Deer"  | 
|           | 
|         elif npcType == IPY_GameWorld.ntDefenceMax:   #ÎÞÏÞ·ÀÓùµÄ¹ÖÎï  | 
|             result = "DefenceMaxNPC"  | 
|           | 
|         elif npcType == IPY_GameWorld.ntGoldenEgg:    #½ðµ°  | 
|             result = "GoldenEgg"  | 
|                                  | 
|         elif npcObjType == IPY_GameWorld.gnotNormal:  #ÆÕͨ¹Ö GetGameObjType() ÊÇÈ¡µÃ³ÌÐòÖÐÅж¨µÄtype  | 
|             result = "NormalNPC"  | 
|           | 
|         elif npcObjType == IPY_GameWorld.gnotSummon:  #ÕÙ»½  | 
|             if hasattr(obj, "GetOwner") and obj.GetOwner() != None:  | 
|                 result = "SummonNPC"  | 
|             else:  | 
|                 result = "NormalNPC"  | 
|                   | 
|         elif npcObjType == IPY_GameWorld.gnotTruck:   #æô³µ  | 
|             result = "Truck"  | 
|               | 
|         elif npcObjType == IPY_GameWorld.gnotPet:     #³èÎï  | 
|             result = "Pet"  | 
|       | 
|     return result  | 
| #------------------------------------------------------------------  | 
| ## »ñµÃÊÇ·ñ¿ÉÒÔ¹¥»÷(²ÎÊý -> ¹¥»÷·½,·ÀÊØ·½,¼¼ÄÜ(ÎÞ -> None),µ±Ç°Ê±¼ä)  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param defender ·ÀÓùObj  | 
| #  @param skill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return Ture or Flase µ±Ç°Ê±¿ÌÄÜ·ñ¹¥»÷  | 
| #  @remarks Í¨¹ýµ÷ÓàObj_Attack_Obj.GetCanAttack »ñÈ¡·µ»ØÖµ  | 
| def GetCanAttack(attacker, defender, skill, tick):  | 
|     callFunc = GameWorld.GetExecFunc(  | 
|                                      AttackLogic, "%s_Attack_%s.%s" % (  | 
|                                      GetObjAttackName(attacker),  | 
|                                      GetObjAttackName(defender),  | 
|                                      "GetCanAttack")  | 
|                                      )  | 
|       | 
|     if not callFunc:  | 
|         #GameWorld.Log( "%d GetCanAttack %d Error !"%( attacker.GetID(), defender.GetID() ) )  | 
|         return False  | 
|       | 
|     return callFunc(attacker, defender, skill, tick)  | 
|   | 
| #------------------------------------------------------------------  | 
| ## »ñȡ˫·½¹ØÏµ  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param defender ·ÀÓùObj  | 
| #  @param skill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ChConfig.Type_Relation_Enemy µÐÓѹØÏµ , ChConfig.Def_PASysMessage_None ¹¥»÷ϵͳÌáʾ  | 
| #  @remarks Í¨¹ýµ÷ÓàObj_Attack_Obj.GetTagRelation »ñÈ¡·µ»ØÖµ  | 
| def GetTagRelation(attacker, defender, skill, tick):  | 
|     #GameWorld.Log("¹¥»÷·½ = %s,·ÀÊØ·½ = %s"%(GetObjAttackName(attacker),GetObjAttackName(defender)))  | 
|     callFunc = GameWorld.GetExecFunc(  | 
|                                      AttackLogic, "%s_Attack_%s.%s" % (  | 
|                                      GetObjAttackName(attacker),  | 
|                                      GetObjAttackName(defender),  | 
|                                      "GetTagRelation")  | 
|                                      )  | 
|     if not callFunc:  | 
|         #GameWorld.Log("%d GetTagRelation %d Error !"%( attacker.GetID(), defender.GetID() ) )  | 
|         return ChConfig.Type_Relation_None , ChConfig.Def_PASysMessage_None  | 
|           | 
|     return callFunc(attacker, defender, skill, tick)  | 
|   | 
|   | 
| def GetFirstHurtObj():  | 
|     global g_skillHurtList  | 
|     if g_skillHurtList.GetHurtCount():  | 
|         return g_skillHurtList.GetHurtAt(0)  | 
|       | 
|     return None  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ¹¥»÷ͨÓú¯Êý  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param defender ·ÀÓùObj  | 
| #  @param skill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param skillPercent ¼¼ÄÜÔöÇ¿°Ù·Ö±È  | 
| #  @param skillEnhance ¼¼ÄÜÔöǿֵ  | 
| #  @param attackTime ¹¥»÷´ÎÊý  | 
| # @param isEnhanceSkill ÊÇ·ñΪ¸½¼Ó¼¼ÄÜ  | 
| #  @return True ¹¥»÷³É¹¦    None ²»¿É¹¥»÷  | 
| #  @remarks Í¨¹ýµ÷ÓàObj_Attack_Obj.GetTagRelation »ñÈ¡·µ»ØÖµ  | 
| def Attack(attacker, defender, useSkill, tick, skillPercent=1, skillEnhance=0, attackTime=1, isEnhanceSkill=False):  | 
|     global g_skillHurtList  | 
|       | 
|     if attacker.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|         #NpcÔÚ·ÀÒ»´Î¹¥»÷ÏÞÖÆ, ·ÀֹѣÔÎʱÄܽøÐÐÆÕ¹¥  | 
|         if not OperControlManager.IsObjCanDoAction(attacker,  | 
|                                                    ChConfig.Def_Obj_ActState_ServerSkill,  | 
|                                                    ChConfig.Def_Action_Attack_Bit):  | 
|             return  False  | 
|   | 
|     #ÅжϹ¥»÷¶ÔÏóÊÇ·ñΪµÐÈË  | 
|     if not GetCanAttack(attacker, defender, useSkill, tick):  | 
|         #GameWorld.Log("²»¿É¹¥»÷")  | 
|         return False  | 
|       | 
|     #===========================================================================  | 
|     # #²»¿ÉÐнøÍ¨µÀ²»¹¥»÷  | 
|     # if not AttackCommon.CanAttackByPath(attacker, defender):  | 
|     #    return  | 
|     #===========================================================================  | 
|       | 
|     #Íæ¼Ò¹ØÏµÂß¼ÔÚÍâ²ãÂß¼Åж¨,NPC¹¥»÷¹ØÏµÔÚÄÚ²ãÅж¨  | 
|     if attacker.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|         #ÅжÏÊÇ·ñµÐ¶Ô¹ØÏµ  | 
|         relation = GetTagRelation(attacker, defender, useSkill, tick)[0]  | 
|           | 
|         if relation != ChConfig.Type_Relation_Enemy:  | 
|             #GameWorld.Log("curTagName = %s ²»ÊǵжԹØÏµ"%(curTag.GetName()))  | 
|             return  | 
|           | 
|     callFunc = GameWorld.GetExecFunc(AttackLogic, "%s_Attack_%s.%s" % (  | 
|                                     GetObjAttackName(attacker),  | 
|                                     GetObjAttackName(defender), "DoAttack"))  | 
|       | 
|     if callFunc == None:  | 
|         GameWorld.Log("%d Attack %d Error !" % (attacker.GetID(), defender.GetID()))  | 
|         return False  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = GameObj.GetHP(attacker)  | 
|     destX = defender.GetPosX()  | 
|     destY = defender.GetPosY()  | 
|       | 
|     #¹¥»÷ǰÁ¬»÷¼ì²é  | 
|     SkillCommon.UpdateSkillCombo(attacker, useSkill, tick)  | 
|       | 
|     # NPC±íÓÐÅäÖÃÆÕ¹¥µÄ¸½¼ÓÉ˺¦  | 
|     if attacker.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|         skillEnhance += NPCCommon.GetSkillEnhance(attacker)   # ¼¼Äܹ¥»÷Á¦¼Ó³É  | 
|           | 
|     #GameWorld.Log("g_skillHurtList.Clear()")  | 
|     g_skillHurtList.Clear()  | 
|     #¸ù¾Ý¹¥»÷´ÎÊý,Ìí¼ÓÉËѪÁÐ±í  | 
|     for i in range(0, attackTime):  | 
|         indance = callFunc(attacker, defender, useSkill, skillEnhance, skillPercent, g_skillHurtList, tick)  | 
|       | 
|     #¹¹½¨ÁÐ±í  | 
| #    __SetHurtIndance(indance)  | 
|       | 
|     #¸½¼Ó¼¼Äܲ»Ôٴδ¥·¢  | 
|     if not isEnhanceSkill:  | 
|         #¹¥»÷½áÊø¶¯×÷  | 
|         __AttackSuccess(attacker, attackerHP, defender, useSkill, tick)  | 
|         #µ÷Óô¥·¢¸½¼Ó¼¼ÄÜ  | 
|         SkillShell.DoLogic_UseEnhanceSkill(attacker, defender, useSkill, tick, destX, destY)  | 
|           | 
|     #Òò¹¥»÷½áÊø¶¯×÷ÖУ¬·¨±¦¹¥»÷½«µ¼ÖÂÄ¿±êËÀÍö¡£ÒªÅж¨ºóÔڴε÷Ó㬱ÜÃâ2´Î->AttackResult  | 
|     if AttackCommon.GetIsDead(defender):  | 
|         return False  | 
|           | 
|     DoLogic_AttackResult(attacker, defender, useSkill, tick)  | 
|     return True  | 
|   | 
| #---------------------------------------------------------------------  | 
| ##Ö´Ðй¥»÷³É¹¦½áÊøÂß¼  | 
| # @param index Íæ¼ÒË÷Òý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Ö´Ðй¥»÷³É¹¦½áÊøÂß¼  | 
| def DoLogic_AttackResult(attacker, defender, useSkill, tick):  | 
|     resultFunc = GameWorld.GetExecFunc(AttackLogic, "%s_Attack_%s.%s" % (  | 
|                                         GetObjAttackName(attacker),  | 
|                                         GetObjAttackName(defender), "AttackResult"))  | 
|       | 
|     if not resultFunc:  | 
|         GameWorld.Log("%d AttackResult %d Error !" % (attacker.GetID(), defender.GetID()))  | 
|         return False  | 
|       | 
|     if GameObj.GetHP(defender) <= 0:  | 
|         defender.SetDict(ChConfig.Def_NPCDead_KillerType, attacker.GetGameObjType())  | 
|         defender.SetDict(ChConfig.Def_NPCDead_KillerID, attacker.GetID())  | 
|         PlayerGeTui.TJGDead(defender, attacker.GetName())  | 
|         if defender.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|             skillID = 0 if not useSkill else useSkill.GetSkillID()  | 
|             # ¼Ç¼ËÀÍöÔÒò  | 
|             defender.SetDict(ChConfig.Def_NPCDead_Reason, skillID)  | 
|       | 
|     resultFunc(attacker, defender, useSkill, tick)  | 
|       | 
|     #Ö´Ðб»¹¥»÷Âß¼  | 
|     DoBeAttackOver(attacker, defender, useSkill, tick)  | 
|     return True  | 
|       | 
| #------------------------------------------------------------------  | 
| ## Èº¹¥¶ªÆ¿×Ó  | 
| #  @param posX ¹¥»÷×ø±êX  | 
| #  @param posY ¹¥»÷×ø±êY  | 
| #  @return ·µ»ØNone  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def TestQun(posX, posY):  | 
|     curSingleItem = ItemCommon.CreateSingleItem(1)  | 
|     ChItem.AddMapDropItem(posX, posY, curSingleItem)  | 
|     return  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ¼ì²éÊÇ·ñ¿ÉÒÔ¹¥»÷  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param curTag ·ÀÓùObj  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return True ¿ÉÒÔ¹¥»÷    None ²»¿É¹¥»÷  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __CheckCanAttack(attacker, curTag, curSkill, tick):  | 
|     #¶ÔÏó´æÔÚ  | 
|     if not curTag:  | 
|         return False  | 
|       | 
|     if GameObj.GetHP(curTag) <=0 :  | 
|         return False  | 
|       | 
|     #Èç¹û¹¥»÷³ÇÃÅ,³ÇÃÅÈç¹ûÔڹرÕ״̬,²»¿É¹¥»÷  | 
|     if GameWorld.GetNPC_Is_Gate(curTag): #and GameWorld.GetGameFB().GetGameFBDictByKey("gate_is_close"):  | 
|         return False  | 
|       | 
|     #GameWorld.Log("¹¥»÷ -> curTagName = %s"%(curTag.GetName()))  | 
|       | 
|     #ÅжÏÊÇ·ñ¿ÉÒÔ¹¥»÷Õâ¸ö¶ÔÏó  | 
|     if not AttackCommon.CheckCanAttackTag(attacker, curTag):  | 
|         #GameWorld.Log("curTagName = %s ²»¿É¹¥»÷"%(curTag.GetName()))  | 
|         return False  | 
|       | 
|     #ÅжÏÊÇ·ñµÐ¶Ô¹ØÏµ  | 
|     relation = GetTagRelation(attacker, curTag, curSkill, tick)[0]  | 
|       | 
|     if relation != ChConfig.Type_Relation_Enemy:  | 
|         #GameWorld.Log("curTagName = %s ²»ÊǵжԹØÏµ"%(curTag.GetName()))  | 
|         return False  | 
|       | 
|     #¿É¹¥»÷µÄÒ°ÍâС¹Ö£¨º¬¾«Ó¢£©¹ÖÎï   | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)         | 
|     if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackBaseNPC:     | 
|         if curTag.GetGameObjType() != IPY_GameWorld.gotNPC:  | 
|             return False  | 
|         if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:  | 
|             return False  | 
|         if curTag.GetIsBoss() > ChConfig.Def_NPCType_Ogre_Super:  | 
|             return False   | 
|     elif curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackPlayer:  | 
|         if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|             return False  | 
|     return True  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## Ç¿ÖÆÌí¼ÓÄ¿±ê  | 
| #  @param resultList ¹¥»÷ÁÐ±í  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param defender ·ÀÓùObj  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return resultList ¹¥»÷ÁÐ±í  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick):  | 
|     if not defender:  | 
|         return resultList  | 
|       | 
|     # Ö÷Ä¿±ê¶ÔÏóÅж¨  | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|     hurtTypeList = ChConfig.Def_Dict_UseSkillTag_ObjType.get(curSkillUseTag)  | 
|     if not hurtTypeList:  | 
|         return resultList  | 
|     if defender.GetGameObjType() not in hurtTypeList:  | 
|         return resultList  | 
|       | 
|     #²»¿É¹¥»÷  | 
|     if not __CheckCanAttack(attacker, defender, curSkill, tick):  | 
|         return resultList  | 
|       | 
|     #²éÕÒÄ¿±êÊÇ·ñÔÚ¹¥»÷ÁбíÖÐ  | 
|     for curObj in resultList:  | 
|         if curObj.GetID() == defender.GetID():  | 
|             #ÒѾ´æÔÚÁË  | 
|             return resultList  | 
|               | 
|     #ÊÖ¶¯Ìí¼Ó     | 
|     resultList.append(defender)  | 
|               | 
|     return resultList  | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ¼¼ÄÜÇøÓò¼ÓBuff  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param srcPosX Êͷż¼ÄÜÆðµã×ø±êX  | 
| #  @param srcPosY Êͷż¼ÄÜÆðµã×ø±êY  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param buffValue buffÖµ  | 
| #  @param isTeamBuff ÊÇ·ñ¶ÓÎé¼¼ÄÜ  | 
| #  @return True  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def SkillAddAreaBuff(attacker, defender, curSkill, srcPosX, srcPosY, tick,   | 
|                      isTeamBuff=False, skillMatrix=None):  | 
|     #¹¥»÷·½¶ÔÏóÀàÐÍ  | 
|     attackObjType = attacker.GetGameObjType()  | 
|     curSkillTypeID = curSkill.GetSkillTypeID()  | 
|     curSkillLV = curSkill.GetSkillLV()  | 
|     buffType = SkillCommon.GetBuffType(curSkill)  | 
|       | 
|     resultList = []  | 
|     if isTeamBuff:  | 
|         #Íæ¼Ò¶ÓÎé  | 
|         resultList = PlayerControl.GetAreaTeamMember(attacker.GetTeam(), srcPosX, srcPosY)  | 
|         #Ìí¼Ó×Ô¼º  | 
|         resultList.append(attacker)  | 
|     else:  | 
|         #È¡µÃÊÜЧ¹ûÄ¿±ê¶ÓÁÐ  | 
|         resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, CheckTagIsBeInfection, skillMatrix)  | 
|       | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|       | 
|     for curTag in resultList:  | 
|         #ÓиüÇ¿´óµÄЧ¹û  | 
|         if not SkillCommon.CheckCanAddBuff(curTag, buffType, curSkillTypeID, curSkillLV):  | 
|             continue  | 
|           | 
|         #Èç¹û¹¥»÷·½ÊÇÕÙ»½ÊÞ,Ìí¼ÓbuffÓµÓÐÕßÒªÊÇÕâ¸öÕÙ»½ÊÞµÄÖ÷ÈË  | 
|         addAngryObj = attacker  | 
|         if attackObjType == IPY_GameWorld.gotNPC and NPCCommon.IsSummonNPC(attacker):  | 
|             useSkillOwner = NPCCommon.GetSummonOwnerDetel(attacker)  | 
|             #ÕÒ²»µ½Ö÷È˾ÍÊÇ×Ô¼º  | 
|             if useSkillOwner != None:  | 
|                 addAngryObj = useSkillOwner  | 
|                   | 
|             #addAngryObj = useSkillOwner  | 
|               | 
|         addBuffValueList = SkillShell.GetAddBuffValue(attacker, curSkill, curTag)  | 
|         BuffSkill.DoAddBuff(curTag, buffType, curSkill, tick, addBuffValueList, addAngryObj)  | 
|           | 
|         #Ìí¼ÓBUFFºó£º´¦Àí¼¼ÄÜЧ¹û£¬´¥·¢¸½¼Ó¼¼ÄÜ£¬¼ÓBUFFºó²úÉúµÄЧ¹û£¬³Í·£ºÍ³ðºÞ  | 
|         SkillShell.AddBuffOver(attacker, defender, curSkill, tick, False)  | 
|           | 
|     #GameWorld.Log("%sʹÓÃÇøÓòBuff¼¼ÄÜ = %s,³É¹¦,buff×ÜÖµ = %s"%(useSkillobj.GetName(),  | 
|                                                 #curSkill.GetSkillName(),buffValue))  | 
|     return True  | 
|   | 
| def SkillAddAuraBuff(curObjDetel, curSkill, tick):  | 
|     '''¹â»·buff¹âÔ´¶Ô¸½½üµ¥Î»Ó°ÏìÌí¼Óbuff'''  | 
|     attackDis = curSkill.GetAtkRadius()  | 
|     # ÓÐÅäÖÃЧ¹û°ë¾¶µÄ×ß³£¹æÂß¼  | 
|     if attackDis:  | 
|         return SkillAddAreaBuff(curObjDetel, None, curSkill, curObjDetel.GetPosX(), curObjDetel.GetPosY(), tick)  | 
|       | 
|     # Ã»ÓÐÅäÖÃЧ¹û°ë¾¶µÄ´ú±íȫͼÓÐЧ, ÔÝʱֻ×öÖ§³ÖNPC  | 
|     if curObjDetel.GetGameObjType() != IPY_GameWorld.gotNPC:  | 
|         return False  | 
|       | 
|     resultList = []  | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|     # ¶ÔNPCµÄ  | 
|     if curSkillUseTag in [ChConfig.Def_UseSkillTag_FriendNPC, ChConfig.Def_UseSkillTag_CanAttackNPC]:  | 
|         isFriendObj = curSkillUseTag == ChConfig.Def_UseSkillTag_FriendNPC  | 
|         gameNPCManager = GameWorld.GetNPCManager()  | 
|         for index in xrange(gameNPCManager.GetNPCCount()):  | 
|             curNPC = gameNPCManager.GetNPCByIndex(index)  | 
|               | 
|             if curNPC.GetID() == 0:  | 
|                 continue  | 
|               | 
|             if curNPC.GetGameNPCObjType() not in [IPY_GameWorld.gnotNormal, IPY_GameWorld.gnotSummon]:  | 
|                 continue  | 
|                   | 
|             if isFriendObj != (curNPC.GetCountry() == curObjDetel.GetCountry()):  | 
|                 continue  | 
|               | 
|             resultList.append(curNPC)  | 
|               | 
|     # ¶ÔÍæ¼ÒµÄ£¬´ýÀ©Õ¹  | 
|     elif curSkillUseTag in [ChConfig.Def_UseSkillTag_PlayerHasHP, ChConfig.Def_UseSkillTag_CanAttackPlayer]:  | 
|         pass  | 
|       | 
|     else:  | 
|         return False  | 
|       | 
|     curSkillTypeID = curSkill.GetSkillTypeID()  | 
|     curSkillLV = curSkill.GetSkillLV()  | 
|     buffType = SkillCommon.GetBuffType(curSkill)  | 
|       | 
|     for curTag in resultList:  | 
|         if not SkillCommon.CheckCanAddBuff(curTag, buffType, curSkillTypeID, curSkillLV):  | 
|             continue  | 
|           | 
|         #GameWorld.DebugLog("¹âÔ´Ó°ÏìÌí¼ÓÖÜΧ¶ÔÏóbuff: curID=%s,tagID=%s,curSkillTypeID=%s" % (curObjDetel.GetID(), curTag.GetID(), curSkillTypeID))  | 
|         addBuffValueList = SkillShell.GetAddBuffValue(curObjDetel, curSkill, curTag)  | 
|         BuffSkill.DoAddBuff(curTag, buffType, curSkill, tick, addBuffValueList, curObjDetel)  | 
|         SkillShell.AddBuffOver(curObjDetel, curTag, curSkill, tick, False)  | 
|           | 
|     return True  | 
|   | 
| ## ¼ì²éÊDz»ÊDZ»Ó°ÏìµÄÄ¿±ê  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ²¼¶ûÖµ  | 
| #  @remarks ¼ì²éÊDz»ÊDZ»Ó°ÏìµÄÄ¿±ê  | 
| def CheckTagIsBeInfection(attacker, defender, curSkill, tick):  | 
|     if attacker.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|         return CheckNPCSkillTagIsBeInfection(attacker, curSkill, defender, tick)  | 
|       | 
|     #¼ì²éÄ¿±ê  | 
|     return SkillShell.CheckTag_DoPlayerUseSkillTag(attacker, curSkill, defender, tick)  | 
|   | 
| def CheckNPCSkillTagIsBeInfection(attacker, curSkill, defender, tick):  | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|     if curSkillUseTag == ChConfig.Def_UseSkillTag_FriendNPC:  | 
|         if defender.GetGameObjType() != IPY_GameWorld.gotNPC:  | 
|             return False  | 
|         #¹ØÏµ  | 
|         relation = GetTagRelation(attacker, defender, curSkill, tick)  | 
|         return relation[0] == ChConfig.Type_Relation_Friend  | 
|       | 
|     return __CheckCanAttack(attacker , defender , curSkill , tick)  | 
|   | 
| ## Èº¹¥µô¹Ì¶¨ÑªÁ¿  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param lostHP ¹Ì¶¨µôѪÁ¿  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param isExSkill ÊÇ·ñÊǸ½¼Ó¼¼ÄÜ, ¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷³É¹¦, Ò²²»Ôٴδ¥·¢ÆäËû¸½¼Ó¼¼ÄÜ  | 
| #  @param skillMatrix ¹¥»÷¾ØÕó  | 
| #  @return True  | 
| def AreaSkillAttackLostHP(attacker, defender, srcPosX, srcPosY, curSkill, lostHP, tick, isExSkill=False, skillMatrix=None):  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = GameObj.GetHP(attacker)  | 
|       | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack, skillMatrix)  | 
|               | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     resultList = __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|   | 
|     #Ö´Ðй¥»÷½á¹û  | 
|     for obj in resultList:  | 
|         SkillCommon.SkillLostHP(obj, curSkill.GetSkillTypeID(), attacker, lostHP, tick, isDoAttackResult=False)  | 
|       | 
|     __DoAreaAttackResult(attacker, defender, curSkill, resultList, attackerHP, tick, isExSkill)    | 
|     return  | 
|   | 
|   | 
| # Ë«·½ÔÚͬһÕŵØÍ¼£¬Õý³£Èº¹¥£¬µ«Í¨ÖªÒÔ±»¹¥»÷¶ÔÏóΪÊÍ·ÅÕߣ¬ÈçÖж¾ºó±¬Õ¨Á½Õß¾àÀë¹ýÔ¶  | 
| def AttackAreaDefenderNotify(attacker, defender, srcPosX, srcPosY, curSkill,  | 
|                             skillPercent, skillEnhance, tick):  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|   | 
|     #resultList = CheckAreaObjServer(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack, None)  | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     #resultList = __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|     #GameWorld.Log("ʹÓÃÎÞÖ¸¶¨´ÎÊýȺ¹¥¼¼ÄÜ = %s ³É¹¦,¸½¼Ó¼¼ÄÜЧ¹û = %s,¸½¼Ó¼¼ÄÜÔöÇ¿ = %s"%\  | 
|     #(curSkill.GetSkillName(),skillValue,skillPer))  | 
|           | 
|     resultList = [defender]  | 
|     __DoAreaAttack(attacker, curSkill, skillEnhance, skillPercent, resultList,  | 
|                                  [], g_skillHurtList, tick)  | 
|       | 
|     # ·ÀÊØÕß×Ô¼ºÍ¨Öª  | 
|     __Sync_AttackResult(defender, defender, curSkill)  | 
|       | 
|   | 
|     DoLogic_AttackResult(attacker, defender, curSkill, tick)  | 
|       | 
|     return True  | 
|   | 
|   | 
| # °Ù·Ö±ÈµôѪ  | 
| def AttackAreaByHPPer(attacker, defender, srcPosX, srcPosY, curSkill, skillPercent, skillEnhance,   | 
|                       tick, isExSkill = False, skillMatrix = None):  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = GameObj.GetHP(attacker)  | 
|       | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack, skillMatrix)  | 
|               | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     resultList = __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|     #GameWorld.Log("ʹÓÃÎÞÖ¸¶¨´ÎÊýȺ¹¥¼¼ÄÜ = %s ³É¹¦,¸½¼Ó¼¼ÄÜЧ¹û = %s,¸½¼Ó¼¼ÄÜÔöÇ¿ = %s"%\  | 
|     #(curSkill.GetSkillName(),skillValue,skillPer))  | 
|   | 
|           | 
|     attackList = __DoAreaAttackByHPPer(attacker, curSkill, skillEnhance, skillPercent, resultList,  | 
|                                        g_skillHurtList, tick)  | 
|   | 
|       | 
|     __DoAreaAttackResult(attacker, defender, curSkill, attackList, attackerHP, tick, isExSkill)  | 
|       | 
|     return True  | 
|   | 
| ## Ö´ÐÐȺ¹¥¹¥»÷, ÑªÁ¿°Ù·Ö±ÈÖ¸¶¨µôѪ£¬²»×ß¹«Ê½  | 
| def __DoAreaAttackByHPPer(attacker, curSkill, skillEnhance, skillPercent, resultList, g_skillHurtList, tick):  | 
|     attackList = []   #±»¹¥»÷¶ÔÏóÁÐ±í  | 
|   | 
|     #Ö´Ðй¥»÷½á¹û  | 
|     for obj in resultList:  | 
|         callName = "%s_Attack_%s.%s" % (GetObjAttackName(attacker),  | 
|                                        GetObjAttackName(obj), "DoAttack")  | 
|           | 
|         callFunc = GameWorld.GetExecFunc(AttackLogic, callName)  | 
|           | 
|         if not callFunc:  | 
|             continue  | 
|           | 
|         # Ã¿¸ö¶ÔÏóµÄ°Ù·Ö±ÈµôѪ  | 
|         skillEnhance = int(skillPercent*GameObj.GetMaxHP(obj) + skillEnhance)  | 
|         callFunc(attacker, obj, curSkill, skillEnhance, 0, g_skillHurtList, tick)  | 
|           | 
|         attackList.append(obj)  | 
|       | 
|     return attackList  | 
|   | 
|   | 
|   | 
|   | 
| #defender : ¹¥»÷Æðµã  | 
| ## ÇøÓò¹¥»÷ͨÓú¯Êý  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param skillPercent ¼¼ÄÜÔöÇ¿°Ù·Ö±È  | 
| #  @param skillEnhance ¼¼ÄÜÔöǿֵ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param powerList Ë¥¼õ»òÔöÇ¿Áбí[ [skillPercent,skillEnhance],...... ]  | 
| #  @param isExSkill ÊÇ·ñÊǸ½¼Ó¼¼ÄÜ, ¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷³É¹¦, Ò²²»Ôٴδ¥·¢ÆäËû¸½¼Ó¼¼ÄÜ  | 
| #  @param skillMatrix ¹¥»÷¾ØÕó  | 
| #  @param isAverageHurt ÊÇ·ñ¾ù·ÖÉ˺¦  | 
| #  @return True  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def AttackerSkillAttackArea(attacker, defender, srcPosX, srcPosY, curSkill,  | 
|                             skillPercent, skillEnhance, tick,  | 
|                             powerList=[], isExSkill = False, skillMatrix = None,  | 
|                             isAverageHurt = False):  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = GameObj.GetHP(attacker)  | 
|       | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack, skillMatrix)  | 
|               | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     resultList = __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|     #GameWorld.Log("ʹÓÃÎÞÖ¸¶¨´ÎÊýȺ¹¥¼¼ÄÜ = %s ³É¹¦,¸½¼Ó¼¼ÄÜЧ¹û = %s,¸½¼Ó¼¼ÄÜÔöÇ¿ = %s"%\  | 
|     #(curSkill.GetSkillName(),skillValue,skillPer))  | 
|   | 
|     # ¾ù·ÖÉ˺¦  | 
|     if isAverageHurt:  | 
|         resultCnt = len(resultList)  | 
|         if resultCnt > 0:  | 
|             skillPercent /= resultCnt  | 
|             skillEnhance /= resultCnt  | 
|           | 
|     attackList = __DoAreaAttack(attacker, curSkill, skillEnhance, skillPercent, resultList,  | 
|                                  powerList, g_skillHurtList, tick)  | 
|   | 
|       | 
|     __DoAreaAttackResult(attacker, defender, curSkill, attackList, attackerHP, tick, isExSkill)  | 
|       | 
|     return True  | 
|   | 
|   | 
| # ´¥·¢¼¼ÄܵÄÀàÐÍΪ µ¥Ìå¹¥»÷£¬»òÕßµ¥Ìåbuff²¢ÇҷǶÔ×Ô¼ºÊͷŵļ¼ÄÜ£¬¿ÉÒÔ¶ÔÉ˺¦Ä¿±êÒ»Ò»Ö´Ðд¥·¢¼¼ÄÜÂß¼  | 
| # ·ñÔòÖ»´¥·¢Ò»´Î¼¼ÄÜ # ÈºÌåBUFFµÄÇë²Î¿¼IsPlayerUseSkill ¿Í»§¶Ë¾ö¶¨¶ÔÏó£¬Ò»Ñù¿ÉÒÔʵÏÖͬÑùЧ¹û  | 
| # ·µ»ØÕæ±íʾ¿ÉÒÔ¶Ôÿ¸öÉ˺¦Ä¿±ê´¥·¢£¬·µ»Ø¼ÙÔòΪµ¥Ìå  | 
| def GetIsEnhanceSkillGroup(curSkill, enhanceSkillID):  | 
|     if not enhanceSkillID:  | 
|         return False  | 
|       | 
|     enhanceSkill = GameWorld.GetGameData().FindSkillByType(enhanceSkillID, curSkill.GetSkillLV())  | 
|     if not enhanceSkill:  | 
|         return False  | 
|       | 
|     if enhanceSkill.GetAtkType() == 1:  | 
|         return True  | 
|       | 
|     if SkillCommon.IsBuff(enhanceSkill) and enhanceSkill.GetAtkType() == 0 and \  | 
|     SkillShell.GetSkillAffectTag(enhanceSkill) not in [ChConfig.Def_UseSkillTag_Self, ChConfig.Def_UseSkillTag_SelfAndFriend]:  | 
|         return True  | 
|   | 
|     return False  | 
|       | 
| ## Ö´ÐÐȺ¹¥»÷½á¹û  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param attackList ¹¥»÷¶ÔÏóÁÐ±í  | 
| #  @param attackerHP ¹¥»÷·½HP ÓÃÓÚ֪ͨÉËѪ·´µ¯  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param isEnhanceSkill ÊÇ·ñÊǸ½¼Ó¼¼ÄÜ, ¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷³É¹¦, Ò²²»Ôٴδ¥·¢ÆäËû¸½¼Ó¼¼ÄÜ  | 
| #  @return ÎÞ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.Ö´ÐÐȺ¹¥»÷½á¹û  | 
| def __DoAreaAttackResult(attacker, defender, curSkill, attackList, attackerHP, tick, isEnhanceSkill):  | 
|     #·Ç¸½¼Ó¼¼ÄÜ´¦Àí  | 
|     if not isEnhanceSkill:  | 
|           | 
|         # Ç¿ÖÆÉèÖÃÉËѪÁбíÀïijһ¶ÔÏóΪdefender, ¹¥»÷½áÊø´¦ÀíÐèÒªÓõ½  | 
|         if not defender and attackList and attacker.GetGameObjType() == IPY_GameWorld.gotNPC:  | 
|             defender = attackList[0]  | 
|               | 
|         #¹¥»÷½áÊø¶¯×÷³É¹¦  | 
|         __AttackSuccess(attacker, attackerHP, defender, curSkill, tick)        | 
|   | 
|         # ¸ù¾Ý´¥·¢¼¼ÄܵÄÌØµã¾ö¶¨ÊÇ´¥·¢Ò»´Î»¹ÊÇ ´¥·¢¶à´Î  | 
|         # ÈºÌåBUFFµÄÇë²Î¿¼IsPlayerUseSkill ¿Í»§¶Ë¾ö¶¨¶ÔÏó£¬Ò»Ñù¿ÉÒÔʵÏÖͬÑùЧ¹û  | 
|         for enhanceSkillID in [curSkill.GetSkillEnhance1(), curSkill.GetSkillEnhance2()]:  | 
|             if GetIsEnhanceSkillGroup(curSkill, enhanceSkillID):  | 
|                 for defObj in attackList:  | 
|                     SkillShell.SkillTrigSkill(attacker, defObj, curSkill, enhanceSkillID, tick)  | 
|             else:  | 
|                 SkillShell.SkillTrigSkill(attacker, defender, curSkill, enhanceSkillID, tick)  | 
|   | 
|     for defObj in attackList:  | 
|               | 
|         #Òò¹¥»÷½áÊø¶¯×÷ÖУ¬·¨±¦¹¥»÷½«µ¼ÖÂÄ¿±êËÀÍö¡£ÒªÅж¨ºóÔڴε÷Ó㬱ÜÃâ2´Î->AttackResult  | 
|         if AttackCommon.GetIsDead(defObj):  | 
|             continue  | 
|   | 
|         DoLogic_AttackResult(attacker, defObj, curSkill, tick)  | 
|   | 
|   | 
|   | 
| ## Ö´ÐÐȺ¹¥¹¥»÷  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param skillEnhance ¼¼ÄÜÔöǿֵ  | 
| #  @param skillPercent ¼¼ÄÜÔöÇ¿°Ù·Ö±È  | 
| #  @param resultList ¹¥»÷¶ÔÏóÁÐ±í  | 
| #  @param powerList Ë¥¼õ»òÔöÇ¿Áбí[ [skillPercent,skillEnhance],...... ]  | 
| #  @param g_skillHurtList ÉËѪÁÐ±í  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ÎÞ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.Ö´ÐÐȺ¹¥¹¥»÷  | 
| def __DoAreaAttack(attacker, curSkill, skillEnhance, skillPercent, resultList,  | 
|                    powerList, g_skillHurtList, tick):  | 
|     attackList = []   #±»¹¥»÷¶ÔÏóÁÐ±í  | 
|   | 
|     checkComboOK = False  | 
|   | 
|     #Ö´Ðй¥»÷½á¹û  | 
|     for obj in resultList:  | 
|         callName = "%s_Attack_%s.%s" % (GetObjAttackName(attacker),  | 
|                                        GetObjAttackName(obj), "DoAttack")  | 
|           | 
|         callFunc = GameWorld.GetExecFunc(AttackLogic, callName)  | 
|           | 
|         if not callFunc:  | 
|             continue  | 
|           | 
|         #Èç¹ûÓÐË¥ÈõºÍÔöÇ¿µÄµÄЧ¹û£¬²»Ê¹ÓòÎÊý´«ÈëµÄ skillEnhance, skillPercent  | 
|         if powerList != []:  | 
|             skillPercent, skillEnhance = powerList.pop(0)  | 
|   | 
|         if not checkComboOK:  | 
|             #¹¥»÷ǰÁ¬»÷¼ì²é  | 
|             SkillCommon.UpdateSkillCombo(attacker, curSkill, tick)  | 
|             checkComboOK = True  | 
|               | 
|         callFunc(attacker, obj, curSkill, skillEnhance, skillPercent, g_skillHurtList, tick)  | 
|           | 
|         attackList.append(obj)  | 
|       | 
|     return attackList  | 
|   | 
| #Ⱥ¹¥Ö÷Ä¿±ê  | 
| def GetAreaAttackAim(attacker, curSkill, CheckFunc, tick):  | 
|     # Èº¹¥Ôö¼Ó¶ÔÏóÖ÷ÒªÊÇΪÁËÈÃÑ¡ÖÐÄ¿±ê¸üÈÝÒ×±»»÷ÖÐ  | 
|     if attacker.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|         return None  | 
|       | 
|     useSkillTagID = attacker.GetUseSkillTagID()  | 
|     useSkillTagType = attacker.GetUseSkillTagType()  | 
|       | 
|     curTag = GameWorld.GetObj(useSkillTagID, useSkillTagType)  | 
|     if not curTag:  | 
|         return None  | 
|       | 
|     if SkillShell.GetSkillAffectTag(curSkill) == ChConfig.Def_UseSkillTag_CanAttackNPC:  | 
|         if NPCCommon.GetNpcObjOwnerIsPlayer(curTag):  | 
|             #npcÖ÷ÈËÊÇÍæ¼Ò²»Äܹ¥»÷  | 
|             return None  | 
|   | 
|     if CheckFunc != None:  | 
|         #¼ì²éÊÇ·ñÊÜÓ°Ïì  | 
|         if not CheckFunc(attacker, curTag, curSkill, tick):  | 
|             return None  | 
|       | 
|     return curTag  | 
|   | 
| # ¿Í»§¶ËËÑË÷Ä¿±ê  | 
| def CheckAreaObjClient(attacker, curSkill, tick, CheckFunc=None):  | 
|     resultList = list()        #¹¥»÷½á¹ûÁÐ±í  | 
|       | 
|     #---¼ì²é¹¥»÷Ä¿±êÀàÐÍ---  | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|     hurtTypeList = ChConfig.Def_Dict_UseSkillTag_ObjType.get(curSkillUseTag)  | 
|   | 
|     #ÕÒ²»µ½¹¥»÷¶ÔÏóÀàÐÍÔòÍ˳ö  | 
|     if hurtTypeList == None:  | 
|         GameWorld.ErrLog("Def_Dict_UseSkillTag_ObjType Ã»ÓжÔÓ¦Ïî %s" % curSkillUseTag)  | 
|         return resultList  | 
|       | 
|     #¼¼Äܹ¥»÷×î´óÊýÁ¿  | 
|     #hurtCount = SkillCommon.GetSkillArea_Atk_Count(attacker, curSkill)  | 
|     hurtDict = SkillShell.GetClientHurtDict()  | 
|     for objInfo in hurtDict:  | 
|           | 
|         curObjType = objInfo[1]  | 
|           | 
|         #²»ÔÚÓ°Ïì¶ÔÏóÁбíÖÐ  | 
|         if curObjType not in hurtTypeList:  | 
|             continue  | 
|                      | 
|         #¹¥»÷¶ÔÏó  | 
|         curTag = GameWorld.GetObj(objInfo[0], curObjType)  | 
|         if not curTag:  | 
|             continue  | 
|           | 
|         if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackNPC:  | 
|             if NPCCommon.GetNpcObjOwnerIsPlayer(curTag):  | 
|                 #npcÖ÷ÈËÊÇÍæ¼Ò²»Äܹ¥»÷  | 
|                 continue  | 
|       | 
|         if GameWorld.GetDist(curTag.GetPosX(), curTag.GetPosY(), attacker.GetPosX(), attacker.GetPosY()) > attacker.GetSight():  | 
|             # ×îÔ¶¾àÀë·À·¶  | 
|             GameWorld.DebugLog("#--- ×îÔ¶¾àÀë·À·¶[%s-%s]"%(attacker.GetID(), curTag.GetID()))  | 
|             continue  | 
|       | 
|         if CheckFunc != None:  | 
|             #¼ì²éÊÇ·ñÊÜÓ°Ïì  | 
|             if not CheckFunc(attacker, curTag, curSkill, tick):  | 
|                 continue  | 
|           | 
|         resultList.append(curTag)  | 
|               | 
|     return resultList  | 
|   | 
| # ·þÎñÆ÷ËÑË÷Ä¿±ê  | 
| def CheckAreaObjServer(attacker, curSkill, srcPosX, srcPosY, tick, CheckFunc=None, skillMatrix=None):  | 
|     resultList = list()        #¹¥»÷½á¹ûÁÐ±í  | 
|       | 
|     #---¼ì²é¹¥»÷Ä¿±êÀàÐÍ---  | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|     hurtTypeList = ChConfig.Def_Dict_UseSkillTag_ObjType.get(curSkillUseTag)  | 
|   | 
|     #ÕÒ²»µ½¹¥»÷¶ÔÏóÀàÐÍÔòÍ˳ö  | 
|     if hurtTypeList == None:  | 
|         GameWorld.ErrLog("Def_Dict_UseSkillTag_ObjType Ã»ÓжÔÓ¦Ïî %s" % curSkillUseTag)  | 
|         return resultList  | 
|       | 
|     gameMap = GameWorld.GetMap()  | 
|      | 
|     if skillMatrix == None:  | 
|         #×÷Ó÷¶Î§ ×÷ÓþØÕó  | 
|         attackDis = curSkill.GetAtkRadius()  | 
|         skillMatrix = ChConfig.MatrixDict.get(attackDis)  | 
|         if skillMatrix == None:  | 
|             GameWorld.ErrLog("CheckAreaObj skillId=%s, attakDis=%s not in matrixDict=%s"   | 
|                              % (curSkill.GetSkillID(), attackDis, ChConfig.MatrixDict))  | 
|             return resultList  | 
|   | 
|     #¼¼Äܹ¥»÷×î´óÊýÁ¿  | 
|     hurtCount = SkillCommon.GetSkillArea_Atk_Count(attacker, curSkill)  | 
|       | 
|     ownerTag = None  | 
|     ownerPlayerID = 0  | 
|     isSummonNPCAtker = attacker.GetGameObjType() == IPY_GameWorld.gotNPC and NPCCommon.IsSummonNPC(attacker)  | 
|     if isSummonNPCAtker:  | 
|         ownerPlayer =  NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, attacker)  | 
|         if ownerPlayer:  | 
|             ownerPlayerID = ownerPlayer.GetPlayerID()  | 
|       | 
|     # Èº¹¥Ôö¼Ó¶ÔÏóÖ÷ÒªÊÇΪÁËÈÃÑ¡ÖÐÄ¿±ê¸üÈÝÒ×±»»÷ÖÐ  | 
|     attackAim = GetAreaAttackAim(attacker, curSkill, CheckFunc, tick)  | 
|     if attackAim:  | 
|         hurtCount -= 1  | 
|         resultList.append(attackAim)  | 
|              | 
|     for curPos in skillMatrix:  | 
|         #É˺¦´ÎÊýµ½ÁË  | 
|         if hurtCount <= 0:  | 
|             break  | 
|           | 
|         #¼ì²éÓÐûÓжÔÏóÔÚÕâÒ»µãÉÏ  | 
|         mapObj = gameMap.GetPosObj(srcPosX + curPos[0], srcPosY + curPos[1])  | 
|           | 
|         if not mapObj:  | 
|             continue  | 
|           | 
|         #TestQun(srcPosX + curPos[0],srcPosY + curPos[1])  | 
|         #±éÀúµ±Ç°µã¶ÔÏó  | 
|         for i in range(0, mapObj.GetObjCount()):  | 
|             #É˺¦´ÎÊýµ½ÁË  | 
|             if hurtCount <= 0:  | 
|                 break  | 
|           | 
|             curObj = mapObj.GetObjByIndex(i)  | 
|             curObjType = curObj.GetGameObjType()  | 
|               | 
|             #²»ÔÚÓ°Ïì¶ÔÏóÁбíÖÐ  | 
|             if curObjType not in hurtTypeList:  | 
|                 continue  | 
|               | 
|             #¹¥»÷¶ÔÏó  | 
|             curTag = GameWorld.GetObj(curObj.GetID(), curObjType)  | 
|             if not curTag:  | 
|                 continue  | 
|               | 
|             if attackAim and attackAim.GetID() == curTag.GetID():  | 
|                 # ²»ÔÚ¹¥»÷Ö÷Ä¿±ê  | 
|                 continue  | 
|               | 
|             #Ⱥ¹¥¼¼Äܲ»ÄܶÔïÚ³µÊÍ·Å, ÓÀºã°æ±¾ÆÁ±Î´ËÏÞÖÆ  | 
|             #if curObjType == IPY_GameWorld.gotNPC and curTag.GetGameNPCObjType() == IPY_GameWorld.gnotTruck:  | 
|             #    continue  | 
|               | 
|             if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackNPC:  | 
|                 if NPCCommon.GetNpcObjOwnerIsPlayer(curTag):  | 
|                     #npcÖ÷ÈËÊÇÍæ¼Ò²»Äܹ¥»÷  | 
|                     continue  | 
|               | 
|             if CheckFunc != None:  | 
|                 #¼ì²éÊÇ·ñÊÜÓ°Ïì  | 
|                 if not CheckFunc(attacker, curTag, curSkill, tick):  | 
|                     continue  | 
|               | 
|             # Èç¹û¹¥»÷ÕßÊÇÕÙ»½ÊÞ ÇÒ ¹¥»÷µÄÊÇÖ÷ÈËÍæ¼Ò£¬Ôò°ÑÖ÷ÈË·ÅÔÚ×îºóÃæÒ»¸ö´¦ÀíÉ˺¦Ä¿±ê£¬·ÀÖ¹ÏÈ´¦ÀíºóÈç¹ûÖ÷ÈËËÀÍö½«µ¼ÖºóÐøµÄÂß¼Òì³£  | 
|             if ownerPlayerID > 0 and curObjType == IPY_GameWorld.gotPlayer and isSummonNPCAtker and ownerPlayerID == curObj.GetID():  | 
|                 ownerTag = curTag  | 
|                 continue  | 
|             hurtCount -= 1  | 
|             resultList.append(curTag)  | 
|               | 
|     if ownerTag:  | 
|         resultList.append(ownerTag)  | 
|           | 
|     return resultList  | 
|   | 
|   | 
| ## »ñµÃ¿É¹¥»÷¶ÔÏóÁÐ±í£¬¸ù¾ÝÊýÁ¿È¡  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param skillMatrix ¹¥»÷¾ØÕó  | 
| #  @return ¹¥»÷Áбí¶ÔÏó  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.»ñµÃ¿É¹¥»÷¶ÔÏóÁÐ±í£¬¸ù¾ÝÊýÁ¿È¡  | 
| def __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, CheckFunc=None, skillMatrix=None):  | 
|     if SkillShell.IsPlayerUseSkill(attacker, curSkill):  | 
|         return CheckAreaObjClient(attacker, curSkill, tick, CheckFunc)  | 
|     else:  | 
|         return CheckAreaObjServer(attacker, curSkill, srcPosX, srcPosY, tick, CheckFunc, skillMatrix)  | 
| #------------------------------------------------------------------  | 
|   | 
| ## warning: ¹¥»÷½áÊø¹«¹²Âß¼, ´ËÂß¼ÐèÖØÐ¿¼ÂÇ£¬´æÔÚÒþ²Øbug  | 
| #  @param attacker ¹¥»÷Õß  | 
| #  @param defender ·ÀÓùÕß  | 
| #  @param useSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def DoAttackResultCommon(attacker, defender, useSkill, tick):  | 
|       | 
|     #¼¼Äܹ¥»÷¶ÔÏóËÀÍö´¥·¢¼¼ÄÜÅÐ¶Ï  | 
|     #SkillShell.DoLogic_SkillAttackDie(attacker, defender, useSkill, tick)  | 
|       | 
|     #Íæ¼ÒËÀÍöÁ÷Ïò¼Ç¼  | 
|     __DR_PlayerDead(attacker, defender)  | 
|     return  | 
|   | 
|   | 
| ## Íæ¼ÒËÀÍöÁ÷Ïò¼Ç¼  | 
| #  @param attacker: ¹¥»÷Õß  | 
| #  @param defender ·ÀÓùÕß  | 
| #  @return None  | 
| def __DR_PlayerDead(attacker, defender):  | 
|       | 
|     #Íæ¼ÒËÀÍöÁ÷Ïò¼Ç¼  | 
|     if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:  | 
|         #FBÖÐËÀÍö²»¼Ç¼  | 
|         return  | 
|       | 
|     defenderType = defender.GetGameObjType()  | 
|     if defenderType != IPY_GameWorld.gotPlayer:  | 
|         #·ÀÊØ·½²»ÊÇÍæ¼Ò  | 
|         return  | 
|   | 
|     if defender.GetHP() > 0:  | 
|         #»¹»î×Å  | 
|         return  | 
|       | 
|     atkObjType = attacker.GetGameObjType()  | 
|     atkObjID = attacker.GetID()  # ¹¥»÷·½ID      | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     DataRecordPack.DR_PlayerDead(atkObjType, atkObjID, defender, mapID)  | 
|           | 
|     return  | 
|   | 
|   | 
| #------------------------------------------------------------------  | 
| ## ±»¹¥»÷½áÊø  | 
| #  @param defender ·ÀÓùÕß  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def DoBeAttackOver(attacker, defender, curSkill, tick):  | 
|     if defender == None:  | 
|         #GameWorld.Log("----------ȺÌå¹¥»÷´íÎó,ÎÞ¶ÔÏó")  | 
|         return  | 
|       | 
|     #·ÀÊØÕßÀàÐÍ  | 
|     defenderType = defender.GetGameObjType()  | 
|       | 
|     if defenderType == IPY_GameWorld.gotPlayer:  | 
|         __DoPlayerBeAttacked(attacker, defender, curSkill, tick)  | 
|           | 
|     elif defenderType == IPY_GameWorld.gotNPC:  | 
|         __DoNPCBeAttacked(defender, curSkill, tick)  | 
|           | 
|     else:  | 
|         GameWorld.Log("±»¹¥»÷´íÎó : %d " % defender.GetGameObjType())  | 
|           | 
|     FBLogic.DoBeAttackOver(attacker, defender, curSkill, tick)  | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## ¹¥»÷³É¹¦  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param attackerHP ¹¥»÷·½¹¥»÷ǰѪÁ¿  | 
| #  @param target ·ÀÊØObj  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return True or False      | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __AttackSuccess(attacker, attackerHP, target, curSkill, tick):  | 
|     #¹¥»÷ÕßÀàÐÍ  | 
|     attackerType = attacker.GetGameObjType()  | 
|     if attackerType == IPY_GameWorld.gotPlayer:  | 
|         return __DoPlayerAttackSuccess(attacker, attackerHP, target, curSkill, tick)  | 
|     elif attackerType == IPY_GameWorld.gotNPC:  | 
|         return __DoNPCAttackSuccess(attacker, attackerHP, target, curSkill, tick)  | 
|     else:  | 
|         GameWorld.Log("¹¥»÷´íÎó : %d " % attacker.GetGameObjType())  | 
|           | 
|     return False  | 
|   | 
| ## Ö´Ðй¥»÷³É¹¦  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param attackerHP ¹¥»÷·½¹¥»÷ǰѪÁ¿  | 
| #  @param target ·ÀÊØObj  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param value Ìí¼ÓÖµ  | 
| #  @return True or False    __AttackSuccessµÄ·µ»ØÖµ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def DoAttackSuccess(attacker, attackerBeHP, target, curSkill, tick, value=0, hurtType=ChConfig.Def_HurtType_Normal):  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|     if target != None and value != 0:  | 
|         AttackCommon.AddHurt(target, g_skillHurtList, hurtType, value)  | 
|     return __AttackSuccess(attacker, attackerBeHP , target, curSkill, tick)  | 
|   | 
| # BUFFרÓà  | 
| def DoAttackSuccessEx(attacker, attackerBeHP, target, curSkill, tick):  | 
|     # ½«É˺¦ÁбíÌáǰ´¦Àí£¬Õâ±ß»áÇå³ýÔì³ÉºóÐø±»¶¯¼¼ÄÜÎÞ·¨Õý³£Ê¹Óã¬ÈçXP´óÕкͽ£Èз籩Àà³ÖÐøÐÔ  | 
|     return __AttackSuccess(attacker, attackerBeHP , target, curSkill, tick)  | 
|   | 
| ## ´¦Àí´¥·¢¼¼Äܺ͹¥»÷³É¹¦Âß¼  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param defender ·ÀÊØ·½  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param isEnhanceSkill ÊÇ·ñ¸½¼Ó¼¼ÄÜ  | 
| #  @return True or False  | 
| #  @remarks ´¦Àí´¥·¢¼¼Äܺ͹¥»÷³É¹¦Âß¼  | 
| def DoSkillEx_AttackSucess(attacker, defender, curSkill, tick, isEnhanceSkill=False):  | 
|     if isEnhanceSkill:  | 
|         return True  | 
|       | 
|     result = DoAttackSuccess(attacker, GameObj.GetHP(attacker), defender, curSkill, tick)  | 
|       | 
|     #µ÷Óô¥·¢¸½¼Ó¼¼ÄÜ  | 
|     SkillShell.DoLogic_UseEnhanceSkill(attacker, defender, curSkill, tick)  | 
|       | 
|     #·Ç¹¥»÷Ðͼ¼ÄÜ(Ò²²»ÊÇBuff)ÐèÒªµ÷ÓÃÊ©·¨³É¹¦  | 
|     return result  | 
|   | 
|   | 
| ## Ö´ÐÐȺ¹¥³É¹¦(²ÎÊý -> ¹¥»÷·½,¹¥»÷·½¹¥»÷ǰѪÁ¿,·ÀÊØ·½,¼¼ÄÜ,µ±Ç°Ê±¼ä)  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param attackerHP ¹¥»÷·½¹¥»÷ǰѪÁ¿  | 
| #  @param targetList ·ÀÊØObjList  | 
| #  @param valueList Ìí¼ÓÖµList  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return True or False    __AttackSuccessµÄ·µ»ØÖµ  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def DoAreaAttackSuccess(attacker, attackerBeHP, targetList, valueList, curSkill, tick, hurtType=ChConfig.Def_HurtType_Normal):  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     target = None  | 
|     for index in range(len(targetList)):  | 
|         target = targetList[index]  | 
|         value = valueList[index]  | 
|         AttackCommon.AddHurt(target, g_skillHurtList, hurtType, value)  | 
|           | 
|     return __AttackSuccess(attacker, attackerBeHP , target, curSkill, tick)  | 
|   | 
| ## Í¨Öª¿Í»§¶Ë¹¥»÷½á¹û  | 
| #  @param attacker ¹¥»÷Obj  | 
| #  @param defender ·ÀÊØObj  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __Sync_AttackResult(attacker, defender, curSkill):  | 
|     #ÆÕͨ¹¥»÷  | 
|     if not curSkill:  | 
|         #GameWorld.Log("Íæ¼ÒÆÕͨ¹¥»÷³É¹¦")  | 
|         if g_skillHurtList.GetHurtCount() != 1:  | 
|             GameWorld.ErrLog(' __Sync_AttackResult attackErr, attackerName = %s, \  | 
|                                 ID = %s, hurtCount = %s ' % (attacker.GetName(), attacker.GetID(),  | 
|                                                            g_skillHurtList.GetHurtCount()))  | 
|         else:  | 
|             curHurt = g_skillHurtList.GetHurtAt(0)  | 
|             attacker.BaseAttack(curHurt.GetObjID(), curHurt.GetObjType(),  | 
|                                 AttackCommon.GetBattleType(attacker, curSkill),  | 
|                                 curHurt.GetAttackType(), curHurt.GetHurtHP(), curHurt.GetCurHP(), curHurt.GetCurHPEx())  | 
|           | 
|         #//·µ»ØÖµÎÞÒâÒå  | 
|         return  | 
|       | 
|     #¼¼Äܹ¥»÷  | 
|     skillID = curSkill.GetSkillID()  | 
|     battleType = AttackCommon.GetBattleType(attacker, curSkill)  | 
|     #ÎÞÄ¿±êÀ༼ÄÜ  | 
|     if not defender:  | 
|         #Íæ¼Ò´¦Àí  | 
|         if attacker.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|           | 
|             useSkillPosX = attacker.GetUseSkillPosX()  | 
|             useSkillPosY = attacker.GetUseSkillPosY()  | 
|               | 
|             if useSkillPosX and useSkillPosY:  | 
|                 #¶ÔµØÃæÀ༼ÄÜ -> Í¨Öª¿Í»§¶Ë  | 
|                 if attacker.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|                     PYView_UseSkillPos(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList, False)  | 
|                     PYView_UseSkillPos_NotifySelf(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList)  | 
|                 else:  | 
|                     if attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX):  | 
|                         useSkillPosX = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX)  | 
|                         useSkillPosY = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY)  | 
|                       | 
|                     PYView_UseSkillPos(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList, False)  | 
|                 #//·µ»ØÖµÎÞÒâÒå  | 
|                 return  | 
|           | 
|         #NPCÎÞÄ¿±êµÄÉ˺¦¹ã²¥  | 
|         #attacker.View_UseSkill(skillID)  | 
|         if attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX):  | 
|             # Î»ÒÆÀà  | 
|             useSkillPosX = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX)  | 
|             useSkillPosY = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY)  | 
|         elif attacker.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosX % 0):  | 
|             # Ô¤¾¯Àà  | 
|             useSkillPosX = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosX % 0)  | 
|             useSkillPosY = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosY % 0)  | 
|         else:  | 
|             useSkillPosX = attacker.GetPosX()  | 
|             useSkillPosY = attacker.GetPosY()  | 
|         # NPCûÓÐC++View_UseSkillPos½Ó¿Ú  | 
|         PYView_UseSkillPos(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList, False)  | 
|       | 
|           | 
|         #//·µ»ØÖµÎÞÒâÒå  | 
|         return  | 
|       | 
|     # Ä¿±êÀ༼ÄÜÒ²¸Ä³É¶ÔµØ¼¼Äܰü, 2017-12-17  | 
|     useSkillPosX, useSkillPosY = defender.GetPosX(), defender.GetPosY()  | 
|     if attacker.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|         # ÎªÁ˿ͻ§¶Ë±íÏÖÌØÊâ´¦Àí£¬³å·æÍ¨ÖªµØ°å×ø±ê¶ø²»Êǵз½×ø±ê  | 
|         if curSkill.GetAtkType() == 9:  | 
|             useSkillPosX, useSkillPosY = attacker.GetUseSkillPosX(), attacker.GetUseSkillPosY()  | 
|         PYView_UseSkillPos(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList, False)  | 
|         PYView_UseSkillPos_NotifySelf(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList)  | 
|     else:  | 
|         if attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX):  | 
|             useSkillPosX = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX)  | 
|             useSkillPosY = attacker.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY)  | 
|   | 
|         # NPCûÓÐC++View_UseSkillPos½Ó¿Ú  | 
|         PYView_UseSkillPos(attacker, skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList, False)  | 
|       | 
|     return  | 
| ##############################Ö÷¶¯¹¥»÷³É¹¦#############################  | 
| ## Íæ¼Ò¹¥»÷³É¹¦  | 
| #  @param curPlayer ¹¥»÷Obj  | 
| #  @param curPlayerBeHP µ±Ç°Íæ¼Ò±»¹¥»÷ǰѪÁ¿  | 
| #  @param target ·ÀÊØObj  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return True  | 
| #  @remarks ÕâÀïÔÚ¹¥»÷½áÊøºó,Ö»»áµ÷ÓÃÒ»´Î,¶ø¹¥»÷·½·¨ÖÐAttackResult½«¶à´Î±»µ÷ÓÃ(Ⱥ¹¥)   | 
| #            ÕâÀïÖ»´¦Àí¹¥»÷·½Âß¼,,ËùÓÐÄ¿±ê·½Âß¼ÔÚAttackResultÖд¦Àí  | 
| def __DoPlayerAttackSuccess(curPlayer, curPlayerBeHP, target, curSkill, tick):  | 
|     #--------------  | 
|     #ÕâÀïÔÚ¹¥»÷½áÊøºó,Ö»»áµ÷ÓÃÒ»´Î,¶ø¹¥»÷·½·¨ÖÐAttackResult½«¶à´Î±»µ÷ÓÃ(Ⱥ¹¥)  | 
|     #ÕâÀïÖ»´¦Àí¹¥»÷·½Âß¼,,ËùÓÐÄ¿±ê·½Âß¼ÔÚAttackResultÖд¦Àí  | 
|     #--------------  | 
|       | 
|     #±»¶¯¼¼ÄÜ´¥·Å²»ÔÙ´¦Àí£¬±ÜÃâËÀÑ»·  | 
|     if SkillCommon.GetUsingPassiveSkill(curPlayer):  | 
|         skillTypeID = curSkill.GetSkillTypeID()  | 
|         curPlayerSkill = curPlayer.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)  | 
|         #֪ͨ¿Í»§¶Ë¹¥»÷½á¹û  | 
|         __Sync_AttackResult(curPlayer, target, curSkill)  | 
|   | 
|         if curPlayerSkill:  | 
|             SkillCommon.SetSkillRemainTime(curPlayerSkill, PlayerControl.GetReduceSkillCDPer(curPlayer), tick, curPlayer)  | 
|         return True  | 
|       | 
|     #Íæ¼Ò½øÈëÕ½¶·×´Ì¬  | 
|     #¼¼ÄÜÊǹ⻷, ²»½øÈëÕ½¶·×´Ì¬ ,ÎÞ¶ÔÏó,²»½øÈëÕ½¶·×´Ì¬  | 
|     if (curSkill == None \  | 
|         or curSkill.GetSkillType() not in ChConfig.Def_NoBattleState_List):  | 
|         #and target != None:  | 
|         AttackCommon.SetPlayerBattleState(curPlayer, tick)  | 
|   | 
|       | 
|     #֪ͨ¿Í»§¶Ë¹¥»÷½á¹û  | 
|     __Sync_AttackResult(curPlayer, target, curSkill)  | 
|       | 
|     #BaseAttack»áÉèÖù¥»÷¼ä¸ôÆðʼʱ¼ä£¬Ë²ÒÆÈ¡Ïû  | 
|     #===========================================================================  | 
|     # if curSkill and curSkill.GetSkillTypeID() in ReadChConfig.GetEvalChConfig("SkillTypeIDNoInterval"):  | 
|     #    #GameWorld.DebugLog("#Ë²ÒÆ¼¼Äܲ»Ó°Ïì¹¥»÷¼ä¸ô£¬Ö»Ó°Ï칫¹²CD")  | 
|     #    curPlayer.SetAttackTick(0)  | 
|     #===========================================================================  | 
|       | 
|     #Èç¹ûÊǼ¼Äܹ¥»÷  | 
|     if curSkill:  | 
|           | 
|         skillTypeID = curSkill.GetSkillTypeID()  | 
|           | 
|         #¿ÛÊôÐÔ,Èçħ·¨,XPµã  | 
|         SetSkillLostAttr(curPlayer, curSkill, tick)  | 
|           | 
|         #¿Û²ÄÁÏ  | 
|         SetSkillLostItem(curPlayer, curSkill)  | 
|          | 
|         #¼¼ÄÜʹÓóɹ¦  | 
|         curPlayerSkill = curPlayer.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)  | 
|           | 
|         if curPlayerSkill:  | 
|   | 
|             #ÉèÖÃÍæ¼ÒËùѧ¼¼ÄÜÀäÈ´CD  | 
|             SkillCommon.SetSkillRemainTime(curPlayerSkill, PlayerControl.GetReduceSkillCDPer(curPlayer), tick, curPlayer)  | 
|             #µ÷ÓÃÈÎÎñ´¥·¢Æ÷  | 
|             #EventShell.EventRespons_UseSkillOK(curPlayer, skillTypeID)  | 
|             #Ö´ÐÐÁ¬»·±»¶¯¼¼ÄÜ´¦Àí  | 
|             #__DealWithPassivitySkill( curPlayer, target, curPlayerSkill, tick )  | 
|             #Ö´Ðб»¶¯buff  | 
|             #__DealWithPassivityBuff( curPlayer, tick )  | 
|           | 
|       | 
|     #¹¥»÷½áÊøºó£¬¸±±¾´¥·¢  | 
|     FBLogic.DoFBAttackedOver(curPlayer, target, curSkill, tick)  | 
|       | 
|     # ÆÕ¹¥ºÍ¶ÔµÐ¼¼ÄÜ  | 
|     UseSkillOver(curPlayer, target, curSkill, tick)  | 
|     return True  | 
|       | 
| # ¸ù¾ÝÉËѪÀàÐÍ´¥·¢¼¼ÄÜ£¬Èº¹¥Ö»´¥·¢Ò»´Î£¬·ÅÔÚÉËѪÁÐ±í±»Çå֮ǰ  | 
| def OnHurtTypeTriggerSkill(attacker, target, curSkill, tick):  | 
|       | 
|     isSuperHit = False  | 
|     usePassiveSkillResult = True    # µÚÒ»´ÎÅжϲ»Äܵ÷Ó㬼´´ú±í¶¼²»¿ÉÓÃÎÞÐèÑ»·  | 
|     usePassiveSkillResultOnSuperHit = True    # ±©»÷¶ÔÏó1V1´¥·¢£¬µÚÒ»´ÎÅжϲ»Äܵ÷Ó㬼´´ú±í¶¼²»¿ÉÓÃÎÞÐèÑ»·  | 
|       | 
|     skillHurtLists = [] # ÄÚ²¿´¥·¢Çå³ýg_skillHurtList  | 
|     for i in xrange(g_skillHurtList.GetHurtCount()):  | 
|         hurtObj = g_skillHurtList.GetHurtAt(i)  | 
|         if not hurtObj:  | 
|             continue  | 
|           | 
|         skillHurtLists.append([hurtObj.GetObjID(), hurtObj.GetObjType(), hurtObj.GetAttackType()])  | 
|       | 
|       | 
|     skillIDSet = set()  | 
|     for hurtList in skillHurtLists:  | 
|         if not isSuperHit and hurtList[2] == ChConfig.Def_HurtType_SuperHit:  | 
|             # ±©»÷Ö»¶ÔÖ÷Ä¿±ê×ö´¦Àí  | 
|             PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, target, curSkill, ChConfig.TriggerType_SuperHit, tick)  | 
|             isSuperHit = True  | 
|           | 
|         defender = GameWorld.GetObj(hurtList[0], hurtList[1])  | 
|         if not defender:  | 
|             continue  | 
|           | 
|         if GameObj.GetHP(defender) <= 0:  | 
|             if hurtList[1] == IPY_GameWorld.gotPlayer:  | 
|                 # ±ôËÀ״̬´¥·¢¼¼ÄÜ, ²»ÄÜÔÚGetHurtHPÄÚ²¿´¥·¢¼¼ÄÜ£¬·ñÔò»áµ¼ÖÂÔ¼¼ÄܵÄÉËѪÁбíÒì³£  | 
|                 PassiveBuffEffMng.OnPassiveSkillTrigger(defender, attacker, None, ChConfig.TriggerType_WillDead, tick)  | 
|             continue  | 
|           | 
|         if usePassiveSkillResult:  | 
|             usePassiveSkillResult = PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, defender, curSkill,   | 
|                                                 ChConfig.TriggerType_HurtObjAddBuff, tick, skillIDSet=skillIDSet)  | 
|           | 
|         if usePassiveSkillResultOnSuperHit and hurtList[2] == ChConfig.Def_HurtType_SuperHit:  | 
|             # ±©»÷¶ÔÄ¿±êÒ»Ò»´¥·¢±»¶¯  | 
|             usePassiveSkillResultOnSuperHit = PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, defender, curSkill,   | 
|                                                         ChConfig.TriggerType_SuperHitOneByOne, tick, skillIDSet=skillIDSet)  | 
|         if hurtList[2] == ChConfig.Def_HurtType_SuperHit:  | 
|             #±»±©»÷´¥·¢¼¼ÄÜ  | 
|             PassiveBuffEffMng.OnPassiveSkillTrigger(defender, attacker, None, ChConfig.TriggerType_BeSuperHit, tick)  | 
|         elif hurtList[2] == ChConfig.Def_HurtType_Miss:  | 
|             PassiveBuffEffMng.OnPassiveSkillTrigger(defender, attacker, None, ChConfig.TriggerType_MissSkill, tick)  | 
|           | 
|   | 
|         if hurtList[2] in ChConfig.Def_RealAttack_Type:  | 
|             # ±»¹¥»÷´¦Àí²ã¼¶  | 
|             PassiveBuffEffMng.OnPassiveBuffTrigger(defender, attacker, None, ChConfig.TriggerType_Buff_BeAttackSubLayer, tick)  | 
|           | 
|   | 
|     # Ò»Ò»´¥·¢¼¼ÄÜÐèÒªÔÚ×îºóÉèÖÃCD  | 
|     for skillTypeID in skillIDSet:  | 
|         passiveSkill = attacker.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)  | 
|         if not passiveSkill:  | 
|             continue  | 
|         SkillCommon.SetSkillRemainTime(passiveSkill, 0, tick, attacker)  | 
|           | 
| # ÁéÎªÍæ¼ÒµÄÌæÉíÐèÒª×ß´ËÂß¼  | 
| # ¼¼ÄÜʹÓýáÊø£¬ÔÚ´¦Àí¼¼ÄÜÂß¼ºÍ֪ͨ·â°üÖ®ºóµ÷Óà  | 
| def UseSkillOver(attacker, defender, curSkill, tick):  | 
|     # ¸ù¾ÝÉËѪÀàÐÍ´¥·¢¼¼ÄÜ£¬Èº¹¥Ö»´¥·¢Ò»´Î£¬·ÅÔÚÉËѪÁÐ±í±»Çå֮ǰ  | 
|     OnHurtTypeTriggerSkill(attacker, defender, curSkill, tick)  | 
|       | 
|     # ÆÕͨ»òÕß¿ÉÒÔÖ÷¶¯ÊͷŵĹ¥»÷ÐÔ¼¼ÄÜ  | 
|     if not curSkill or (curSkill.GetSkillType() == ChConfig.Def_SkillType_Atk and\  | 
|                          curSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_FbSkill,  | 
|                                                     ChConfig.Def_SkillFuncType_PetSkill,  | 
|                                                     ChConfig.Def_SkillFuncType_NormalAttack]):  | 
|         # ¹¥»÷¼õ²ã¼¶ ÓÅÏÈ´¦Àí£¬ÒòΪͬ¸ö¼¼ÄÜ´¥·¢buffºó£¬»áÔÙ´¦Àí²ã¼¶£¬µ¼ÖÂÁ¢¼´¼õ²ã¼¶  | 
|         PassiveBuffEffMng.OnPassiveBuffTrigger(attacker, defender, curSkill, ChConfig.TriggerType_Buff_AttackSubLayer, tick)  | 
|           | 
|     # ÆÕ¹¥ºÍ¶ÔµÐ¼¼ÄÜ  | 
|     if not curSkill or curSkill.GetSkillType() in ChConfig.Def_CanAttackSkill_List:  | 
|           | 
|         PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, defender, curSkill, ChConfig.TriggerType_AttackOver, tick)  | 
|         PassiveBuffEffMng.OnPassiveBuffTrigger(attacker, defender, curSkill, ChConfig.TriggerType_AttackOver, tick)  | 
|   | 
|         # TriggerType_AttackOver ºÍ TriggerType_AttackOverPassive ¸ù¾Ý´¥·¢µÄ±»¶¯buffЧ¹û˳Ðò¶ø¶¨  | 
|         PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, defender, curSkill, ChConfig.TriggerType_AttackOverPassive, tick)  | 
|           | 
|         AttackFaintRate(attacker, defender, curSkill, tick)  | 
|     else:  | 
|         PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, defender, curSkill, ChConfig.TriggerType_SkillOverNoAttack, tick)  | 
|       | 
|     return  | 
|   | 
|   | 
| # ÊôÐÔ»÷ÔÎ  | 
| def AttackFaintRate(attacker, defender, curSkill, tick):  | 
|     if attacker.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|         return  | 
|       | 
|     if curSkill:  | 
|         useSkillData = attacker.GetUseSkill()  | 
|         # ·ÇÖ÷¶¯ÐÔ¼¼Äܲ»´¥·¢  | 
|         if not useSkillData:  | 
|             return  | 
|         if useSkillData.GetSkillID() != curSkill.GetSkillID():  | 
|             return  | 
|           | 
|     if not defender:  | 
|         useSkillTagID = attacker.GetUseSkillTagID()  | 
|         useSkillTagType = attacker.GetUseSkillTagType()  | 
|         defender = GameWorld.GetObj(useSkillTagID, useSkillTagType)  | 
|         if not defender:  | 
|             return  | 
|       | 
|     if attacker.GetID() == defender.GetID():  | 
|         return  | 
|   | 
|     if GameObj.GetHP(defender) <= 0:  | 
|         return  | 
|   | 
|     tagFaintRate = PlayerControl.GetFaintDefRate(defender) if defender.GetGameObjType() == IPY_GameWorld.gotPlayer else 0  | 
|   | 
|     rate = max(PlayerControl.GetFaintRate(attacker) - tagFaintRate, 0)  | 
|     if not GameWorld.CanHappen(rate):  | 
|         return  | 
|   | 
|     SkillCommon.AddBuffBySkillType(defender, ChConfig.Def_SkillID_AtkerFaint, tick)  | 
|     return  | 
|   | 
|   | 
| #---------------------------------------------------------------------  | 
| ## ÉèÖü¼ÄÜÏûºÄÎïÆ·  | 
| #  @param curPlayer Ê¹Óü¼ÄÜÕß  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def SetSkillLostItem(curPlayer, curSkill):  | 
|     useItemID = curSkill.GetUseItemID()   | 
|     useItemCount = curSkill.GetUseItemCount()  | 
|       | 
|     if not useItemID or not useItemCount:  | 
|         return  | 
|       | 
|     item = ItemCommon.FindItemInPackByItemID(curPlayer, useItemID, IPY_GameWorld.rptItem)  | 
|       | 
|     if not item:  | 
|         GameWorld.ErrLog('###Êͷż¼ÄÜ = %s¿Û³ý²ÄÁÏ = %sÒì³£' % (  | 
|                             curSkill.GetSkillTypeID(), useItemID), curPlayer.GetID())  | 
|         return  | 
|       | 
|     #PlayerControl.NotifyCode(curPlayer, "LostRes", [useItemID, useItemCount])  | 
|       | 
|     itemCount = item.GetCount()  | 
|       | 
|     DataRecordPack.DR_UseSkilLostItem(curPlayer, useItemID, useItemCount, item.GetGUID(), curSkill.GetSkillTypeID())  | 
|       | 
|     if itemCount < useItemCount:  | 
|         GameWorld.ErrLog('###Êͷż¼ÄÜ  = %s¿Û³ý²ÄÁÏ = %sÒì³£, ÊýÁ¿²»×ã' % (  | 
|                             curSkill.GetSkillTypeID(), useItemID), curPlayer.GetID())  | 
|         item.Clear()  | 
|         return  | 
|       | 
|     ItemControler.SetItemCount(item, itemCount - useItemCount, curPlayer.GetID(), curPlayer.GetAccID(),  | 
|                                curPlayer.GetPlayerName())  | 
|     return  | 
| #---------------------------------------------------------------------  | 
| ## Ö´Ðй¥»÷³É¹¦ºóµÄ±»¶¯buffЧ¹û  | 
| #  @param curPlayer Ê¹Óü¼ÄÜÕß  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __DealWithPassivityBuff(curPlayer, tick):  | 
|     return  | 
|   | 
| ## ÉèÖÃÍæ¼ÒÊôÐÔÏûºÄ,Èçħ·¨,XPµã£¬HP  | 
| #  @param curPlayer Ê¹Óü¼ÄÜÕß  | 
| #  @param curSkill Ê¹Óü¼ÄÜ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks ÉèÖÃÍæ¼ÒÊôÐÔÏûºÄ,Èçħ·¨,XPµã£¬HP  | 
| def SetSkillLostAttr(curPlayer, curSkill, tick):  | 
|     #-----------¿Ûħ·¨  | 
|     lostMPValue = curSkill.GetMP()  | 
|     curPlayerMP = curPlayer.GetMP()  | 
|       | 
|     if curPlayerMP < lostMPValue:  | 
|         GameWorld.ErrLog('Êͷż¼ÄÜ = %sÒì³£, Ä§·¨ = %s²»×ã = %s' % (  | 
|                             curSkill.GetSkillTypeID(), curPlayerMP, lostMPValue))  | 
|       | 
|     if lostMPValue > 0:  | 
|         curPlayer.SetMP(curPlayer.GetMP() - lostMPValue)  | 
|         #×Ô¶¯»ØÄ§  | 
|         PlayerControl.PlayerAutoRestoreMP(curPlayer, tick)  | 
|       | 
|     #----------¿ÛXPµã  | 
|     lostXPValue = curSkill.GetXP()  | 
|     curPlayerXP = curPlayer.GetXP()  | 
|       | 
|     if curPlayerXP < lostXPValue:  | 
|         GameWorld.ErrLog('Êͷż¼ÄÜ = %sÒì³£, XPµã = %s²»×ã = %s' % (  | 
|                             curSkill.GetSkillTypeID(), curPlayerXP, lostXPValue))  | 
|       | 
|     if lostXPValue > 0:  | 
|         remain = curPlayer.GetXP() - lostXPValue  | 
|         remain = max(0, remain)  | 
|         curPlayer.SetDict(ChConfig.Def_PlayerKey_RecordXPValue, remain)  | 
|         curPlayer.SetXP(remain)  | 
|   | 
|     #----------¿ÛHPµã  | 
|     lostHPValue = curSkill.GetHP()  | 
|     curPlayerHP = curPlayer.GetHP()  | 
|       | 
|     if curPlayerHP < lostHPValue:  | 
|         GameWorld.ErrLog('Êͷż¼ÄÜ = %sÒì³£, HPµã = %s²»×ã = %s' % (  | 
|                             curSkill.GetSkillTypeID(), curPlayerHP, lostHPValue))  | 
|       | 
|     if lostHPValue > 0:  | 
|         curPlayer.SetHP(curPlayer.GetHP() - lostHPValue)  | 
|           | 
|     return  | 
|   | 
| ## Ö´Ðб»¶¯¼¼ÄÜ´¦Àí  | 
| #  @param curPlayer Ê¹Óü¼ÄÜÕß  | 
| #  @param target ·ÀÓùÕß  | 
| #  @param curPlayerSkill Ê¹Óü¼ÄÜ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __DealWithPassivitySkill(curPlayer, target, curPlayerSkill, tick):  | 
| #===============================================================================  | 
| #    isSuperHit = GetIsSuperHit()  | 
| #    isMiss = GetIsMiss()  | 
| #    lostHP = GetLostHP()  | 
| #    skillManager = curPlayer.GetSkillManager()  | 
| #    #È«¾Ö±»¶¯¼¼ÄÜÊÇ·ñ¿ÉÒÔ´¥·¢  | 
| #    #×¢:Ìí¼ÓÕâ¸öÅж¨,ÐèҪͬʱÐÞ¸ÄChConfig.Def_SkillID_TrigÅä¶ÔʹÓà  | 
| #    canDealWithTrigSkill = ( (tick - skillManager.GetTrigBuffSkillTick()) \  | 
| #                                > ChConfig.Def_Skill_PassivityTick )  | 
| #    curPlayerJob = curPlayer.GetJob()  | 
| #    skillTypeID = curPlayerSkill.GetSkillTypeID()  | 
| #===============================================================================  | 
|     return  | 
| #------------------------------------------------------------------  | 
| ## NPC¹¥»÷³É¹¦(²ÎÊý -> µ±Ç°NPC,µ±Ç°NPC±»»÷ǰѪÁ¿,¹¥»÷¶ÔÏó,¼¼ÄÜ,µ±Ç°Ê±¼ä)  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param curNPCBeHP µ±Ç°NPC±»»÷ǰѪÁ¿  | 
| #  @param target ¹¥»÷¶ÔÏó  | 
| #  @param curSkill ¼¼ÄÜ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return True  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __DoNPCAttackSuccess(curNPC, curNPCBeHP, target, curSkill, tick):  | 
|     #--------------  | 
|     #ÕâÀïÔÚ¹¥»÷½áÊøºó,Ö»»áµ÷ÓÃÒ»´Î,¶ø¹¥»÷·½·¨ÖÐAttackResult½«¶à´Î±»µ÷ÓÃ(Ⱥ¹¥)  | 
|     #ÕâÀïÖ»´¦Àí¹¥»÷·½Âß¼,,ËùÓÐÄ¿±ê·½Âß¼ÔÚAttackResultÖд¦Àí  | 
|     #--------------  | 
|     #ÉèÖù¥»÷¼ä¸ô  | 
|     curNPC.SetAttackTick(tick)  | 
|     #֪ͨÉËѪ·´µ¯  | 
|     #hurtHPValueSelf = curNPCBeHP - curNPC.GetHP()  | 
|       | 
|     #֪ͨ¿Í»§¶Ë¹¥»÷½á¹û  | 
|     __Sync_AttackResult(curNPC, target, curSkill)  | 
|       | 
|     #¼¼ÄÜʹÓóɹ¦  | 
|     if curSkill:  | 
|         skillTypeID = curSkill.GetSkillTypeID()  | 
|           | 
|         #¼¼ÄÜʹÓóɹ¦  | 
|         curNPCSkill = curNPC.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)  | 
|           | 
|         if not curNPCSkill:  | 
|             pass  | 
|             #GameWorld.ErrLog('NPC = %s, useSkillErr skillTypeID = %s' % (curNPC.GetNPCID(), skillTypeID))  | 
|         else:  | 
|             #ÉèÖü¼Äܹ«¹²CD  | 
|             curNPC.SetUseSkillTick(tick)  | 
|             #ÉèÖõ¥¸ö¼¼ÄÜÀäȱCD  | 
|             SkillCommon.SetSkillRemainTime(curNPCSkill, 0, tick, curNPC)  | 
|             #__DealWithNPCPassSkill(curNPC,curSkill)  | 
|               | 
|         #Ôö¼ÓNPC¼¼ÄÜʹÓôÎÊý  | 
|         useCnt = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillUseCnt % skillTypeID)  | 
|         curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillUseCnt % skillTypeID, min(useCnt + 1, ChConfig.Def_UpperLimit_DWord))  | 
|       | 
| #===============================================================================  | 
| #    #¼¼ÄÜÀàÐÍ :¹â»·¡¡²»ÈÃÖ÷È˽øÈëÕ½¶·×´Ì¬  | 
| #    if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotSummon :  | 
| #        #»ñÈ¡µÄÖ÷ÈË  | 
| #        curPlayer = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer,curNPC)  | 
| #        #Èç¹ûÖ÷ÈËÊÇÍæ¼Ò  | 
| #        if curPlayer != None and curPlayer.GetHP() > 0:  | 
| #            if curSkill == None or curSkill.GetSkillType() != ChConfig.Def_SkillType_Aura:   | 
| #                #½øÈëÕ½¶·×´Ì¬  | 
| #                AttackCommon.SetPlayerBattleState(curPlayer,tick)  | 
| #===============================================================================  | 
|       | 
|     #³èÎïÕÒµ½Ö÷È˽øÈëÕ½¶·×´Ì¬£¬¹â»·¼¼Äܲ»½øÈë  | 
|     if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotPet:  | 
|         curPlayer = PetControl.GetPetOwner(curNPC)  | 
|           | 
|         if curPlayer != None and curPlayer.GetHP() > 0:  | 
|             if curSkill == None or curSkill.GetSkillType() not in ChConfig.Def_NoBattleState_List:   | 
|                 AttackCommon.SetPlayerBattleState(curPlayer, tick)  | 
|       | 
|     FBLogic.DoOverNPCAttackSuccess(curNPC, target, tick)  | 
|       | 
|     # ÁéÎªÍæ¼ÒµÄÌæÉíÐèÒª×ß´ËÂß¼  | 
|     UseSkillOver(curNPC, target, curSkill, tick)  | 
|     return True  | 
|   | 
| ## ´¦ÀíNPC¸½¼Ó±»¶¯¼¼ÄÜ  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param curSkill Ê¹Óü¼ÄÜ  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __DealWithNPCPassSkill(curNPC, curSkill):  | 
|     return  | 
|       | 
| ##############################±»¹¥»÷³É¹¦#############################  | 
|   | 
| ## Íæ¼Ò±»¹¥»÷(µ±Ç°Íæ¼Ò,¼¼ÄÜ,µ±Ç°Ê±¼ä)  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param curSkill Ê¹Óü¼ÄÜ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __DoPlayerBeAttacked(attacker, curPlayer, curSkill, tick):  | 
|     #Íæ¼ÒÒѾËÀÍö  | 
|     if curPlayer.GetHP() <= 0:  | 
|         return  | 
|        | 
|     #Æï³Ë״̬±»¹¥»÷£¬Ôò×Ô¶¯ÏÂÂí  | 
|     #===========================================================================  | 
|     # if attacker and attacker.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|     #    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:  | 
|     #        PlayerHorse.PlayerRideHorseDown(curPlayer)     | 
|     #===========================================================================  | 
|           | 
|     #BeHitWarn ×¢Ò⣺ÄúÕýÔÚÔâÊܹ¥»÷  | 
|     #PlayerControl.NotifyCode(curPlayer, "BeHitWarn")  | 
|     #²É¼¯ÖÐ¶Ï  | 
|     PlayerControl.BreakPlayerCollect(curPlayer)  | 
|     #´ò×øÖÐ¶Ï  | 
|     #PlayerControl.DoPlayerStand(curPlayer)  | 
|     #¼¤»îÍæ¼Ò  | 
|     PlayerControl.SetIsNeedProcess(curPlayer, True)  | 
|   | 
|     # ÔÝÇÒÖ»ÓÐÍæ¼Ò±»¹¥»÷´¥·¢  | 
|     if not curSkill or curSkill.GetSkillType() in ChConfig.Def_CanAttackSkill_List:  | 
|         PassiveBuffEffMng.OnPassiveSkillTrigger(curPlayer, attacker, None, ChConfig.TriggerType_BeAttackOver, tick)  | 
|         PassiveBuffEffMng.OnPassiveBuffTrigger(curPlayer, attacker, None, ChConfig.TriggerType_BeAttackOver, tick)  | 
|     return  | 
|   | 
| ## NPC±»¹¥»÷(µ±Ç°NPC,¼¼ÄÜ,µ±Ç°Ê±¼ä)  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __DoNPCBeAttacked(curNPC, curSkill, tick):  | 
|     #NPCÒѾËÀÍö  | 
|     if GameObj.GetHP(curNPC) <= 0:  | 
|         return  | 
|       | 
|     #ÅųýïÚ³µ  | 
|     if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotTruck:  | 
|         return  | 
|       | 
|     #Åųý¹  | 
|     if curNPC.GetType() == IPY_GameWorld.ntDeer:  | 
|         return  | 
|       | 
|     #ÉèÖýøÈëÕ½¶·×´Ì¬  | 
|     NPCCommon.SetNPCInBattleState(curNPC)  | 
|       | 
|     # ±»»÷Ìí¼Ó²»ÈÃÖ÷¶¯Òƶ¯£¬Ó¦ÓÃAI1  | 
|     if curNPC.GetIsBoss() == 0:  | 
|         curNPC.SetDict("NPCBeAttackedAI1", tick)  | 
|     return  | 
|   | 
| # ¿Í»§¶ËËÑË÷¶ÔÏóµÄÁ´Ê½¹¥»÷  | 
| def ChainAttackAreaEx(attacker, defender, curSkill, srcPosX, srcPosY,  | 
|                           skillValue, skillPerList, tick,  | 
|                           powerList = [], isExSkill = False):  | 
|       | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = attacker.GetHP()  | 
|       | 
|     attackObjName = GetObjAttackName(attacker)  | 
|       | 
|     resultList = list()     #¹¥»÷½á¹ûÁÐ±í  | 
|       | 
|     #ÎÞ·¨ÕÒµ½ÏÂÒ»¸ö¶ÔÏóÔòÍ˳ö¹¥»÷  | 
|     resultList = __DoNextDefenderEx(attacker, curSkill, skillValue, skillPerList,  | 
|                                attackObjName, resultList, tick)  | 
|               | 
|     #Ö´ÐÐȺ¹¥½á¹û  | 
|     __DoAreaAttackResult(attacker, defender, curSkill, resultList, attackerHP, tick, isExSkill)  | 
|       | 
|     return True  | 
|   | 
| # Á´Ê½¹¥»÷ÖðÒ»¶ÔÓ¦É˺¦  | 
| def __DoNextDefenderEx(attacker, curSkill, skillValue, skillPerList,  | 
|                        attackObjName, resultList, tick):  | 
|       | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|     hurtTypeList = ChConfig.Def_Dict_UseSkillTag_ObjType.get(curSkillUseTag)  | 
|       | 
|     #ÕÒ²»µ½¹¥»÷¶ÔÏóÀàÐÍÔòÍ˳ö  | 
|     if hurtTypeList == None:  | 
|         GameWorld.ErrLog("Def_Dict_UseSkillTag_ObjType Ã»ÓжÔÓ¦Ïî %s" % curSkillUseTag)  | 
|         return resultList  | 
|    | 
|     hurtDict = SkillShell.GetClientHurtDict()  | 
|       | 
|     for i in range(len(skillPerList)):  | 
|         objID, curObjType = hurtDict.keys()[i]  | 
|         #²»Ôڿɹ¥»÷¶ÔÏóÁбíÖÐ  | 
|         if curObjType not in hurtTypeList:  | 
|             continue  | 
|           | 
|         #¹¥»÷¶ÔÏó  | 
|         curTag = GameWorld.GetObj(objID, curObjType)  | 
|         if not curTag:  | 
|             continue  | 
|       | 
|         #Á´Ê½¹¥»÷²»ÄܶÔïÚ³µÊÍ·Å  | 
|         if curObjType == IPY_GameWorld.gotNPC and curTag.GetGameNPCObjType() == IPY_GameWorld.gnotTruck:  | 
|             continue  | 
|          | 
|         #¾ßÌåÅж¨¶ÔÏóÊÇ·ñ¿É¹¥»÷  | 
|         if not __DoAttack(attacker, curTag, curSkill, attackObjName,  | 
|                             skillValue, skillPerList[i], g_skillHurtList, tick):  | 
|             continue  | 
|          | 
|         resultList.append(curTag)  | 
|          | 
|     return resultList  | 
| #------------------------------------------------------------------  | 
| ## ÇøÓòÌØÊâ¹¥»÷ͨÓú¯Êý,ÓÃÓÚ¸ü¸ÄÆðµã,Óй¥»÷´ÎÊý,¹¥»÷Ë¥¼õµÈ(ÈçÂÒ½£á÷»ê)  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param skillValue ¼¼ÄÜÔöǿֵ  | 
| #  @param skillPerList ¼¼ÄÜÔöÇ¿°Ù·Ö±ÈÁÐ±í  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param powerList Ë¥¼õ»òÔöÇ¿Áбí[ [skillPercent,skillEnhance],...... ]  | 
| #  @param isExSkill ÊÇ·ñÊǸ½¼Ó¼¼ÄÜ, ¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷³É¹¦, Ò²²»Ôٴδ¥·¢ÆäËû¸½¼Ó¼¼ÄÜ  | 
| #  @return Õæ/¼Ù ÊÇ·ñ¹¥»÷³É¹¦  | 
| #  @remarks ÇøÓòÌØÊâ¹¥»÷ͨÓú¯Êý,ÓÃÓÚ¸ü¸ÄÆðµã,Óй¥»÷´ÎÊý,¹¥»÷Ë¥¼õµÈ(ÈçÂÒ½£á÷»ê)  | 
| def ChainAttackArea(attacker, defender, curSkill, srcPosX, srcPosY,  | 
|                           skillValue, skillPerList, tick,  | 
|                           powerList = [], isExSkill = False):  | 
|       | 
|     #×÷Ó÷¶Î§ ×÷ÓþØÕó  | 
|     attackDis = curSkill.GetAtkRadius()  | 
|     skillMatrix = ChConfig.MatrixDict.get(attackDis)  | 
|     if skillMatrix == None:  | 
|         GameWorld.ErrLog("ChainAttackArea skillId=%s, attakDis=%s not in matrixDict=%s"   | 
|                          % (curSkill.GetSkillID(), attackDis, ChConfig.MatrixDict))  | 
|         return False  | 
|       | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     #ÏÈ»ñµÃ¹¥»÷µÄ´ÎÊý  | 
|     attackTimeSum = len(skillPerList)  | 
|   | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = attacker.GetHP()  | 
|       | 
|     attackObjName = GetObjAttackName(attacker)  | 
|       | 
|     #µÚÒ»´Î¹¥»÷Ñ¡ÖÐÄ¿±ê  | 
|     if not __DoAttack(attacker, defender, curSkill, attackObjName, skillValue,  | 
|                       skillPerList[0], g_skillHurtList, tick):  | 
|         return False  | 
|       | 
|     #GameWorld.Log("¹¥»÷Ä¿±ê: curTagID = %s,curTagName = %s "%(  | 
|     #                    defender.GetID(),defender.GetName()))  | 
|     gameMap = GameWorld.GetMap()  | 
|       | 
|     resultList = list()     #¹¥»÷½á¹ûÁÐ±í  | 
|     resultList.append(defender)  | 
|       | 
|     srcPos = [srcPosX, srcPosY]  | 
|       | 
|     #---Á´Ê½¹¥»÷ÏÂÒ»¸öÄ¿±ê---  | 
|     for index in range(1, attackTimeSum):  | 
|         #ÎÞ·¨ÕÒµ½ÏÂÒ»¸ö¶ÔÏóÔòÍ˳ö¹¥»÷  | 
|         if not __DoNextDefender(attacker, curSkill, skillValue, skillPerList,  | 
|                                attackObjName, srcPos, index,  | 
|                                resultList, skillMatrix, gameMap, tick):  | 
|             #GameWorld.Log("3ÎÞ·¨ÕÒµ½ÏÂÒ»¸ö¶ÔÏóÔòÍ˳ö¹¥»÷")  | 
|             break  | 
|               | 
|     #Ö´ÐÐȺ¹¥½á¹û  | 
|     __DoAreaAttackResult(attacker, defender, curSkill, resultList, attackerHP, tick, isExSkill)  | 
|       | 
|     return True  | 
|   | 
| ## Á´Ê½¹¥»÷Ö´Ðе¥´ÎDoAttackÂß¼  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param attackObjName ¹¥»÷ÕßÀàÐÍÖ¸¶¨Ãû³Æ  | 
| #  @param skillValue ¼¼ÄÜÔöǿֵ  | 
| #  @param skillPer ¼¼ÄÜÔöÇ¿°Ù·Ö±È  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return Õæ/¼Ù ÊÇ·ñ¹¥»÷³É¹¦  | 
| #  @remarks Á´Ê½¹¥»÷Ö´Ðе¥´ÎDoAttackÂß¼  | 
| def __DoAttack(attacker, defender, curSkill, attackObjName, skillValue, skillPer,  | 
|                g_skillHurtList, tick):  | 
|     #²»¿É¹¥»÷Ñ¡ÖÐÄ¿±ê  | 
|     if not __CheckCanAttack(attacker, defender, curSkill, tick):  | 
|         return  | 
|       | 
|     callName = "%s_Attack_%s.%s" % (attackObjName, GetObjAttackName(defender), "DoAttack")  | 
|       | 
|     callFunc = GameWorld.GetExecFunc(AttackLogic, callName)  | 
|       | 
|     if not callFunc:  | 
|         return  | 
|       | 
|     #¹¥»÷ǰÁ¬»÷¼ì²é  | 
|     SkillCommon.UpdateSkillCombo(attacker, curSkill, tick)  | 
|     #GameWorld.Log("1skillPer: %s"%skillPer)  | 
|     callFunc(attacker, defender, curSkill, skillValue, skillPer, g_skillHurtList, tick)  | 
|       | 
|     return True  | 
|   | 
|   | 
| ## ÅжÏÔÚÁ´Ê½¹¥»÷ÖÐÊÇ·ñ±»¹¥»÷¹ý  | 
| #  @param curTag ±»¹¥»÷Ä¿±ê  | 
| #  @param resultList Òѱ»¹¥»÷ÁÐ±í  | 
| #  @return Õæ/¼Ù ÊÇ·ñÒѱ»¹¥»÷  | 
| #  @remarks ÅжÏÔÚÁ´Ê½¹¥»÷ÖÐÊÇ·ñ±»¹¥»÷¹ý  | 
| def __IsAlreadyAttack(curTag, resultList):  | 
|     #¶ÔÏó²»´æÔÚ  | 
|     if curTag == None:  | 
|         return True  | 
|       | 
|     #¸ÃλÖÃÒÑÓÐNPC±»´Ë´ÎÁ´Ê½¹¥»÷  | 
|     for tag in resultList:  | 
|         if not tag:  | 
|             continue  | 
|           | 
|         if GameWorld.IsSameObj(curTag, tag):  | 
|             return True  | 
|       | 
|     return False  | 
|   | 
| ## ¹¥»÷ÏÂÒ»¸öÁ´Ê½Ä¿±ê(ÈçÂÒ½£á÷»ê)  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param skillValue ¼¼ÄÜÔöǿֵ  | 
| #  @param skillPerList ¼¼ÄÜÔöÇ¿°Ù·Ö±ÈÁÐ±í  | 
| #  @param attackObjName ¹¥»÷ÕßÀàÐÍÖ¸¶¨Ãû³Æ  | 
| #  @param srcPos ¹¥»÷ÆðµãX/Y  | 
| #  @param index ¹¥»÷Ë÷Òý  | 
| #  @param resultList Òѱ»¹¥»÷ÁÐ±í  | 
| #  @param skillMatrix ¼¼ÄÜ·¶Î§¾ØÕó  | 
| #  @param gameMap µØÍ¼¹ÜÀíÆ÷  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return Õæ/¼Ù ÊÇ·ñ¹¥»÷³É¹¦  | 
| #  @remarks ¹¥»÷ÏÂÒ»¸öÁ´Ê½Ä¿±ê(ÈçÂÒ½£á÷»ê)  | 
| def __DoNextDefender(attacker, curSkill, skillValue, skillPerList,  | 
|                        attackObjName, srcPos, index,  | 
|                        resultList, skillMatrix, gameMap, tick):  | 
|       | 
|     isSucceed = False  | 
|    | 
|     curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)  | 
|       | 
|     hurtTypeList = ChConfig.Def_Dict_UseSkillTag_ObjType.get(curSkillUseTag)  | 
|       | 
|     #ÕÒ²»µ½¹¥»÷¶ÔÏóÀàÐÍÔòÍ˳ö  | 
|     if hurtTypeList == None:  | 
|         GameWorld.ErrLog("Def_Dict_UseSkillTag_ObjType Ã»ÓжÔÓ¦Ïî %s" % curSkillUseTag)  | 
|         return isSucceed  | 
|    | 
|     for curPos in skillMatrix:  | 
|         #¹¥»÷³É¹¦  | 
|         if isSucceed:  | 
|             #GameWorld.Log("2srcPos: %s"%srcPos)  | 
|             break  | 
|           | 
|         #¼ì²éÓÐûÓжÔÏóÔÚÕâÒ»µãÉÏ  | 
|         mapObj = gameMap.GetPosObj(srcPos[0] + curPos[0], srcPos[1] + curPos[1])  | 
|           | 
|         if not mapObj:  | 
|             continue  | 
|    | 
|         #±éÀúµ±Ç°µã¶ÔÏó  | 
|         for i in range(0, mapObj.GetObjCount()):  | 
|             curObj = mapObj.GetObjByIndex(i)  | 
|             curObjType = curObj.GetGameObjType()  | 
|               | 
|             #²»Ôڿɹ¥»÷¶ÔÏóÁбíÖÐ  | 
|             if curObjType not in hurtTypeList:  | 
|                 continue  | 
|                | 
|             #¹¥»÷¶ÔÏó  | 
|             curTag = GameWorld.GetObj(curObj.GetID(), curObjType)  | 
|             if not curTag:  | 
|                 continue  | 
|    | 
|             #Á´Ê½¹¥»÷²»ÄܶÔïÚ³µÊÍ·Å  | 
|             if curObjType == IPY_GameWorld.gotNPC and curTag.GetGameNPCObjType() == IPY_GameWorld.gnotTruck:  | 
|                 continue  | 
|               | 
|             if __IsAlreadyAttack(curTag, resultList):  | 
|                 continue  | 
|               | 
|             #¾ßÌåÅж¨¶ÔÏóÊÇ·ñ¿É¹¥»÷  | 
|             if not __DoAttack(attacker, curTag, curSkill, attackObjName,  | 
|                                  skillValue, skillPerList[index], g_skillHurtList, tick):  | 
|                 continue  | 
|               | 
|             resultList.append(curTag)  | 
|               | 
|             #´Ó±»¹¥»÷Õß¿ªÊ¼ÖØÐ¼ÆËã×ø±ê  | 
|             srcPos[0] = curTag.GetPosX()  | 
|             srcPos[1] = curTag.GetPosY()  | 
|               | 
|             isSucceed = True  | 
|             break  | 
|    | 
|     return isSucceed  | 
|   | 
| ## ±¬ÁÑʽȺ¹¥ (½£Èë»ÆÈª)  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param skillPercent ¼¼ÄÜÔöÇ¿°Ù·Ö±È  | 
| #  @param skillEnhance ¼¼ÄÜÔöǿֵ  | 
| #  @param changePer ½¥±äÖµ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param powerList Ë¥¼õ»òÔöÇ¿Áбí[ [skillPercent,skillEnhance],...... ]  | 
| #  @param isEnhanceSkill ÊÇ·ñÊǸ½¼Ó¼¼ÄÜ, ¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷³É¹¦, Ò²²»Ôٴδ¥·¢ÆäËû¸½¼Ó¼¼ÄÜ  | 
| #  @return True  | 
| #  @remarks ±¬ÁÑʽȺ¹¥ (½£Èë»ÆÈª)  | 
| def CrackAttackArea(attacker, defender, srcPosX, srcPosY, curSkill,  | 
|                     skillPercent, skillEnhance, changePer, tick,  | 
|                     powerList = [], isEnhanceSkill = False):      | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|     attackList = []  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = GameObj.GetHP(attacker)  | 
|       | 
|     #È¡µÃ¿É¹¥»÷¶ÔÏóÁÐ±í  | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack)  | 
|       | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|       | 
|     for tagObj in resultList:  | 
|         dist = GameWorld.GetDist(tagObj.GetPosX(), tagObj.GetPosY(),  | 
|                          defender.GetPosX(), defender.GetPosY())  | 
|           | 
|         skillPer = (skillPercent - dist * changePer) / float(ChConfig.Def_MaxRateValue)  | 
|           | 
|         #GameWorld.Log("skillPer :%s"%skillPer)  | 
|         #Ö´ÐÐȺ¹¥ ²¢È¡µÃ±»¹¥»÷¶ÔÏóÁÐ±í  | 
|         tmpList = __DoAreaAttack(attacker, curSkill, skillEnhance, skillPer,  | 
|                                  [tagObj], powerList, g_skillHurtList, tick)  | 
|         attackList.extend(tmpList)  | 
|   | 
|     #Ö´ÐÐȺ¹¥½á¹û  | 
|     __DoAreaAttackResult(attacker, defender, curSkill, attackList, attackerHP, tick, isEnhanceSkill)  | 
|      | 
|     return True  | 
|   | 
| ## ÎÞµÐÕ¶Ëæ»ú¹¥»÷·¶Î§ÄÚÄ¿±ê  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ÊÇ·ñ¹¥»÷³É¹¦  | 
| #  @remarks ÎÞµÐÕ¶Ëæ»ú¹¥»÷·¶Î§ÄÚÄ¿±ê  | 
| def SuperLinkRandomAttack(attacker, curSkill, tick):  | 
|     #·µ»ØÊÇ·ñ¹¥»÷³É¹¦£¬ÅжÏÒª²»ÒªÏÂÒ»´Î¹¥»÷  | 
|     result = False  | 
|       | 
|     defender = attacker.GetActionObj()  | 
|       | 
|     if defender != None:  | 
|         defender = GameWorld.GetObjDetail(defender)  | 
|           | 
|         attacker.SetActionObj(None)  | 
| #        #Í˳ö¶ÔÖÅ  | 
| #        attacker.SetIsConfronting(False)  | 
| #        #֪ͨ¿Í»§¶Ë //0½øÈë;ÆäËûÍ˳ö  | 
| #        attacker.View_PlayerBattle(0, 0, 1)  | 
|         #Ìí¼Ó²âÊÔÐÅÏ¢  | 
|         GameWorld.GodLog(attacker, 'ÎÞµÐÕ¶£¬Í˳öÕ½¶·¶ÔÖųɹ¦')  | 
|     else:  | 
|         resultList = __GetAreaAtackObj(attacker, curSkill, attacker.GetPosX(),  | 
|                                        attacker.GetPosY(), tick, __CheckCanAttack)  | 
|           | 
|         if resultList == []:  | 
|             return result  | 
|       | 
|         defender = random.choice(resultList)  | 
|       | 
|     #¹¥»÷Ä¿±ê  | 
|     result = SuperLinkAttackObj(attacker, defender, curSkill, tick)  | 
|   | 
|     return result  | 
|   | 
| ## ÎÞµÐÕ¶¹¥»÷Ä¿±ê  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓù×ÅʵÀý  | 
| #  @param curSkill ¼¼ÄÜ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ÊÇ·ñ¹¥»÷³É¹¦  | 
| #  @remarks ÎÞµÐÕ¶¹¥»÷Ä¿±ê  | 
| def SuperLinkAttackObj(attacker, defender, curSkill, tick):  | 
|     #·µ»ØÊÇ·ñ¹¥»÷³É¹¦£¬ÅжÏÒª²»ÒªÏÂÒ»´Î¹¥»÷  | 
|     result = False  | 
|     #---Ч¹û2 AֵΪ¹¥»÷¼¼ÄÜID---  | 
|     attackSkillEff = SkillCommon.GetSkillEffectByEffectID(curSkill, ChConfig.Def_Skill_Effect_SuperLinkAtk)  | 
|       | 
|     curSkillLV = curSkill.GetSkillLV()  | 
|     curSkillID = curSkill.GetSkillID()  | 
|       | 
|     #ûÓй¥»÷¼¼ÄÜ  | 
|     if attackSkillEff == None:  | 
|         GameWorld.ErrLog("ûÓÐÎ޵й¥»÷¼¼ÄÜЧ¹ûÏî%s ID=%s, Lv=%s" % (ChConfig.Def_Skill_Effect_SuperLinkAtk,  | 
|                                                        curSkillID, curSkillLV))  | 
|         return result  | 
|   | 
|     attackSkillID = attackSkillEff.GetEffectValue(0)  | 
|   | 
|     #Ïȼì²éÊý¾Ý¿âÓÐû¸ÃÀ༼ÄÜ£¬Èç¹û×î¸ßµÈ¼¶²»Ò»Ñù»áÕÒ²»µ½  | 
|     attackSkill = GameWorld.GetGameData().FindSkillByType(attackSkillID, curSkillLV)  | 
|     #Òì³£  | 
|     if not attackSkill:  | 
|         GameWorld.ErrLog("Êý¾Ý¿âûÓÐÎ޵й¥»÷¼¼ÄÜ ID = %s, skillLv = %s" % (attackSkillID, curSkillLV))  | 
|         return result  | 
|       | 
|       | 
|     #ÕÒµ½±»¶¯¼¼ÄÜ£¬Ìí¼Ó±©»÷ÂÊ  | 
|     #---Ч¹û4 AֵΪ±»¶¯¼¼ÄÜID, ±»¶¯¼¼ÄܵÄЧ¹û2Ôö¼Ó±©»÷---  | 
|     passiveSkill = SkillCommon.GetSkillFromOtherSkillByEffectID(attacker, curSkill,  | 
|                                                                 ChConfig.Def_Skill_Effect_PassiveSkillID)  | 
|       | 
|     beforeSuperHitRate = attacker.GetSuperHitRate()  | 
|     #¸Ã±»¶¯¼¼ÄÜÒÑѧ  | 
|     if passiveSkill != None and SkillCommon.isPassiveSkill(passiveSkill):  | 
|         superHitEff = SkillCommon.GetSkillEffectByEffectID(passiveSkill, ChConfig.Def_Skill_Effect_SuperAtkSHit)  | 
|         if superHitEff != None:  | 
|             superHitRate = superHitEff.GetEffectValue(0)  | 
|             superHitPer = (ChConfig.Def_MaxRateValue + superHitEff.GetEffectValue(1)) / float(ChConfig.Def_MaxRateValue)  | 
|               | 
|             #ÉèÖÃеı©»÷ÂÊ  | 
|             attacker.SetSuperHitRate(int(max(beforeSuperHitRate, superHitRate) * superHitPer))  | 
|         else:  | 
|             GameWorld.ErrLog("ûÓб©»÷Ч¹ûÏî%s ID=%s, Lv=%s" % (ChConfig.Def_Skill_Effect_SuperAtkSHit,  | 
|                                                      passiveSkill.GetSkillID(), passiveSkill.GetSkillLV()))  | 
|   | 
|     #ÉèÖù¥»÷ÆðµãÎªÍæ¼Ò×ÔÉí×ø±ê  | 
|     attacker.SetAttackTargetPos(attacker.GetPosX(), attacker.GetPosY())  | 
|     result = SkillShell.DoLogic_UseSkill(attacker, defender, attackSkill, tick)  | 
|       | 
|     attacker.SetSuperHitRate(beforeSuperHitRate)  | 
|       | 
|     return result  | 
|   | 
|   | 
| ## ½£Èз籩¹¥»÷  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param skillPercent ¼¼ÄÜÔöÇ¿°Ù·Ö±È  | 
| #  @param skillEnhance ¼¼ÄÜÔöǿֵ  | 
| #  @param skillMatrix Ö¸¶¨¹¥»÷¾ØÕó   | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ÎÞ  | 
| #  @remarks ½£Èз籩¹¥»÷  | 
| def SwordStormAttack(attacker, srcPosX, srcPosY, curSkill, skillPercent,  | 
|                      skillEnhance, skillMatrix, tick):  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack, skillMatrix)  | 
|             | 
|     attackList = __DoAreaAttack(attacker, curSkill, skillEnhance, skillPercent,  | 
|                                 resultList, [], g_skillHurtList, tick)  | 
|       | 
|     #²»Í¨Öª¹¥»÷³É¹¦°ü Ö»¹ã²¥µôѪ  | 
|     #===========================================================================  | 
|     # for index in range(g_skillHurtList.GetHurtCount()):  | 
|     #    hurtObj = g_skillHurtList.GetHurtAt(index)  | 
|     #      | 
|     #    curObj = GameWorld.GetObj(hurtObj.GetObjID(), hurtObj.GetObjType())  | 
|     #      | 
|     #    if curObj == None:  | 
|     #        continue  | 
|     #      | 
|     #    curObj.ChangeHPView(curSkill.GetSkillTypeID(), hurtObj.GetHurtHP(), hurtObj.GetAttackType())  | 
|     #      | 
|     #    SkillCommon.NotifyNPCHP(curObj)  | 
|     #===========================================================================  | 
|     Sync_SkillHurtList(attacker, curSkill.GetSkillID(), srcPosX, srcPosY, g_skillHurtList)  | 
|           | 
|     skillIDSet = set()  | 
|     #¹¥»÷½á¹û ²»´¦Àí´¥·¢Âß¼  | 
|     for defObj in attackList:  | 
|           | 
|         #Òò¹¥»÷½áÊø¶¯×÷ÖУ¬·¨±¦¹¥»÷½«µ¼ÖÂÄ¿±êËÀÍö¡£ÒªÅж¨ºóÔڴε÷Ó㬱ÜÃâ2´Î->AttackResult  | 
|         if AttackCommon.GetIsDead(defObj):  | 
|             continue  | 
|           | 
|         #·ÅÔÚº¯ÊýÖпɶà´Î´¥·¢ ÈçSP ´¥·¢¼õËÙ»òÕßÉ˺¦£¬µ«²»ÄÜ·ÅÔÚ¹¥»÷¼ÆËãÖУ¬ÒòΪÉ˺¦Ðͼ¼ÄÜ»áÓ°ÏìÉËѪÁÐ±í  | 
|         PassiveBuffEffMng.OnPassiveSkillTrigger(attacker, defObj, curSkill, ChConfig.TriggerType_AttackPlayer, tick,  | 
|                                                 isEnhanceSkill=False, skillIDSet=skillIDSet)  | 
|           | 
|         DoLogic_AttackResult(attacker, defObj, curSkill, tick)  | 
|         skillEffect = SkillCommon.GetSkillEffectByEffectID(curSkill, ChConfig.Def_Skill_Effect_ProcessAttack)  | 
|         if skillEffect:  | 
|             skillID = skillEffect.GetEffectValue(2)  | 
|             if skillID != 0:  | 
|                 triggerSkill = GameWorld.GetGameData().GetSkillBySkillID(skillID)  | 
|                 if not triggerSkill:  | 
|                     continue  | 
|                 SkillShell.UsePassiveTriggerSkill(attacker, triggerSkill, defObj, tick)  | 
|   | 
|     # Ò»Ò»´¥·¢¼¼ÄÜÐèÒªÔÚ×îºóÉèÖÃCD  | 
|     for skillTypeID in skillIDSet:  | 
|         curSkill = attacker.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)  | 
|         if not curSkill:  | 
|             continue  | 
|         SkillCommon.SetSkillRemainTime(curSkill, 0, tick, attacker)  | 
|       | 
| ## Çå¿ÕÉËѪÁÐ±í  | 
| #  @param ÎÞ  | 
| #  @return ÎÞ  | 
| #  @remarks Çå¿ÕÉËѪÁбí ÓÃÓÚÊͷż¼ÄÜ´¦ÀíÂ߼ǰÇå  | 
| def ClearSkillHurtList():  | 
|     global g_skillHurtList  | 
|       | 
|     g_skillHurtList.Clear()  | 
|       | 
|   | 
| ## »ñÈ¡·ÀÊØÕߵı»¹¥»÷ÀàÐÍ  | 
| #  @param defender ·ÀÊØÕß  | 
| #  @return ¹¥»÷ÀàÐÍ  | 
| #  @remarks »ñÈ¡·ÀÊØÕߵı»¹¥»÷ÀàÐÍ  | 
| def GetHurtType(defender):  | 
|     if defender == None:  | 
|         return ChConfig.Def_HurtType_Normal  | 
|       | 
|     #ÔÚÉËѪÁбíÖÐÕÒ³ö·ÀÊØ·½µÄÉËѪ½á¹¹  | 
|     for index in range(g_skillHurtList.GetHurtCount()):  | 
|         hurtObj = g_skillHurtList.GetHurtAt(index)  | 
|           | 
|         curObj = GameWorld.GetObj(hurtObj.GetObjID(), hurtObj.GetObjType())  | 
|           | 
|         if curObj == None:  | 
|             continue  | 
|           | 
|         if not GameWorld.IsSameObj(curObj, defender):  | 
|             continue  | 
|   | 
|         return hurtObj.GetAttackType()  | 
|   | 
|     return ChConfig.Def_HurtType_Normal  | 
|   | 
|   | 
| ## °´°Ù·Ö±ÈȺÌå¿ÛѪ  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param defender ·ÀÓùÕßʵÀý  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êX  | 
| #  @param srcPosX ¹¥»÷Æðµã×ø±êY  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @param isExSkill ÊÇ·ñÊǸ½¼Ó¼¼ÄÜ, ¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷³É¹¦, Ò²²»Ôٴδ¥·¢ÆäËû¸½¼Ó¼¼ÄÜ  | 
| #  @param skillMatrix ¹¥»÷¾ØÕó  | 
| #  @return True  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def AttackerSkillAttackAreaLostHP(attacker, defender, srcPosX, srcPosY, curSkill, tick,  | 
|                             isExSkill = False, skillMatrix = None):  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|       | 
|     #¹¥»÷·½ÔÓÐѪÁ¿,ÓÃÀ´Í¨Öª·´µ¯  | 
|     attackerHP = attacker.GetHP()  | 
|       | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, __CheckCanAttack, skillMatrix)  | 
|               | 
|     #ÓÐÄ¿±êÀ༼ÄÜ,²éÕÒÖ¸¶¨µÄ¹¥»÷Ä¿±êÊÇ·ñÔÚÁбíÖÐ,²»ÔÚÌí¼Ó  | 
|     resultList = __AddObj_In_resultList(resultList, attacker, defender, curSkill, tick)  | 
|     #GameWorld.Log("ʹÓÃÎÞÖ¸¶¨´ÎÊýȺ¹¥¼¼ÄÜ = %s ³É¹¦,¸½¼Ó¼¼ÄÜЧ¹û = %s,¸½¼Ó¼¼ÄÜÔöÇ¿ = %s"%\  | 
|     #(curSkill.GetSkillName(),skillValue,skillPer))  | 
|           | 
|     attackList = __DoAreaAttackLostHP(attacker, curSkill, resultList, g_skillHurtList, tick)  | 
|   | 
|       | 
|     __DoAreaAttackResult(attacker, defender, curSkill, attackList, attackerHP, tick, isExSkill)  | 
|       | 
|     return True  | 
|   | 
| ## Ö´Ðа´°Ù·Ö±ÈȺÌå¿ÛѪ  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param resultList ¹¥»÷¶ÔÏóÁÐ±í  | 
| #  @param skillHurtList ÉËѪÁÐ±í  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ÎÞ  | 
| #  @remarks  | 
| def __DoAreaAttackLostHP(attacker, curSkill, resultList, skillHurtList, tick):  | 
|     attackList = []   #±»¹¥»÷¶ÔÏóÁÐ±í  | 
|       | 
|     checkComboOK = False  | 
|       | 
|     #Ö´Ðй¥»÷½á¹û  | 
|     for obj in resultList:  | 
|         callName = "%s_Attack_%s.%s" % (GetObjAttackName(attacker),  | 
|                                        GetObjAttackName(obj), "DoAttack")  | 
|           | 
|         callFunc = GameWorld.GetExecFunc(AttackLogic, callName)  | 
|           | 
|         if not callFunc:  | 
|             continue  | 
|           | 
|         if not checkComboOK:  | 
|             #¹¥»÷ǰÁ¬»÷¼ì²é  | 
|             SkillCommon.UpdateSkillCombo(attacker, curSkill, tick)  | 
|             checkComboOK = True  | 
|               | 
|         curObjMaxHp = GameObj.GetMaxHP(obj)  | 
|         rate = curSkill.GetEffect(0).GetEffectValue(0) / float(ChConfig.Def_MaxRateValue)  # ¿ÛѪµÄ°Ù·Ö±È  | 
|         lostHP = int(curObjMaxHp * rate)  | 
|           | 
|         callFunc(attacker, obj, curSkill, lostHP, 0, skillHurtList, tick)  | 
|           | 
|         attackList.append(obj)  | 
|       | 
|     return attackList  | 
|       | 
|       | 
| # Òý±¬ÊÓÒ°ÄÚµÄÖÖ×Ó  | 
| def AttackDetonateSeed(attacker, curSkill, seedTypeID, tick, owner=None):  | 
|     if not seedTypeID:  | 
|         return  | 
|     buffSkill = GameWorld.GetGameData().GetSkillBySkillID(seedTypeID)  | 
|     if not buffSkill:  | 
|         return  | 
|       | 
|     buffType = SkillCommon.GetBuffType(buffSkill)  | 
|       | 
|     if owner:  | 
|         ownerID, ownerType = owner.GetID(), owner.GetGameObjType()  | 
|     else:  | 
|         ownerID, ownerType = attacker.GetID(), attacker.GetGameObjType()  | 
|           | 
|     GameWorld.DebugLog("ownerID---%s-%s"%(ownerID, ownerType))  | 
|     #Çå¿ÕÉËѪÁÐ±í  | 
|     global g_skillHurtList  | 
|     g_skillHurtList.Clear()  | 
|     hurtPer = 0  | 
|       | 
|     attackerHP = GameObj.GetHP(attacker)  | 
|     attackList = []  | 
|     seeObjCount = attacker.GetInSightObjCount()  | 
|     for i in range(0, seeObjCount):  | 
|         seeObj = attacker.GetInSightObjByIndex(i)  | 
|           | 
|         #ÓпÉÄÜΪ¿Õ  | 
|         if seeObj == None :  | 
|             continue  | 
|   | 
|         seeObjType = seeObj.GetGameObjType()  | 
|           | 
|         #²»ÊÇÍæ¼Ò  | 
|         if seeObjType not in [IPY_GameWorld.gotPlayer, IPY_GameWorld.gotNPC] :  | 
|             continue  | 
|           | 
|         if seeObj.IsEmpty():  | 
|             continue  | 
|           | 
|         #ÒѾËÀÍö  | 
|         if GameObj.GetHP(seeObj) <= 0 :  | 
|             continue  | 
|           | 
|         #ÒþÉí  | 
|         if seeObj.GetVisible() == False:  | 
|             continue  | 
|           | 
|         tagObj = GameWorld.GetObj(seeObj.GetID(), seeObjType)  | 
|         if not tagObj:  | 
|             continue  | 
|           | 
|         buffTuple = SkillCommon.GetBuffManagerByBuffType(tagObj, buffType)  | 
|         #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö  | 
|         if buffTuple == ():  | 
|             continue  | 
|   | 
|         buffManager = buffTuple[0]  | 
|         buff = buffManager.FindBuff(seedTypeID)  | 
|         if not buff:  | 
|             continue  | 
|   | 
|         if buff.GetOwnerID() != ownerID or buff.GetOwnerType() != ownerType:  | 
|             # ·ÇËùÊôBUFF  | 
|             continue  | 
|           | 
|         if not hurtPer:  | 
|             curBuffSkill = buff.GetSkill()  | 
|       | 
|             hurtEffect = SkillCommon.GetSkillEffectByEffectID(curBuffSkill, ChConfig.Def_Skill_Effect_BoomSeedHurt)  | 
|             if not hurtEffect:  | 
|                   | 
|                 continue  | 
|             hurtPer = hurtEffect.GetEffectValue(0)*1.0/ChConfig.Def_MaxRateValue  # µ¥²ãÉ˺¦  | 
|           | 
|         # É˺¦³ËÒÔ²ã  | 
|         skillPercent = hurtPer * max(buff.GetLayer(), 1)  | 
|         DoAttackSingle(attacker, tagObj, curSkill, 0, skillPercent, tick)  | 
|           | 
|         attackList.append(tagObj)  | 
|           | 
|     # ½áÊø´¦Àí  | 
|     DoAttackSuccessEx(attacker, attackerHP, None, curSkill, tick)  | 
|   | 
|     for defObj in attackList:  | 
|                           | 
|         if AttackCommon.GetIsDead(defObj):  | 
|             continue  | 
|   | 
|         DoLogic_AttackResult(attacker, defObj, curSkill, tick)  | 
|   | 
|     return True  | 
|       | 
|       | 
|       | 
| #µ¥Ò»¶ÔÏó¼ÆËã¹¥»÷É˺¦£¬ÈçÓÃÓÚÖÖ×Ó±¬Õ¨  | 
| def DoAttackSingle(attacker, obj, curSkill, skillEnhance, skillPercent, tick):  | 
|     callName = "%s_Attack_%s.%s" % (GetObjAttackName(attacker),  | 
|                                    GetObjAttackName(obj), "DoAttack")  | 
|       | 
|     callFunc = GameWorld.GetExecFunc(AttackLogic, callName)  | 
|       | 
|     if not callFunc:  | 
|         return  | 
|       | 
|     callFunc(attacker, obj, curSkill, skillEnhance, skillPercent, g_skillHurtList, tick)  | 
|       | 
|     return obj  | 
|   | 
|   | 
|   | 
| ## È¡Ïû±»ÇøÓòÄÚ¶ÔÏó¶ÔÖÅÑ¡ÖÐ  | 
| #  @param attacker ¹¥»÷ÕßʵÀý  | 
| #  @param curSkill ¼¼ÄÜʵÀý  | 
| #  @param srcPosX Êͷż¼ÄÜÆðµã×ø±êX  | 
| #  @param srcPosY Êͷż¼ÄÜÆðµã×ø±êY  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return ÎÞ  | 
| def CancelAreaActioned(attacker, curSkill, srcPosX, srcPosY, tick):  | 
|   | 
|     #È¡µÃÊÜЧ¹ûÄ¿±ê¶ÓÁÐ  | 
|     resultList = __GetAreaAtackObj(attacker, curSkill, srcPosX, srcPosY, tick, CheckTagIsBeInfection)  | 
|   | 
|     # Í¨ÖªÈ¡ÏûÑ¡ÖÐÍæ¼ÒÁÐ±í  | 
|     #GameWorld.DebugLog("resultList=%s" % resultList)  | 
|       | 
|     for curTag in resultList:  | 
|           | 
|         # ²»ÊÇÍæ¼Ò²»´¦Àí  | 
|         if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|             continue  | 
|           | 
|         curTagID = curTag.GetPlayerID()  | 
|         curActionObj = curTag.GetActionObj()  | 
|         if not curActionObj:  | 
|             #GameWorld.DebugLog("curTagID=%s, not actionObj" % curTagID)  | 
|             continue  | 
|           | 
|         # ¶ÔÖÅÄ¿±ê²»ÊÇÍæ¼Ò²»´¦Àí  | 
|         if curActionObj.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|             #GameWorld.DebugLog("curTagID=%s, actionObj not gotPlayer" % curTagID)  | 
|             continue  | 
|           | 
|         actionPlayer = GameWorld.GetObjDetail(curActionObj)  | 
|           | 
|         # Èç¹ûÑ¡ÖÐÕßÊÇÊͷż¼ÄÜÍæ¼Ò£¬ÔòÈ¡Ïû¶ÔÆäÑ¡ÖÐ  | 
|         if actionPlayer.GetPlayerID() == attacker.GetPlayerID():  | 
|             curTag.SetActionObj(None)  | 
|             # ·â°ü֪ͨ¶Ô·½£¬È¡ÏûÑ¡ÖÐ  | 
|             PlayerControl.Sync_SelectObj(curTag, IPY_GameWorld.gotPlayer, actionPlayer.GetPlayerID(), 0)  | 
|     return  | 
|   | 
| # Íæ¼Ò·ÇÖ±½ÓÊͷŵļ¼Äܳɹ¦°üÓÉ´Ë·â°ü´¦Àí£¬Âß¼Àà0614 0604  | 
| # attacker.View_UseSkillPos(skillID, battleType, useSkillPosX, useSkillPosY, g_skillHurtList)  | 
| def Sync_SkillHurtList(curPlayer, skillID, posX, posY, skillHurtList):  | 
|     if curPlayer.GetGameObjType() != IPY_GameWorld.gotPlayer:  | 
|         return  | 
|     sendPack = ChPyNetSendPack.tagMCSkillHurtList()  | 
|     sendPack.Clear()  | 
|     sendPack.ObjID = curPlayer.GetID()  | 
|     sendPack.ObjType = IPY_GameWorld.gotPlayer  | 
|     sendPack.SkillID = skillID  | 
|     sendPack.PosX = posX  | 
|     sendPack.PosY = posY  | 
|       | 
|     for i in range(skillHurtList.GetHurtCount()):  | 
|         hurtObj = skillHurtList.GetHurtAt(i)  | 
|         hurtList = ChPyNetSendPack.tagSkillPosHurtObj()  | 
|         hurtList.ObjType = hurtObj.GetObjType()  | 
|         hurtList.ObjID = hurtObj.GetObjID()  | 
|         hurtList.AttackType = hurtObj.GetAttackType()  | 
|         hurtList.HurtHP = hurtObj.GetHurtHP()  | 
|         hurtList.CurHP = hurtObj.GetCurHP()  | 
|         hurtList.CurHPEx = hurtObj.GetCurHPEx()  | 
|           | 
|         sendPack.HurtList.append(hurtList)  | 
|           | 
|     sendPack.HurtCount = len(sendPack.HurtList)  | 
|   | 
|     PlayerControl.PyNotifyAll(curPlayer, sendPack, notifySelf=True, notifyCnt=0)  | 
|   | 
|   | 
| # pyÖØÏÖView_UseSkillPosЧ¹û£¬¶ÔµØÍ¨Öª£¬Ö»ÓÃÓÚÍæ¼Ò  | 
| def PYView_UseSkillPos(attacker, skillID, battleType, useSkillPosX, useSkillPosY, skillHurtList, notifySelf):  | 
|     #===========================================================================  | 
|     # C++ ´Ë´¦´úÂëPYÒÑ´¦Àí£¬Ôݲ»¼ÓÈë  | 
|     # SetAttackTick(GetGameWorldManager()->GetTick());  | 
|     # ChangeAction(paAttack);  | 
|     # m_LastBattleTick = GetGameWorldManager()->GetTick();  | 
|     #===========================================================================  | 
|     sendPack = ChNetSendPack.tagUseSkillPos()  | 
|     sendPack.Clear()  | 
|     sendPack.ObjID = attacker.GetID()  | 
|     sendPack.ObjType = attacker.GetGameObjType()  | 
|     sendPack.BattleType = battleType  | 
|     sendPack.SkillID = skillID  | 
|     sendPack.PosX = useSkillPosX  | 
|     sendPack.PosY = useSkillPosY  | 
|       | 
|     for i in range(skillHurtList.GetHurtCount()):  | 
|         hurtObj = skillHurtList.GetHurtAt(i)  | 
|         hurtList = ChNetSendPack.tagSkillPosHurtObj()  | 
|         hurtList.ObjType = hurtObj.GetObjType()  | 
|         hurtList.ObjID = hurtObj.GetObjID()  | 
|         hurtList.AttackType = hurtObj.GetAttackType()  | 
|         hurtList.HurtHP = hurtObj.GetHurtHP()  | 
|         hurtList.CurHP = hurtObj.GetCurHP()  | 
|         hurtList.CurHPEx = hurtObj.GetCurHPEx()  | 
|           | 
|         sendPack.HurtList.append(hurtList)  | 
|           | 
|     sendPack.HurtCount = len(sendPack.HurtList)  | 
|     if attacker.GetGameObjType() == IPY_GameWorld.gotPlayer:  | 
|         PlayerControl.PyNotifyAll(attacker, sendPack, notifySelf, -1)  | 
|     else:  | 
|         attacker.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())  | 
|     return  | 
|   | 
| # Íæ¼Ò×ÔÉíÒªÌØÊâ¹ýÂË֪ͨ  | 
| def PYView_UseSkillPos_NotifySelf(curPlayer, skillID, battleType, useSkillPosX, useSkillPosY, skillHurtList):  | 
|     #===========================================================================  | 
|     # C++ ´Ë´¦´úÂëPYÒÑ´¦Àí£¬Ôݲ»¼ÓÈë  | 
|     # SetAttackTick(GetGameWorldManager()->GetTick());  | 
|     # ChangeAction(paAttack);  | 
|     # m_LastBattleTick = GetGameWorldManager()->GetTick();  | 
|     #===========================================================================  | 
|     useSkillData = curPlayer.GetUseSkill()  | 
|     useSkillID = useSkillData.GetSkillID() if useSkillData else 0  | 
|       | 
|     sendPack = ChNetSendPack.tagUseSkillPos()  | 
|     sendPack.Clear()  | 
|     sendPack.ObjID = curPlayer.GetID()  | 
|     sendPack.ObjType = IPY_GameWorld.gotPlayer  | 
|     sendPack.BattleType = battleType  | 
|     sendPack.SkillID = skillID  | 
|     sendPack.PosX = useSkillPosX  | 
|     sendPack.PosY = useSkillPosY  | 
|       | 
|     for i in range(skillHurtList.GetHurtCount()):  | 
|         hurtObj = skillHurtList.GetHurtAt(i)  | 
|         # ¿Í»§¶Ë¼ÆËãÉ˺¦²»Í¨Öª×Ô¼º  | 
|         if useSkillID == skillID and SkillShell.isClientHurtValue(hurtObj.GetObjID(), hurtObj.GetObjType()):  | 
|             continue  | 
|         hurtList = ChNetSendPack.tagSkillPosHurtObj()  | 
|         hurtList.ObjType = hurtObj.GetObjType()  | 
|         hurtList.ObjID = hurtObj.GetObjID()  | 
|         hurtList.AttackType = hurtObj.GetAttackType()  | 
|         hurtList.HurtHP = hurtObj.GetHurtHP()  | 
|         hurtList.CurHP = hurtObj.GetCurHP()  | 
|         hurtList.CurHPEx = hurtObj.GetCurHPEx()  | 
|           | 
|         sendPack.HurtList.append(hurtList)  | 
|           | 
|     sendPack.HurtCount = len(sendPack.HurtList)  | 
|     NetPackCommon.SendFakePack(curPlayer, sendPack)  | 
|     return  | 
|   |