xiandie/scene/ground/script/c03/s04_closeup麻将出千游戏.gd
2025-07-11 00:29:46 +08:00

312 lines
9.9 KiB
GDScript
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.

extends CanvasLayer
signal exit(arg)
@onready var bg = $BG as TextureRect
@onready var front_lay = $MahjongsFrontLay as CanvasItem
@onready var hand = $Hand as CanvasItem
@onready var stand_root = $Stand as CanvasItem
@onready var grid = $Stand/MahjongGrid as GridContainer
var mahjongs = {
# [type][number]
"风南": preload("uid://6hdekasuabnm"),
"万2": preload("uid://c6xcefh4x2t5h"),
"万3": preload("uid://dc6sj2holh1gn"),
"万5": preload("uid://bd12rrssmrdbs"),
"条1": preload("uid://batbu02i8svf6"),
"条2": preload("uid://cbn74yc8j72v6"),
"条3": preload("uid://b66kqhy1mmhc5"),
"筒1": preload("uid://ccpexjd64s5nn"),
"筒2": preload("uid://djefka3gyhxsv"),
"筒4": preload("uid://da50cog64b0tb"),
"筒7": preload("uid://c7tea8ostqbiu"),
"筒8": preload("uid://cr6404ghilc7u"),
"筒9": preload("uid://iovhne3h5dqe"),
}
@onready var standing_mahjongs_btn: Array[TextureButton] = [%"0", %"1", %"2", %"3", %"4", %"5", %"6", %"7", %"8", %"9", %"10", %"11", %"12", %"13"]
# 替换后会从数组中移除
@onready var holding_mahjongs_btn_dict: Dictionary[int, TextureButton] = {14: %"14", 15: %"15", 16: %"16"}
var current_round := 0
# 回合1-4摸牌3万、2万、1条、2筒胜利
var dispatched_card_per_round: Array[String] = ["万3", "万2", "条1", "筒2"]
# 回合1-3自动打出的牌+3个密码共六张2万、3万、1条、南风、4筒、1筒
var useless_cards: Array[String] = ["万2", "万3", "条1", "风南", "筒4", "筒1"]
# 玩家初始牌型13张78筒x1 南风x1 12条x1 4筒x1 5万x2 2筒x2 9筒x2 1筒
# 胜利牌型2筒x3、9筒x2、5万x3、123条x1、789筒x1
var standing_cards: Array[String] = ["筒7", "筒8", "风南", "条1", "条2", "筒4", "万5", "万5", "筒2", "筒2", "筒9", "筒9", "筒1", ""]
# 赖子手在左下角桌子下手中为三个麻将5万、3条、9筒
var holding_cards_dict: Dictionary[int, String] = {14: "万5", 15: "条3", 16: "筒9"}
var freezing = true:
set(val):
if freezing != val:
freezing = val
if freezing and selected_btn:
_toggle_selected(selected_btn, false)
var success = false
var selected_btn: TextureButton
var c03_dialog = preload("uid://b66v5hsf3tdox")
func _ready() -> void:
layer = GlobalConfig.CANVAS_LAYER_LITTLE_GAME
stand_root.hide()
hand.hide()
_toggle_hightlight_for_all(false)
for b in standing_mahjongs_btn:
b.mouse_entered.connect(_toggel_hover.bind(b, true))
b.mouse_exited.connect(_toggel_hover.bind(b, false))
b.pressed.connect(_on_btn_pressed.bind(b))
for b in holding_mahjongs_btn_dict.values():
b.mouse_entered.connect(_toggel_hover.bind(b, true))
b.mouse_exited.connect(_toggel_hover.bind(b, false))
b.pressed.connect(_on_btn_pressed.bind(b))
# 检查是否从整理麻将游戏中跳转过来
var transition_time = ArchiveManager.runtime_get("c03_mahjong_game_black_transition_time", 0.0)
if transition_time > 0:
await Util.wait(transition_time)
_play_dialogue_with_update_stage(0)
await _await_dialog(0)
_start_game()
func _toggel_hover(btn: TextureButton, hovering: bool) -> void:
if freezing:
return
if btn.disabled:
hovering = false
_toggle_hightlight(btn, hovering)
func _on_btn_pressed(btn: TextureButton) -> void:
if freezing:
return
if btn != selected_btn:
if selected_btn:
_toggle_selected(selected_btn, false)
_exchange_texture_and_card(btn, selected_btn)
selected_btn = null
else:
$SfxSelect.play()
_toggle_selected(btn, true)
selected_btn = btn
else:
$SfxSelect.play()
_toggle_selected(btn, false)
selected_btn = null
func _toggle_selected(btn:TextureButton, selected: bool) -> void:
# 0-13 push up. 14-16 in hand, push down.
var front := int(btn.name) <= 13
if (front and selected) or (not front and not selected):
btn.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
else:
btn.size_flags_vertical = Control.SIZE_SHRINK_END
func _align_card_textures() -> void:
# holding_mahjongs_btn 长度会变
for k in holding_mahjongs_btn_dict:
holding_mahjongs_btn_dict[k].texture_normal = mahjongs[holding_cards_dict[k]]
# standing_mahjongs_btn 长度不变
for i in 14:
if standing_cards[i]:
standing_mahjongs_btn[i].texture_normal = mahjongs[standing_cards[i]]
standing_mahjongs_btn[i].modulate = Color.WHITE
standing_mahjongs_btn[i].show()
else:
standing_mahjongs_btn[i].hide()
# 发牌
func _start_game() -> void:
# show_hand 结束时会自动 hand_swing
$AnimationPlayer.play("show_hand")
_play_dialogue_with_update_stage(1)
$SfxStart.play()
stand_root.show()
hand.show()
front_lay.hide()
# dispatch and shuffle
standing_cards[13] = dispatched_card_per_round[current_round]
standing_cards.shuffle()
_align_card_textures()
# shuffle all cards
for b in standing_mahjongs_btn:
_toggle_selected(b, true)
var tween = create_tween()
tween.tween_interval(1.0)
var sfx = $SfxPlace
for b in standing_mahjongs_btn:
tween.tween_interval(0.15)
tween.tween_callback(sfx.play.bind(0.15))
tween.tween_callback(_toggle_selected.bind(b, false))
tween.tween_interval(1.5)
tween.tween_callback(standing_cards.sort)
tween.tween_callback(_align_card_textures)
tween.tween_callback($SfxShuffle.play)
await _await_dialog(1)
if tween and tween.is_running():
await tween.finished
freezing = false
_play_dialogue_with_update_stage(2)
func _play_dialogue_with_update_stage(stage: int):
DialogueManager.show_dialogue_balloon(c03_dialog, "c03_s04_打麻将游戏" + str(stage))
if DialogueManager.dialogue_ended.is_connected(_update_last_dialog):
DialogueManager.dialogue_ended.disconnect(_update_last_dialog)
DialogueManager.dialogue_ended.connect(_update_last_dialog.bind(stage), CONNECT_ONE_SHOT)
var _last_dialog_stage := -1
signal _last_dialog_updated
func _update_last_dialog(_res, id: int) -> void:
if id > _last_dialog_stage:
_last_dialog_stage = id
_last_dialog_updated.emit()
func _await_dialog(id: int) -> void:
if _last_dialog_stage >= id:
return
await _last_dialog_updated
await _await_dialog(id)
func _exchange_texture_and_card(btn1: TextureButton, btn2: TextureButton) -> void:
if btn1 and btn2:
$SfxSwitch.play()
# exchange texture
var texture = btn1.texture_normal
btn1.texture_normal = btn2.texture_normal
btn2.texture_normal = texture
# exchange card name
var id1 := int(btn1.name)
var id2 := int(btn2.name)
var card_name1 = standing_cards[id1] if id1 <= 13 else holding_cards_dict[id1]
var card_name2 = standing_cards[id2] if id2 <= 13 else holding_cards_dict[id2]
if id1 <= 13:
standing_cards[id1] = card_name2
else:
holding_cards_dict[id1] = card_name2
if id2 <= 13:
standing_cards[id2] = card_name1
else:
holding_cards_dict[id2] = card_name1
# 判断回合是否成功
# 要求: 1、standing 区域有 auto_deal_card 2、holding 区域有 should_be_replaced_card
# 查找手牌 id 与区域 id
# 优先先从手里着,再从桌面找不重复的
var require_replacing_card = intersect(useless_cards, holding_cards_dict)
var require_dealing_card = intersect(useless_cards, standing_cards, require_replacing_card)
if require_replacing_card and require_dealing_card:
useless_cards.erase(require_replacing_card)
useless_cards.erase(require_dealing_card)
_toggle_hightlight_for_all(false)
# 开始执行替换
freezing = true
await Util.wait(2.0)
# 重新排序
standing_cards.sort()
$SfxShuffle.play()
_align_card_textures()
var standing_id = standing_cards.find(require_dealing_card)
standing_cards.remove_at(standing_id)
standing_cards.append("")
# 替换到手牌后消失
var holding_id = holding_cards_dict.find_key(require_replacing_card)
var holding_btn = holding_mahjongs_btn_dict[holding_id]
holding_mahjongs_btn_dict.erase(holding_id)
holding_cards_dict.erase(holding_id)
var tween = create_tween()
# 渐隐,表示打出
tween.tween_property(standing_mahjongs_btn[standing_id], "modulate:a", 0.0, 3.0)
# tween.parallel().tween_property(holding_btn, "modulate:a", 0.0, 3.0)
# tween.tween_callback(holding_btn.queue_free)
tween.tween_callback(func(): holding_btn.disabled = true)
tween.tween_callback(_align_card_textures)
tween.tween_callback($SfxShuffle.play)
# 下一回合 unfreeze
tween.tween_interval(2.0)
tween.tween_callback(_next_round)
func intersect(arr:Array, b, except := ""):
var first_intersection = ""
if b is Dictionary:
for item in b.values():
if except and item == except:
continue
if arr.has(item):
first_intersection = item
break
elif b is Array:
for item in arr:
if except and item == except:
continue
if b.has(item):
first_intersection = item
break
return first_intersection
func _next_round() -> void:
freezing = true
current_round += 1
if current_round == 1:
# 第一回合结束
await _await_dialog(2)
_play_dialogue_with_update_stage(3)
# 对话结束后,开始第二回合
await _await_dialog(3)
_play_dialogue_with_update_stage(4)
elif current_round == 2:
# 第二回合结束
await _await_dialog(4)
_play_dialogue_with_update_stage(5)
# 对话结束后,开始第三回合
await _await_dialog(5)
_play_dialogue_with_update_stage(6)
elif current_round == 3:
# 第三回合结束
await _await_dialog(6)
_play_dialogue_with_update_stage(7)
await _await_dialog(7)
# 开始第四回合,自摸后成功
_play_dialogue_with_update_stage(8)
standing_cards[13] = dispatched_card_per_round[current_round]
$SfxPlace.play()
_align_card_textures()
await Util.wait(1.0)
standing_cards.sort()
$SfxShuffle.play()
_align_card_textures()
# 第四回合胜利
if current_round == 3:
await Util.wait(1.0)
$SfxSuccess.play()
print("success")
await _await_dialog(8)
exit.emit(true)
else:
freezing = false
func _toggle_hightlight(btn: TextureButton, hightlight: bool) -> void:
if null == btn:
return
btn.get_node("光束").enabled = hightlight
func _toggle_hightlight_for_all(hightlighted: bool) -> void:
for b in standing_mahjongs_btn:
_toggle_hightlight(b, hightlighted)
for b in holding_mahjongs_btn_dict.values():
_toggle_hightlight(b, hightlighted)