| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package PlayerAction  | 
| #  | 
| # @todo:Íæ¼Ò»î¶¯Ä£¿é  | 
| # @author hxp  | 
| # @date 2013-12-23 14:00  | 
| # @version 2.0  | 
| #  | 
| # @change: "2014-10-29 15:30" hxp Ôö¼Ó½ÚÈÕ¶Ò»»ÎïÆ·»î¶¯  | 
| # @change: "2014-12-03 21:30" hxp ¸ù¾Ýʱ¼ä»î¶¯Ìí¼ÓÍæ¼Òbuff  | 
| # @change: "2014-12-06 22:30" hxp »î¶¯buff״̬±ä¸ü  | 
| # @change: "2015-01-06 13:30" hxp Ôö¼ÓÕÒ²»µ½buff¼¼ÄÜÊý¾Ý·À´í; Ôö¼Ó¶Ò»»ÎïÆ·¹ã²¥Ö§³Ö  | 
| # @change: "2015-01-06 21:00" hxp Ôö¼Ó¸ù¾Ý»î¶¯keyÖØÖÃÎïÆ·¶Ò»»¼Ç¼  | 
| # @change: "2015-03-21 21:30" hxp Ôö¼Ó¸öÈ˵ôÂäÖÜÆÚ¿ØÖÆ  | 
| # @change: "2015-04-15 19:30" hxp Ôö¼Ó±³°üÖиöÊýÏÞÖÆ  | 
| # @change: "2015-04-28 16:00" hxp ÎïÆ·¶Ò»»Ö§³Ö¶Ò»»¶à¸öÎïÆ·  | 
| # @change: "2016-08-30 21:30" hxp È«·þ¹ã²¥ÓÅ»¯  | 
| # @change: "2016-09-19 10:30" hxp È«·þÍæ¼ÒÈËÊý»ñÈ¡·½Ê½ÐÞ¸Ä  | 
| #  | 
| # ÏêϸÃèÊö: Íæ¼Ò»î¶¯Ä£¿é  | 
| #  | 
| #---------------------------------------------------------------------  | 
| #"""Version = 2016-09-19 10:30"""  | 
| #---------------------------------------------------------------------  | 
|   | 
| import ReadChConfig  | 
| import GameWorld  | 
| import PlayerControl  | 
| import ItemCommon  | 
| import ItemControler  | 
| import IPY_GameWorld  | 
| import ChPyNetSendPack  | 
| import DataRecordPack  | 
| import NetPackCommon  | 
| import ShareDefine  | 
| import SkillCommon  | 
| import SkillShell  | 
| import BuffSkill  | 
| import ChConfig  | 
|   | 
| import math  | 
| import time  | 
|   | 
| #----------------------------------------------------------------------  | 
|   | 
| # ½±ÀøÐÅÏ¢Ë÷Òý¶¨Òå  | 
| (  | 
| Def_AwardInfo_PlayerMinLV, # ²ÎÓë»î¶¯Íæ¼Ò×îµÍµÈ¼¶ÏÞÖÆ  | 
| Def_AwardInfo_DropRate, # µôÂä»î¶¯ÎïÆ·¸ÅÂÊ  | 
| Def_AwardInfo_RandomItemList, # Ëæ»úÎïÆ·ÁÐ±í  | 
| Def_AwardInfo_ItemInfoDict, # ÎïÆ·Ïà¹ØÐÅÏ¢  | 
| ) = range(4)  | 
|   | 
| # ÎïÆ·ÐÅÏ¢Ë÷Òý¶¨Òå  | 
| (  | 
| Def_ItemInfo_IsBind, # ÊÇ·ñ°ó¶¨  | 
| Def_ItemInfo_Circle, # µôÂäÖÜÆÚ£¬Ãë  | 
| Def_ItemInfo_CircleSelf, # ¸öÈ˵ôÂäÖÜÆÚ£¬Ãë  | 
| Def_ItemInfo_MaxCnt, # ±³°üÖÐ×î´ó¸öÊý  | 
| ) = range(4)  | 
|   | 
| ##»ñÈ¡»÷ɱNPC»î¶¯ÎïÆ·½±Àø  | 
| # @param lastTimeHurtObj ²¹µ¶Õß(Íæ¼Ò£¬×é¶Ó)  | 
| # @param curNPC »÷ɱµÄNPC  | 
| # @return None  | 
| def GetAwardOnKillNPC(lastTimeHurtObj, curNPC):   | 
|     actionAward = ReadChConfig.GetEvalChConfig("PlayerActionAward")  | 
|     if not actionAward:  | 
|         GameWorld.ErrLog("Info is null! Please check PlayerActionAward.txt!")  | 
|         return  | 
|       | 
|     gameWorldMgr = GameWorld.GetGameWorld()  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     for keyInfo, awardInfo in actionAward.items():  | 
|           | 
|         if len(keyInfo) != 2:  | 
|             GameWorld.ErrLog("keyInfo=%s len!=2 error! Check PlayerActionAward.txt!" % str(keyInfo))  | 
|             continue  | 
|           | 
|         if gameWorldMgr.GetGameWorldDictByKey(keyInfo[0]) != keyInfo[1]:  | 
|             #GameWorld.DebugLog("keyInfo[0]=%s,keyInfo[1]=%s" % (keyInfo[0], keyInfo[1]))  | 
|             continue  | 
|           | 
|         if len(awardInfo) != 4:  | 
|             GameWorld.ErrLog("keyInfo=%s awardInfo len!=4 error! Check PlayerActionAward.txt!" % str(keyInfo))  | 
|             continue  | 
|           | 
|         curPlayer, curTeam = lastTimeHurtObj  | 
|           | 
|         #²¹µ¶ÊÇÍæ¼Ò  | 
|         if curPlayer:  | 
|             __DoPlayerGetActionAward(keyInfo, curPlayer, curNPC, awardInfo, tick)  | 
|           | 
|         #²¹µ¶ÊÇ×é¶Ó  | 
|         elif curTeam:  | 
|             #¶ÓÔ±ÁÐ±í  | 
|             playerlist = PlayerControl.GetAreaTeamMember(curTeam, curNPC.GetPosX(), curNPC.GetPosY())      | 
|             #±éÀú×é¶Ó¶ÓÔ±½øÐзÖÏíÁ¬Õ¶ÊýºÍ¾Ñé¼Ó³É  | 
|             for curPlayer in playerlist:  | 
|                 __DoPlayerGetActionAward(keyInfo, curPlayer, curNPC, awardInfo, tick)  | 
|                   | 
|     return  | 
|   | 
|   | 
| ##¶Ôµ¥¸öÍæ¼Ò½øÐл÷ɱNPC»î¶¯Áì½±´¦Àí  | 
| # @param keyInfo »î¶¯keyÐÅÏ¢  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curNPC »÷ɱµÄNPC  | 
| # @param awardInfo ½±ÀøÐÅÏ¢  | 
| # @param tick Ê±¼ä  | 
| # @return None  | 
| def __DoPlayerGetActionAward(keyInfo, curPlayer, curNPC, awardInfo, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|       | 
|     if curPlayer.GetLV() < awardInfo[Def_AwardInfo_PlayerMinLV]:  | 
|         #GameWorld.DebugLog("__DoPlayerGetActionAward playerLV Limit!")  | 
|         return  | 
|       | 
|     npcLV = curNPC.GetLV()  | 
|     curPlayerLV = curPlayer.GetLV()  | 
|     #GameWorld.DebugLog("curPlayerLV=%s" % curPlayerLV)  | 
|     modulus = 1  | 
|     rate = awardInfo[Def_AwardInfo_DropRate] * modulus  | 
|     #GameWorld.DebugLog("__DoPlayerGetActionAward modulus=%s,rate=%s" % (modulus, rate))  | 
|     if not GameWorld.CanHappen(rate):  | 
|         return  | 
|       | 
|     itemID = GameWorld.GetResultByRandomList(awardInfo[Def_AwardInfo_RandomItemList])  | 
|       | 
|     itemInfoDict = awardInfo[Def_AwardInfo_ItemInfoDict]  | 
|     if not itemInfoDict:  | 
|         return  | 
|       | 
|     itemInfo = itemInfoDict.get(itemID, [])  | 
|     if not itemInfo:  | 
|         GameWorld.ErrLog("itemInfo Error! Check PlayerActionAward.txt! itemID=%s,awardInfo=%s,"   | 
|                                                         % (itemID, str(awardInfo)))  | 
|         return  | 
|       | 
|     #GameWorld.DebugLog("__DoPlayerGetActionAward itemID=%s,itemInfo=%s" % (itemID, str(itemInfo)))  | 
|     # ¼ì²éµôÂäÖÜÆÚ  | 
|     circleTime = itemInfo[Def_ItemInfo_Circle]  | 
|     if circleTime > 0:  | 
|         # keyName_sign_itemID  | 
|         lastDropTickKey = "%s_%s_%d" % (keyInfo[0], keyInfo[1], itemID)  | 
|         gameWorldMgr = GameWorld.GetGameWorld()  | 
|         lastDropTick = gameWorldMgr.GetGameWorldDictByKey(lastDropTickKey)  | 
|         # µôÂäÖÜÆÚÏÞÖÆ  | 
|         if tick - lastDropTick < circleTime * 1000:  | 
|             return  | 
|         #GameWorld.DebugLog("lastDropTickKey=%s,lastDropTick=%s,tick=%s,circleTime=%s,passTime=%s"   | 
|         #                % (lastDropTickKey, lastDropTick, tick, circleTime * 1000, tick - lastDropTick))  | 
|         GameWorld.GetGameWorld().SetGameWorldDict(lastDropTickKey, tick)  | 
|           | 
|     # ¸öÈ˵ôÂäÖÜÆÚ  | 
|     if len(itemInfo) > Def_ItemInfo_CircleSelf:  | 
|         circleTimeSelf = itemInfo[Def_ItemInfo_CircleSelf]  | 
|         if circleTimeSelf > 0:  | 
|             lastDropTimeSelfKey = ChConfig.Def_PDict_ActionItemDropTime % itemID  | 
|             lastDropTime = curPlayer.NomalDictGetProperty(lastDropTimeSelfKey)  | 
|             curTime = int(time.time())  | 
|             if curTime - lastDropTime < circleTimeSelf:  | 
|                 return  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, lastDropTimeSelfKey, curTime)  | 
|       | 
|     # ±³°üÖиöÊýÏÞÖÆ  | 
|     if len(itemInfo) > Def_ItemInfo_MaxCnt:  | 
|         packMaxItemCnt = itemInfo[Def_ItemInfo_MaxCnt]  | 
|         itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)  | 
|         hasEnough = ItemCommon.GetItem_FromPack_ByID(itemID, itemPack, packMaxItemCnt)[0]  | 
|         if hasEnough:  | 
|             #GameWorld.DebugLog("»î¶¯ÎïÆ·ÒÑ´ïµ½±³°ü×î´ó¸öÊý=%s£¬²»ÄÜÔÙµôÁË£¡" % packMaxItemCnt)  | 
|             return  | 
|       | 
|     # ¸øÎïÆ·  | 
|     giveItem = ItemCommon.CreateSingleItem(itemID)  | 
|           | 
|     if not giveItem:  | 
|         GameWorld.ErrLog('__DoPlayerGetActionAward giveItemErr=%s' % (itemID), playerID)  | 
|         return  | 
|   | 
|     ItemControler.SetItemIsBind(giveItem, itemInfo[Def_ItemInfo_IsBind])  | 
|     itemControler = ItemControler.PlayerItemControler(curPlayer)  | 
|     if not itemControler.PutInItem(IPY_GameWorld.rptItem, giveItem):  | 
|         giveItem.Clear()  | 
|         return  | 
|       | 
|     #PlayerControl.NotifyCode(curPlayer, "ObtainRes01", [itemID, 1])   | 
|     return  | 
|   | 
|   | 
| ##-----------------------------»î¶¯¶Ò»»ÎïÆ·-------------------------------  | 
|   | 
| # »î¶¯¶Ò»»ÅäÖÃË÷Òý  | 
| (  | 
| Def_ExcCfg_GameWorldActionKey, # ¶ÔÓ¦»î¶¯key  | 
| Def_ExcCfg_ActionState, # ¿É¶Ò»»ÎïÆ·µÄ»î¶¯×´Ì¬  | 
| Def_ExcCfg_RecordResetWay, # ¶Ò»»´ÎÊýÖØÖ÷½Ê½ 0-»î¶¯Öв»ÖØÖÃ, 1-»î¶¯ÖйýÌìÖØÖà  | 
| Def_ExcCfg_ItemDict, # ¶Ò»»ÎïÆ·ÐÅÏ¢  | 
| ) = range(4)  | 
|   | 
|   | 
| # ¶Ò»»ÎïÆ·ÐÅÏ¢ÅäÖÃË÷Òý  | 
| (  | 
| Def_ExcItem_RecordMark, # ¶Ò»»¼Ç¼±àºÅ±êʶ, ´Ó0¿ªÊ¼ÒÀ´ÎµÝÔö  | 
| Def_ExcItem_GetCnt, # µ¥´Î¶Ò»»¿É»ñµÃµÄ¸öÊý  | 
| Def_ExcItem_MaxCnt, # ×î´ó¿É¶Ò»»´ÎÊý  | 
| Def_ExcItem_CostItem, # ÏûºÄ²ÄÁÏÁбí[(ÏûºÄÎïÆ·ID,¸öÊý),(ÏûºÄÎïÆ·ID,¸öÊý),...]  | 
| Def_ExcItem_CostMoney, # [ÏûºÄ»õ±ÒÀàÐÍ, »õ±ÒÊý]  | 
| Def_ExcItem_NotifyMark, # È«·þ¹ã²¥mark, ²ÎÊý[Íæ¼ÒÃû,itemID,itemID]  | 
| Def_ExcItem_NeedSpace, # ËùÐè¸ñ×ÓÊý  | 
| Def_ExcItem_GiveItem, # ¸øÓèµÄÎïÆ·Áбí, Èç¹û¸ÃÅäÖÿÕÔòĬÈÏÈ¡key×÷ΪitemID  | 
| ) = range(8)  | 
|   | 
|   | 
| ## ½ÚÈÕ»î¶¯Íæ¼ÒµÇ¼  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def ActionOnLogin(curPlayer):  | 
|     actionItemExchangeInfo = ReadChConfig.GetEvalChConfig("ActionItemExchange")  | 
|       | 
|     for actionKey, excCfg in actionItemExchangeInfo.items():  | 
|         gwDictKey = excCfg[Def_ExcCfg_GameWorldActionKey]  | 
|         curState = GameWorld.GetGameWorld().GetGameWorldDictByKey(gwDictKey)  | 
|           | 
|         # Èç¹ûÊǶһ»»î¶¯ÖУ¬Í¬²½¶Ò»»´ÎÊý  | 
|         if curState == excCfg[Def_ExcCfg_ActionState]:  | 
|             Sync_ExcItemCnt(curPlayer, actionKey)  | 
|               | 
|     DoPlayerActionBuffOnLogin(curPlayer)  | 
|     return  | 
|   | 
| ## ½ÚÈջ¹ýÌì  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def ActionOnDay(curPlayer):  | 
|     actionItemExchangeInfo = ReadChConfig.GetEvalChConfig("ActionItemExchange")  | 
|       | 
|     for actionKey, excCfg in actionItemExchangeInfo.items():  | 
|         gwDictKey = excCfg[Def_ExcCfg_GameWorldActionKey]  | 
|         curState = GameWorld.GetGameWorld().GetGameWorldDictByKey(gwDictKey)  | 
|           | 
|         # ²»Êǿɶһ»ÎïÆ·»î¶¯ÆÚ¼ä£¬ÖØÖöһ»¼Ç¼  | 
|         if curState != excCfg[Def_ExcCfg_ActionState]:  | 
|             GameWorld.DebugLog("·Ç»î¶¯ÖУ¬ÖØÖûÎïÆ·¶Ò»»Êý¾ÝactionKey=%s" % actionKey)  | 
|             __ResetExcRecord(curPlayer, actionKey, excCfg, False)  | 
|         else:  | 
|             resetWay = excCfg[Def_ExcCfg_RecordResetWay]  | 
|             # »î¶¯ÖйýÌìÖØÖöһ»´ÎÊýµÄ  | 
|             if resetWay == 1:  | 
|                 GameWorld.DebugLog("»î¶¯ÖУ¬¹ýÌìÖØÖûÎïÆ·¶Ò»»Êý¾ÝactionKey=%s" % actionKey)  | 
|                 __ResetExcRecord(curPlayer, actionKey, excCfg, True)  | 
|       | 
|     return  | 
|   | 
|   | 
| ## ÖØÖöһ»´ÎÊý¼Ç¼  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def __ResetExcRecord(curPlayer, actionKey, excCfg, isNotify):  | 
|     itemDict = excCfg[Def_ExcCfg_ItemDict]  | 
|     for itemInfo in itemDict.values():  | 
|         recordMark = itemInfo[Def_ExcItem_RecordMark]  | 
|         excCntKey = ChConfig.Def_PDict_ExcActionItemCnt % (actionKey, recordMark)  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, excCntKey, 0)  | 
|       | 
|     if isNotify:  | 
|         Sync_ExcItemCnt(curPlayer, actionKey)  | 
|     return  | 
|   | 
| ## ¸ù¾Ý»î¶¯keyÖØÖöһ»´ÎÊý¼Ç¼  | 
| #  @param curPlayer  | 
| #  @param keyList [keyÁбí]  | 
| #  @return None  | 
| def ResetExcRecordByKey(curPlayer, keyList, isNotify=False):  | 
|       | 
|     if not keyList:  | 
|         return  | 
|       | 
|     actionItemExchangeInfo = ReadChConfig.GetEvalChConfig("ActionItemExchange")  | 
|       | 
|     for actionKey, excCfg in actionItemExchangeInfo.items():  | 
|           | 
|         if actionKey in keyList:  | 
|             __ResetExcRecord(curPlayer, actionKey, excCfg, isNotify)  | 
|       | 
|     return  | 
|   | 
| ##// AB 06 »î¶¯ÎïÆ·¶Ò»» #tagCMExchangeActionItem  | 
| #  | 
| #struct     tagCMExchangeActionItem  | 
| #  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        ActionKeyLen;   | 
| #    char        ActionKey[ActionKeyLen];  | 
| #    DWORD        ItemID; // ¶Ò»»µÄÄ¿±êÎïÆ·ID  | 
| #    WORD        ExcCnt; // ¶Ò»»¸öÊý£¬Ä¬ÈÏ1¸ö  | 
| #};  | 
| ## »î¶¯ÎïÆ·¶Ò»»  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def OnExchangeActionItem(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     if not curPlayer:  | 
|         return  | 
|       | 
|     actionKey = clientData.ActionKey  | 
|     itemID = clientData.ItemID  | 
|     excCnt = clientData.ExcCnt  | 
|     excCnt = max(1, excCnt)  | 
|       | 
|     GameWorld.DebugLog("»î¶¯¶Ò»»ÎïÆ·actionKey=%s,itemID=%s,excCnt=%s" % (actionKey, itemID, excCnt))  | 
|     actionItemExchangeInfo = ReadChConfig.GetEvalChConfig("ActionItemExchange")  | 
|       | 
|     if actionKey not in actionItemExchangeInfo:  | 
|         GameWorld.ErrLog("    ActionItemExchange.txtÎ޸û£¡actionKey=%s" % (actionKey))  | 
|         return  | 
|       | 
|     excCfg = actionItemExchangeInfo[actionKey]  | 
|     gwDictKey = excCfg[Def_ExcCfg_GameWorldActionKey]  | 
|     curState = GameWorld.GetGameWorld().GetGameWorldDictByKey(gwDictKey)  | 
|     exchangeState = excCfg[Def_ExcCfg_ActionState]  | 
|     if curState != exchangeState:  | 
|         GameWorld.DebugLog("    ·Ç¶Ò»»ÎïÆ·ÆÚ¼ä£¬²»¿É¶Ò»»£¡curState=%s,exchangeState=%s"   | 
|                            % (curState, exchangeState))  | 
|         return  | 
|       | 
|     itemDict = excCfg[Def_ExcCfg_ItemDict]  | 
|       | 
|     if itemID not in itemDict:  | 
|         GameWorld.ErrLog("    ActionItemExchange.txtδÅäÖöһ»¸ÃÎïÆ·¶Ò»»ÐÅÏ¢£¡actionKey=%s,itemID=%s"   | 
|                          % (actionKey, itemID))  | 
|         return  | 
|       | 
|     itemInfo = itemDict[itemID]  | 
|           | 
|     recordMark = itemInfo[Def_ExcItem_RecordMark]  | 
|     getCnt = itemInfo[Def_ExcItem_GetCnt] # µ¥´Î¶Ò»»¿É»ñµÃ¸öÊý  | 
|     maxCnt = itemInfo[Def_ExcItem_MaxCnt] # ×î´ó¶Ò»»´ÎÊý£¬0Ϊ²»ÏÞÖÆ  | 
|     costItemList = itemInfo[Def_ExcItem_CostItem]  | 
|     costMoneyInfo = itemInfo[Def_ExcItem_CostMoney]  | 
|     notifyMark = itemInfo[Def_ExcItem_NotifyMark]  | 
|     needSpace = itemInfo[Def_ExcItem_NeedSpace]  | 
|     giveItemList = itemInfo[Def_ExcItem_GiveItem]  | 
|       | 
|     excCntKey = ChConfig.Def_PDict_ExcActionItemCnt % (actionKey, recordMark)  | 
|     exchangeCnt = curPlayer.NomalDictGetProperty(excCntKey) # ÒѶһ»´ÎÊý  | 
|       | 
|     if maxCnt > 0 and exchangeCnt + excCnt > maxCnt:  | 
|         GameWorld.DebugLog("    ¶Ò»»´ÎÊý²»×㣬²»¿É¶Ò»»£¡ÒѶһ»=%s,Òª¶Ò»»=%s,×î´ó=%s,"   | 
|                            % (exchangeCnt, excCnt, maxCnt))  | 
|         return  | 
|       | 
|     packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem)  | 
|     #ÑéÖ¤±³°ü¿Õ¼ä  | 
|     if needSpace > packSpace:  | 
|         PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_998371")  | 
|         return  | 
|       | 
|     needMoney = 0  | 
|     if costMoneyInfo:  | 
|         moneyType, needMoney = costMoneyInfo  | 
|         needMoney = needMoney * excCnt  | 
|         if not PlayerControl.HaveMoney(curPlayer, moneyType, needMoney):  | 
|             GameWorld.DebugLog("    »õ±Ò²»×ã moneyType=%s,needMoney=%s" % (moneyType, needMoney))  | 
|             return  | 
|           | 
|     costItemCntDict = {} # ÏûºÄÎïÆ·×ܸöÊý×Öµä  | 
|     for costItemID, costCnt in costItemList:  | 
|         costItemCntDict[costItemID] = costCnt * excCnt # µ¥´ÎÏûºÄ¸öÊý*¶Ò»»´ÎÊý  | 
|       | 
|     delItemInfoList, findItemIsBind, lackItemCntDict = __GetCostItem(curPlayer, costItemCntDict)  | 
|       | 
|     if lackItemCntDict:  | 
|         GameWorld.DebugLog("    ¶Ò»»²ÄÁϲ»×㣬»¹Ðè %s" % str(lackItemCntDict))  | 
|         return  | 
|   | 
|     # Ö§¸¶ËùÐè»õ±Ò  | 
|     if needMoney > 0:  | 
|         infoDict = {ChConfig.Def_Cost_Reason_SonKey:"%s_%s" % (actionKey, itemID)}  | 
|         PlayerControl.PayMoney(curPlayer, moneyType, needMoney, ChConfig.Def_Cost_ExchangeActionItem, infoDict)  | 
|           | 
|     # ¿Û³ý¸½¼ÓÎïÆ·  | 
|     for item, delCnt in delItemInfoList:  | 
|         ItemCommon.DelItem(curPlayer, item, delCnt, True, "ExchangeActionItem")     | 
|       | 
|     # ¸üжһ»´ÎÊý  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, excCntKey, exchangeCnt + excCnt)  | 
|     Sync_ExcItemCnt(curPlayer, actionKey)  | 
|       | 
|     notifyItemID = 0  | 
|     if not giveItemList:  | 
|         giveItemList = [(itemID, getCnt)]  | 
|         notifyItemID = itemID  | 
|           | 
|     for giveItemID, giveCnt in giveItemList:  | 
|         if not notifyItemID:  | 
|             notifyItemID = giveItemID  | 
|         giveTotalCnt = giveCnt * excCnt  | 
|         if not ItemControler.GivePlayerItem(curPlayer, giveItemID, giveTotalCnt, findItemIsBind,  | 
|                                             [IPY_GameWorld.rptItem, IPY_GameWorld.rptAnyWhere]):  | 
|             GameWorld.ErrLog("OnExchangeActionItem(), give itemID:%s,count:%s fail!"   | 
|                              % (giveItemID, giveTotalCnt), curPlayer.GetPlayerID())  | 
|         # Äú»ñµÃÁËÎïÆ·XX XX¸ö  | 
|         #PlayerControl.NotifyCode(curPlayer, "ObtainRes01", [giveItemID, giveTotalCnt])  | 
|       | 
|     # È«·þ¹ã²¥  | 
|     if notifyMark and notifyItemID:  | 
|         PlayerControl.WorldNotify(0, notifyMark, [curPlayer.GetPlayerName(), notifyItemID, notifyItemID])  | 
|           | 
|     # ¶Ò»»Á÷Ïò  | 
|     addDataDict = {"ActionKey":actionKey, "ExchangeCnt":excCnt, "ExchangeItemIDKey":itemID}  | 
|     DataRecordPack.DR_FuncGiveItem(curPlayer, "ExchangeItem", addDataDict)  | 
|            | 
|     GameWorld.DebugLog("    OK!»ñµÃgiveItemList=%s * excCnt=%s" % (giveItemList, excCnt))  | 
|     return  | 
|   | 
| ## »ñÈ¡¶Ò»»ÎïÆ·Ðè¿Û³ýµÄÎïÆ·ÐÅÏ¢  | 
| #  @param curPlayer  | 
| #  @param costItemCntDict: ÏûºÄ²ÄÁϸöÊý×Öµä  | 
| #  @return ·µ»ØÁбí[Òª¿Û³ýµÄÎïÆ·ÐÅÏ¢, ËùÕҵIJÄÁÏÊÇ·ñÓа󶨵Ä, ²»×ãµÄ¸öÊýÐÅÏ¢×Öµä]  | 
| def __GetCostItem(curPlayer, costItemCntDict):  | 
|     findItemIsBind = False  | 
|     delItemInfoList = []  | 
|   | 
|     itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)  | 
|     for i in range(itemPack.GetCount()):  | 
|         curItem = itemPack.GetAt(i)  | 
|         #¹ýÂ˲»·ûºÏÆäËûÌõ¼þµÄÎïÆ·  | 
|         if not ItemCommon.CheckItemCanUse(curItem):  | 
|             continue  | 
|           | 
|         itemID = curItem.GetItemTypeID()  | 
|         if itemID not in costItemCntDict:  | 
|             continue  | 
|                   | 
|         #²éÕÒµ½µÄÎïÆ·Îª°ó¶¨ÎïÆ·  | 
|         if not findItemIsBind and curItem.GetIsBind():  | 
|             findItemIsBind = True  | 
|           | 
|         needCnt = costItemCntDict[itemID]  | 
|         itemCount = curItem.GetCount()  | 
|           | 
|         #²»¹»  | 
|         if needCnt > itemCount:  | 
|             needCnt -= itemCount  | 
|             costItemCntDict[itemID] = needCnt # ¸üл¹Ðè¸öÊý  | 
|             delItemInfoList.append([curItem, itemCount])  | 
|         else:  | 
|             costItemCntDict.pop(itemID)  | 
|             delItemInfoList.append([curItem, needCnt])  | 
|               | 
|             # Èç¹û¶¼¹»ÁË£¬Ìø³ö£¬²»ÔÙ²éÕÒ  | 
|             if not costItemCntDict:  | 
|                 break  | 
|               | 
|     #·µ»ØÁбí[Òª¿Û³ýµÄÎïÆ·ÐÅÏ¢, ËùÕҵIJÄÁÏÊÇ·ñÓа󶨵Ä, ²»×ãµÄ¸öÊýÐÅÏ¢×Öµä]  | 
|     return delItemInfoList, findItemIsBind, costItemCntDict  | 
|   | 
|   | 
| ## Í¬²½¶Ò»»´ÎÊý  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def Sync_ExcItemCnt(curPlayer, actionKey):  | 
|     actionItemExchangeInfo = ReadChConfig.GetEvalChConfig("ActionItemExchange")  | 
|       | 
|     if actionKey not in actionItemExchangeInfo:  | 
|         return  | 
|       | 
|     excCfg = actionItemExchangeInfo[actionKey]  | 
|       | 
|     exRecordPack = ChPyNetSendPack.tagMCExchangeActionItemCntRecord()  | 
|     exRecordPack.Clear()  | 
|     exRecordPack.ActionKey = actionKey  | 
|     exRecordPack.ActionKeyLen = len(actionKey)  | 
|     exRecordPack.RecordList = []  | 
|       | 
|     itemDict = excCfg[Def_ExcCfg_ItemDict]  | 
|     for itemID, itemInfo in itemDict.items():  | 
|         recordMark = itemInfo[Def_ExcItem_RecordMark]  | 
|         excCntKey = ChConfig.Def_PDict_ExcActionItemCnt % (actionKey, recordMark)  | 
|         exchangeCnt = curPlayer.NomalDictGetProperty(excCntKey) # ÒѶһ»´ÎÊý  | 
|         excItem = ChPyNetSendPack.tagMCExchangeActionItemCnt()  | 
|         excItem.Clear()  | 
|         excItem.ItemID = itemID  | 
|         excItem.ExcCnt = exchangeCnt  | 
|         exRecordPack.RecordList.append(excItem)  | 
|       | 
|     exRecordPack.RecordCnt = len(exRecordPack.RecordList)  | 
|     NetPackCommon.SendFakePack(curPlayer, exRecordPack)  | 
|     return  | 
|   | 
| ##------------------------------- °´»î¶¯Ê±¼ä¸øbuff ------------------------------  | 
|   | 
| ## »î¶¯buff״̬±ä¸ü  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def OnActionBuffStateChange(key, tick):  | 
|     buffID = key[len(ShareDefine.Def_Notify_WorldKey_ActionBuffState) - 2:]  | 
|     try:  | 
|         buffID = int(buffID)              | 
|     except BaseException:  | 
|         GameWorld.ErrLog("»î¶¯buffIDÅäÖÃkey´íÎó, key=%s" % key)  | 
|         return  | 
|       | 
|     actionBuffList = ReadChConfig.GetEvalChConfig("PlayerActionBuff")  | 
|     if buffID not in actionBuffList:  | 
|         GameWorld.ErrLog("»î¶¯buffID²»ÔÚPlayerActionBuff.txtÀï, buffID=%s" % buffID)  | 
|         return  | 
|       | 
|     buffState = GameWorld.GetGameWorld().GetGameWorldDictByKey(key)  | 
|     GameWorld.DebugLog("OnActionBuffStateChange buffID=%s,state=%s" % (buffID, buffState))  | 
|       | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for index in range(0, playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(index)  | 
|         if curPlayer.GetID() == 0:  | 
|             continue  | 
|               | 
|         isOK = __AddPlayerActionBuff(curPlayer, buffID, buffState, tick)  | 
|         if isOK:  | 
|             playerControl = PlayerControl.PlayerControl(curPlayer)  | 
|             playerControl.RefreshPlayerAttrByBuff()  | 
|     return  | 
|   | 
| ## Íæ¼Ò»î¶¯buffÂß¼  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def DoPlayerActionBuffOnLogin(curPlayer):  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     actionBuffList = ReadChConfig.GetEvalChConfig("PlayerActionBuff")  | 
|     isNeedRefresh = False  | 
|     for buffID in actionBuffList:  | 
|         stateKey = ShareDefine.Def_Notify_WorldKey_ActionBuffState % buffID  | 
|         buffState = GameWorld.GetGameWorld().GetGameWorldDictByKey(stateKey)  | 
|         isOK = __AddPlayerActionBuff(curPlayer, buffID, buffState, tick)  | 
|         isNeedRefresh = True if isOK else isNeedRefresh  | 
|       | 
|     if isNeedRefresh:  | 
|         playerControl = PlayerControl.PlayerControl(curPlayer)  | 
|         playerControl.RefreshPlayerAttrByBuff()  | 
|     return  | 
|   | 
| ## Ìí¼ÓÍæ¼Ò»î¶¯buff  | 
| #  @param curPlayer  | 
| #  @param buffID  | 
| #  @param isAddBuff ÊÇ·ñÌí¼Ó  | 
| #  @return None  | 
| def __AddPlayerActionBuff(curPlayer, buffID, isAddBuff, tick):  | 
|       | 
|     if isAddBuff:  | 
|         skillInfo = SkillCommon.FindBuffByID(curPlayer, buffID)  | 
|         findBuff, buffManager, buffType, findSkill = skillInfo  | 
|         if findBuff == None:  | 
|             if not findSkill:  | 
|                 return False  | 
|               | 
|             return BuffSkill.AddBuffNoRefreshState(curPlayer, buffType, findSkill, tick, [], curPlayer)  | 
|     else:  | 
|         return BuffSkill.DelBuffBySkillID(curPlayer, buffID, tick)  | 
|       | 
|     return False  | 
|   |