/**
* @class HumanInventoryWithFSM
* @brief HumanInventory... with FSM (synchronous, no anims)
**/
class HumanInventoryWithFSM : HumanInventory
{
protected ref HandFSM m_FSM; /// hand slot state machine
protected ref HandStateBase m_Empty;
protected ref HandStateBase m_Equipped;
void HumanInventoryWithFSM ()
{
m_FSM = new HandFSM();
}
void CreateStableStates ()
{
// stable states are created only if they do not exist already (for example created by derived class like DayZPlayerInventory)
// @NOTE: this cannot be done in constructor, as there is NO owner set yet. GetManOwner() will therefore return NULL.
if (!m_Empty)
m_Empty = new HandStateEmpty(GetManOwner());
if (!m_Equipped)
m_Equipped = new HandStateEquipped(GetManOwner());
}
override void Init ()
{
// setup state machine
if (LogManager.IsInventoryHFSMLogEnable()) hndDebugPrint("[hndfsm] Initializing Human Inventory FSM");
// basic states
CreateStableStates();
// events
HandEventBase __T__ = new HandEventTake;
HandEventBase __D__ = new HandEventDrop;
HandEventBase __Tw_ = new HandEventThrow;
HandEventBase __M__ = new HandEventMoveTo;
HandEventBase __W__ = new HandEventSwap;
HandEventBase __F__ = new HandEventForceSwap;
HandEventBase __X__ = new HandEventDestroy;
HandEventBase __Xd_ = new HandEventDestroyed;
HandEventBase __R__ = new HandEventDestroyAndReplaceWithNew;
HandEventBase __Re_ = new HandEventDestroyAndReplaceWithNewElsewhere;
HandEventBase __Rh_ = new HandEventDestroyElsewhereAndReplaceWithNewInHands;
HandEventBase __Rd_ = new HandEventReplaced;
HandEventBase __Cd_ = new HandEventCreated;
HandEventBase _fin_ = new HandEventHumanCommandActionFinished;
HandEventBase _abt_ = new HandEventHumanCommandActionAborted;
HandReplacingItemInHands replacing = new HandReplacingItemInHands(GetManOwner());
HandReplacingItemInHands replacingElsewhere = new HandReplacingItemInHands(GetManOwner());
HandReplacingItemElsewhereWithNewInHands replacingElsewhere3 = new HandReplacingItemElsewhereWithNewInHands(GetManOwner());
// setup transitions
m_FSM.AddTransition(new HandTransition( m_Empty , __T__, m_Equipped, new HandActionTake, new HandGuardHasItemInEvent(GetManOwner())));
m_FSM.AddTransition(new HandTransition( m_Empty , __Cd_, m_Equipped, new HandActionCreated, new HandGuardHasItemInEvent(GetManOwner())));
m_FSM.AddTransition(new HandTransition(m_Equipped, __D__, m_Empty, new HandActionDrop, null));
m_FSM.AddTransition(new HandTransition(m_Equipped, __Tw_, m_Empty, new HandActionThrow, null));
m_FSM.AddTransition(new HandTransition(m_Equipped, __M__, m_Empty, new HandActionMoveTo, new HandGuardAnd(new HandGuardHasItemInHands(GetManOwner()), new HandGuardCanMove(GetManOwner()))));
m_FSM.AddTransition(new HandTransition(m_Equipped, __X__, m_Empty, new HandActionDestroy, new HandGuardHasItemInHands(GetManOwner())));
m_FSM.AddTransition(new HandTransition(m_Equipped, __Xd_, m_Empty, new HandActionDestroyed, new HandGuardHasDestroyedItemInHands(GetManOwner())));
m_FSM.AddTransition(new HandTransition(m_Equipped, __Xd_, m_Equipped, new HandActionDestroyed, new HandGuardNot(new HandGuardHasDestroyedItemInHands(GetManOwner()))));
m_FSM.AddTransition(new HandTransition(m_Equipped, __R__, replacing));
m_FSM.AddTransition(new HandTransition(replacing, _fin_, m_Equipped));
replacing.AddTransition(new HandTransition(replacing.m_Replacing, _abt_, m_Equipped));
m_FSM.AddTransition(new HandTransition(m_Equipped, __Re_, replacingElsewhere));
m_FSM.AddTransition(new HandTransition(replacingElsewhere, _fin_, m_Empty));
replacingElsewhere.AddTransition(new HandTransition(replacingElsewhere.m_Replacing, _abt_, m_Equipped));
m_FSM.AddTransition(new HandTransition(m_Empty, __Rh_, replacingElsewhere3));
m_FSM.AddTransition(new HandTransition(replacingElsewhere3, _fin_, m_Equipped));
replacingElsewhere3.AddTransition(new HandTransition(replacingElsewhere3.m_Replacing, _abt_, m_Empty));
m_FSM.AddTransition(new HandTransition(m_Equipped, __Rd_, m_Equipped, new HandActionReplaced, null));
m_FSM.AddTransition(new HandTransition(m_Equipped, __W__, m_Equipped, new HandActionSwap, new HandGuardAnd(new HandGuardHasItemInHands(GetManOwner()), new HandGuardCanSwap(GetManOwner()))));
m_FSM.AddTransition(new HandTransition(m_Equipped, __F__, m_Equipped, new HandActionForceSwap, new HandGuardAnd(new HandGuardHasItemInHands(GetManOwner()), new HandGuardCanForceSwap(GetManOwner()))));
// start FSM
m_FSM.SetInitialState(m_Empty);
m_FSM.Start();
super.Init();
}
bool CanProcessHandEvents () { return m_FSM && m_FSM.IsRunning(); }
/**@fn ProcessHandEvent
* @brief hand's fsm handling of events
* @NOTE: warning: ProcessHandEvent can be called only within DayZPlayer::HandleInventory (or ::CommandHandler)
**/
override bool ProcessHandEvent (HandEventBase e)
{
//SyncRemote(e);
if (m_FSM.ProcessEvent(e) == ProcessEventResult.FSM_OK)
{
#ifdef ENABLE_LOGGING
if ( LogManager.IsInventoryHFSMLogEnable() )
{
Debug.InventoryHFSMLog("STS = " + GetManOwner().GetSimulationTimeStamp() , e.ToString(), "ProcessHandEvent", e.m_Player.ToString() );
}
#endif
return true;
}
else
{
//if (LogManager.IsInventoryHFSMLogEnable()) hndDebugPrint("FSM refused to process event (no transition): src=" + GetCurrentState().ToString() + " event=" + e.ToString());
return false;
}
}
bool ProcessHandAbortEvent (HandEventBase e)
{
//SyncRemote(e);
ProcessEventResult aa;
m_FSM.ProcessAbortEvent(e, aa);
if (aa == ProcessEventResult.FSM_OK)
{
if (LogManager.IsInventoryHFSMLogEnable()) hndDebugSpam("[hndfsm] STS = " + GetManOwner().GetSimulationTimeStamp() + " Processed event e=" + e.ToString());
return true;
}
else
{
//if (LogManager.IsInventoryHFSMLogEnable()) hndDebugPrint("FSM refused to process event (no transition): src=" + GetCurrentState().ToString() + " event=" + e.ToString());
return false;
}
}
void CheckFSMState()
{
if (GetEntityInHands())
{
if (!m_FSM.IsRunning() || GetCurrentStateID() == HandStateID.Empty) //forcing when not running or in stable state only
m_FSM.SetCurrentState(m_Equipped);
}
else
{
if (!m_FSM.IsRunning() || GetCurrentStateID() == HandStateID.Equipped) //forcing when not running or in stable state only
m_FSM.SetCurrentState(m_Empty);
}
}
override bool OnStoreLoad (ParamsReadContext ctx, int version)
{
if ( !super.OnStoreLoad(ctx, version) )
return false;
//@TODO
//m_FSM.OnStoreLoad(ctx, version);
return true;
}
override void OnStoreSave (ParamsWriteContext ctx)
{
super.OnStoreSave(ctx);
//@TODO
//m_FSM.OnStoreSave(ctx, version);
}
/**@fn GetCurrentStateID
* @return identifier of current stable state
**/
int GetCurrentStateID () { return m_FSM.GetCurrentStateID(); }
bool IsIdle () { return m_FSM.GetCurrentState().IsIdle(); }
/**@fn NetSyncCurrentStateID
* @brief Engine callback - network synchronization of FSM's state. not intended to direct use.
**/
void NetSyncCurrentStateID (int id)
{
m_FSM.NetSyncCurrentStateID(id);
}
};