diff --git a/cutscene/dialogue/DialogueAction.gd b/cutscene/dialogue/DialogueAction.gd index 054b858..21a4009 100644 --- a/cutscene/dialogue/DialogueAction.gd +++ b/cutscene/dialogue/DialogueAction.gd @@ -16,11 +16,8 @@ static func dialogueCallable(params:Dictionary) -> int: UI.dialogueActive = true var line:DialogueLine = await DialogueManager.get_next_dialogue_line(resource, title, extraStates) while line != null: - var text:String = line.text - if line.character: - text = line.character + ": " + text - var target:Node3D = _getLineTarget(line.character, characterTargets) + var text:String = line.text if line.responses.size() > 0: # Show text then auto-pick the first allowed response. diff --git a/overworld/entity/EntityMovement.gd b/overworld/entity/EntityMovement.gd index 4cdb492..8267096 100644 --- a/overworld/entity/EntityMovement.gd +++ b/overworld/entity/EntityMovement.gd @@ -20,7 +20,7 @@ func _applyGravity() -> void: func _applyPlayerMovement(delta:float): # Interactions, may move if Input.is_action_just_pressed("interact") && interactingArea && interactingArea.hasInteraction(): - if !UI.hasAdvanceableChatBox(): + if !UI.hasAdvanceableChatBox() && !UI.dialogueActive: interactingArea.interact() return @@ -63,8 +63,6 @@ func _applyFriction(delta:float) -> void: entity.velocity.z *= delta * FRICTION func _canMove() -> bool: - if UI.dialogueActive: - return false if !UI.MAIN_CHATBOX.isClosed: return false if UI.GAME_MENU && UI.GAME_MENU.isOpen(): diff --git a/overworld/entity/EntityProximityArea.gd b/overworld/entity/EntityProximityArea.gd index 11e020d..6ebd1a4 100644 --- a/overworld/entity/EntityProximityArea.gd +++ b/overworld/entity/EntityProximityArea.gd @@ -3,9 +3,11 @@ class_name EntityProximityArea extends Area3D @export var entity:Entity var _triggered:bool = false +var _chatbox:WorldChatBox = null func _ready() -> void: body_entered.connect(_onBodyEntered) + body_exited.connect(_onBodyExited) func _onBodyEntered(body:Node3D) -> void: if _triggered: @@ -16,5 +18,15 @@ func _onBodyEntered(body:Node3D) -> void: return _triggered = true assert(entity != null && entity.chatboxMessage != "") - var chatbox:WorldChatBox = UI.spawnWorldChatBox(entity) - chatbox.showTimed(entity.chatboxMessage, entity.chatboxDuration) + if is_instance_valid(_chatbox) and _chatbox.visible: + _chatbox.resetTimer(entity.chatboxDuration) + else: + _chatbox = UI.spawnWorldChatBox(entity) + _chatbox.showTimed(entity.chatboxMessage, entity.chatboxDuration) + +func _onBodyExited(body:Node3D) -> void: + if !(body is Entity): + return + if (body as Entity).entityId != "player": + return + _triggered = false diff --git a/ui/component/VNTextbox.gd b/ui/component/VNTextbox.gd index 0c2639d..66f5cbc 100644 --- a/ui/component/VNTextbox.gd +++ b/ui/component/VNTextbox.gd @@ -68,75 +68,86 @@ func _updateWorldPosition() -> void: func _process(delta: float) -> void: if isClosed: - return; + return _updateWorldPosition() - # _recalcText always resets fit_content to false; re-apply so the - # PanelContainer can grow to its content height in world-space mode. + # _recalcText always resets fit_content; keep it on in world-space mode so + # the PanelContainer auto-sizes to the full speech-bubble content. if worldTarget != null and !label.fit_content: label.fit_content = true if label.getFinalText() == "": - isClosed = true; - return; - - if Input.is_action_just_released("interact") && !hasLetGoOfInteract: - hasLetGoOfInteract = true; + isClosed = true return - # Have we finished displaying the current page? - if label.visible_characters >= label.getCharactersDisplayedCount(): - # Not finished displaying current page + if Input.is_action_just_released("interact") and !hasLetGoOfInteract: + hasLetGoOfInteract = true + return + + # World-space (speech-bubble) mode: all text is shown immediately with no + # typing reveal. One press advances to the next page; release closes the last. + if worldTarget != null: if (label.maxLines + label.startLine) < label.getTotalLineCount(): - if Input.is_action_just_pressed("interact") && hasLetGoOfInteract: - label.startLine += label.maxLines; - label.visible_characters = 0; - currentViewScrolled = false; - return - - currentViewScrolled = true; + if Input.is_action_just_pressed("interact") and hasLetGoOfInteract: + label.startLine += label.maxLines + label.fit_content = true else: - # On last page - if Input.is_action_just_released("interact") && hasLetGoOfInteract: - chatboxClosing.emit(); - isClosed = true; + if Input.is_action_just_released("interact") and hasLetGoOfInteract: + chatboxClosing.emit() + isClosed = true + return + + # Bottom-bar mode: typing reveal with paging. + if label.visible_characters >= label.getCharactersDisplayedCount(): + if (label.maxLines + label.startLine) < label.getTotalLineCount(): + if Input.is_action_just_pressed("interact") and hasLetGoOfInteract: + label.startLine += label.maxLines + label.visible_characters = 0 + currentViewScrolled = false + return currentViewScrolled = true - return; + else: + if Input.is_action_just_released("interact") and hasLetGoOfInteract: + chatboxClosing.emit() + isClosed = true + currentViewScrolled = true + return - # This prevents the game trying to advance if the player is still holding - # down interact. - if Input.is_action_just_pressed("interact") && hasLetGoOfInteract: - isSpeedupDown = true; - elif Input.is_action_just_released("interact") && hasLetGoOfInteract: - isSpeedupDown = false; - elif !Input.is_action_pressed("interact") && hasLetGoOfInteract: - isSpeedupDown = false; + if Input.is_action_just_pressed("interact") and hasLetGoOfInteract: + isSpeedupDown = true + elif Input.is_action_just_released("interact") and hasLetGoOfInteract: + isSpeedupDown = false + elif !Input.is_action_pressed("interact") and hasLetGoOfInteract: + isSpeedupDown = false - revealTimer += delta; + revealTimer += delta if isSpeedupDown: - revealTimer += delta; + revealTimer += delta if revealTimer > VN_REVEAL_TIME: - revealTimer = 0; - label.visible_characters += 1; + revealTimer = 0 + label.visible_characters += 1 func setText(text:String, target:Node3D = null) -> void: worldTarget = target _setWorldLayout(worldTarget != null) - # Resets scroll - revealTimer = 0; - currentViewScrolled = false; - label.startLine = 0; + revealTimer = 0 + currentViewScrolled = false + label.startLine = 0 + label.text = text - label.text = text; - label.visible_characters = 0; + if worldTarget != null: + # Speech-bubble mode: show all text immediately and auto-size the container. + # _recalcText already sets visible_characters = -1; just enable fit_content. + label.fit_content = true + else: + label.visible_characters = 0 - # Resets speedup and advancing - hasLetGoOfInteract = !Input.is_action_pressed("interact"); + hasLetGoOfInteract = !Input.is_action_pressed("interact") isSpeedupDown = false - isClosed = false; + isClosed = false func setTextAndWait(text:String, target:Node3D = null) -> void: self.setText(text, target); diff --git a/ui/component/WorldChatBox.gd b/ui/component/WorldChatBox.gd index b9e94b2..cec7218 100644 --- a/ui/component/WorldChatBox.gd +++ b/ui/component/WorldChatBox.gd @@ -22,6 +22,9 @@ func showTimed(text:String, duration:float) -> void: _label.text = text visible = true +func resetTimer(duration:float) -> void: + _timer = duration + func showAdvanceable(text:String) -> void: mode = Mode.ADVANCEABLE _label.text = text