typedef Param4 DayZCreatureAnimScriptDebugAnimEventData; typedef Param1 DayZCreatureAnimScriptDebugAnimPredictionData; typedef Param1 DayZCreatureAnimScriptDebugAnimTagData; class DayZCreatureAnimScriptDebug { proto native void SetCreature(DayZCreature creature); proto native int GetVariableCount(); proto native owned string GetVariableName(int index); proto native int GetVariableType(int index); proto native int GetVariableInt(int index); proto native float GetVariableFloat(int index); proto native bool GetVariableBool(int index); proto native int SetVariableInt(int index, int value); proto native float SetVariableFloat(int index, float value); proto native bool SetVariableBool(int index, bool value); proto native int GetCommandCount(); proto native owned string GetCommandName(int index); proto native int GetCommandID(int index); proto native void ActivateCommand(int index, int userInt, float userFloat); const int m_iMaxAnimEventsCount = 50; ref array m_EventsFilter = new array; ref array m_AnimEvents = new array; ref array m_AnimPredictions = new array; ref array m_AnimTags = new array; void OnAnimationEventsStart() { m_AnimPredictions.Clear(); m_AnimTags.Clear(); } void OnAnimationEvent(string evType, int userInt, string userString) { if (m_EventsFilter.Find(evType) != -1) { return; } m_AnimEvents.InsertAt(new DayZCreatureAnimScriptDebugAnimEventData(GetWorldTime(), evType, userInt, userString), 0); if (m_AnimEvents.Count() > m_iMaxAnimEventsCount) { m_AnimEvents.Remove(m_AnimEvents.Count() - 1); } } void OnAnimationPrediction(string predName) { m_AnimPredictions.Insert(new DayZCreatureAnimScriptDebugAnimPredictionData(predName)); } void OnAnimationTag(string tagName) { m_AnimTags.Insert(new DayZCreatureAnimScriptDebugAnimTagData(tagName)); } } enum PluginDayZCreatureAIDebugSyncMessageType { INIT_DEBUG_OBJECT, RELEASE_DEBUG_OBJECT, SET_VALUE_INT, SET_VALUE_FLOAT, SET_VALUE_BOOL, ACTIVATE_COMMAND, ENABLE_AI, DISABLE_AI, COUNT } class PluginDayZCreatureAIDebug extends PluginBase { int m_iDebugMenu = -1; DayZCreatureAI m_DebugEntity = NULL; string m_sDebugEntityName = ""; ref DayZCreatureAnimScriptDebug m_EntityAnimDbg = NULL; ref Timer m_TickTimer; bool m_IsActive = false; bool m_ShowDbgUI = false; bool m_bIsCaptureMode = false; bool m_bEditMode = false; bool m_bAIEnabled = true; bool m_bShowAnimEvents = false; bool m_bBulkSet = false; ref array m_SetVariableCheckStates = new array; ref array m_SetCommandCheckStates = new array; ref array m_SyncMessages = new array; void PluginDayZCreatureAIDebug() { } void ~PluginDayZCreatureAIDebug() { } override void OnInit() { } override void OnDestroy() { } void CheckShowMode() { int actMenuValue = DiagMenu.GetEngineValue(DayZCreatureAIConstants.DEBUG_SHOWDEBUGPLUGIN); if (actMenuValue != m_iDebugMenu) { SetDebugShowMode(actMenuValue); m_iDebugMenu = actMenuValue; } } override void OnUpdate(float delta_time) { if (!GetGame().IsDedicatedServer()) { CheckShowMode(); } } string GetStrValue(int index) { string strVal; switch (m_EntityAnimDbg.GetVariableType(index)) { case DayZCreatureAnimScriptDebugVarType.INT: int valInt = m_EntityAnimDbg.GetVariableInt(index); strVal = valInt.ToString(); break; case DayZCreatureAnimScriptDebugVarType.FLOAT: float valFloat = m_EntityAnimDbg.GetVariableFloat(index); strVal = valFloat.ToString(); break; case DayZCreatureAnimScriptDebugVarType.BOOL: bool valBool = m_EntityAnimDbg.GetVariableBool(index); if (valBool) { strVal = "true"; } else { strVal = "false"; } break; default: strVal = "unk"; } return strVal; } string GetStrValueType(int index) { string strValType; switch (m_EntityAnimDbg.GetVariableType(index)) { case DayZCreatureAnimScriptDebugVarType.INT: strValType = "int"; break; case DayZCreatureAnimScriptDebugVarType.FLOAT: strValType = "float"; break; case DayZCreatureAnimScriptDebugVarType.BOOL: strValType = "bool"; break; default: strValType = "unk"; } return strValType; } void InitDebugObject(Object obj) { m_EntityAnimDbg = new DayZCreatureAnimScriptDebug(); m_EntityAnimDbg.SetCreature( DayZCreature.Cast( obj ) ); m_DebugEntity = DayZCreatureAI.Cast( obj ); m_sDebugEntityName = obj.GetType(); int varCount = m_EntityAnimDbg.GetVariableCount(); int cmdCount = m_EntityAnimDbg.GetCommandCount(); int toAddCount = 0; if (m_SetVariableCheckStates.Count() < varCount) { toAddCount = varCount - m_SetVariableCheckStates.Count(); for (int idxVar = 0; idxVar < toAddCount; idxVar++) { m_SetVariableCheckStates.Insert(false); } } if (m_SetCommandCheckStates.Count() < cmdCount) { toAddCount = cmdCount - m_SetCommandCheckStates.Count(); for (int idxCmd = 0; idxCmd < toAddCount; idxCmd++) { m_SetCommandCheckStates.Insert(false); } } } void ReleaseDebugObject() { m_DebugEntity = NULL; m_EntityAnimDbg = NULL; m_sDebugEntityName = ""; m_SetVariableCheckStates.Clear(); m_SetCommandCheckStates.Clear(); } void SetValueInt(int index, int value) { m_EntityAnimDbg.SetVariableInt(index, value); } void SetValueFloat(int index, float value) { m_EntityAnimDbg.SetVariableFloat(index, value); } void SetValueBool(int index, bool value) { m_EntityAnimDbg.SetVariableBool(index, value); } void ActivateCommand(int commandIdx, int userInt, float userFloat) { int commandId = m_EntityAnimDbg.GetCommandID(commandIdx); m_EntityAnimDbg.ActivateCommand(commandId, userInt, userFloat); } void EnableAI(bool enable) { if (m_DebugEntity.IsInherited(DayZCreatureAI)) { DayZCreatureAI creatureAI = m_DebugEntity; if (enable) { #ifdef DIAG_DEVELOPER creatureAI.DebugRestoreAIControl(); #endif } else { #ifdef DIAG_DEVELOPER creatureAI.DebugDisableAIControl(); #endif } } } DayZCreatureAnimScriptDebugVarType GetVariableType(int index) { return m_EntityAnimDbg.GetVariableType(index); } void OnGUI_Variables() { int varCount = m_EntityAnimDbg.GetVariableCount(); for (int i=0; i < varCount; i++) { DbgUI.BeginCleanupScope(); DbgUI.Text(m_EntityAnimDbg.GetVariableName(i) + ": " + GetStrValue(i)); DbgUI.EndCleanupScope(); } } void OnGUI_VariablesEdit() { const int INPUT_BOX_SIZE = 35; DbgUI.PushID_Str("VariablesEdit"); int varCount = m_EntityAnimDbg.GetVariableCount(); for (int i=0; i < varCount; i++) { DbgUI.BeginCleanupScope(); DbgUI.PushID_Int(i); bool result; DbgUI.Check("", result); m_SetVariableCheckStates[i] = result; DbgUI.SameLine(); bool setButtonPressed = DbgUI.Button("Set"); DbgUI.SameLine(); string strUserVal; DbgUI.InputText(GetStrValueType(i), strUserVal, INPUT_BOX_SIZE); DbgUI.SameLine(); DbgUI.Text(m_EntityAnimDbg.GetVariableName(i)); if (setButtonPressed || (m_bBulkSet && m_SetVariableCheckStates[i])) { GUIAction_SetValue(i, strUserVal); } DbgUI.PopID(); DbgUI.EndCleanupScope(); } DbgUI.PopID(); } void OnGUI_CommandsEdit() { const int INPUT_BOX_SIZE = 35; DbgUI.PushID_Str("CommandsEdit"); int cmdCount = m_EntityAnimDbg.GetCommandCount(); for (int i=0; i < cmdCount; i++) { DbgUI.BeginCleanupScope(); DbgUI.PushID_Int(i); bool result; DbgUI.Check("", result); m_SetCommandCheckStates[i] = result; DbgUI.SameLine(); bool setButtonPressed = DbgUI.Button("Set"); DbgUI.SameLine(); string strUserInt; DbgUI.InputText("int", strUserInt, INPUT_BOX_SIZE); DbgUI.SameLine(); string strUserFloat; DbgUI.InputText("float", strUserFloat, INPUT_BOX_SIZE); DbgUI.SameLine(); DbgUI.Text(m_EntityAnimDbg.GetCommandName(i) + "[" + m_EntityAnimDbg.GetCommandID(i) + "]"); if (setButtonPressed || (m_bBulkSet && m_SetCommandCheckStates[i])) { GUIAction_ActivateCommand(i, strUserInt.ToInt(), strUserFloat.ToFloat()); } DbgUI.PopID(); DbgUI.EndCleanupScope(); } DbgUI.PopID(); } void OnGUI_AIControlEdit() { bool buttonPressed = false; if (m_bAIEnabled) { buttonPressed = DbgUI.Button("Disable AI"); } else { buttonPressed = DbgUI.Button("Enable AI"); } if (buttonPressed) { m_bAIEnabled = !m_bAIEnabled; GUIAction_EnableAI(m_bAIEnabled); } } void OnGUI_BulkSet() { m_bBulkSet = false; if (DbgUI.Button("Bulk set")) { m_bBulkSet = true; } } void OnGUI_AnimEvents() { DbgUI.PushID_Str("AnimEvents"); const int panelMinSizeX = 350; DbgUI.Panel("MinimumSize", panelMinSizeX, 1); string strTags; for (int tagIdx = 0; tagIdx < m_EntityAnimDbg.m_AnimTags.Count(); ++tagIdx) { if (tagIdx != 0) strTags += ", "; strTags += m_EntityAnimDbg.m_AnimTags[tagIdx].param1; } string strPredictions; for (int predIdx = 0; predIdx < m_EntityAnimDbg.m_AnimPredictions.Count(); ++predIdx) { if (predIdx != 0) strPredictions += ", "; strPredictions += m_EntityAnimDbg.m_AnimPredictions[predIdx].param1; } DbgUI.PushID_Str("AnimTagsDisplay"); DbgUI.Text(strTags); DbgUI.PopID(); DbgUI.PushID_Str("AnimPredictionsDisplay"); DbgUI.Text(strPredictions); DbgUI.PopID(); string strFilter; DbgUI.InputText("Filter", strFilter, panelMinSizeX); m_EntityAnimDbg.m_EventsFilter.Clear(); strFilter.Split(" ", m_EntityAnimDbg.m_EventsFilter); DbgUI.Button("TakeMyFocus"); const int evDisplayCount = 15; int evToDisplayCount = (int)Math.Min(m_EntityAnimDbg.m_AnimEvents.Count(), evDisplayCount); for (int evIdx = 0; evIdx < evToDisplayCount; ++evIdx) { DbgUI.PushID_Int(evIdx); if (m_EntityAnimDbg.m_AnimEvents[evIdx].param2.Length() > 0) { DbgUI.Text((m_EntityAnimDbg.m_AnimEvents[evIdx].param1 / 1000.0).ToString() + " - " + m_EntityAnimDbg.m_AnimEvents[evIdx].param2); } DbgUI.PopID(); } DbgUI.PopID(); } void OnGUI(bool show) { const int windowPosX = 0; const int windowPosY = 300; const int mainPanelSizeX = 200; const int mainPanelSizeY = 1; const int margin = 10; DbgUI.BeginCleanupScope(); DbgUI.Begin("CretureAI debug", windowPosX, windowPosY); if (show) { if (m_EntityAnimDbg == NULL) { if (m_bIsCaptureMode == true) { DbgUI.Text("Capturing..."); } else { if (DbgUI.Button("Capture")) { m_bIsCaptureMode = true; } } // Clear additional windows DbgUI.Begin("CreatureAI EditMenu"); DbgUI.End(); DbgUI.Begin("CreatureAI AnimEvents"); DbgUI.End(); } else { DbgUI.Panel("MinimumSize", mainPanelSizeX, mainPanelSizeY); DbgUI.Text(m_sDebugEntityName); DbgUI.SameLine(); bool btnReleasePressed = DbgUI.Button("Release"); DbgUI.Check("Edit", m_bEditMode); DbgUI.Check("ShowAnimEvents", m_bShowAnimEvents); #ifdef _DAYZ_CREATURE_DEBUG_SHADOW if (!GetGame().IsMultiplayer()) { DbgUI.SameLine(); if (DbgUI.Button("CreateShadow")) { GUIAction_CreateShadow(); } } #endif if (!GetGame().IsMultiplayer()) { const int simLODInputSize = 20; int simLOD; DbgUI.InputInt("SimLOD", simLOD, simLODInputSize); DbgUI.SameLine(); if (DbgUI.Button("UpdateSimulationPrecision")) { GUIAction_UpdateSimulationPrecision(simLOD); } } if (btnReleasePressed) { GUIAction_ReleaseDebugObject(); } else { OnGUI_Variables(); DbgUI.Begin("CreatureAI EditMenu", windowPosX + mainPanelSizeX + margin, windowPosY); if (m_bEditMode) { OnGUI_AIControlEdit(); OnGUI_BulkSet(); OnGUI_VariablesEdit(); DbgUI.Spacer(20); OnGUI_CommandsEdit(); } DbgUI.End(); DbgUI.Begin("CreatureAI AnimEvents", windowPosX + mainPanelSizeX + margin, windowPosY); if (m_bShowAnimEvents) { OnGUI_AnimEvents(); } DbgUI.End(); } } } DbgUI.End(); DbgUI.EndCleanupScope(); } void OnGUITimer() { OnGUI(m_IsActive); if (GetGame().IsMultiplayer() && GetGame().IsClient()) { SendSyncMessages(); } } void SetDebugShowMode(int mode) { switch (mode) { case 0: { Hide(); } break; case 1: { Show(); } break; } } void Show() { m_IsActive = true; m_TickTimer = new Timer(); m_TickTimer.Run(0.1, this, "OnGUITimer", NULL, true); } void Hide() { m_IsActive = false; m_TickTimer = NULL; OnGUI(false); } void Event_OnClick() { if (m_IsActive == false) return; const float MAX_RAYCAST_RANGE = 1000; if (m_bIsCaptureMode) { vector dir = GetGame().GetPointerDirection(); vector pos = GetGame().GetCurrentCameraPosition(); // Raycast vector from = pos; vector to = pos + (dir * MAX_RAYCAST_RANGE); vector contact_pos; vector contact_dir; int contact_component; set objects = new set; if (DayZPhysics.RaycastRV(from, to, contact_pos, contact_dir, contact_component, objects, NULL, GetGame().GetPlayer())) { for ( int i = 0; i < objects.Count(); i++ ) { Object obj = objects.Get(i); if (obj && obj.IsInherited(DayZCreature)) { m_bIsCaptureMode = false; GUIAction_InitDebugObject(obj); return; } } } } } /// //! GUI actions /// void GUIAction_InitDebugObject(Object obj) { InitDebugObject(obj); if (GetGame().IsMultiplayer()) { SyncInitDebugObject(obj); } } #ifdef _DAYZ_CREATURE_DEBUG_SHADOW void GUIAction_CreateShadow() { auto shadowEntity = GetGame().CreateObject(m_sDebugEntityName, m_DebugEntity.GetPosition(), false, true); m_DebugEntity.DebugSetShadow(shadowEntity); } #endif void GUIAction_UpdateSimulationPrecision(int simLOD) { m_DebugEntity.UpdateSimulationPrecision(simLOD); } void GUIAction_ReleaseDebugObject() { ReleaseDebugObject(); if (GetGame().IsMultiplayer()) { SyncReleaseDebugObject(); } } void GUIAction_SetValue(int index, string strVal) { switch (GetVariableType(index)) { case DayZCreatureAnimScriptDebugVarType.INT: int intValue = strVal.ToInt(); if (GetGame().IsMultiplayer()) { SyncSetValueInt(index, intValue); } else { SetValueInt(index, intValue); } break; case DayZCreatureAnimScriptDebugVarType.FLOAT: float floatValue = strVal.ToFloat(); if (GetGame().IsMultiplayer()) { SyncSetValueFloat(index, floatValue); } else { SetValueFloat(index, floatValue); } break; case DayZCreatureAnimScriptDebugVarType.BOOL: bool boolValue; strVal.ToLower(); if (strVal.Contains("true")) { boolValue = true; } else if (strVal.Contains("false")) { boolValue = false; } else { boolValue = (bool)strVal.ToInt(); } if (GetGame().IsMultiplayer()) { SyncSetValueBool(index, boolValue); } else { SetValueBool(index, boolValue); } break; } } void GUIAction_ActivateCommand(int commandIdx, int userInt, float userFloat) { if (GetGame().IsMultiplayer()) { SyncActivateCommand(commandIdx, userInt, userFloat); } else { ActivateCommand(commandIdx, userInt, userFloat); } } void GUIAction_EnableAI(bool enable) { if (GetGame().IsMultiplayer()) { SyncEnableAI(enable); } else { EnableAI(enable); } } /// //! sync /// void SendSyncMessages() { int count = m_SyncMessages.Count(); if (count > 0) { Param1 paramCount = new Param1(count); m_SyncMessages.InsertAt(paramCount, 0); GetGame().GetPlayer().RPC(ERPCs.DEV_RPC_PLUGIN_DZCREATURE_DEBUG, m_SyncMessages, true); m_SyncMessages.Clear(); } } void OnRpc(PlayerBase player, int rpc_type, ParamsReadContext ctx) { if (rpc_type == ERPCs.DEV_RPC_PLUGIN_DZCREATURE_DEBUG) { SyncReceiveMessage(ctx); } } void SyncReceiveMessage(ParamsReadContext ctx) { Param1 count = new Param1(0); if (ctx.Read(count)) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.COUNT); for (int i=0; i < count.param1; ++i) { if (ctx.Read(type)) { switch (type.param1) { case PluginDayZCreatureAIDebugSyncMessageType.INIT_DEBUG_OBJECT: SyncReceiveInitDebugObject(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.RELEASE_DEBUG_OBJECT: SyncReceiveReleaseDebugObject(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.SET_VALUE_INT: SyncReceiveValueInt(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.SET_VALUE_FLOAT: SyncReceiveValueFloat(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.SET_VALUE_BOOL: SyncReceiveValueBool(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.ACTIVATE_COMMAND: SyncReceiveActivateCommand(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.ENABLE_AI: SyncReceiveEnableAI(ctx); break; case PluginDayZCreatureAIDebugSyncMessageType.DISABLE_AI: SyncReceiveDisableAI(ctx); break; } } type.param1 = PluginDayZCreatureAIDebugSyncMessageType.COUNT; } } } void SyncInitDebugObject(Object obj) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.INIT_DEBUG_OBJECT); Param1 object = new Param1(obj); m_SyncMessages.Insert(type); m_SyncMessages.Insert(object); } void SyncReceiveInitDebugObject(ParamsReadContext ctx) { Param1 object = new Param1(NULL); if (ctx.Read(object)) { InitDebugObject(object.param1); } } void SyncReleaseDebugObject() { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.RELEASE_DEBUG_OBJECT); m_SyncMessages.Insert(type); } void SyncReceiveReleaseDebugObject(ParamsReadContext ctx) { ReleaseDebugObject(); } void SyncSetValueInt(int index, int value) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.SET_VALUE_INT); Param2 paramValue = new Param2(index, value); m_SyncMessages.Insert(type); m_SyncMessages.Insert(paramValue); } void SyncReceiveValueInt(ParamsReadContext ctx) { Param2 paramValue = new Param2(-1, 0); if (ctx.Read(paramValue)) { SetValueInt(paramValue.param1, paramValue.param2); } } void SyncSetValueFloat(int index, float value) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.SET_VALUE_FLOAT); Param2 paramValue = new Param2(index, value); m_SyncMessages.Insert(type); m_SyncMessages.Insert(paramValue); } void SyncReceiveValueFloat(ParamsReadContext ctx) { Param2 paramValue = new Param2(-1, 0.0); if (ctx.Read(paramValue)) { SetValueFloat(paramValue.param1, paramValue.param2); } } void SyncSetValueBool(int index, bool value) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.SET_VALUE_BOOL); Param2 paramValue = new Param2(index, value); m_SyncMessages.Insert(type); m_SyncMessages.Insert(paramValue); } void SyncReceiveValueBool(ParamsReadContext ctx) { Param2 paramValue = new Param2(-1, false); if (ctx.Read(paramValue)) { SetValueBool(paramValue.param1, paramValue.param2); } } void SyncActivateCommand(int commandIdx, int userInt, float userFloat) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.ACTIVATE_COMMAND); Param3 command = new Param3(commandIdx, userInt, userFloat); m_SyncMessages.Insert(type); m_SyncMessages.Insert(command); } void SyncReceiveActivateCommand(ParamsReadContext ctx) { Param3 command = new Param3(-1, 0, 0.0); if (ctx.Read(command)) { ActivateCommand(command.param1, command.param2, command.param3); } } void SyncEnableAI(bool enable) { Param1 type = new Param1(PluginDayZCreatureAIDebugSyncMessageType.COUNT); if (enable) { type.param1 = PluginDayZCreatureAIDebugSyncMessageType.ENABLE_AI; } else { type.param1 = PluginDayZCreatureAIDebugSyncMessageType.DISABLE_AI; } m_SyncMessages.Insert(type); } void SyncReceiveEnableAI(ParamsReadContext ctx) { EnableAI(true); } void SyncReceiveDisableAI(ParamsReadContext ctx) { EnableAI(false); } }