#!/usr/bin/python
|
# -*- coding: GBK -*-
|
#-------------------------------------------------------------------------------
|
#
|
##@package TurnAttack
|
#
|
# @todo:»ØºÏÖÆ¹¥»÷Âß¼
|
# @author hxp
|
# @date 2023-11-30
|
# @version 1.0
|
#
|
# ÏêϸÃèÊö: »ØºÏÖÆ¹¥»÷Âß¼
|
#
|
#-------------------------------------------------------------------------------
|
#"""Version = 2023-11-30 15:30"""
|
#-------------------------------------------------------------------------------
|
|
import ChConfig
|
import AICommon
|
import BaseAttack
|
import PlayerState
|
import IpyGameDataPY
|
import IPY_GameWorld
|
import ChPyNetSendPack
|
import PlayerViewCacheTube
|
import NetPackCommon
|
import PlayerControl
|
import SkillCommon
|
import NPCCommon
|
import GameWorld
|
import GameObj
|
|
(
|
FightState_Start,
|
FightState_Fighting,
|
FightState_Win,
|
FightState_Fail,
|
FightState_Over,
|
) = range(5)
|
|
#// B4 10 »ØºÏÖÆÕ½¶· #tagCMTurnFight
|
#
|
#struct tagCMTurnFight
|
#{
|
# tagHead Head;
|
# DWORD MapID; // ×Ô¶¨ÒåµØÍ¼ID£¬¿ÉÓÃÓÚ°ó¶¨Õ½¶·³¡¾°¹¦ÄÜ£¨ÈçÒ°Íâ¹Ø¿¨£¬ÅÀËþ¹¦ÄÜ£¬¾º¼¼³¡µÈ£©
|
# WORD FuncLineID;
|
# DWORD PlayerID; // ¶ÔÓ¦Íæ¼ÒID£¬¿ÉΪ0£¬Ä³Ð©¹¦ÄÜ¿ÉÄÜÓÐÓã¬È羺¼¼³¡
|
#};
|
def OnTurnFight(index, clientData, tick):
|
curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
mapID = clientData.MapID
|
funcLineID = clientData.FuncLineID
|
tagPlayerID = clientData.PlayerID
|
|
if curPlayer.GetSightLevel() != curPlayer.GetID():
|
PlayerControl.SetPlayerSightLevel(curPlayer, curPlayer.GetID())
|
|
SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Start)
|
|
if tagPlayerID:
|
PlayerViewCacheTube.GetPlayerPropDataCall(curPlayer, tagPlayerID, DoTrunFightVSPlayer, [mapID, funcLineID])
|
return
|
|
DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick)
|
|
SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Over)
|
return
|
|
def DoTrunFightVSPlayer(curPlayer, tagPlayerID, callData, PropDict):
|
mapID, funcLineID = callData
|
if PropDict and curPlayer.GetPlayerID() != tagPlayerID:
|
tick = GameWorld.GetGameWorld().GetTick()
|
DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick)
|
SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Over)
|
return
|
|
def DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick):
|
playerID = curPlayer.GetPlayerID()
|
tagObj = None
|
if tagPlayerID:
|
npcID = ChConfig.Def_NPCID_PVP
|
tagObj = NPCCommon.SummonMapNpc(npcID, curPlayer.GetPosX(), curPlayer.GetPosY(), sightLevel=playerID, pvpPlayerID=tagPlayerID)
|
else:
|
ipyData = IpyGameDataPY.GetIpyGameData("FBTurn", mapID, funcLineID)
|
if not ipyData:
|
return
|
npcID = ipyData.GetNPCID()
|
if not npcID:
|
return
|
tagObj = NPCCommon.SummonMapNpc(npcID, curPlayer.GetPosX(), curPlayer.GetPosY(), sightLevel=playerID)
|
|
if not tagObj:
|
return
|
|
turnMax = IpyGameDataPY.GetFuncCfg("TurnFight", 1)
|
curPet = curPlayer.GetPetMgr().GetFightPet()
|
tagPet = None
|
|
GameWorld.DebugLog("===== Ö´ÐлغÏÖÆÕ½¶·: mapID=%s,funcLineID=%s,tagPlayerID=%s,tagObjID=%s"
|
% (mapID, funcLineID, tagPlayerID, tagObj.GetID()), playerID)
|
GameWorld.DebugLog("curPlayer.GetSightLevel=%s,tagObj.GetSightLevel=%s"
|
% (curPlayer.GetSightLevel(), tagObj.GetSightLevel()), playerID)
|
|
#Ò»¸ö»ØºÏ¹¥»÷˳Ðò
|
#1. ¿ì·½³èÎï¹¥»÷£¬²»´æÔÚÌø¹ý
|
#2. Âý·½³èÎï¹¥»÷£¬²»´æÔÚÌø¹ý
|
#3. ¿ì·½Ö÷Ìå¹¥»÷
|
#4. Âý·½Ö÷Ìå¹¥»÷
|
|
# Õ½¶·Ç°³õʼ»¯
|
factionObjMax = 0 # ij¸öÕóÓªµÄ×î´óÕ½¶·ÊµÀýÊý
|
factionObjDict = {1:[curPet, curPlayer], 2:[tagPet, tagObj]}
|
for objList in factionObjDict.values():
|
if factionObjMax < len(objList):
|
factionObjMax = len(objList)
|
for gameObj in objList:
|
TurnFightObjStartInit(gameObj)
|
|
curAtkSpeed = GameObj.GetAtkSpeed(curPlayer)
|
tagAtkSpeed = GameObj.GetAtkSpeed(tagObj)
|
orderList = [1, 2] if curAtkSpeed >= tagAtkSpeed else [2, 1]
|
GameWorld.DebugLog("playerHP=%s,tagHP=%s,curAtkSpeed=%s,tagAtkSpeed=%s"
|
% (GameObj.GetHP(curPlayer), GameObj.GetHP(tagObj), curAtkSpeed, tagAtkSpeed), playerID)
|
|
isWin = None
|
for turnNum in range(1, turnMax + 1):
|
GameWorld.DebugLog("----- »ØºÏÖÆÕ½¶·ÂÖ´Î: %s -----" % turnNum, playerID)
|
SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Fighting, turnNum, turnMax)
|
|
# »ØºÏ¿ªÊ¼: ×öһЩÿ»ØºÏÖØÖÃÂß¼»òÕßijЩ¸ù¾Ý»ØºÏ´¥·¢µÄЧ¹ûµÈ
|
for objList in factionObjDict.values():
|
for gameObj in objList:
|
TurnFightObjTurnStart(gameObj, turnNum)
|
|
# »ØºÏÕ½¶·£º ÂÖÁ÷ÒÀ´Î¹¥»÷
|
for index in range(factionObjMax):
|
for faction in orderList:
|
objList = factionObjDict[faction]
|
if index >= len(objList):
|
continue
|
gameObj = objList[index]
|
if not gameObj:
|
continue
|
|
tagGameObj = tagObj if faction == 1 else curPlayer
|
objType = gameObj.GetGameObjType()
|
objID = gameObj.GetID()
|
tagObjType = tagGameObj.GetGameObjType()
|
tagObjID = tagGameObj.GetID()
|
|
GameWorld.DebugLog(" Ðж¯: turnNum=%s,index=%s,faction=%s,objType=%s,objID=%s,tagObjType=%s,tagObjID=%s"
|
% (turnNum, index, faction, objType, objID, tagObjType, tagObjID), playerID)
|
DoAttack(gameObj, tagGameObj, tick)
|
|
if tagGameObj and GameObj.GetHP(tagGameObj) > 0:
|
continue
|
|
isWin = faction == 1
|
GameWorld.DebugLog(" tagObjType=%s,tagObjID=%s,±»»÷ɱ£¬½áÊøÕ½¶·: isWin=%s" % (tagObjType, tagObjID, isWin))
|
break
|
|
if isWin != None:
|
break
|
|
if isWin != None:
|
break
|
|
overState = FightState_Win if isWin else FightState_Fail
|
SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, overState, turnNum, turnMax)
|
|
for objList in factionObjDict.values():
|
for gameObj in objList:
|
TurnFightObjOverReset(gameObj)
|
|
GameWorld.DebugLog("===== »ØºÏÖÆÕ½¶·½áÊø: mapID=%s,funcLineID=%s,tagPlayerID=%s,isWin=%s,overState=%s"
|
% (mapID, funcLineID, tagPlayerID, isWin, overState), playerID)
|
return
|
|
def TurnFightObjStartInit(gameObj):
|
## »ØºÏÖÆÕ½¶·ÊµÀý³õʼ»¯
|
if not gameObj:
|
return
|
|
gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 1)
|
GameObj.SetHPFull(gameObj)
|
gameObj.RefreshView()
|
|
objType = gameObj.GetGameObjType()
|
# ÖØÖü¼ÄÜCD¡¢Õ½¶·buff
|
if objType == IPY_GameWorld.gotPlayer:
|
skillManager = gameObj.GetSkillManager()
|
for i in range(skillManager.GetSkillCount()):
|
skill = skillManager.GetSkillByIndex(i)
|
skill.SetRemainTime(0)
|
|
elif objType == IPY_GameWorld.gotNPC:
|
pass
|
return
|
|
def TurnFightObjTurnStart(gameObj, turnNum):
|
## »ØºÏÖÆÕ½¶·ÊµÀý - ÿ»ØºÏ¿ªÊ¼Ê±´¦Àí
|
if not gameObj:
|
return
|
|
gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, turnNum)
|
# ÖØÖÃÁ¬»÷¡¢·´»÷Êý
|
gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
|
gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, 0)
|
|
objType = gameObj.GetGameObjType()
|
if objType == IPY_GameWorld.gotPlayer:
|
pass
|
|
elif objType == IPY_GameWorld.gotNPC:
|
pass
|
|
return
|
|
def TurnFightObjOverReset(gameObj):
|
## »ØºÏÖÆÕ½¶·ÊµÀý½áÊøÖØÖÃ
|
if not gameObj:
|
return
|
gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 0)
|
gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0)
|
|
objType = gameObj.GetGameObjType()
|
if objType == IPY_GameWorld.gotPlayer:
|
pass
|
|
elif objType == IPY_GameWorld.gotNPC:
|
npcObjType = gameObj.GetGameNPCObjType()
|
if npcObjType != IPY_GameWorld.gnotPet and GameObj.GetHP(gameObj):
|
NPCCommon.SetDeadEx(gameObj)
|
|
return
|
|
def DoAttack(curObj, tagObj, tick):
|
curID = curObj.GetID()
|
tagID = tagObj.GetID()
|
if curObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
|
atkRet = PlayerAttack(curObj, tagObj, tick)
|
else:
|
atkRet = NPCAttack(curObj, tagObj, tick)
|
|
turnBattleType = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnBattleType)
|
curObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0) # ÎÞÂÛ¹¥»÷³É¹¦Óë·ñ¶¼ÖØÖÃÕ½¶·ÀàÐÍ
|
|
if not atkRet:
|
return
|
|
if turnBattleType == ChConfig.TurnBattleType_Combo:
|
comboNum = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum) + 1
|
curObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, comboNum)
|
GameWorld.DebugLog(" Á¬»÷: comboID=%s,comboNum=%s" % (curID, comboNum))
|
elif turnBattleType == ChConfig.TurnBattleType_AtkBack:
|
atkBackNum = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) + 1
|
curObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, atkBackNum)
|
GameWorld.DebugLog(" ·´»÷: atkBackID=%s,atkBackNum=%s" % (curID, atkBackNum))
|
|
GameWorld.DebugLog(" curID-HP=(%s-%s),tagID-HP=(%s-%s)" % (curID, GameObj.GetHP(curObj), tagID, GameObj.GetHP(tagObj)))
|
|
# ·´»÷£¬·´»÷¿É´ò¶ÏÁ¬»÷£¬ËùÒÔÓÅÏÈÅжÏ
|
if CanAtkBack(curObj, tagObj):
|
DoAttack(tagObj, curObj, tick)
|
return
|
|
# Á¬»÷
|
if CanCombo(curObj, tagObj):
|
DoAttack(curObj, tagObj, tick)
|
|
return
|
|
def CanAtkBack(atkObj, defObj):
|
## ¿É·ñ·´»÷
|
|
defAtkBackRate = GameObj.GetAtkBackRate(defObj) # ·À·½·´»÷ÂÊ
|
atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # ÒÑ·´»÷´ÎÊý
|
if atkBackNum > 10:
|
# ÄÚÖÃ×î¸ß·´»÷Êý·À·¶
|
return False
|
if atkBackNum > 0:
|
validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 4)
|
vaildPer = validPerList[atkBackNum - 1] if len(validPerList) >= atkBackNum else 0
|
defAtkBackRate = int(defAtkBackRate * vaildPer / 100.0)
|
|
atkAtkBackDefRate = GameObj.GetAtkBackDefRate(atkObj) # ¹¥·½µÖ¿¹·´»÷ÂÊ
|
atkBackRate = max(0, defAtkBackRate - atkAtkBackDefRate)
|
if atkBackRate <= 0 or not GameWorld.CanHappen(atkBackRate):
|
GameWorld.DebugLog(" ÎÞ·¨·´»÷: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)"
|
% (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
|
return False
|
GameWorld.DebugLog(" ¿ÉÒÔ·´»÷: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)"
|
% (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
|
defObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, ChConfig.TurnBattleType_AtkBack)
|
return True
|
|
def CanCombo(atkObj, defObj):
|
## ¿É·ñÁ¬»÷
|
|
atkComboRate = GameObj.GetComboRate(atkObj) # ¹¥·½Á¬»÷ÂÊ
|
comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum) # ÒÑÁ¬»÷´ÎÊý
|
if comboNum > 10:
|
# ÄÚÖÃ×î¸ßÁ¬»÷Êý·À·¶
|
return False
|
if comboNum > 0:
|
validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 3)
|
vaildPer = validPerList[comboNum - 1] if len(validPerList) >= comboNum else 0
|
atkComboRate = int(atkComboRate * vaildPer / 100.0)
|
|
defComboReduce = GameObj.GetComboDefRate(defObj) # ·À·½µÖ¿¹Á¬»÷ÂÊ
|
comboRate = max(0, atkComboRate - defComboReduce)
|
if comboRate <= 0 or not GameWorld.CanHappen(comboRate):
|
GameWorld.DebugLog(" ÎÞ·¨Á¬»÷: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)"
|
% (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
|
return False
|
GameWorld.DebugLog(" ¿ÉÒÔÁ¬»÷: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)"
|
% (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
|
atkObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, ChConfig.TurnBattleType_Combo)
|
return True
|
|
def NPCAttack(curObj, tagObj, tick):
|
## NPC¹¥»÷
|
if not curObj:
|
return
|
tagDist = 0
|
atkRet = AICommon.DoAutoUseSkill(curObj, tagObj, tagDist, tick)
|
#---ÓÅÏÈÊͷż¼ÄÜ---
|
if not atkRet:
|
#ÆÕͨ¹¥»÷
|
atkRet = BaseAttack.Attack(curObj, tagObj, None, tick)
|
if atkRet:
|
GameWorld.DebugLog(" NPCÆÕͨ¹¥»÷: curID=%s,tagID=%s,atkRet=%s" % (curObj.GetID(), tagObj.GetID(), atkRet))
|
else:
|
GameWorld.DebugLog(" NPC¹¥»÷ʧ°Ü: curID=%s,tagID=%s,atkRet=%s" % (curObj.GetID(), tagObj.GetID(), atkRet))
|
else:
|
GameWorld.DebugLog(" NPC¼¼Äܹ¥»÷: curID=%s,tagID=%s,atkRet=%s" % (curObj.GetID(), tagObj.GetID(), atkRet))
|
return atkRet
|
|
def PlayerAttack(curPlayer, tagObj, tick):
|
## Íæ¼Ò¹¥»÷£¬ ²Î¿¼¼¼ÄÜʹÓà #def UseSkillEx(index, clientData, tick):
|
playerID = curPlayer.GetPlayerID()
|
job = curPlayer.GetJob()
|
jobAutoUseSkillDict = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 2, {})
|
if job not in jobAutoUseSkillDict:
|
return
|
skillList = jobAutoUseSkillDict[job]
|
|
posX, posY = tagPosX, tagPosY = curPlayer.GetPosX(), curPlayer.GetPosY()
|
tagObjType, tagObjID = tagObj.GetGameObjType(), tagObj.GetID()
|
|
curPlayer.ClearUseSkillRec()
|
curPlayer.SetAttackTargetPos(posX, posY)
|
curPlayer.SetUseSkillPosX(tagPosX)
|
curPlayer.SetUseSkillPosY(tagPosY)
|
curPlayer.SetUseSkillTagType(tagObjType)
|
curPlayer.SetUseSkillTagID(tagObjID)
|
|
#PlayerControl.SetIsNeedProcess(curPlayer, True)
|
#PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
|
|
useSkillResult = False
|
skillMgr = curPlayer.GetSkillManager()
|
for skillID in skillList:
|
curSkill = skillMgr.FindSkillBySkillID(skillID)
|
if not curSkill:
|
continue
|
|
#CheckSkillCondition
|
#±»¶¯¼¼ÄÜÎÞ·¨Ê¹ÓÃ
|
if SkillCommon.isPassiveSkill(curSkill):
|
continue
|
#»¹ÔÚÀäȴʱ¼äÄÚÎÞ·¨ÊÍ·Å
|
if SkillCommon.RefreshSkillRemainTime(curSkill, tick) != 0:
|
continue
|
|
curPlayer.SetUseSkill(curSkill.GetSkillData())
|
useSkillData = curPlayer.GetUseSkill()
|
if not PlayerState.__DoClientUseSkillEx(curPlayer, useSkillData, tick):
|
GameWorld.DebugLog(" ¼¼Äܹ¥»÷ʧ°Ü%s" % skillID, playerID)
|
continue
|
useSkillResult = True
|
GameWorld.DebugLog(" ¼¼Äܹ¥»÷³É¹¦%s" % skillID, playerID)
|
|
break
|
|
curPlayer.ClearUseSkillRec()
|
return useSkillResult
|
|
def SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, state, turnNum=0, turnMax=0):
|
clientPack = ChPyNetSendPack.tagMCTurnFightState()
|
clientPack.Clear()
|
clientPack.MapID = mapID
|
clientPack.FuncLineID = funcLineID
|
clientPack.PlayerID = tagPlayerID
|
clientPack.State = state
|
clientPack.TurnNum = turnNum
|
clientPack.TurnMax = turnMax
|
NetPackCommon.SendFakePack(curPlayer, clientPack)
|
return
|