예제 #1
0
void RPG_ActionHandler::PerformAction(RPG_ActionType_e const& action, bool forceAction /*= false*/, RPG_BaseEntity* const interactionEntity /*= NULL*/, 
                                      hkvVec3 const& interactionPosition /*= hkvVec3(0, 0, 0)*/, int const flags /*= 0*/)
{
  // if the action and the target are the same, we're just updating flags or interaction.
  bool updatingActionParams = false;
  
  if(m_activeAction.m_Action == action)
  {
    if(m_activeAction.m_interactionEntity != interactionEntity ||
       !m_activeAction.m_interactionPosition.isIdentical(interactionPosition) ||
       m_activeAction.m_flags != flags)
    {
      updatingActionParams = true;
    }
  }

  if(!forceAction && 
     m_activeAction.m_Action != AT_None &&
     action != AT_None)
  {  
    // there's an action already playing, and we aren't forcing the new one. perfor more checks.
    if(m_Actions[m_activeAction.m_Action]->CanOverrideActionWith(action) ||
       m_Actions[action]->CanThisActionOverride(m_activeAction.m_Action))
    {
      forceAction = true;
    }
  }

  if (forceAction || updatingActionParams || CanPerformAction(action))
  {
    // bundle the action into a struct for easier network replication
    RPG_ActionData actionData(action, interactionEntity, interactionPosition, flags);

    // simulate the action locally
    ProcessAction(actionData, forceAction);

    // replicate the action to the server
    //@todo: Once the network branch is integrated, here's where we replicate this action to the server.
    /*
    Work that needs to happen here:
    - Find out whether this is a non-authoritative client.
    - If all we're doing is updating action flags, preserve bandwidth by calling a client->server UpdateActionFlags() with just that data
    - If we're doing a new Action, call a client->server ProcessAction() using the constructed struct.
    */
  }
  else if(action != AT_None &&
     m_Actions[m_activeAction.m_Action]->CanChainAction(action))
  {
    // can't process the new action, so check to see if we can chain it
    RPG_ActionData actionData(action, interactionEntity, interactionPosition, flags);
    m_pendingAction = actionData;
  }
}
예제 #2
0
json_t * NetworkGroup::ToJson() const
{
    json_t * jsonGroup = json_object();
    json_object_set_new(jsonGroup, "id", json_integer(Id));
    json_object_set_new(jsonGroup, "name", json_string(GetName().c_str()));
    json_t * actionsArray = json_array();
    for (size_t i = 0; i < NetworkActions::Actions.size(); i++)
    {
        if (CanPerformAction(i))
        {
            const char * perm_name = NetworkActions::Actions[i].PermissionName.c_str();
            json_array_append_new(actionsArray, json_string(perm_name));
        }
    }
    json_object_set_new(jsonGroup, "permissions", actionsArray);
    return jsonGroup;
}
예제 #3
0
	virtual void EnumerateActions(TArray<EFriendActionType::Type>& Actions, bool bFromChat = false) override
	{
		bool bIsFriendInSameSession = FriendsAndChatManager.Pin()->IsFriendInSameSession(FriendItem);

		if(FriendItem->IsGameRequest())
		{
			if (FriendItem->IsGameJoinable())
			{
				Actions.Add(EFriendActionType::JoinGame);
			}
			Actions.Add(EFriendActionType::RejectGame);
		}
		else if(FriendItem->IsPendingAccepted())
		{
			Actions.Add(EFriendActionType::Updating);
		}
		else if (FriendItem->GetListType() == EFriendsDisplayLists::RecentPlayersDisplay)
		{
			TSharedPtr<IFriendItem> ExistingFriend = FriendsAndChatManager.Pin()->FindUser(*FriendItem->GetUniqueID());
			if (!ExistingFriend.IsValid())
			{
				Actions.Add(EFriendActionType::SendFriendRequest);
			}
			if (FriendsAndChatManager.Pin()->IsInJoinableGameSession() && FriendItem->IsOnline())
			{
				Actions.Add(EFriendActionType::InviteToGame);
			}
		}
		else
		{
			switch (FriendItem->GetInviteStatus())
			{
				case EInviteStatus::Accepted :
				{
					if (FriendItem->IsOnline() && !bIsFriendInSameSession && FriendItem->IsGameJoinable())
					{
						if(CanPerformAction(EFriendActionType::JoinGame))
						{
							Actions.Add(EFriendActionType::JoinGame);
						}
					}
					if (FriendItem->IsOnline() && !bIsFriendInSameSession && FriendItem->CanInvite() && FriendsAndChatManager.Pin()->IsInJoinableGameSession())
					{
						Actions.Add(EFriendActionType::InviteToGame);
					}
					if(!bFromChat)
					{
						if (FriendItem->IsOnline())
						{
							Actions.Add(EFriendActionType::Chat);
						}
						Actions.Add(EFriendActionType::RemoveFriend);
					}
				}
				break;
				case EInviteStatus::PendingInbound :
				{
					Actions.Add(EFriendActionType::AcceptFriendRequest);
					Actions.Add(EFriendActionType::IgnoreFriendRequest);
				}
				break;
				case EInviteStatus::PendingOutbound :
				{
					Actions.Add(EFriendActionType::CancelFriendRequest);
				}
				break;
			default:
				Actions.Add(EFriendActionType::SendFriendRequest);
				break;
			}
		}
	}
예제 #4
0
void RPG_ActionHandler::ProcessAction(RPG_ActionData const& actionData, bool const forceAction /*= false*/)
{
  // if we're already doing the requested move, ignore the call except to update flags or interaction entities.
  if (actionData.m_Action == m_activeAction.m_Action)
  {
    // same move, updated flags
    if (actionData.m_Action != AT_None && actionData.m_flags != m_activeAction.m_flags)
    {
      m_activeAction.m_flags = actionData.m_flags;
      //@todo: if this is happening on the authoritative server, replicate this flag change to clients.
      if (m_Actions[actionData.m_Action])
      {
        m_Actions[actionData.m_Action]->UpdateFlags(actionData.m_flags);
      }
    }

    // same move, updated interaction entity
    if(actionData.m_interactionEntity != m_activeAction.m_interactionEntity ||
        !actionData.m_interactionPosition.isIdentical(m_activeAction.m_interactionPosition))
    {
      m_activeAction.m_interactionEntity = actionData.m_interactionEntity;
      m_activeAction.m_interactionPosition = actionData.m_interactionPosition;

      if(m_Actions[actionData.m_Action])
      {
        m_Actions[actionData.m_Action]->UpdateInteraction(actionData.m_interactionEntity, actionData.m_interactionPosition);

        // clear the pending action, as enough data has changed for the pending action to probably not be the desired behavior.
        m_pendingAction.Clear();
      }
    }

    // clear the pending action if this was forced
    if(forceAction)
    {
      m_pendingAction.Clear();
    }

    // no further action required, since this isn't a new move.
    return;
  }

  // if we're chaining from an action that needs to complete first, defer this action
  if (m_endingAction)
  {
    m_pendingAction = actionData;
    return;
  }

  // verify that we can do this move
  if (actionData.m_Action != AT_None && !forceAction && !m_chainingAction && !CanPerformAction(actionData.m_Action))
  {
    Vision::Error.Warning("Cannot perform requested Action.");
    return;
  }

  // ready to go.
  m_previousAction = m_activeAction;

  // stop the previous action, if any
  if (m_activeAction.m_Action != AT_None)
  {
    m_endingAction = true;
    m_activeAction.m_Action = AT_None;
    RPG_ActionType_e nextAction = actionData.m_Action;
    if (nextAction == AT_None && m_pendingAction.m_Action != AT_None)
    {
      nextAction = m_pendingAction.m_Action;
    }
    CleanUpAction(m_previousAction.m_Action, nextAction);
    m_endingAction = false;
  }

  // if we need to start a pending action, do it now
  if (actionData.m_Action == AT_None && m_pendingAction.m_Action != AT_None)
  {
    // Recursively Process the pending action if one exists.
    
    m_chainingAction = true;
    m_activeAction.m_Action = m_previousAction.m_Action;  // restore this value, since the pending action call will need it.
    ProcessAction(m_pendingAction);
    m_chainingAction = false;
    
    if (m_activeAction.m_Action == m_pendingAction.m_Action)
    {
      m_pendingAction.Clear();
      return;
    }
  }

  // set the new Action
  m_activeAction = actionData;

  // @todo: Once the network branch is in, replicate these values.
  // - m_replicatedAction = m_activeAction;
  // - force net update

  if (m_activeAction.m_Action != AT_None)
  {
    StartAction(m_activeAction.m_Action, m_previousAction.m_Action, forceAction, m_activeAction.m_interactionEntity, m_activeAction.m_interactionPosition, m_activeAction.m_flags);

    // if this was a forced action, clear any pending action, as this was an interrupt of the current action
    if (forceAction)
    {
      m_pendingAction.Clear();
    }
  }
}