From ce1c9849a88e8f2f88444e66329c0a500fb21e8e Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 17:34:17 +0200 Subject: [PATCH 01/16] feat: add NSCreateChoiceOnPlayer server-side function --- .../mod/scripts/vscripts/sh_message_utils.gnut | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 4cfdc6fba..e9c7ffab0 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -3,6 +3,7 @@ global function MessageUtils_ServerInit global function NSCreatePollOnPlayer global function NSGetPlayerResponse +global function NSCreateChoiceOnPlayer global function NSSendLargeMessageToPlayer global function NSSendPopUpMessageToPlayer @@ -76,7 +77,8 @@ enum eMessageType INFO, CREATE_STATUS, EDIT_STATUS, - DELETE_STATUS + DELETE_STATUS, + CHOICE } enum eDataType @@ -92,7 +94,9 @@ enum eDataType COLOR, PRIORITY, STYLE, - ID + ID, + CHOICE_OPTION, + CHOICE_DURATION } #if SERVER @@ -168,6 +172,14 @@ int function NSGetPlayerResponse( entity player ) return server.playerPollResponses[ player ] - 1 } +void function NSCreateChoiceOnPlayer( entity player, string option1, string option2, float duration ) +{ + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option1 ) + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option2 ) + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_DURATION + " " + duration ) + ServerToClientStringCommand( player, "ServerHUDMessageShow " + eMessageType.CHOICE ) +} + void function NSSendLargeMessageToPlayer( entity player, string title, string description, float duration, string image ) { ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.TITLE + " " + title ) From c16037fd42c447f20f9b610c1d7d1d1f92fd8c94 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 17:40:53 +0200 Subject: [PATCH 02/16] feat: send choice parameters to client --- .../mod/scripts/vscripts/sh_message_utils.gnut | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index e9c7ffab0..7aa5c18a4 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -50,6 +50,15 @@ struct bool pollActive array ruis } poll + + struct + { + string option1 + string option2 + float duration + bool active + var rui + } choice string id tempMessage temp @@ -282,6 +291,15 @@ void function ServerCallback_UpdateServerHUDMessage ( array args ) case eDataType.ID: client.id = args[1] break + case eDataType.CHOICE_OPTION: + if (client.choice.option1.len() == 0) + client.choice.option1 = CombineArgsIntoString( args ) + else + client.choice.option2 = CombineArgsIntoString( args ) + break + case eDataType.CHOICE_DURATION: + client.choice.duration = args[1].tofloat() + break } } From 749d20066cd6df8902f47d9081cecce4f72c9f77 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 18:15:28 +0200 Subject: [PATCH 03/16] feat: use RUI component to display choice on client --- .../scripts/vscripts/sh_message_utils.gnut | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 7aa5c18a4..d7889a9e5 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -331,6 +331,9 @@ void function ServerCallback_CreateServerHUDMessage ( array args ) case eMessageType.DELETE_STATUS: thread DeleteStatusMessage( client.id ) break + case eMessageType.CHOICE: + thread ShowChoice_Threaded() + break } } @@ -449,6 +452,42 @@ void function ShowPollMessage_Threaded() client.poll.pollActive = false } +void function ShowChoice_Threaded() +{ + if( client.choice.active ) + return + + client.choice.active = true + + // durations + float introDuration = 1.0 + float promptDuration = client.choice.duration + + // RUI creation + var rui = RuiCreate( $"ui/conversation.rpak", clGlobal.topoFullScreen, RUI_DRAW_HUD, 0 ) + RuiSetFloat( rui, "startTime", Time() ) + RuiSetFloat( rui, "introDuration", introDuration ) + RuiSetFloat( rui, "timer", promptDuration ) + RuiSetResolutionToScreenSize( rui ) + + // first answer + RuiSetString( rui, "text1", client.choice.option1 ) + RuiSetBool( rui, "choice1Available", true ) + RuiSetBool( rui, "choice1WasSelected", false ) + + // second answer + RuiSetString( rui, "text2", client.choice.option2 ) + RuiSetBool( rui, "choice2Available", true ) + RuiSetBool( rui, "choice2WasSelected", false ) + + client.choice.rui = rui + + wait introDuration + promptDuration + RuiDestroyIfAlive( client.choice.rui ) + client.choice.rui = null + client.choice.active = false +} + void function InfoMessageHandler_Threaded() { while( true ) From 51fbb68c0ad2fcffc800ef88ee5817d8ac406a17 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 18:20:52 +0200 Subject: [PATCH 04/16] feat: emit sound on choice UI spawn --- Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut | 1 + 1 file changed, 1 insertion(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index d7889a9e5..188ab6813 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -481,6 +481,7 @@ void function ShowChoice_Threaded() RuiSetBool( rui, "choice2WasSelected", false ) client.choice.rui = rui + EmitSoundOnEntity( GetLocalViewPlayer(), "UI_PlayerDialogue_Selection" ) wait introDuration + promptDuration RuiDestroyIfAlive( client.choice.rui ) From fd06f346b8e005989a0bac338d56d472c5da1089 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 18:42:50 +0200 Subject: [PATCH 05/16] feat: RUI disappears with a smooth transition --- .../mod/scripts/vscripts/sh_message_utils.gnut | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 188ab6813..74f2a9119 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -484,6 +484,18 @@ void function ShowChoice_Threaded() EmitSoundOnEntity( GetLocalViewPlayer(), "UI_PlayerDialogue_Selection" ) wait introDuration + promptDuration + + int choice = 0 + float textFadeOutDuration = choice == 0 ? 1.0 : 0.75 + float responseDuration = choice == 0 ? 0.0 : 3.0 + RuiSetFloat( client.choice.rui, "choiceMadeTime", Time() ) + RuiSetFloat( client.choice.rui, "choiceDuration", responseDuration ) + RuiSetFloat( client.choice.rui, "textRemoveDuration", textFadeOutDuration ) + RuiSetInt( client.choice.rui, "choiceMade", choice ) + + EmitSoundOnEntity( GetLocalViewPlayer(), choice == 0 ? "UI_PlayerDialogue_Notification" : "ui_holotutorial_Analyzingfinish" ) + wait textFadeOutDuration + responseDuration + RuiDestroyIfAlive( client.choice.rui ) client.choice.rui = null client.choice.active = false From e5454d4bb7c247917e384cc1fb1749fe9190efc0 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 18:47:58 +0200 Subject: [PATCH 06/16] fix: multiple choices can be triggered one after another --- Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 74f2a9119..5711d56a5 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -499,6 +499,8 @@ void function ShowChoice_Threaded() RuiDestroyIfAlive( client.choice.rui ) client.choice.rui = null client.choice.active = false + client.choice.option1 = "" + client.choice.option2 = "" } void function InfoMessageHandler_Threaded() From 07f519e996da8273c6216472f345543e15e3305e Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 19:28:06 +0200 Subject: [PATCH 07/16] feat: player can answer choice prompts --- .../scripts/vscripts/sh_message_utils.gnut | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 5711d56a5..460c88ede 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -229,6 +229,13 @@ void function NSSendInfoMessageToPlayer( entity player, string text ) #if CLIENT void function MessageUtils_ClientInit() { + // Choice RUI signals + RegisterSignal( "DialogueChoice1" ) + RegisterSignal( "DialogueChoice2" ) + RegisterSignal( "DialogueChoiceTimeout" ) + RegisterConCommandTriggeredCallback( "+scriptCommand1", Pressed_Choice1 ) + RegisterConCommandTriggeredCallback( "+scriptCommand2", Pressed_Choice2 ) + // ServerHUDMessageRequest AddServerToClientStringCommandCallback( "ServerHUDMessageShow", ServerCallback_CreateServerHUDMessage ) // ServerHUDMessageRequest @@ -458,6 +465,7 @@ void function ShowChoice_Threaded() return client.choice.active = true + entity player = GetLocalViewPlayer() // durations float introDuration = 1.0 @@ -481,11 +489,18 @@ void function ShowChoice_Threaded() RuiSetBool( rui, "choice2WasSelected", false ) client.choice.rui = rui - EmitSoundOnEntity( GetLocalViewPlayer(), "UI_PlayerDialogue_Selection" ) + EmitSoundOnEntity( player, "UI_PlayerDialogue_Selection" ) - wait introDuration + promptDuration + // Wait for player answer + thread DialogueChoiceTimeout( player, "DialogueChoice1", "DialogueChoice2", introDuration + promptDuration ) + table results = WaitSignal( player, "DialogueChoice1", "DialogueChoice2", "DialogueChoiceTimeout" ) int choice = 0 + if ( results.signal == "DialogueChoice1" ) + choice = 1 + else if ( results.signal == "DialogueChoice2" ) + choice = 2 + float textFadeOutDuration = choice == 0 ? 1.0 : 0.75 float responseDuration = choice == 0 ? 0.0 : 3.0 RuiSetFloat( client.choice.rui, "choiceMadeTime", Time() ) @@ -503,6 +518,29 @@ void function ShowChoice_Threaded() client.choice.option2 = "" } +void function DialogueChoiceTimeout( entity player, string cancelTimeoutSignal_A, string cancelTimeoutSignal_B, float waitTime ) +{ + EndSignal( player, "OnDeath" ) + EndSignal( player, "OnDestroy" ) + EndSignal( player, cancelTimeoutSignal_A ) + EndSignal( player, cancelTimeoutSignal_B ) + + wait waitTime + + if ( IsValid( player ) ) + Signal( player, "DialogueChoiceTimeout" ) +} + +void function Pressed_Choice1( entity player ) +{ + Signal( player, "DialogueChoice1" ) +} + +void function Pressed_Choice2( entity player ) +{ + Signal( player, "DialogueChoice2" ) +} + void function InfoMessageHandler_Threaded() { while( true ) From f50ed8962a596bbb6d913061c78fcb8c768a1beb Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 22:54:10 +0200 Subject: [PATCH 08/16] feat: add NSGetPlayerChoiceResponse method --- .../scripts/vscripts/sh_message_utils.gnut | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 460c88ede..3c16be1ce 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -4,6 +4,7 @@ global function MessageUtils_ServerInit global function NSCreatePollOnPlayer global function NSGetPlayerResponse global function NSCreateChoiceOnPlayer +global function NSGetPlayerChoiceResponse global function NSSendLargeMessageToPlayer global function NSSendPopUpMessageToPlayer @@ -17,6 +18,7 @@ global function NSDeleteStatusMessageOnPlayer struct { table playerPollResponses + table playerChoiceResponses } server #endif // SERVER @@ -113,6 +115,7 @@ void function MessageUtils_ServerInit() { AddClientCommandCallback( "vote", ClientCommand_Vote ) AddClientCommandCallback( "poll_respond", ClientCommand_PollRespond ) + AddClientCommandCallback( "choice_respond", ClientCommand_ChoiceRespond ) } bool function ClientCommand_Vote( entity player, array args ) @@ -133,6 +136,15 @@ bool function ClientCommand_PollRespond( entity player, array args ) return true } +bool function ClientCommand_ChoiceRespond( entity player, array args ) +{ + if( args.len() == 0 ) + return false + + server.playerChoiceResponses[player] <- args[0].tointeger() + return true +} + void function NSCreateStatusMessageOnPlayer( entity player, string title, string description, string id ) { ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.TITLE + " " + title ) @@ -186,9 +198,19 @@ void function NSCreateChoiceOnPlayer( entity player, string option1, string opti ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option1 ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option2 ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_DURATION + " " + duration ) + + server.playerChoiceResponses[player] <- 0 // Reset choice response table entry ServerToClientStringCommand( player, "ServerHUDMessageShow " + eMessageType.CHOICE ) } +int function NSGetPlayerChoiceResponse( entity player ) +{ + if( !( player in server.playerChoiceResponses ) ) + return -1 + + return server.playerChoiceResponses[ player ] +} + void function NSSendLargeMessageToPlayer( entity player, string title, string description, float duration, string image ) { ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.TITLE + " " + title ) @@ -534,11 +556,13 @@ void function DialogueChoiceTimeout( entity player, string cancelTimeoutSignal_A void function Pressed_Choice1( entity player ) { Signal( player, "DialogueChoice1" ) + player.ClientCommand( "choice_respond 1" ) } void function Pressed_Choice2( entity player ) { Signal( player, "DialogueChoice2" ) + player.ClientCommand( "choice_respond 2" ) } void function InfoMessageHandler_Threaded() From ee9d35b08df339680c02d903d9076dff7a8d368c Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 5 Aug 2024 23:06:30 +0200 Subject: [PATCH 09/16] refactor: NSGetPlayerChoiceResponse returns -2 if input player is not found --- .../mod/scripts/vscripts/sh_message_utils.gnut | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 3c16be1ce..9598d0cd9 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -199,14 +199,14 @@ void function NSCreateChoiceOnPlayer( entity player, string option1, string opti ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option2 ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_DURATION + " " + duration ) - server.playerChoiceResponses[player] <- 0 // Reset choice response table entry + server.playerChoiceResponses[player] <- -1 // Reset choice response table entry ServerToClientStringCommand( player, "ServerHUDMessageShow " + eMessageType.CHOICE ) } int function NSGetPlayerChoiceResponse( entity player ) { if( !( player in server.playerChoiceResponses ) ) - return -1 + return -2 return server.playerChoiceResponses[ player ] } @@ -522,6 +522,7 @@ void function ShowChoice_Threaded() choice = 1 else if ( results.signal == "DialogueChoice2" ) choice = 2 + player.ClientCommand( "choice_respond " + choice ) float textFadeOutDuration = choice == 0 ? 1.0 : 0.75 float responseDuration = choice == 0 ? 0.0 : 3.0 @@ -556,13 +557,11 @@ void function DialogueChoiceTimeout( entity player, string cancelTimeoutSignal_A void function Pressed_Choice1( entity player ) { Signal( player, "DialogueChoice1" ) - player.ClientCommand( "choice_respond 1" ) } void function Pressed_Choice2( entity player ) { Signal( player, "DialogueChoice2" ) - player.ClientCommand( "choice_respond 2" ) } void function InfoMessageHandler_Threaded() From 6787f28950ee0f84269790d81a00472f0fe99ca8 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Tue, 6 Aug 2024 01:21:31 +0200 Subject: [PATCH 10/16] refactor: integrate key to choice API --- .../scripts/vscripts/sh_message_utils.gnut | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 9598d0cd9..856ce163b 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -18,7 +18,7 @@ global function NSDeleteStatusMessageOnPlayer struct { table playerPollResponses - table playerChoiceResponses + table > playerChoiceResponses } server #endif // SERVER @@ -60,6 +60,7 @@ struct float duration bool active var rui + string key } choice string id @@ -107,7 +108,8 @@ enum eDataType STYLE, ID, CHOICE_OPTION, - CHOICE_DURATION + CHOICE_DURATION, + CHOICE_KEY } #if SERVER @@ -138,10 +140,16 @@ bool function ClientCommand_PollRespond( entity player, array args ) bool function ClientCommand_ChoiceRespond( entity player, array args ) { - if( args.len() == 0 ) + if( args.len() != 2 ) + return false + + int responseValue = args[0].tointeger() + string key = args[1] + + if ( !( key in server.playerChoiceResponses ) || !( player in server.playerChoiceResponses[key] ) ) return false - server.playerChoiceResponses[player] <- args[0].tointeger() + server.playerChoiceResponses[key][player] <- responseValue return true } @@ -193,22 +201,32 @@ int function NSGetPlayerResponse( entity player ) return server.playerPollResponses[ player ] - 1 } -void function NSCreateChoiceOnPlayer( entity player, string option1, string option2, float duration ) +string function NSCreateChoiceOnPlayer( entity player, string option1, string option2, float duration, string key = "" ) { + string id = key != "" ? key : UniqueString() + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option1 ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option2 ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_DURATION + " " + duration ) + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_KEY + " " + id ) - server.playerChoiceResponses[player] <- -1 // Reset choice response table entry + if( !( id in server.playerChoiceResponses ) ) + server.playerChoiceResponses[id] <- {} + server.playerChoiceResponses[id][player] <- -1 // Reset choice response table entry ServerToClientStringCommand( player, "ServerHUDMessageShow " + eMessageType.CHOICE ) + + return id } -int function NSGetPlayerChoiceResponse( entity player ) +int function NSGetPlayerChoiceResponse( entity player, string key ) { - if( !( player in server.playerChoiceResponses ) ) + if( !( key in server.playerChoiceResponses ) ) + return -3 + + if( !( player in server.playerChoiceResponses[key] ) ) return -2 - return server.playerChoiceResponses[ player ] + return server.playerChoiceResponses[ key ][ player ] } void function NSSendLargeMessageToPlayer( entity player, string title, string description, float duration, string image ) @@ -329,6 +347,9 @@ void function ServerCallback_UpdateServerHUDMessage ( array args ) case eDataType.CHOICE_DURATION: client.choice.duration = args[1].tofloat() break + case eDataType.CHOICE_KEY: + client.choice.key = args[1] + break } } @@ -522,7 +543,7 @@ void function ShowChoice_Threaded() choice = 1 else if ( results.signal == "DialogueChoice2" ) choice = 2 - player.ClientCommand( "choice_respond " + choice ) + player.ClientCommand( "choice_respond " + choice + " " + client.choice.key) float textFadeOutDuration = choice == 0 ? 1.0 : 0.75 float responseDuration = choice == 0 ? 0.0 : 3.0 @@ -539,6 +560,7 @@ void function ShowChoice_Threaded() client.choice.active = false client.choice.option1 = "" client.choice.option2 = "" + client.choice.key = "" } void function DialogueChoiceTimeout( entity player, string cancelTimeoutSignal_A, string cancelTimeoutSignal_B, float waitTime ) From e19cb6ce6786d7613c09d18806ee9efe63a927f0 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Tue, 6 Aug 2024 01:29:50 +0200 Subject: [PATCH 11/16] feat: add NSCreateChoiceOnAllPlayers util function --- .../mod/scripts/vscripts/sh_message_utils.gnut | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 856ce163b..3536a7594 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -3,6 +3,7 @@ global function MessageUtils_ServerInit global function NSCreatePollOnPlayer global function NSGetPlayerResponse +global function NSCreateChoiceOnAllPlayers global function NSCreateChoiceOnPlayer global function NSGetPlayerChoiceResponse @@ -201,6 +202,18 @@ int function NSGetPlayerResponse( entity player ) return server.playerPollResponses[ player ] - 1 } +string function NSCreateChoiceOnAllPlayers( string option1, string option2, float duration ) +{ + string key = UniqueString() + foreach( player in GetPlayerArray() ) + { + if ( !IsValid( player ) ) + continue + NSCreateChoiceOnPlayer( player, option1, option2, duration, key ) + } + return key +} + string function NSCreateChoiceOnPlayer( entity player, string option1, string option2, float duration, string key = "" ) { string id = key != "" ? key : UniqueString() From 7a8b711ce50b1f6277276ffdb573d09a310333d8 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Aug 2024 23:34:09 +0200 Subject: [PATCH 12/16] refactor: API takes an array of strings as input parameter --- .../mod/scripts/vscripts/sh_message_utils.gnut | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 3536a7594..1cf1e234f 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -202,24 +202,24 @@ int function NSGetPlayerResponse( entity player ) return server.playerPollResponses[ player ] - 1 } -string function NSCreateChoiceOnAllPlayers( string option1, string option2, float duration ) +string function NSCreateChoiceOnAllPlayers( array options, float duration ) { string key = UniqueString() foreach( player in GetPlayerArray() ) { if ( !IsValid( player ) ) continue - NSCreateChoiceOnPlayer( player, option1, option2, duration, key ) + NSCreateChoiceOnPlayer( player, options, duration, key ) } return key } -string function NSCreateChoiceOnPlayer( entity player, string option1, string option2, float duration, string key = "" ) +string function NSCreateChoiceOnPlayer( entity player, array options, float duration, string key = "" ) { string id = key != "" ? key : UniqueString() - ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option1 ) - ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + option2 ) + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + options[0] ) + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + options[1] ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_DURATION + " " + duration ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_KEY + " " + id ) From 18ec783e63434393b5c9c854bf49e4edf7af131b Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Sun, 18 Aug 2024 23:49:38 +0200 Subject: [PATCH 13/16] feat: NSCreateChoiceOnPlayer throws when not getting 1 or 2 options --- Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 1cf1e234f..8812a66cd 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -216,6 +216,11 @@ string function NSCreateChoiceOnAllPlayers( array options, float duratio string function NSCreateChoiceOnPlayer( entity player, array options, float duration, string key = "" ) { + if ( ![1, 2].contains( options.len() ) ) + { + throw "NSCreateChoiceOnPlayer expected one or two options (got " + options.len() + ")." + } + string id = key != "" ? key : UniqueString() ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + options[0] ) From 39cacda8f48ed963045f54c13146cba51e6cb851 Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 19 Aug 2024 14:54:45 +0200 Subject: [PATCH 14/16] refactor: add ePlayerChoiceStatus enum --- .../scripts/vscripts/sh_message_utils.gnut | 41 ++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 8812a66cd..fcdb26bbe 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -16,6 +16,18 @@ global function NSCreateStatusMessageOnPlayer global function NSEditStatusMessageOnPlayer global function NSDeleteStatusMessageOnPlayer +global enum ePlayerChoiceStatus +{ + UNKNOWN, + NOT_FOUND, // no choice matching the key was found + NOT_FOUND_FOR_PLAYER, // choice exists, but the player was not proposed with it + + ONGOING, // choice is currently proposed to the player, whom hasn't answered it yet + NOT_ANSWERED, // player did not answer the choice (RUI timed out) + CHOICE_1, // player selected first option + CHOICE_2 // player selected second option +} + struct { table playerPollResponses @@ -144,9 +156,28 @@ bool function ClientCommand_ChoiceRespond( entity player, array args ) if( args.len() != 2 ) return false - int responseValue = args[0].tointeger() - string key = args[1] + // todo: what if args[0] is not an integer? + int responseCode = args[0].tointeger() + int responseValue = ePlayerChoiceStatus.NOT_FOUND + switch( responseCode ) + { + case 0: + responseValue = ePlayerChoiceStatus.NOT_ANSWERED + break + case 1: + responseValue = ePlayerChoiceStatus.CHOICE_1 + break + case 2: + responseValue = ePlayerChoiceStatus.CHOICE_2 + break + default: + // todo: test this usecase + print( format( "Player %s sent incorrect choice response value (was %s).", player.GetPlayerName(), responseCode ) ) + responseValue = ePlayerChoiceStatus.UNKNOWN + break + } + string key = args[1] if ( !( key in server.playerChoiceResponses ) || !( player in server.playerChoiceResponses[key] ) ) return false @@ -230,7 +261,7 @@ string function NSCreateChoiceOnPlayer( entity player, array options, fl if( !( id in server.playerChoiceResponses ) ) server.playerChoiceResponses[id] <- {} - server.playerChoiceResponses[id][player] <- -1 // Reset choice response table entry + server.playerChoiceResponses[id][player] <- ePlayerChoiceStatus.ONGOING // Reset choice response table entry ServerToClientStringCommand( player, "ServerHUDMessageShow " + eMessageType.CHOICE ) return id @@ -239,10 +270,10 @@ string function NSCreateChoiceOnPlayer( entity player, array options, fl int function NSGetPlayerChoiceResponse( entity player, string key ) { if( !( key in server.playerChoiceResponses ) ) - return -3 + return ePlayerChoiceStatus.NOT_FOUND if( !( player in server.playerChoiceResponses[key] ) ) - return -2 + return ePlayerChoiceStatus.NOT_FOUND_FOR_PLAYER return server.playerChoiceResponses[ key ][ player ] } From 71a79f2c6ba007abf199fca64bf6bdc23ce65e7c Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 26 Aug 2024 22:36:00 +0200 Subject: [PATCH 15/16] style: use spaces to align enum (instead of tabs) --- .../mod/scripts/vscripts/sh_message_utils.gnut | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index fcdb26bbe..4a2125d51 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -19,13 +19,13 @@ global function NSDeleteStatusMessageOnPlayer global enum ePlayerChoiceStatus { UNKNOWN, - NOT_FOUND, // no choice matching the key was found - NOT_FOUND_FOR_PLAYER, // choice exists, but the player was not proposed with it + NOT_FOUND, // no choice matching the key was found + NOT_FOUND_FOR_PLAYER, // choice exists, but the player was not proposed with it - ONGOING, // choice is currently proposed to the player, whom hasn't answered it yet - NOT_ANSWERED, // player did not answer the choice (RUI timed out) - CHOICE_1, // player selected first option - CHOICE_2 // player selected second option + ONGOING, // choice is currently proposed to the player, whom hasn't answered it yet + NOT_ANSWERED, // player did not answer the choice (RUI timed out) + CHOICE_1, // player selected first option + CHOICE_2 // player selected second option } struct From 8141ccdf83852f72495a78a93bdc44faf07d11ed Mon Sep 17 00:00:00 2001 From: Remy Raes Date: Mon, 26 Aug 2024 23:30:24 +0200 Subject: [PATCH 16/16] feat: support one choice only --- .../scripts/vscripts/sh_message_utils.gnut | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut index 4a2125d51..048182959 100644 --- a/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut +++ b/Northstar.Custom/mod/scripts/vscripts/sh_message_utils.gnut @@ -255,7 +255,11 @@ string function NSCreateChoiceOnPlayer( entity player, array options, fl string id = key != "" ? key : UniqueString() ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + options[0] ) - ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + options[1] ) + if ( options.len() > 1 ) + { + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_OPTION + " " + options[1] ) + } + ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_DURATION + " " + duration ) ServerToClientStringCommand( player, "ServerHUDMessagePut " + eDataType.CHOICE_KEY + " " + id ) @@ -576,16 +580,30 @@ void function ShowChoice_Threaded() RuiSetBool( rui, "choice1WasSelected", false ) // second answer - RuiSetString( rui, "text2", client.choice.option2 ) - RuiSetBool( rui, "choice2Available", true ) + bool hasSecondOption = client.choice.option2 != "" + if ( hasSecondOption ) + { + RuiSetString( rui, "text2", client.choice.option2 ) + } + RuiSetBool( rui, "choice2Available", hasSecondOption ) RuiSetBool( rui, "choice2WasSelected", false ) + RuiSetInt( rui, "numChoices", hasSecondOption ? 2 : 1 ) client.choice.rui = rui EmitSoundOnEntity( player, "UI_PlayerDialogue_Selection" ) // Wait for player answer - thread DialogueChoiceTimeout( player, "DialogueChoice1", "DialogueChoice2", introDuration + promptDuration ) - table results = WaitSignal( player, "DialogueChoice1", "DialogueChoice2", "DialogueChoiceTimeout" ) + table results + if ( hasSecondOption ) + { + thread DialogueChoiceTimeout( player, introDuration + promptDuration, "DialogueChoice1", "DialogueChoice2" ) + results = WaitSignal( player, "DialogueChoice1", "DialogueChoice2", "DialogueChoiceTimeout" ) + } + else + { + thread DialogueChoiceTimeout( player, introDuration + promptDuration, "DialogueChoice1" ) + results = WaitSignal( player, "DialogueChoice1", "DialogueChoiceTimeout" ) + } int choice = 0 if ( results.signal == "DialogueChoice1" ) @@ -612,12 +630,15 @@ void function ShowChoice_Threaded() client.choice.key = "" } -void function DialogueChoiceTimeout( entity player, string cancelTimeoutSignal_A, string cancelTimeoutSignal_B, float waitTime ) +void function DialogueChoiceTimeout( entity player, float waitTime, string cancelTimeoutSignal_A, string cancelTimeoutSignal_B = "") { EndSignal( player, "OnDeath" ) EndSignal( player, "OnDestroy" ) EndSignal( player, cancelTimeoutSignal_A ) - EndSignal( player, cancelTimeoutSignal_B ) + if ( cancelTimeoutSignal_B != "") + { + EndSignal( player, cancelTimeoutSignal_B ) + } wait waitTime