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)