Files
StellaSora_DataLua/lua/game/ui/play_penguincard/penguinlevel.lua
T
SL1900 8c4bd41668 Update - 1.13.0.124
EN: 1.13.0.124
CN: 1.13.0.124
JP: 1.13.0.128
KR: 1.13.0.130
2026-07-21 12:30:00 +09:00

1186 lines
36 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local PenguinLevel = class("PenguinLevel")
local PenguinCard = require("Game.UI.Play_PenguinCard.PenguinCard")
local PenguinCardBuff = require("Game.UI.Play_PenguinCard.PenguinCardBuff")
local TimerManager = require("GameCore.Timer.TimerManager")
local LocalData = require("GameCore.Data.LocalData")
local ConfigData = require("GameCore.Data.ConfigData")
local PenguinCardUtils = require("Game.UI.Play_PenguinCard.PenguinCardUtils")
function PenguinLevel:ParseConfigData()
self.nBaseCardCount = ConfigTable.GetConfigNumber("PenguinCardHandCardCount")
self.nFireScore = ConfigTable.GetConfigNumber("PenguinCardFeverScore")
self.nPenguinCardRollCount = ConfigTable.GetConfigNumber("PenguinCardRollCount")
self.mapBuyCost = {}
local func_ForEach_Line = function(mapData)
self.mapBuyCost[mapData.Count] = {
Turn = mapData.Turn,
Cost = mapData.Cost
}
end
ForEachTableLine(DataTable.PenguinCardCost, func_ForEach_Line)
self.mapHandRankRule = {}
local func_ForEach_Rank = function(mapData)
self.mapHandRankRule[mapData.Order] = {
Id = mapData.Id,
SuitCount = mapData.SuitCount,
Value = mapData.Value,
Ratio = mapData.Ratio * ConfigData.IntFloatPrecision
}
end
ForEachTableLine(DataTable.PenguinCardHandRank, func_ForEach_Rank)
self.mapTendencyScore = {}
local func_ForEach_Tendency = function(mapData)
if not self.mapTendencyScore[mapData.GroupId] then
self.mapTendencyScore[mapData.GroupId] = {}
end
table.insert(self.mapTendencyScore[mapData.GroupId], mapData.Score)
end
ForEachTableLine(DataTable.PenguinCardTendency, func_ForEach_Tendency)
for _, v in pairs(self.mapTendencyScore) do
table.sort(v)
end
if type(self.ParseModeConfigData) == "function" then
self:ParseModeConfigData()
end
end
function PenguinLevel:ParseServerData(nFloorId, nLevelId, nActId, tbStarScore)
self.nFloorId = nFloorId
self.nLevelId = nLevelId
self.nActId = nActId
self.tbStarScore = tbStarScore or {
0,
0,
0
}
end
function PenguinLevel:ParseLocalData()
local bAuto = LocalData.GetPlayerLocalData("PenguinCardAuto")
self.bAuto = bAuto == true
local nSpeed = LocalData.GetPlayerLocalData("PenguinCardSpeed")
self.nSpeed = nSpeed or 1
end
function PenguinLevel:ParseLevelData(nFloorId)
self.nMaxTurn = 0
self.nScore = 0
self.nTotalScore = 0
self.nSlotCount = 0
self.nRoundLimit = 0
self.nCheckRoundLimit = 0
self.nBuyLimit = 0
self.nWeightGroupId = 0
self.mapBaseCardPool = {
tbId = {},
tbWeight = {}
}
if type(self.ParseModeLevelData) == "function" then
self:ParseModeLevelData(nFloorId)
end
end
function PenguinLevel:ClearLevelData()
self.nGameState = nil
self.nCurTurn = 0
self.nCurRound = 0
self.nHp = 3
if self.tbBuffPool == nil then
self.tbBuffPool = {}
end
if self.tbBuff == nil then
self.tbBuff = {}
elseif next(self.tbBuff) ~= nil then
local nCount = #self.tbBuff
for i = nCount, 1, -1 do
self:RecycleBuff(self.tbBuff[i])
table.remove(self.tbBuff, i)
end
end
if self.tbPenguinCardPool == nil then
self.tbPenguinCardPool = {}
end
if self.tbPenguinCard == nil then
self.tbPenguinCard = {}
for i = 1, 6 do
self.tbPenguinCard[i] = 0
end
elseif next(self.tbPenguinCard) ~= nil then
for i = 1, 6 do
local mapCard = self.tbPenguinCard[i]
if mapCard ~= 0 then
self:RecyclePenguinCard(mapCard)
self.tbPenguinCard[i] = 0
end
end
end
self.mapLog = {}
self.nTotalRound = 0
self.nBestTurnScore = 0
self.nBestRoundScore = 0
self.mapHandRankHistory = {}
self.mapSuitHistory = {}
self.nGetPenguinCardCount = 0
self.mapSnapshot = nil
self.bRestoreSnapshot = false
if type(self.ClearModeLevelData) == "function" then
self:ClearModeLevelData()
end
end
function PenguinLevel:StartGame()
math.randomseed(os.time())
self:ClearLevelData()
self:ParseLevelData(self.nFloorId)
self:SwitchGameState()
end
function PenguinLevel:CompleteGame()
local nNextState = PenguinCardUtils.GameState.Complete
self:SwitchNextGameState(nNextState, {bManual = true})
end
function PenguinLevel:RestartGame()
local nNextState = PenguinCardUtils.GameState.Start
local nWaitTime = self:QuitGameState(nNextState)
if nWaitTime == 0 then
self:StartGame()
else
EventManager.Hit(EventId.TemporaryBlockInput, nWaitTime)
TimerManager.Add(1, nWaitTime, self, function()
self:StartGame()
end, true, true, true)
end
end
function PenguinLevel:QuitGame(callback)
local bAct = false
if self.nActId then
local actData = PlayerData.Activity:GetActivityDataById(self.nActId)
if actData then
local bOpen = actData:CheckActivityOpen()
if bOpen then
bAct = true
local nScore = math.floor(self.nScore)
actData:SendActivityPenguinCardSettleReq(self.nLevelId, self.nStar or 1, nScore, callback)
else
EventManager.Hit(EventId.OpenMessageBox, {
nType = AllEnum.MessageBox.Alert,
sContent = ConfigTable.GetUIText("Activity_Invalid_Tip_3")
})
end
end
end
if not bAct then
callback(true)
end
self:QuitGameState()
self:ClearLevelData()
if type(self.Exit) == "function" then
self:Exit()
end
end
function PenguinLevel:SwitchGameState()
local nNextState = PenguinCardUtils.GameState.Start
if type(self.CheckNextGameState) == "function" then
nNextState = self:CheckNextGameState()
end
self:SwitchNextGameState(nNextState)
end
function PenguinLevel:RunGameState(mapParam)
if self.nGameState == PenguinCardUtils.GameState.Start then
if type(self.RunState_Start) == "function" then
self:RunState_Start()
end
elseif self.nGameState == PenguinCardUtils.GameState.Prepare then
if type(self.RunState_Prepare) == "function" then
self:RunState_Prepare()
end
elseif self.nGameState == PenguinCardUtils.GameState.Dealing then
if type(self.RunState_Dealing) == "function" then
self:RunState_Dealing()
end
elseif self.nGameState == PenguinCardUtils.GameState.Flip then
if type(self.RunState_Flip) == "function" then
self:RunState_Flip()
end
elseif self.nGameState == PenguinCardUtils.GameState.Settlement then
if type(self.RunState_Settlement) == "function" then
self:RunState_Settlement()
end
elseif self.nGameState == PenguinCardUtils.GameState.Complete then
if type(self.RunState_Complete) == "function" then
self:RunState_Complete(mapParam)
end
elseif self.nGameState == PenguinCardUtils.GameState.Quest and type(self.RunState_Quest) == "function" then
self:RunState_Quest()
end
end
function PenguinLevel:QuitGameState(nNextState)
local nWaitTime = 0
if self.nGameState == PenguinCardUtils.GameState.Start then
if type(self.QuitState_Start) == "function" then
nWaitTime = self:QuitState_Start()
end
elseif self.nGameState == PenguinCardUtils.GameState.Prepare then
if type(self.QuitState_Prepare) == "function" then
nWaitTime = self:QuitState_Prepare(nNextState)
end
elseif self.nGameState == PenguinCardUtils.GameState.Dealing then
if type(self.QuitState_Dealing) == "function" then
nWaitTime = self:QuitState_Dealing(nNextState)
end
elseif self.nGameState == PenguinCardUtils.GameState.Flip then
if type(self.QuitState_Flip) == "function" then
nWaitTime = self:QuitState_Flip(nNextState)
end
elseif self.nGameState == PenguinCardUtils.GameState.Settlement then
if type(self.QuitState_Settlement) == "function" then
nWaitTime = self:QuitState_Settlement(nNextState)
end
elseif self.nGameState == PenguinCardUtils.GameState.Complete then
if type(self.QuitState_Complete) == "function" then
nWaitTime = self:QuitState_Complete()
end
elseif self.nGameState == PenguinCardUtils.GameState.Quest and type(self.QuitState_Quest) == "function" then
nWaitTime = self:QuitState_Quest(nNextState)
end
return nWaitTime
end
function PenguinLevel:SwitchNextGameState(nNextState, mapParam)
local nWaitTime = self:QuitGameState(nNextState)
if nWaitTime == 0 then
self.nGameState = nNextState
self:RunGameState(mapParam)
else
EventManager.Hit(EventId.TemporaryBlockInput, nWaitTime)
TimerManager.Add(1, nWaitTime, self, function()
self.nGameState = nNextState
self:RunGameState(mapParam)
end, true, true, true)
end
end
function PenguinLevel:ChangeHp(nChange)
self.nHp = self.nHp + nChange
if NovaAPI.IsEditorPlatform() then
printLog("Hp变化:" .. " " .. nChange .. " 当前:" .. self.nHp)
end
EventManager.Hit("PenguinCard_ChangeHp", nChange)
if self.nHp <= 0 then
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.FatalDamage, {nHpChange = nChange})
end
end
function PenguinLevel:AddBuff(mapBuff, bWaitShow)
if mapBuff.bOnly then
local nBuffCount = #self.tbBuff
for i = nBuffCount, 1, -1 do
if mapBuff.nId == self.tbBuff[i].nId then
self:DeleteBuff(i)
end
end
table.insert(self.tbBuff, mapBuff)
EventManager.Hit("PenguinCard_AddBuff", mapBuff, bWaitShow)
else
local nHasKey = 0
for k, v in pairs(self.tbBuff) do
if v.nId == mapBuff.nId then
nHasKey = k
break
end
end
if 0 < nHasKey then
self.tbBuff[nHasKey]:AddGrowthLayer()
else
table.insert(self.tbBuff, mapBuff)
EventManager.Hit("PenguinCard_AddBuff", mapBuff, bWaitShow)
end
end
if NovaAPI.IsEditorPlatform() then
printLog("获得buff" .. " " .. mapBuff.nId)
end
end
function PenguinLevel:DeleteBuff(i, nDelayTime, bSkipAni)
self:RecycleBuff(self.tbBuff[i])
table.remove(self.tbBuff, i)
EventManager.Hit("PenguinCard_DeleteBuff", i, nDelayTime, bSkipAni)
end
function PenguinLevel:RecycleBuff(mapBuff)
mapBuff:Clear()
table.insert(self.tbBuffPool, mapBuff)
end
function PenguinLevel:CreateBuff(nId)
local mapBuff
if next(self.tbBuffPool) == nil then
mapBuff = PenguinCardBuff.new(nId)
else
mapBuff = table.remove(self.tbBuffPool, 1)
mapBuff:Init(nId)
end
return mapBuff
end
function PenguinLevel:ClearTurnData()
self.nTurnScore = 0
self.tbHandRankCount = {}
self.nCheckRoundCount = 0
self.nUpgradeDiscount = 1
self.nTempAddRound = 0
self.nTempAddRollCount = 0
end
function PenguinLevel:ClearStateData_Prepare()
self.nTurnBuyCount = 0
self.tbSelectablePenguinCard = {}
self.bSelectedPenguinCard = false
end
function PenguinLevel:GetRoundLimitInTurn()
local nAdd = 0
if self.nTempAddRound ~= nil then
nAdd = nAdd + self.nTempAddRound
end
return self.nRoundLimit + nAdd
end
function PenguinLevel:AfterUpgrade(nUpgradeCost)
self.nUpgradeDiscount = 1
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.AfterUpgrade, {nUpgradeCost = nUpgradeCost})
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.BeforeUpgrade)
end
function PenguinLevel:FreeRollPenguinCard()
local tbId = self:GetRollPenguinCardResult()
if next(tbId) == nil then
EventManager.Hit(EventId.OpenMessageBox, {
nType = AllEnum.MessageBox.Tips,
sSound = "Mode_Card_refresh_falied",
sContent = ConfigTable.GetUIText("PenguinCard_Error_EmptyPenguinCard")
})
return
end
self:ClearSelectablePenguinCard()
for _, nId in ipairs(tbId) do
local mapCard = self:CreatePenguinCard(nId)
table.insert(self.tbSelectablePenguinCard, mapCard)
end
self.bSelectedPenguinCard = false
end
function PenguinLevel:RollPenguinCard()
if self.nTurnBuyCount >= self.nBuyLimit then
EventManager.Hit(EventId.OpenMessageBox, {
nType = AllEnum.MessageBox.Tips,
sSound = "Mode_Card_refresh_falied",
sContent = ConfigTable.GetUIText("PenguinCard_RollMax")
})
return
end
local nCost = self:GetRollPenguinCardCost()
if nCost > self.nScore then
EventManager.Hit(EventId.OpenMessageBox, {
nType = AllEnum.MessageBox.Tips,
sSound = "Mode_Card_refresh_falied",
sContent = ConfigTable.GetUIText("PenguinCard_NotEnoughScoreRoll")
})
return
end
local tbId = self:GetRollPenguinCardResult()
if next(tbId) == nil then
EventManager.Hit(EventId.OpenMessageBox, {
nType = AllEnum.MessageBox.Tips,
sSound = "Mode_Card_refresh_falied",
sContent = ConfigTable.GetUIText("PenguinCard_Error_EmptyPenguinCard")
})
return
end
self.nTurnBuyCount = self.nTurnBuyCount + 1
self:ChangeScore(-1 * nCost)
self:ClearSelectablePenguinCard()
for _, nId in ipairs(tbId) do
local mapCard = self:CreatePenguinCard(nId)
table.insert(self.tbSelectablePenguinCard, mapCard)
end
self.bSelectedPenguinCard = false
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.ManualRoll)
EventManager.Hit("PenguinCard_RollPenguinCard")
end
function PenguinLevel:SelectPenguinCard(nIndex)
local mapSelectCard = self.tbSelectablePenguinCard[nIndex]
local bUpgrade, nAimIndex = self:CheckUpgradePenguinCard(mapSelectCard)
if not bUpgrade and self:GetOwnPenguinCardCount() >= self.nSlotCount then
EventManager.Hit(EventId.OpenMessageBox, ConfigTable.GetUIText("PenguinCard_SlotMax"))
return
end
if bUpgrade then
local nAddLevel = mapSelectCard.nLevel
self.tbPenguinCard[nAimIndex]:Upgrade(nAddLevel)
else
local mapCard = self:CreatePenguinCard(mapSelectCard.nId)
self.tbPenguinCard[nAimIndex] = mapCard
end
self.tbPenguinCard[nAimIndex]:SetSlotIndex(nAimIndex)
self.tbPenguinCard[nAimIndex]:ResetAllTrigger()
self.bSelectedPenguinCard = true
self.nGetPenguinCardCount = self.nGetPenguinCardCount + 1
self:AfterChangePenguinCard()
EventManager.Hit("PenguinCard_SelectPenguinCard", nAimIndex, bUpgrade)
end
function PenguinLevel:AfterChangePenguinCard()
local nAllLevel = 0
for _, v in ipairs(self.tbPenguinCard) do
if v ~= 0 then
nAllLevel = nAllLevel + v.nLevel
end
end
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.PenguinCardChange, {PenguinCardLevel = nAllLevel})
end
function PenguinLevel:CheckUpgradePenguinCard(mapSelectCard)
local bUpgrade = false
local nFirstEmpty = 0
local nAimIndex = 0
for i, v in ipairs(self.tbPenguinCard) do
if v == 0 and nFirstEmpty == 0 then
nFirstEmpty = i
end
if v ~= 0 and v.nGroupId == mapSelectCard.nGroupId then
bUpgrade = true
nAimIndex = i
break
end
end
if not bUpgrade then
nAimIndex = nFirstEmpty
end
return bUpgrade, nAimIndex
end
function PenguinLevel:SalePenguinCard(nIndex)
self:ChangeScore(self.tbPenguinCard[nIndex].nSoldPrice)
local mapCard = self.tbPenguinCard[nIndex]
local nGroupId = mapCard.nGroupId
self:RecyclePenguinCard(mapCard)
self.tbPenguinCard[nIndex] = 0
self:AfterChangePenguinCard()
EventManager.Hit("PenguinCard_SalePenguinCard", nIndex, nGroupId)
end
function PenguinLevel:GetRollPenguinCardCost()
local findIntervalIndex = function(x, starts)
if not starts or #starts == 0 or x < starts[1] then
return 1
end
local low, high = 1, #starts
local best = 1
while low <= high do
local mid = math.floor((low + high) / 2)
if x >= starts[mid] then
best = mid
low = mid + 1
else
high = mid - 1
end
end
return best
end
local mapData = self.mapBuyCost[self.nTurnBuyCount + 1]
local nIndex = findIntervalIndex(self.nCurTurn, mapData.Turn)
local nCost = mapData.Cost[nIndex]
return nCost
end
function PenguinLevel:ClearSelectablePenguinCard()
if next(self.tbSelectablePenguinCard) ~= nil then
for i = #self.tbSelectablePenguinCard, 1, -1 do
local mapCard = table.remove(self.tbSelectablePenguinCard, i)
self:RecyclePenguinCard(mapCard)
end
end
end
function PenguinLevel:GetRollPenguinCardResult()
local nLevel = self.nCurTurn
if type(self.GetPenguinCardWeightLevel) == "function" then
nLevel = self:GetPenguinCardWeightLevel()
end
local mapWeightCfg = ConfigTable.GetData("PenguinCardWeight", self.nWeightGroupId * 100 + nLevel)
if not mapWeightCfg then
return {}
end
local tbWeight = clone(mapWeightCfg.Weight)
self:AddPenguinCardWeightByTendency(tbWeight, mapWeightCfg.CardList)
local tbMaxGroupId = self:GetMaxLevelPenguinCard()
local nRoll = self.nPenguinCardRollCount + self.nTempAddRollCount
local tbId = PenguinCardUtils.WeightedRandom(mapWeightCfg.CardList, tbWeight, nRoll, tbMaxGroupId)
return tbId
end
function PenguinLevel:AddPenguinCardWeightByTendency(tbWeight, tbCardList)
local tbCardAdd = {}
local tbTendencyId = self:GetRollPenguinCardTendency()
for _, nTendencyId in pairs(tbTendencyId) do
local mapTendencyCfg = ConfigTable.GetData("PenguinCardTendency", nTendencyId)
if mapTendencyCfg then
local mapAddWeight = {}
for i, v in ipairs(mapTendencyCfg.CardGroup) do
mapAddWeight[v] = mapTendencyCfg.AddWeight[i]
end
for i, v in ipairs(tbCardList) do
local mapCardCfg = ConfigTable.GetData("PenguinCard", v)
if mapCardCfg and mapAddWeight[mapCardCfg.GroupId] then
tbWeight[i] = tbWeight[i] + mapAddWeight[mapCardCfg.GroupId]
if not tbCardAdd[v] then
tbCardAdd[v] = 0
end
tbCardAdd[v] = tbCardAdd[v] + mapAddWeight[mapCardCfg.GroupId]
end
end
end
end
return tbCardAdd
end
function PenguinLevel:GetRollPenguinCardTendency()
local mapTendency = {}
for _, v in ipairs(self.tbPenguinCard) do
if v ~= 0 and 0 < v.nTendencyGroup then
if not mapTendency[v.nTendencyGroup] then
mapTendency[v.nTendencyGroup] = 0
end
mapTendency[v.nTendencyGroup] = mapTendency[v.nTendencyGroup] + v.nTendencyScore
end
end
local tbTendencyId = {}
for nGroup, nScore in pairs(mapTendency) do
local tbScore = self.mapTendencyScore[nGroup]
local nLevel = 0
for k, v in ipairs(tbScore) do
if v <= nScore then
nLevel = k
end
end
if 0 < nLevel then
local nTendencyId = nGroup * 100 + nLevel
table.insert(tbTendencyId, nTendencyId)
end
end
return tbTendencyId
end
function PenguinLevel:GetMaxLevelPenguinCard()
local tbGroupId = {}
for _, v in ipairs(self.tbPenguinCard) do
if v ~= 0 and v.nLevel == v.nMaxLevel then
table.insert(tbGroupId, v.nGroupId)
end
end
return tbGroupId
end
function PenguinLevel:ChangeSpecificCard(tbAimId)
if next(self.tbSelectablePenguinCard) == nil then
return
end
local tbMaxGroupId = self:GetMaxLevelPenguinCard()
for i = #tbAimId, 1, -1 do
local mapCardCfg = ConfigTable.GetData("PenguinCard", tbAimId[i])
if mapCardCfg and table.indexof(tbMaxGroupId, mapCardCfg.GroupId) > 0 then
table.remove(tbAimId, i)
end
end
if next(tbAimId) == nil then
return
end
local nHasIndex = 0
for i, v in ipairs(self.tbSelectablePenguinCard) do
if 0 < table.indexof(tbAimId, v.nId) then
nHasIndex = i
v:SetHighLight(true)
break
end
end
if nHasIndex == 0 then
local nAimId = tbAimId[math.random(#tbAimId)]
local tbAimIndex = {}
for i, v in ipairs(self.tbSelectablePenguinCard) do
if not v.bHighLight then
table.insert(tbAimIndex, i)
end
end
if next(tbAimIndex) == nil then
return
end
local nAimIndex = tbAimIndex[math.random(#tbAimIndex)]
self.tbSelectablePenguinCard[nAimIndex]:Init(nAimId)
self.tbSelectablePenguinCard[nAimIndex]:SetHighLight(true)
end
end
function PenguinLevel:RecyclePenguinCard(mapCard)
mapCard:Clear()
table.insert(self.tbPenguinCardPool, mapCard)
end
function PenguinLevel:CreatePenguinCard(nId)
local mapCard
if next(self.tbPenguinCardPool) == nil then
mapCard = PenguinCard.new(nId)
else
mapCard = table.remove(self.tbPenguinCardPool, 1)
mapCard:Init(nId)
end
return mapCard
end
function PenguinLevel:ClearRoundData()
self.tbHandRank = {}
self.nHandRankId = 0
self.mapAllSuit = {}
self.nRoundScore = 0
self.nRoundValue = 0
self.nRoundRatio = 1
self.nRoundMultiRatio = 0
self.mapCalBaseCardPool = {}
end
function PenguinLevel:ChangeBaseCardWeight(tbChangeWeight)
for k, v in pairs(tbChangeWeight) do
local nIndex = table.indexof(self.mapCalBaseCardPool.tbId, tonumber(k))
self.mapCalBaseCardPool.tbWeight[nIndex] = self.mapCalBaseCardPool.tbWeight[nIndex] + v
end
end
function PenguinLevel:ShowBaseCard(nIndex)
local add = function(i)
if self.tbShowedCard[i] == false then
self.tbShowedCard[i] = true
local nId = self.tbBaseCardId[i]
local mapCfg = ConfigTable.GetData("PenguinBaseCard", nId)
if mapCfg then
local SuitCards = {}
local SuitCount = {}
for j = 1, 3 do
local nSuit = mapCfg["Suit" .. j]
local nCount = mapCfg["SuitCount" .. j]
if 0 < nSuit and 0 < nCount then
if not self.mapAllSuit[nSuit] then
self.mapAllSuit[nSuit] = 0
end
self.mapAllSuit[nSuit] = self.mapAllSuit[nSuit] + nCount
table.insert(SuitCards, nSuit)
SuitCount[nSuit] = nCount
end
end
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.Flip, {
SuitCards = SuitCards,
SuitCount = SuitCount,
BaseCard = {
nId = nId,
nIndex = i,
bReplaced = false
}
})
end
local mapAfterCfg = ConfigTable.GetData("PenguinBaseCard", self.tbBaseCardId[i])
if mapAfterCfg then
self:TriggerEffect(GameEnum.PenguinCardTriggerPhase.FlipEnd, {
BaseCard = {
nId = self.tbBaseCardId[i],
nIndex = i
}
})
if type(self.AfterShowBaseCard) == "function" then
self:AfterShowBaseCard(mapAfterCfg)
end
end
end
end
local bAll = nIndex == nil
if bAll then
for i = 1, self.nBaseCardCount do
add(i)
end
else
add(nIndex)
end
local nShowed = self:GetShowedCardCount()
if nShowed == self.nBaseCardCount then
self:CheckHandRank()
self:SwitchGameState()
end
EventManager.Hit("PenguinCard_ShowBaseCard", nIndex)
end
function PenguinLevel:CheckHandRank()
local tbAllSuit = {}
for k, v in pairs(self.mapAllSuit) do
table.insert(tbAllSuit, {nSuit = k, nCount = v})
end
local mapTendency = {}
for i = 1, 3 do
mapTendency[i] = 0
end
for _, v in ipairs(self.tbPenguinCard) do
if v ~= 0 and 0 < v.nTendencyGroup then
mapTendency[v.nTendencyGroup] = mapTendency[v.nTendencyGroup] + v.nTendencyScore
end
end
table.sort(tbAllSuit, function(a, b)
if a.nCount ~= b.nCount then
return a.nCount > b.nCount
elseif mapTendency[a.nSuit] ~= mapTendency[b.nSuit] then
return mapTendency[a.nSuit] > mapTendency[b.nSuit]
else
return a.nSuit < b.nSuit
end
end)
for _, v in ipairs(self.mapHandRankRule) do
self.tbHandRank = {}
local tbCount = v.SuitCount
local nType = #tbCount
local nHasType = #tbAllSuit
local nAble = 0
if nType <= nHasType then
for i = 1, nType do
if tbAllSuit[i].nCount >= tbCount[i] then
nAble = nAble + 1
for _ = 1, tbCount[i] do
table.insert(self.tbHandRank, tbAllSuit[i].nSuit)
end
end
end
end
if nAble == nType then
if next(self.tbHandRank) == nil then
for kk, vv in pairs(self.mapAllSuit) do
for _ = 1, vv do
table.insert(self.tbHandRank, kk)
end
end
end
self.nHandRankId = v.Id
if not self.tbHandRankCount[self.nHandRankId] then
self.tbHandRankCount[self.nHandRankId] = 0
end
self.tbHandRankCount[self.nHandRankId] = self.tbHandRankCount[self.nHandRankId] + 1
self:ChangeRoundScore(v.Value, v.Ratio, 0, true)
if type(self.AfterCheckHandRank) == "function" then
self:AfterCheckHandRank()
end
break
end
end
end
function PenguinLevel:ChangeRoundScore(nAddValue, nAddRatio, nAddMultiRatio, bFromHandRank)
local nBeforeScore = self.nRoundScore
local nBeforeBase = self.nRoundValue
local nBeforeMultiRatio = self.nRoundMultiRatio
local nBeforeRatio = self.nRoundRatio
self.nRoundValue = self.nRoundValue + nAddValue
if 0 < nAddMultiRatio then
if self.nRoundMultiRatio == 0 then
self.nRoundMultiRatio = 1
end
self.nRoundMultiRatio = self.nRoundMultiRatio + (nAddMultiRatio - 1)
end
self.nRoundRatio = self.nRoundRatio + nAddRatio
local nBeforeAllRatio = 0 < nBeforeMultiRatio and nBeforeMultiRatio * nBeforeRatio or nBeforeRatio
local nAfterAllRatio = self.nRoundMultiRatio > 0 and self.nRoundRatio * self.nRoundMultiRatio or self.nRoundRatio
nBeforeAllRatio = math.floor(nBeforeAllRatio * 100) / 100
nAfterAllRatio = math.floor(nAfterAllRatio * 100) / 100
self.nRoundScore = self.nRoundValue * nAfterAllRatio
local nAddScore = self.nRoundScore - nBeforeScore
self.nTurnScore = self.nTurnScore + nAddScore
if self.nTurnScore > self.nBestTurnScore then
self.nBestTurnScore = self.nTurnScore
end
if self.nRoundScore > self.nBestRoundScore then
self.nBestRoundScore = self.nRoundScore
end
EventManager.Hit("PenguinCard_ChangeRoundScore", nBeforeBase, nBeforeAllRatio, nBeforeScore, bFromHandRank)
if NovaAPI.IsEditorPlatform() then
printLog("轮积分变化:" .. nAddScore .. " (" .. nBeforeScore .. " -> " .. self.nRoundScore .. ")")
printLog("基础变化:" .. nAddValue .. " (" .. nBeforeBase .. " -> " .. self.nRoundValue .. ")")
printLog("倍率变化:" .. nAfterAllRatio - nBeforeAllRatio .. " (" .. nBeforeAllRatio .. " -> " .. nAfterAllRatio .. ")")
end
end
function PenguinLevel:GetShowedCardCount()
local nShowed = 0
for _, v in pairs(self.tbShowedCard) do
if v then
nShowed = nShowed + 1
end
end
return nShowed
end
function PenguinLevel:ReplaceBaseCard(nIndex, nBeforeId, mapAfter)
local tbId, tbWeight = {}, {}
for k, v in pairs(mapAfter) do
table.insert(tbId, tonumber(k))
table.insert(tbWeight, tonumber(v))
end
local tbAfter = PenguinCardUtils.WeightedRandom(tbId, tbWeight, 1)
local nAfterId = tbAfter[1]
local mapBeforeCfg = ConfigTable.GetData("PenguinBaseCard", nBeforeId)
local mapAfterCfg = ConfigTable.GetData("PenguinBaseCard", nAfterId)
if not mapBeforeCfg or not mapAfterCfg then
return
end
for i = 1, 3 do
local nSuit = mapBeforeCfg["Suit" .. i]
local nCount = mapBeforeCfg["SuitCount" .. i]
if 0 < nSuit and 0 < nCount then
self.mapAllSuit[nSuit] = self.mapAllSuit[nSuit] - nCount
end
end
for i = 1, 3 do
local nSuit = mapAfterCfg["Suit" .. i]
local nCount = mapAfterCfg["SuitCount" .. i]
if 0 < nSuit and 0 < nCount then
if not self.mapAllSuit[nSuit] then
self.mapAllSuit[nSuit] = 0
end
self.mapAllSuit[nSuit] = self.mapAllSuit[nSuit] + nCount
end
end
local bStone = true
for i = 1, 3 do
if mapAfterCfg["Suit" .. i] > 0 and mapAfterCfg["SuitCount" .. i] > 0 then
bStone = false
break
end
end
self.tbBaseCardId[nIndex] = nAfterId
EventManager.Hit("PenguinCard_ReplaceBaseCard", nIndex, bStone)
end
function PenguinLevel:AddSettlementHistory()
if not self.mapHandRankHistory[self.nHandRankId] then
self.mapHandRankHistory[self.nHandRankId] = 0
end
self.mapHandRankHistory[self.nHandRankId] = self.mapHandRankHistory[self.nHandRankId] + 1
local HandRankSuitCount = {}
for _, v in ipairs(self.tbHandRank) do
if not HandRankSuitCount[v] then
HandRankSuitCount[v] = 0
end
HandRankSuitCount[v] = HandRankSuitCount[v] + 1
if not self.mapSuitHistory[v] then
self.mapSuitHistory[v] = 0
end
self.mapSuitHistory[v] = self.mapSuitHistory[v] + 1
end
return HandRankSuitCount
end
function PenguinLevel:EndTurn()
local nBuffCount = #self.tbBuff
for i = nBuffCount, 1, -1 do
local bAble = self.tbBuff[i]:AddDuration_Turn()
if not bAble then
self:DeleteBuff(i)
end
end
end
function PenguinLevel:EndRound()
local nBuffCount = #self.tbBuff
for i = nBuffCount, 1, -1 do
local bAble = self.tbBuff[i]:AddDuration_Round()
if not bAble then
self:DeleteBuff(i)
end
end
end
function PenguinLevel:AddLog()
if not self.mapLog[self.nCurTurn] then
self.mapLog[self.nCurTurn] = {
nTurnScore = 0,
tbRound = {}
}
end
self.mapLog[self.nCurTurn].nTurnScore = self.nTurnScore
if not self.mapLog[self.nCurTurn].tbRound[self.nCurRound] then
self.mapLog[self.nCurTurn].tbRound[self.nCurRound] = {
nRoundScore = 0,
tbHandRank = {}
}
end
self.mapLog[self.nCurTurn].tbRound[self.nCurRound].nRoundScore = self.nRoundScore
self.mapLog[self.nCurTurn].tbRound[self.nCurRound].tbHandRank = clone(self.tbHandRank)
self.mapLog[self.nCurTurn].tbRound[self.nCurRound].nHandRankId = self.nHandRankId
end
function PenguinLevel:NextRound()
self:StopAuto()
if self:GetRoundLimitInTurn() == self.nCurRound and self.nCurTurn < self.nMaxTurn then
local callback = function()
self:SwitchGameState()
end
EventManager.Hit("PenguinCard_OpenLog", self.nCurTurn, false, callback)
else
self:SwitchGameState()
end
end
function PenguinLevel:CheckRound()
if self.nCheckRoundCount >= self.nCheckRoundLimit then
EventManager.Hit(EventId.OpenMessageBox, ConfigTable.GetUIText("PenguinCard_CheckRound_TurnFail"))
return false
end
if self.bCheckRound then
EventManager.Hit(EventId.OpenMessageBox, ConfigTable.GetUIText("PenguinCard_CheckRound_RoundFail"))
return false
end
self.nCheckRoundCount = self.nCheckRoundCount + 1
self:StopAuto()
self:RestoreSnapshot()
self:SwitchGameState()
return true
end
function PenguinLevel:GetMostHandRank()
local nCount = 0
local nId = 0
for k, v in pairs(self.mapHandRankHistory) do
if v > nCount then
nCount = v
nId = k
end
end
return nId, nCount
end
function PenguinLevel:GetMostSuit()
local nCount = 0
local nId = 0
for k, v in pairs(self.mapSuitHistory) do
if v > nCount then
nCount = v
nId = k
end
end
return nId, nCount
end
function PenguinLevel:GetBestPenguinCard()
local nCount = 0
local mapCard
for _, v in ipairs(self.tbPenguinCard) do
if v ~= 0 and nCount < v.nLevel then
nCount = v.nLevel
mapCard = v
end
end
return mapCard
end
function PenguinLevel:SetAutoState(bAuto)
self.bAuto = bAuto
LocalData.SetPlayerLocalData("PenguinCardAuto", self.bAuto)
end
function PenguinLevel:SetAutoSpeed(nSpeed)
self.nSpeed = nSpeed
LocalData.SetPlayerLocalData("PenguinCardSpeed", self.nSpeed)
if self.sequence then
self:StopAuto()
self:PlayAuto()
end
end
function PenguinLevel:PlayAuto(bClick)
if not self.bAuto or self.bPause then
return
end
if self.nGameState == PenguinCardUtils.GameState.Flip then
self.sequence = DOTween.Sequence()
for j = 1, self.nBaseCardCount do
if self.tbShowedCard[j] == false then
self.sequence:AppendCallback(function()
self:ShowBaseCard(j)
end)
self.sequence:AppendInterval(0.2 / self.nSpeed)
end
end
self.sequence:SetUpdate(true)
elseif self.nGameState == PenguinCardUtils.GameState.Settlement then
local bKeep = not PlayerData.Guide:CheckGuideFinishById(302)
if EditorSettings and EditorSettings.bJumpGuide then
bKeep = false
end
if bKeep then
return
end
self.sequence = DOTween.Sequence()
if not bClick then
self.sequence:AppendInterval((self.nRoundValue >= self.nFireScore and 7 or 5) / self.nSpeed)
end
self.sequence:AppendCallback(function()
EventManager.Hit("PenguinCard_QuitScoreAni")
if self:GetRoundLimitInTurn() == self.nCurRound and self.nCurTurn < self.nMaxTurn then
local callback = function()
self:SwitchGameState()
end
EventManager.Hit("PenguinCard_OpenLog", self.nCurTurn, false, callback)
else
self:SwitchGameState()
end
end)
self.sequence:SetUpdate(true)
end
end
function PenguinLevel:StopAuto()
if self.sequence then
self.sequence:Kill()
self.sequence = nil
end
end
function PenguinLevel:Pause()
self.bPause = true
if self.sequence then
self.sequence:Pause()
end
EventManager.Hit("PenguinCard_Pause")
end
function PenguinLevel:Resume()
self.bPause = false
if self.sequence then
self.sequence:Play()
else
self:PlayAuto()
end
EventManager.Hit("PenguinCard_Resume")
end
function PenguinLevel:ChangeScore(nChange)
if not nChange or nChange == 0 then
return
end
local nBefore = self.nScore
self.nScore = self.nScore + nChange
EventManager.Hit("PenguinCard_ChangeScore", nBefore)
if NovaAPI.IsEditorPlatform() then
printLog("总积分变化:" .. nChange .. " (" .. nBefore .. " -> " .. self.nScore .. ")")
end
end
function PenguinLevel:GetStar()
local nStar = 0
for i, v in ipairs(self.tbStarScore) do
if v <= self.nScore then
nStar = i
end
end
return nStar
end
function PenguinLevel:GetOwnPenguinCardCount()
local nCount = 0
for i = 1, 6 do
if self.tbPenguinCard[i] ~= 0 then
nCount = nCount + 1
end
end
return nCount
end
function PenguinLevel:ExecuteEffect(nEffectType, mapEffectValue, mapTriggerSource)
if nEffectType == GameEnum.PenguinCardEffectType.AddBaseCardWeight then
self:ChangeBaseCardWeight(mapEffectValue)
elseif nEffectType == GameEnum.PenguinCardEffectType.ReplaceBaseCard then
self:ReplaceBaseCard(mapTriggerSource.BaseCard.nIndex, mapTriggerSource.BaseCard.nId, mapEffectValue)
elseif nEffectType == GameEnum.PenguinCardEffectType.IncreaseBasicChips then
self:ChangeRoundScore(mapEffectValue, 0, 0)
elseif nEffectType == GameEnum.PenguinCardEffectType.IncreaseMultiplier then
self:ChangeRoundScore(0, mapEffectValue, 0)
elseif nEffectType == GameEnum.PenguinCardEffectType.MultiMultiplier then
self:ChangeRoundScore(0, 0, mapEffectValue)
elseif nEffectType == GameEnum.PenguinCardEffectType.UpgradeDiscount then
self.nUpgradeDiscount = mapEffectValue / 100
elseif nEffectType == GameEnum.PenguinCardEffectType.AddRound then
self.nTempAddRound = self.nTempAddRound + mapEffectValue
elseif nEffectType == GameEnum.PenguinCardEffectType.AddCardRollCount then
self.nTempAddRollCount = self.nTempAddRollCount + mapEffectValue
elseif nEffectType == GameEnum.PenguinCardEffectType.BlockFatalDamage then
self:ChangeHp(-1 * mapTriggerSource.nHpChange)
EventManager.Hit("PenguinCard_BlockFatalDamage")
elseif nEffectType == GameEnum.PenguinCardEffectType.UpgradeRebate then
self:ChangeScore(mapTriggerSource.nUpgradeCost * mapEffectValue / 100)
elseif nEffectType == GameEnum.PenguinCardEffectType.RollSpecificCard then
self:ChangeSpecificCard(mapEffectValue)
end
end
function PenguinLevel:TriggerEffect(nTriggerPhase, mapTriggerSource)
local callback = function(nEffectType, mapEffectValue)
self:ExecuteEffect(nEffectType, mapEffectValue, mapTriggerSource)
end
local nBuffCount = #self.tbBuff
for i = nBuffCount, 1, -1 do
local bTriggered = self.tbBuff[i]:Trigger(nTriggerPhase, mapTriggerSource, callback)
if bTriggered then
local bAble = self.tbBuff[i]:AddDuration_Count()
if not bAble then
local nDelayTime = self.tbBuff[i]:GetDelayTime()
self:DeleteBuff(i, nDelayTime)
end
end
end
for _, v in ipairs(self.tbPenguinCard) do
if v ~= 0 then
v:Trigger(nTriggerPhase, mapTriggerSource, callback)
v:Growth(nTriggerPhase, mapTriggerSource)
end
end
end
function PenguinLevel:SaveSnapshot()
local mapSnapshot = {
nCurTurn = self.nCurTurn,
nCurRound = self.nCurRound,
nHp = self.nHp,
nScore = self.nScore,
nTurnScore = self.nTurnScore,
tbHandRankCount = clone(self.tbHandRankCount),
mapLog = clone(self.mapLog),
nTotalRound = self.nTotalRound,
nBestTurnScore = self.nBestTurnScore,
nBestRoundScore = self.nBestRoundScore,
mapHandRankHistory = clone(self.mapHandRankHistory),
mapSuitHistory = clone(self.mapSuitHistory),
nGetPenguinCardCount = self.nGetPenguinCardCount
}
local tbBuffSnap = {}
local tbBuff = self.tbBuff or {}
for i = 1, #tbBuff do
tbBuffSnap[i] = tbBuff[i]:Serialize()
end
mapSnapshot.tbBuff = tbBuffSnap
local tbPenguinCardSnap = {}
local tbPenguinCard = self.tbPenguinCard or {}
for i = 1, 6 do
local v = tbPenguinCard[i]
if v == 0 or v == nil then
tbPenguinCardSnap[i] = 0
else
tbPenguinCardSnap[i] = v:Serialize()
end
end
mapSnapshot.tbPenguinCard = tbPenguinCardSnap
if type(self.SaveModeSnapshot) == "function" then
self:SaveModeSnapshot(mapSnapshot)
end
self.mapSnapshot = mapSnapshot
if self.bRestoreSnapshot == nil then
self.bRestoreSnapshot = false
end
end
function PenguinLevel:GetSnapshotState()
local bRestoreSnapshot = self.bRestoreSnapshot
self.bRestoreSnapshot = false
return bRestoreSnapshot == true
end
function PenguinLevel:RestoreSnapshot()
local mapSnapshot = self.mapSnapshot
if not mapSnapshot then
return
end
self.nCurTurn = mapSnapshot.nCurTurn
self.nCurRound = mapSnapshot.nCurRound
self.nHp = mapSnapshot.nHp
self.nScore = mapSnapshot.nScore
self.nTurnScore = mapSnapshot.nTurnScore
self.tbHandRankCount = clone(mapSnapshot.tbHandRankCount)
self.mapLog = clone(mapSnapshot.mapLog)
self.nTotalRound = mapSnapshot.nTotalRound
self.nBestTurnScore = mapSnapshot.nBestTurnScore
self.nBestRoundScore = mapSnapshot.nBestRoundScore
self.mapHandRankHistory = clone(mapSnapshot.mapHandRankHistory)
self.mapSuitHistory = clone(mapSnapshot.mapSuitHistory)
self.nGetPenguinCardCount = mapSnapshot.nGetPenguinCardCount
self:ClearRoundData()
local nBuffCount = #self.tbBuff
for i = nBuffCount, 1, -1 do
self:DeleteBuff(i, 0, true)
end
for _, mapData in ipairs(mapSnapshot.tbBuff) do
local mapBuff = self:CreateBuff(mapData.nId)
mapBuff:Deserialize(mapData)
self:AddBuff(mapBuff)
end
for i = 1, 6 do
local v = self.tbPenguinCard[i]
if v ~= 0 and v ~= nil then
self:RecyclePenguinCard(v)
end
local mapData = mapSnapshot.tbPenguinCard[i]
if mapData == 0 then
self.tbPenguinCard[i] = 0
else
local mapCard = self:CreatePenguinCard(mapData.nId)
mapCard:Deserialize(mapData)
self.tbPenguinCard[i] = mapCard
end
end
if type(self.RestoreModeSnapshot) == "function" then
self:RestoreModeSnapshot(mapSnapshot)
end
self.mapSnapshot = nil
self.bRestoreSnapshot = true
end
return PenguinLevel