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