|
|
|
@ -21,14 +21,19 @@
|
|
|
|
|
*/ |
|
|
|
|
class ChatApi extends AcediaObject; |
|
|
|
|
|
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_ACKNOWLEDGEMENTS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_ALERTS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_DIRECTIONS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_INSULTS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_TRADER; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_AUTO; |
|
|
|
|
var private const int VOICE_MESSAGES_TOTAL; |
|
|
|
|
///! API for accessing chat-related events. |
|
|
|
|
///! |
|
|
|
|
///! # Implementation |
|
|
|
|
///! |
|
|
|
|
///! Signal functions that track text chat messages `OnMessage()` and `OnMessageFor()` simply |
|
|
|
|
///! hook into [`BroadcastApi`] the first time such signal is requested. |
|
|
|
|
///! |
|
|
|
|
///! Signal function [`OnVoiceMessage()`] for tracking voice replaces a function in |
|
|
|
|
///! [`KFPlayerController`] to track when they are replicated. |
|
|
|
|
///! Then replaced function informs [`ChatApi`] about new voice message transmissions via |
|
|
|
|
///! internal [`_EmitOnVoiceMessage()`] method. |
|
|
|
|
|
|
|
|
|
/// Lists voice messages built-in in the game. |
|
|
|
|
enum BuiltInVoiceMessage { |
|
|
|
|
// Support |
|
|
|
|
BIVM_SupportMedic, |
|
|
|
@ -98,41 +103,53 @@ enum BuiltInVoiceMessage {
|
|
|
|
|
BIVM_Unknown |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// Killing Floor's native voice message is defined by `name` and `byte` pair. |
|
|
|
|
/// This struct is added to allow returning them as a pair. |
|
|
|
|
struct NativeVoiceMessage { |
|
|
|
|
var name type; |
|
|
|
|
var byte index; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// Tracks whether we've already connected to broadcast signals. |
|
|
|
|
var protected bool connectedToBroadcastAPI; |
|
|
|
|
/// Tracks whether we've already replaced a function that allows us to catch voice messages. |
|
|
|
|
var private bool replacedSendVoiceMessage; |
|
|
|
|
|
|
|
|
|
/// Auxiliary constants that store amount of values in [`BuiltInVoiceMessage`] before |
|
|
|
|
/// a certain group. |
|
|
|
|
/// Used for conversion between native voice messages and [`BuiltInVoiceMessage`] |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_ACKNOWLEDGEMENTS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_ALERTS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_DIRECTIONS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_INSULTS; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_TRADER; |
|
|
|
|
var private const int VOICE_MESSAGES_BEFORE_AUTO; |
|
|
|
|
var private const int VOICE_MESSAGES_TOTAL; |
|
|
|
|
|
|
|
|
|
var protected ChatAPI_OnMessage_Signal onMessageSignal; |
|
|
|
|
var protected ChatAPI_OnMessageFor_Signal onMessageForSignal; |
|
|
|
|
var protected ChatAPI_OnVoiceMessage_Signal onVoiceMessageSignal; |
|
|
|
|
|
|
|
|
|
protected function Constructor() { |
|
|
|
|
onMessageSignal = ChatAPI_OnMessage_Signal(_.memory.Allocate(class'ChatAPI_OnMessage_Signal')); |
|
|
|
|
onMessageForSignal = |
|
|
|
|
ChatAPI_OnMessageFor_Signal(_.memory.Allocate(class'ChatAPI_OnMessageFor_Signal')); |
|
|
|
|
onVoiceMessageSignal = |
|
|
|
|
ChatAPI_OnVoiceMessage_Signal(_.memory.Allocate(class'ChatAPI_OnVoiceMessage_Signal')); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected function Finalizer() { |
|
|
|
|
_.memory.Free(onMessageSignal); |
|
|
|
|
_.memory.Free(onMessageForSignal); |
|
|
|
|
_.memory.Free(onVoiceMessageSignal); |
|
|
|
|
onMessageSignal = none; |
|
|
|
|
onMessageForSignal = none; |
|
|
|
|
onVoiceMessageSignal = none; |
|
|
|
|
_server.unreal.broadcasts.OnHandleText(self).Disconnect(); |
|
|
|
|
_server.unreal.broadcasts.OnHandleTextFor(self).Disconnect(); |
|
|
|
|
connectedToBroadcastAPI = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final function TryConnectingBroadcastSignals() { |
|
|
|
|
if (connectedToBroadcastAPI) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
connectedToBroadcastAPI = true; |
|
|
|
|
_server.unreal.broadcasts.OnHandleText(self).connect = HandleText; |
|
|
|
|
_server.unreal.broadcasts.OnHandleTextFor(self).connect = HandleTextFor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Signal that will be emitted when a player sends a message into the chat. |
|
|
|
|
/// |
|
|
|
|
/// Allows to modify message before sending it, as well as prevent it from being sent at all. |
|
|
|
@ -189,6 +206,27 @@ public /*signal*/ function ChatAPI_OnMessageFor_Slot OnMessageFor(AcediaObject r
|
|
|
|
|
return ChatAPI_OnMessageFor_Slot(onMessageForSignal.NewSlot(receiver)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Signal that will be emitted when a player sends a voice message. |
|
|
|
|
/// |
|
|
|
|
/// # Slot description |
|
|
|
|
/// |
|
|
|
|
/// bool <slot>(EPlayer sender, ChatApi.BuiltInVoiceMessage message) |
|
|
|
|
/// |
|
|
|
|
/// ## Parameters |
|
|
|
|
/// |
|
|
|
|
/// * [`sender`]: `EPlayer` that has sent the voice message. |
|
|
|
|
/// * [`message`]: Message that `sender` has sent. |
|
|
|
|
public /*signal*/ function ChatAPI_OnVoiceMessage_Slot OnVoiceMessage(AcediaObject receiver) { |
|
|
|
|
if (!replacedSendVoiceMessage) { |
|
|
|
|
_.unflect.ReplaceFunction_S( |
|
|
|
|
"KFMod.KFPlayerController.SendVoiceMessage", |
|
|
|
|
"AcediaCore.Unflect_ChatApi_Controller.SendVoiceMessage", |
|
|
|
|
"`ChatApi` was required to catch voice messages"); |
|
|
|
|
replacedSendVoiceMessage = true; |
|
|
|
|
} |
|
|
|
|
return ChatAPI_OnVoiceMessage_Slot(onVoiceMessageSignal.NewSlot(receiver)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public /*internal*/ function NativeVoiceMessage _enumIntoNativeVoiceMessage( |
|
|
|
|
BuiltInVoiceMessage voiceMessage |
|
|
|
|
) { |
|
|
|
@ -275,6 +313,36 @@ public /*internal*/ function BuiltInVoiceMessage _nativeVoiceMessageIntoEnum(
|
|
|
|
|
return BIVM_Unknown; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public final /*internal*/ /*native*/ function _EmitOnVoiceMessage( |
|
|
|
|
PlayerController sender, |
|
|
|
|
name messageType, |
|
|
|
|
byte messageID |
|
|
|
|
) { |
|
|
|
|
local EPlayer wrapper; |
|
|
|
|
local NativeVoiceMessage nativeVoiceMessage; |
|
|
|
|
local BuiltInVoiceMessage builtInVoiceMessage; |
|
|
|
|
|
|
|
|
|
if (sender == none) return; |
|
|
|
|
wrapper = _.players.FromController(sender); |
|
|
|
|
if (wrapper == none) return; |
|
|
|
|
|
|
|
|
|
nativeVoiceMessage.type = messageType; |
|
|
|
|
nativeVoiceMessage.index = messageID; |
|
|
|
|
builtInVoiceMessage = _nativeVoiceMessageIntoEnum(nativeVoiceMessage); |
|
|
|
|
if (builtInVoiceMessage != BIVM_Unknown) { |
|
|
|
|
onVoiceMessageSignal.Emit(wrapper, builtInVoiceMessage); |
|
|
|
|
} |
|
|
|
|
_.memory.Free(wrapper); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final function TryConnectingBroadcastSignals() { |
|
|
|
|
if (connectedToBroadcastAPI) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
connectedToBroadcastAPI = true; |
|
|
|
|
_server.unreal.broadcasts.OnHandleText(self).connect = HandleText; |
|
|
|
|
_server.unreal.broadcasts.OnHandleTextFor(self).connect = HandleTextFor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private function bool HandleText( |
|
|
|
|
Actor sender, |
|
|
|
|