rp_11001/assets/Game/scripts/game/HistoryDetail.ts
2025-12-09 10:49:19 +08:00

660 lines
24 KiB
TypeScript
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.

import { _decorator, assetManager, AssetManager, Button, Color, Component, instantiate, JsonAsset, Label, Layout, Node, resources, ScrollView, sp, Sprite, SpriteAtlas, SpriteFrame, tween, UITransform, Vec3 } from 'cc';
import { ScrollControl } from './ScrollControl';
import { fixNum, getTimezoneOffsetString, getTranslate, hideAllChildren, isBrahmic, updateLang, waitNextFrame } from './Tools';
const { ccclass, property } = _decorator;
@ccclass('HistoryDetail')
export class HistoryDetail extends Component {
@property(JsonAsset)
langJson: JsonAsset | null = null;
/**loading 动画节点*/
@property(Node)
loading: Node = null
@property(Node)
pnl_title: Node = null;
@property(Node)
item_round_winning: Node = null;
@property(ScrollView)
list_round_winning: ScrollView = null;
@property(Node)
item_detail: Node = null;
@property(ScrollView)
list_detail: ScrollView = null;
@property(Node)
item_symbol: Node = null;
@property(Node)
item_win_kind: Node = null;
@property(Node)
flip: Node = null;
@property(ScrollControl)
scrollControl: ScrollControl = null
@property(SpriteAtlas)
symbolsAtlas: SpriteAtlas = null!;
@property([SpriteFrame])
multiFrame = new Array<SpriteFrame>;
dict = null
data: any = null
protected onLoad(): void {
this.node.on("show_history_formula_detail", this.showFormulaDetail, this)
this.node.on("hide_history_formula_detail", this.hideFormulaDetail, this)
this.node.on("remark_round_winning_list", this.remarkRoundWinningList, this)
this.list_round_winning.node.active = false
this.item_round_winning.active = false
this.item_symbol.active = false
this.item_win_kind.active = false
this.item_detail.active = false
}
protected start(): void {
}
protected onDisable(): void {
this.node.off("show_history_formula_detail", this.showFormulaDetail, this)
this.node.off("hide_history_formula_detail", this.hideFormulaDetail, this)
this.node.off("remark_round_winning_list", this.remarkRoundWinningList, this)
}
setDetailData(data, lang: string) {
this.data = null
this.data = JSON.parse(JSON.stringify(data));
this.dict = this.langJson.json[lang] ?? this.langJson.json["en"];
updateLang(this.node, this.dict, lang)
// console.error(`0 this.data.panDetails.length, ${this.data.panDetails.length}`)
// for (let i = 0; i < 100; i++) {
// let one = JSON.parse(JSON.stringify(data.panDetails[0]))
// this.data.panDetails.push(one)
// }
// console.error(`0 this.data.panDetails.length, ${this.data.panDetails.length}`)
}
loadRoundWinningList(scoreInfos) {
this.data.scoreInfos = scoreInfos
const content = this.list_round_winning.content
content.destroyAllChildren()
const currencySymbol = this.data.currencySymbol
const yellowColor = new Color(0xFF, 0xAE, 0x00)
scoreInfos.forEach((v, i) => {
const item = instantiate(this.item_round_winning)
const txt_round = item.getChildByName("txt_round").getComponent(Label)
const txt_score = item.getChildByName("txt_score").getComponent(Label)
if (i == 0) {
txt_round.string = getTranslate(this.dict, "Normal Spin")
txt_round.color = yellowColor
txt_score.color = yellowColor
} else {
txt_round.string = getTranslate(this.dict, "Free Spin:") + ` ${i}/${scoreInfos.length - 1}`
txt_round.color = Color.WHITE
txt_score.color = Color.WHITE
}
txt_score.string = `${currencySymbol}${fixNum(v.Score)}`
item.name = v.StartIndex.toString()
item.position = new Vec3()
content.addChild(item)
});
}
jumpToPage(event) {
const item = event.target as any as Node
const page = item.name
this.scrollControl.jumpToPage(Number(page))
this.hideRoundWinningList()
}
remarkRoundWinningList(page) {
const txt_spin = this.pnl_title.getChildByName("txt_spin").getComponent(Label)
if (!this.data) {
return
}
if (!this.data.scoreInfos) {
txt_spin.string = getTranslate(this.dict, "Normal Spin")
return
}
let maxIdx = this.data.scoreInfos.length - 1
let findIndex = maxIdx
for (let i = maxIdx; i >= 0; i--) {
let scoreInfo = this.data.scoreInfos[i]
if (page >= scoreInfo.StartIndex) {
findIndex = i
break
}
}
// console.log(`findIndex, ${findIndex}`)
if (findIndex == 0) {
txt_spin.string = getTranslate(this.dict, "Normal Spin")
} else {
txt_spin.string = getTranslate(this.dict, "Free Spin:") + `${findIndex}/${maxIdx}`
}
const yellowColor = new Color(0xFF, 0xAE, 0x00)
this.list_round_winning.content.children.forEach((item, i) => {
const txt_round = item.getChildByName("txt_round").getComponent(Label)
const txt_score = item.getChildByName("txt_score").getComponent(Label)
if (i == findIndex) {
txt_round.color = yellowColor
txt_score.color = yellowColor
} else {
txt_round.color = Color.WHITE
txt_score.color = Color.WHITE
}
})
}
showRoundWinningList() {
let isActive = this.list_round_winning.node.active
if (isActive) {
this.hideRoundWinningList()
return
}
const node = this.list_round_winning.node
const content = this.list_round_winning.content
content.children.forEach(v => { v.active = true })
node.active = true
let startVec = new Vec3(0, 3000)
let endVec = new Vec3(0, 800)
node.position = startVec
tween(node).to(0.2, { position: endVec }).call(() => {
let sp = this.pnl_title.getChildByName("txt_spin").getChildByName("sp")
sp.scale = new Vec3(1, -1)
}).start()
}
hideRoundWinningList() {
const node = this.list_round_winning.node
const content = this.list_round_winning.content
let startVec = new Vec3(0, 3000)
tween(this.list_round_winning.node).to(0.2, { position: startVec })
.call(() => {
content.children.forEach(v => { v.active = false })
node.active = false
let sp = this.pnl_title.getChildByName("txt_spin").getChildByName("sp")
sp.scale = new Vec3(1, 1)
}).start()
}
// 加载一盘数据
loadOne(item: Node, pan, idx) {
item.position = new Vec3()
this.list_detail.content.addChild(item)
const currencySymbol = this.data.currencySymbol
const currency = this.data.currency
const info = item.getChildByName("info");
info.getChildByName("txt_transaction").getComponent(Label).string = this.data.roundId;
let bet = idx == 0 ? fixNum(pan.Bet) : fixNum(0)
info.getChildByName("txt_bet").getComponent(Label).string = bet;
info.getChildByName("Label_Bet").getComponent(Label).string = getTranslate(this.dict, "Bet") + `(${currencySymbol})`;
info.getChildByName("txt_profit").getComponent(Label).string = fixNum(pan.AllScore - pan.Bet);
info.getChildByName("Label_Profit").getComponent(Label).string = getTranslate(this.dict, "Profit") + `(${currencySymbol})`;
info.getChildByName("txt_balance_before").getComponent(Label).string = fixNum(pan.Balance - pan.AllScore + pan.Bet) + "➡️";
info.getChildByName("txt_balance_after").getComponent(Label).string = fixNum(pan.Balance);
info.getChildByName("Label_Balance").getComponent(Label).string = getTranslate(this.dict, "Balance") + `(${currencySymbol})`;
const content = item.getComponent(ScrollView).content;
const bet_info = content.getChildByName("bet_info")
if (pan.RoundInfo) {
const txt_round = bet_info.getChildByName("txt_round").getComponent(Label)
txt_round.string = getTranslate(this.dict, "Round:") + ` ${pan.RoundInfo.Current}/${pan.RoundInfo.Total}`
} else {
bet_info.getChildByName("txt_round").active = false
}
// 顶上四个横着摆的
// const hor_symbols = content.getChildByName("hor_symbols")
// hor_symbols.destroyAllChildren()
// pan.PanColor.Top.forEach((v, i) => {
// const item_symbol = instantiate(this.item_symbol)
// const bg = item_symbol.getChildByName("bg").getComponent(Sprite)
// const path_bg = `symbol_bg_${v}`
// bg.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_bg)
// const symbol = item_symbol.getChildByName("symbol").getComponent(Sprite)
// const path_symbol = `symbol_${v}_x1`
// symbol.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol)
// //顶部横着的一排全是铁框
// const frame = item_symbol.getChildByName("frame").getComponent(Sprite)
// const path_frame = `frame_0`
// frame.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_frame)
// // scatter 和 wild symbol没有金/银/铁框
// frame.node.active = !this.isScatterOrWild(v)
// item_symbol.position = new Vec3()
// item_symbol.active = true
// hor_symbols.addChild(item_symbol)
// })
// 下面几列竖着摆的
// 5行6列 的网格固定有6个竖列 每一列25个symbol
const vert_symbols = content.getChildByName("vert_symbols")
vert_symbols.children.forEach(vert => { vert.destroyAllChildren() });
// 每一竖列最多有5个symbol
const EACH_LINE_MAX_SYMBOL = 5
const sortArr = [];
const CroSymbolsKeys = Object.keys(pan.CroSymbols)
CroSymbolsKeys.forEach(v => {
sortArr.push(pan.CroSymbols[Number(v)])
})
sortArr.sort((a, b) => {
return a.PosFirst - b.PosFirst
})
let curCross = sortArr.shift()
let curSymbolIdx = curCross?.PosFirst
for (let i = 0; i < pan.Symbol.Middle.length;) {
// 如果i不等于当前需要处理的连体符号正常生成一个symbol
if (i != curSymbolIdx) {
const item_symbol = instantiate(this.item_symbol)
let v = pan.Symbol.Middle[i]
const bg = item_symbol.getChildByName("bg").getComponent(Sprite)
const path_bg = `${v > 8 ? 8 : v}_1`
bg.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_bg)
const symbol = item_symbol.getChildByName("symbol").getComponent(Sprite)
const path_symbol = `${v}`
symbol.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol)
//单个symbol 无框
const frame = item_symbol.getChildByName("frame").getComponent(Sprite)
// const path_frame = `frame_0`
// frame.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_frame)
frame.node.active = false
item_symbol.position = new Vec3()
item_symbol.active = true
// 通过 i 计算在第几行第几列
let row = i % EACH_LINE_MAX_SYMBOL
let line = Math.floor(i / EACH_LINE_MAX_SYMBOL)
// console.log(`第${i}个元素在,第${row}横行,第${line}竖列`)
vert_symbols.children[line].addChild(item_symbol)
i++
} else {
// console.log(`当前处理到CroSymbols ,curCrossIdx=${curCrossIdx}`)
// console.log(`遇到了连体元素i=${i},curSymbolIdx = ${curSymbolIdx}`)
const item_symbol = instantiate(this.item_symbol)
let v = pan.Symbol.Middle[i]
let length = curCross.PosLast - curCross.PosFirst + 1
// console.log(`${length}连框`)
// 组件长度拉长
item_symbol.getComponent(UITransform).height = item_symbol.getComponent(UITransform).height * length;
// 背景拉长
const bg = item_symbol.getChildByName("bg").getComponent(Sprite)
const path_bg = `${v > 8 ? 8 : v}_${length}`
bg.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_bg);
bg.node.getComponent(UITransform).height = bg.node.getComponent(UITransform).height * length;
const symbol = item_symbol.getChildByName("symbol").getComponent(Sprite)
const path_symbol = `${v}`
symbol.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol)
const frame = item_symbol.getChildByName("frame").getComponent(Sprite)
if (curCross?.Type != 0) {
let height = frame.node.getComponent(UITransform).height * length;
const path_frame = `13_${length}`
frame.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_frame)
frame.node.getComponent(UITransform).height = height;
frame.node.active = true
} else {
frame.node.active = false
}
item_symbol.position = new Vec3()
item_symbol.active = true
// 通过 i 计算在第几行第几列
let tmp = i
let row = tmp % EACH_LINE_MAX_SYMBOL
let line = Math.floor(tmp / EACH_LINE_MAX_SYMBOL)
// console.log(`第${i}个元素在,第${line}竖列,第${row}横行`)
vert_symbols.children[line].addChild(item_symbol)
curCross = sortArr.shift()
curSymbolIdx = curCross?.PosFirst
// 连体symbol的数据视为一个
i = i + length
}
}
// No Winning Combination
const node_no_winning = content.getChildByName("node_no_winning")
node_no_winning.active = !pan.WinInfo
// feature_buy
const node_feature_buy = content.getChildByName("node_feature_buy")
const isActive = this.data.isBuy && idx == 0
node_feature_buy.active = isActive
//showMulti
const showMultiNode = content.getChildByName('showMulti')
let multiValue = pan.Symbol.MultiValue
multiValue.push(multiValue[3] + 2)
for (let i = 0; i < multiValue.length; i++) {
showMultiNode.getChildByName('bg').children[i].getChildByName('multi').getComponent(Label).string = 'x' + multiValue[i]
showMultiNode.getChildByName('bg').children[i].getChildByName('multi').setPosition(0, 0, 0)
switch (true) {
case multiValue[i] <= 4:
showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[0]
break
case multiValue[i] <= 8 && multiValue[i] > 4:
showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[1]
break
case multiValue[i] <= 16 && multiValue[i] > 8:
showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[2]
break
case multiValue[i] > 16:
showMultiNode.getChildByName('bg').children[i].getComponent(Sprite).spriteFrame = this.multiFrame[3]
break
}
}
if (pan.WinInfo && pan.WinInfo.MultPos) {
for (let key in pan.WinInfo.MultPos) {
console.log('key', key)
showMultiNode.getChildByName('bg').children[key].getChildByName('multi').setPosition(0, 110, 0)
}
}
// Win Multiplier x ?
const node_win_multiplier = content.getChildByName("node_win_multiplier")
const txt_win_multiplier = node_win_multiplier.getChildByName("txt_win_multiplier")
if (pan.WinInfo && pan.WinInfo.Multi > 0) {
let multi = pan.WinInfo.Multi == 0 ? 1 : pan.WinInfo.Multi
txt_win_multiplier.getComponent(Label).string = getTranslate(this.dict, "Win Multiplier") + " x " + multi
node_win_multiplier.active = true
} else {
node_win_multiplier.active = false
}
// scatter 数量统计 node_scatter
if (pan.ScNum >= 4 && pan.GetGamesTimes >= 10) {
const node_scatter = content.getChildByName("node_scatter")
const txt_scatter_num = node_scatter.getChildByName("txt_scatter_num").getComponent(Label)
txt_scatter_num.string = "x " + pan.ScNum
const txt_free_spin = node_scatter.getChildByName("txt_free_spin").getComponent(Label)
txt_free_spin.string = pan.GetGamesTimes + " " + getTranslate(this.dict, "Free Spins")
node_scatter.active = true
} else {
const node_scatter = content.getChildByName("node_scatter")
node_scatter.removeFromParent()
node_scatter.destroy()
}
const symbolWinInfosKeys = pan.WinInfo ? Object.keys(pan.WinInfo.Desc) : []
// 赢分符号统计
if (symbolWinInfosKeys.length > 0) {
const node_formula = content.getChildByName("node_formula")
symbolWinInfosKeys.forEach((v) => {
// console.log("symbol:", v, " = ", pan.SymbolWinInfos[v])
const symbolWinInfo = pan.WinInfo.Desc[v]
const item_win_kind = instantiate(this.item_win_kind)
item_win_kind.name = `item_win_kind_${v}`
const sp = item_win_kind.getChildByName("sp").getComponent(Sprite)
const path_symbol = `${v}`
sp.spriteFrame = this.symbolsAtlas.getSpriteFrame(path_symbol)
const txt_kind = item_win_kind.getChildByName("txt_kind").getComponent(Label)
txt_kind.string = symbolWinInfo.WinAxisNum.toString() + " " + getTranslate(this.dict, "of a Kind")
const txt_ways = item_win_kind.getChildByName("txt_ways").getComponent(Label)
txt_ways.string = symbolWinInfo.Ways.toString() + " " + getTranslate(this.dict, "way(s)")
const txt_win = item_win_kind.getChildByName("txt_win").getComponent(Label)
txt_win.string = currencySymbol + fixNum(symbolWinInfo.Score)
const txt_formula = item_win_kind.getChildByName("txt_formula").getComponent(Label)
txt_formula.string = symbolWinInfo.Formula
const formula_detail = item_win_kind.getChildByName("formula_detail")
const txt_formual_detail = formula_detail.getChildByName("txt_formual_detail").getComponent(Label)
txt_formual_detail.string = symbolWinInfo.FormulaDetail
formula_detail.active = false
item_win_kind.position = new Vec3()
item_win_kind.active = true
node_formula.addChild(item_win_kind)
})
// 每一条 item_win_kind 可以点开 自己的 formula_detail
// 要求列表前面的item_win_kind弹出来formula_detail ,盖住后面的 item_win_kind
// 但 addChild的顺序决定后 后面会盖住前面,所以这里要反转一下
// 而且一定要关掉 Layout ,因为它会把 SiblingIndex最小的放到最上面
const lyt = node_formula.getComponent(Layout)
lyt.updateLayout()
lyt.enabled = false
const children = node_formula.children.slice().reverse();
children.forEach((child, i) => {
child.active = true
child.setSiblingIndex(i);
});
const contentlyt = content.getComponent(Layout)
contentlyt.updateLayout()
contentlyt.enabled = false
// 多给一截滑动空间
content.getComponent(UITransform).height = content.getComponent(UITransform).height + 160
}
hideAllChildren(item)
}
async loadDetailList() {
// 时间
let pnl_title = this.node.getChildByName("pnl_title")
let txt_time = pnl_title.getChildByName("txt_time").getComponent(Label)
const timestamp = this.data.startTime;
const date = new Date(timestamp * 1000); // JS 使用毫秒,所以要 *1000
const pad = (n: number) => (n < 10 ? '0' + n : String(n));
const formatted = `${date.getFullYear()}/${pad(date.getMonth() + 1)}/${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
let str = formatted + getTimezoneOffsetString()
txt_time.string = str
const currencySymbol = this.data.currencySymbol
const currency = this.data.currency
const scoreInfos = this.data.panDetails[0].ScoreInfos
const btn_winning_list = this.pnl_title.getChildByName("txt_spin").getChildByName("btn_winning_list").getComponent(Button)
const sp = this.pnl_title.getChildByName("txt_spin").getChildByName("sp")
if (scoreInfos) {
this.loadRoundWinningList(scoreInfos)
btn_winning_list.interactable = true
sp.active = true
} else {
btn_winning_list.interactable = false
sp.active = false
}
this.data.panDetails.forEach(async (pan, idx) => {
const item = instantiate(this.item_detail);
item.active = true
this.loadOne(item, pan, idx)
if (idx == this.data.panDetails.length - 1) {
// console.log("已全部生成完")
this.hideLoading()
this.scrollControl.jumpToPage(0)
}
// 等待下一帧再生成下一个
await waitNextFrame();
})
this.scrollControl.vert_scrollView = this.list_detail.content.children[0].getComponent(ScrollView)
this.list_detail.node.active = true
}
// wild 是0 scatter 是1
isScatterOrWild(v) {
return v == 0 || v == 1
}
clickPageUp() {
this.scrollControl.pageUp()
}
clickPageDown() {
this.scrollControl.pageDown()
}
async entryFinish() {
// this.node.children.forEach((node, i) => {
// node.active = true
// })
this.showLoading()
await this.loadDetailList()
}
removeReturnBtn() {
let btn_return = this.node.getChildByName("btn_return")
btn_return.destroy()
}
clickReturn() {
const self = this
tween(this.node).to(0.2, { position: new Vec3(2000, 0) })
.call(() => {
self.node.destroy()
})
.start()
}
// 传过来的是 item_win_kind
showFormulaDetail(item_win_kind) {
// 隐藏其他的formula_detail
item_win_kind.parent.children.forEach(child => {
if (child != item_win_kind)
child.getChildByName("formula_detail").active = false
})
// 显示就隐藏,隐藏就显示
let isActive = item_win_kind.getChildByName("formula_detail").active
item_win_kind.getChildByName("formula_detail").active = !isActive
}
// 传过来的是 item_win_kind
showFormulaDetail2(event) {
const btn = event.target as Node as any
const item_win_kind = btn.parent
// 隐藏其他的formula_detail
item_win_kind.parent.children.forEach(child => {
if (child != item_win_kind)
child.getChildByName("formula_detail").active = false
})
// 显示就隐藏,隐藏就显示
let isActive = item_win_kind.getChildByName("formula_detail").active
item_win_kind.getChildByName("formula_detail").active = !isActive
}
hideFormulaDetail(scrollVeiw: ScrollView) {
const node_formula = scrollVeiw.content.getChildByName("node_formula")
node_formula.children.forEach(node => {
node.getChildByName("formula_detail").active = false
})
}
showLoading() {
this.loading.active = true
let sk = this.loading.getComponent(sp.Skeleton)
sk.paused = false
sk.loop = true
}
hideLoading() {
let sk = this.loading.getComponent(sp.Skeleton)
sk.paused = true
sk.loop = false
this.loading.active = false
}
}