RedDobe Posted October 7, 2018 Share Posted October 7, 2018 Hey All. I need some assistance with this. I am trying to create a sound alert once a destructible object is destroyed. The event trigger that I am using is `XEVENTMGR.RegisterForEvent(ThisObj, 'ObjectDestroyed', OnExplosion, ELD_OnStateSubmitted); 'Object Destroyed' is triggered on the TakeDamage event (code cut below) in the XComGameState_Destructible class which has all of the information I need to create the alert. I just don't know how to get to it properly. Snipped from TakeDamage in XComGameState_Destructible { // fire an event to notify that this object was destroyed KillerUnitState = XComGameState_Unit( `XCOMHISTORY.GetGameStateForObjectID( DamageSource.ObjectID ) ); `XEVENTMGR.TriggerEvent( 'ObjectDestroyed', KillerUnitState, self, NewGameState ); bRequiresVisibilityUpdate = true; } if (Visualizer.IsTargetable( )) { // Add an environment damage state at our location. This will cause the actual damage to the // destructible actor in the world. DamageEvent = XComGameState_EnvironmentDamage( NewGameState.CreateNewStateObject( class'XComGameState_EnvironmentDamage' ) ); DamageEvent.DEBUG_SourceCodeLocation = "UC: XComGameState_Destructible:TakeEffectDamage"; DamageEvent.DamageAmount = DamageAmount; DamageEvent.DamageTypeTemplateName = 'Explosion'; DamageEvent.HitLocation = WorldData.GetPositionFromTileCoordinates( TileLocation ); DamageEvent.DamageTiles.AddItem( TileLocation ); DamageEvent.DamageCause = DamageSource; DamageEvent.DamageSource = DamageEvent.DamageCause; DamageEvent.bTargetableDamage = true; DamageEvent.DamageTarget = GetReference( ); } Here is what I have so far, but Modbuddy is throwing up an error on DamageGameState == none, saying that left type is incompatible with ==. //My attempt at created hear explosion alerts function EventListenerReturn OnExplosion(Object EventData, Object EventSource, XComGameState GameState, Name EventID, Object CallbackData) { local XComGameStateHistory History; local XComGameState_EnvironmentDamage DamageGameState; local TTile SoundTileLocation; local AlertAbilityInfo AlertInfo; local XComGameState_Unit kUnitState; local XComGameState_AIUnitData NewUnitAIState, kAIData; local array<StateObjectReference> AliensInRange; // LWS Added DamageGameState = XComGameState_EnvironmentDamage(EventData); if (DamageGameState == none) { `RedScreen("OnExplosion: no environment damage"); return ELR_NoInterrupt; } SoundTileLocation = DamageGameState.DamageTiles[0]; if (SoundTileLocation == none) { `RedScreen("OnExplosion: no damage tile found"); return ELR_NoInterrupt; } History = `XCOMHISTORY; AlertInfo.AlertTileLocation = SoundTileLocation; AlertInfo.AlertRadius = 30; AlertInfo.AlertUnitSourceID = DamageGameState.DamageCause.ObjectID; AlertInfo.AnalyzingHistoryIndex = History.GetCurrentHistoryIndex( ); //NewGameState.HistoryIndex; <- this value is -1. // Gather the units in sound range of this explosion. class'HelpersYellowAlert'.static.GetAlienUnitsInRange(SoundTileLocation, 30, AliensInRange); foreach History.IterateByClassType( class'XComGameState_AIUnitData', kAIData ) { kUnitState = XComGameState_Unit( History.GetGameStateForObjectID( kAIData.m_iUnitObjectID ) ); if (kUnitState != None && kUnitState.IsAlive( )) { // LWS Add: Skip units outside of sound range if (AliensInRange.Find('ObjectID', kUnitState.ObjectID) < 0) continue; CleanupAIData = false; // LWS: Check to see if we already have ai data for this unit in this game state (alert may already have been propagated to // group members). NewUnitAIState = XComGameState_AIUnitData(NewGameState.GetGameStateForObjectID(kAIData.ObjectID)); if (NewUnitAIState == none) { NewUnitAIState = XComGameState_AIUnitData( NewGameState.CreateStateObject( kAIData.Class, kAIData.ObjectID ) ); // LWS: This unit will need cleanup if we fail to add the alert. CleanupAIData = true; } if( NewUnitAIState.AddAlertData( kAIData.m_iUnitObjectID, eAC_SeesExplosion, AlertInfo, NewGameState ) ) { NewGameState.AddStateObject(NewUnitAIState); } else { // LWS Add: Don't cleanup this AI unit data unless we created it. if (CleanupAIData) { NewGameState.PurgeGameStateForObjectID(NewUnitAIState.ObjectID); } } } } if( NewGameState.GetNumGameStateObjects() > 0 ) { `GAMERULES.SubmitGameState(NewGameState); } else { History.CleanupPendingGameState(NewGameState); } return ELR_NoInterrupt; } Link to comment Share on other sites More sharing options...
RedDobe Posted October 9, 2018 Author Share Posted October 9, 2018 Well I found the problem. I was using the wrong trigger. It turns out there is a trigger for each XComGameState_EnvironmentDamage called 'OnEnvironmentalDamage' that gave me the correct gamestate. This now works and I will be updating the Yellow Alert mod to include explosion alerts. `XEVENTMGR.RegisterForEvent(ThisObj, 'OnEnvironmentalDamage', OnExplosion, ELD_OnStateSubmitted); //Create Seesexplosion alerts (truly it is produced by sound but I am using the default eAC_SeesExplosion) function EventListenerReturn OnExplosion(Object EventData, Object EventSource, XComGameState GameState, Name EventID, Object CallbackData) { local XComGameStateHistory History; local XComGameState_EnvironmentDamage DamageGameState; local TTile DamageTileLocation; local Name DamageType; local bool CanTarget; local XComGameState NewGameState; local AlertAbilityInfo AlertInfo; local XComGameState_Unit kUnitState; local XComGameState_AIUnitData NewUnitAIState, kAIData; local array<StateObjectReference> AliensInRange; // LWS Added local bool CleanupAIData; // LWS Added DamageGameState = XComGameState_EnvironmentDamage(EventData); CanTarget = DamageGameState.bTargetableDamage; DamageType = DamageGameState.DamageTypeTemplateName; if(CanTarget && DamageType == 'Explosion') { `Log("OnExplosion: Can target is "@CanTarget@" and Damage type is "@DamageType); } else { return ELR_NoInterrupt; } DamageTileLocation = DamageGameState.DamageTiles[0]; `Log("OnExplosion: Damage tile location found at " $DamageTileLocation.X$","@DamageTileLocation.Y$","@DamageTileLocation.Z); History = `XCOMHISTORY; // Kick off mass alert to location. NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState( "Explosion Alert" ); AlertInfo.AlertTileLocation = DamageTileLocation; AlertInfo.AlertRadius = 30; AlertInfo.AlertUnitSourceID = DamageGameState.DamageCause.ObjectID; AlertInfo.AnalyzingHistoryIndex = History.GetCurrentHistoryIndex( ); //NewGameState.HistoryIndex; <- this value is -1. // Gather the units in sound range of this explosion. class'HelpersYellowAlert'.static.GetAlienUnitsInRange(DamageTileLocation, 30, AliensInRange); foreach History.IterateByClassType( class'XComGameState_AIUnitData', kAIData ) { kUnitState = XComGameState_Unit( History.GetGameStateForObjectID( kAIData.m_iUnitObjectID ) ); if (kUnitState != None && kUnitState.IsAlive( )) { // LWS Add: Skip units outside of sound range if (AliensInRange.Find('ObjectID', kUnitState.ObjectID) < 0) continue; CleanupAIData = false; // LWS: Check to see if we already have ai data for this unit in this game state (alert may already have been propagated to // group members). NewUnitAIState = XComGameState_AIUnitData(NewGameState.GetGameStateForObjectID(kAIData.ObjectID)); if (NewUnitAIState == none) { NewUnitAIState = XComGameState_AIUnitData( NewGameState.CreateStateObject( kAIData.Class, kAIData.ObjectID ) ); // LWS: This unit will need cleanup if we fail to add the alert. CleanupAIData = true; } if( NewUnitAIState.AddAlertData( kAIData.m_iUnitObjectID, eAC_SeesExplosion, AlertInfo, NewGameState ) ) { NewGameState.AddStateObject(NewUnitAIState); } else { // LWS Add: Don't cleanup this AI unit data unless we created it. if (CleanupAIData) { NewGameState.PurgeGameStateForObjectID(NewUnitAIState.ObjectID); } } } } if( NewGameState.GetNumGameStateObjects() > 0 ) { `GAMERULES.SubmitGameState(NewGameState); } else { History.CleanupPendingGameState(NewGameState); } return ELR_NoInterrupt; } Link to comment Share on other sites More sharing options...
Recommended Posts