aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/Tutorial
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/Common/Tutorial')
-rw-r--r--Minecraft.Client/Common/Tutorial/AreaConstraint.cpp52
-rw-r--r--Minecraft.Client/Common/Tutorial/AreaConstraint.h24
-rw-r--r--Minecraft.Client/Common/Tutorial/AreaHint.cpp49
-rw-r--r--Minecraft.Client/Common/Tutorial/AreaHint.h25
-rw-r--r--Minecraft.Client/Common/Tutorial/AreaTask.cpp69
-rw-r--r--Minecraft.Client/Common/Tutorial/AreaTask.h24
-rw-r--r--Minecraft.Client/Common/Tutorial/ChangeStateConstraint.cpp136
-rw-r--r--Minecraft.Client/Common/Tutorial/ChangeStateConstraint.h37
-rw-r--r--Minecraft.Client/Common/Tutorial/ChoiceTask.cpp135
-rw-r--r--Minecraft.Client/Common/Tutorial/ChoiceTask.h27
-rw-r--r--Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.cpp37
-rw-r--r--Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.h20
-rw-r--r--Minecraft.Client/Common/Tutorial/ControllerTask.cpp123
-rw-r--r--Minecraft.Client/Common/Tutorial/ControllerTask.h24
-rw-r--r--Minecraft.Client/Common/Tutorial/CraftTask.cpp66
-rw-r--r--Minecraft.Client/Common/Tutorial/CraftTask.h25
-rw-r--r--Minecraft.Client/Common/Tutorial/DiggerItemHint.cpp76
-rw-r--r--Minecraft.Client/Common/Tutorial/DiggerItemHint.h18
-rw-r--r--Minecraft.Client/Common/Tutorial/EffectChangedTask.cpp31
-rw-r--r--Minecraft.Client/Common/Tutorial/EffectChangedTask.h19
-rw-r--r--Minecraft.Client/Common/Tutorial/FullTutorial.cpp653
-rw-r--r--Minecraft.Client/Common/Tutorial/FullTutorial.h21
-rw-r--r--Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.cpp26
-rw-r--r--Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.h18
-rw-r--r--Minecraft.Client/Common/Tutorial/FullTutorialMode.cpp16
-rw-r--r--Minecraft.Client/Common/Tutorial/FullTutorialMode.h12
-rw-r--r--Minecraft.Client/Common/Tutorial/InfoTask.cpp137
-rw-r--r--Minecraft.Client/Common/Tutorial/InfoTask.h25
-rw-r--r--Minecraft.Client/Common/Tutorial/InputConstraint.cpp18
-rw-r--r--Minecraft.Client/Common/Tutorial/InputConstraint.h15
-rw-r--r--Minecraft.Client/Common/Tutorial/LookAtEntityHint.cpp25
-rw-r--r--Minecraft.Client/Common/Tutorial/LookAtEntityHint.h20
-rw-r--r--Minecraft.Client/Common/Tutorial/LookAtTileHint.cpp68
-rw-r--r--Minecraft.Client/Common/Tutorial/LookAtTileHint.h22
-rw-r--r--Minecraft.Client/Common/Tutorial/PickupTask.cpp17
-rw-r--r--Minecraft.Client/Common/Tutorial/PickupTask.h26
-rw-r--r--Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.cpp263
-rw-r--r--Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.h36
-rw-r--r--Minecraft.Client/Common/Tutorial/ProgressFlagTask.cpp17
-rw-r--r--Minecraft.Client/Common/Tutorial/ProgressFlagTask.h25
-rw-r--r--Minecraft.Client/Common/Tutorial/StatTask.cpp25
-rw-r--r--Minecraft.Client/Common/Tutorial/StatTask.h18
-rw-r--r--Minecraft.Client/Common/Tutorial/StateChangeTask.h27
-rw-r--r--Minecraft.Client/Common/Tutorial/TakeItemHint.cpp45
-rw-r--r--Minecraft.Client/Common/Tutorial/TakeItemHint.h19
-rw-r--r--Minecraft.Client/Common/Tutorial/Tutorialbin0 -> 8973500 bytes
-rw-r--r--Minecraft.Client/Common/Tutorial/Tutorial.cpp2160
-rw-r--r--Minecraft.Client/Common/Tutorial/Tutorial.h199
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialConstraint.h41
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialConstraints.h4
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialEnum.h329
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialHint.cpp128
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialHint.h53
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialHints.h7
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialMessage.cpp23
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialMessage.h20
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialMode.cpp124
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialMode.h28
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialTask.cpp78
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialTask.h63
-rw-r--r--Minecraft.Client/Common/Tutorial/TutorialTasks.h16
-rw-r--r--Minecraft.Client/Common/Tutorial/UseItemTask.cpp25
-rw-r--r--Minecraft.Client/Common/Tutorial/UseItemTask.h20
-rw-r--r--Minecraft.Client/Common/Tutorial/UseTileTask.cpp40
-rw-r--r--Minecraft.Client/Common/Tutorial/UseTileTask.h24
-rw-r--r--Minecraft.Client/Common/Tutorial/XuiCraftingTask.cpp42
-rw-r--r--Minecraft.Client/Common/Tutorial/XuiCraftingTask.h36
67 files changed, 6071 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/Tutorial/AreaConstraint.cpp b/Minecraft.Client/Common/Tutorial/AreaConstraint.cpp
new file mode 100644
index 00000000..f133d604
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/AreaConstraint.cpp
@@ -0,0 +1,52 @@
+#include "stdafx.h"
+
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "AreaConstraint.h"
+#include "..\..\..\Minecraft.World\AABB.h"
+
+AreaConstraint::AreaConstraint( int descriptionId, double x0, double y0, double z0, double x1, double y1, double z1, bool contains /*= true*/, bool restrictsMovement /*=true*/ )
+ : TutorialConstraint( descriptionId )
+{
+ messageArea = AABB::newPermanent(x0+2, y0+2, z0+2, x1-2, y1-2, z1-2);
+ movementArea = AABB::newPermanent(x0, y0, z0, x1, y1, z1);
+
+ this->contains = contains;
+ m_restrictsMovement = restrictsMovement;
+}
+
+AreaConstraint::~AreaConstraint()
+{
+ delete messageArea;
+ delete movementArea;
+}
+
+bool AreaConstraint::isConstraintSatisfied(int iPad)
+{
+ Minecraft *minecraft = Minecraft::GetInstance();
+ return messageArea->contains( minecraft->localplayers[iPad]->getPos(1) ) == contains;
+}
+
+bool AreaConstraint::isConstraintRestrictive(int iPad)
+{
+ return m_restrictsMovement;
+}
+
+
+bool AreaConstraint::canMoveToPosition(double xo, double yo, double zo, double xt, double yt, double zt)
+{
+ if(!m_restrictsMovement) return true;
+
+ Vec3 *targetPos = Vec3::newTemp(xt, yt, zt);
+ Minecraft *minecraft = Minecraft::GetInstance();
+
+ if(movementArea->contains( targetPos ) == contains)
+ {
+ return true;
+ }
+ Vec3 *origPos = Vec3::newTemp(xo, yo, zo);
+
+ double currDist = origPos->distanceTo(movementArea);
+ double targetDist = targetPos->distanceTo(movementArea);
+ return targetDist < currDist;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/AreaConstraint.h b/Minecraft.Client/Common/Tutorial/AreaConstraint.h
new file mode 100644
index 00000000..f98945e1
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/AreaConstraint.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "TutorialConstraint.h"
+
+class AABB;
+
+class AreaConstraint : public TutorialConstraint
+{
+private:
+ AABB *movementArea;
+ AABB *messageArea;
+ bool contains; // If true we must stay in this area, if false must stay out of this area
+ bool m_restrictsMovement;
+
+public:
+ virtual ConstraintType getType() { return e_ConstraintArea; }
+
+ AreaConstraint( int descriptionId, double x0, double y0, double z0, double x1, double y1, double z1, bool contains = true, bool restrictsMovement =true );
+ ~AreaConstraint();
+
+ virtual bool isConstraintSatisfied(int iPad);
+ virtual bool isConstraintRestrictive(int iPad);
+ virtual bool canMoveToPosition(double xo, double yo, double zo, double xt, double yt, double zt);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/AreaHint.cpp b/Minecraft.Client/Common/Tutorial/AreaHint.cpp
new file mode 100644
index 00000000..8b711c88
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/AreaHint.cpp
@@ -0,0 +1,49 @@
+#include "stdafx.h"
+
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "AreaHint.h"
+#include "..\..\..\Minecraft.World\AABB.h"
+#include "Tutorial.h"
+
+AreaHint::AreaHint(eTutorial_Hint id, Tutorial *tutorial, eTutorial_State displayState, eTutorial_State completeState,
+ int descriptionId, double x0, double y0, double z0, double x1, double y1, double z1, bool allowFade /*= false*/, bool contains /*= true*/ )
+ : TutorialHint( id, tutorial, descriptionId, e_Hint_Area, allowFade )
+{
+ area = AABB::newPermanent(x0, y0, z0, x1, y1, z1);
+
+ this->contains = contains;
+
+ m_displayState = displayState;
+ m_completeState = completeState;
+}
+
+AreaHint::~AreaHint()
+{
+ delete area;
+}
+
+int AreaHint::tick()
+{
+ Minecraft *minecraft = Minecraft::GetInstance();
+ if( (m_displayState == e_Tutorial_State_Any || m_tutorial->getCurrentState() == m_displayState) &&
+ m_hintNeeded &&
+ area->contains( minecraft->player->getPos(1) ) == contains )
+ {
+ if( m_completeState == e_Tutorial_State_None )
+ {
+ m_hintNeeded = false;
+ }
+ else if ( m_tutorial->isStateCompleted( m_completeState ) )
+ {
+ m_hintNeeded = false;
+ return -1;
+ }
+
+ return m_descriptionId;
+ }
+ else
+ {
+ return -1;
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/AreaHint.h b/Minecraft.Client/Common/Tutorial/AreaHint.h
new file mode 100644
index 00000000..12ef8977
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/AreaHint.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "TutorialHint.h"
+
+class AABB;
+
+class AreaHint : public TutorialHint
+{
+private:
+ AABB *area;
+ bool contains; // If true we must stay in this area, if false must stay out of this area
+
+ // Only display the hint if the game is in this state
+ eTutorial_State m_displayState;
+
+ // Only display the hint if this state is not completed
+ eTutorial_State m_completeState;
+
+public:
+ AreaHint(eTutorial_Hint id, Tutorial *tutorial, eTutorial_State displayState, eTutorial_State completeState,
+ int descriptionId, double x0, double y0, double z0, double x1, double y1, double z1, bool allowFade = true, bool contains = true );
+ ~AreaHint();
+
+ virtual int tick();
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/AreaTask.cpp b/Minecraft.Client/Common/Tutorial/AreaTask.cpp
new file mode 100644
index 00000000..de29ab1b
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/AreaTask.cpp
@@ -0,0 +1,69 @@
+#include "stdafx.h"
+#include "Tutorial.h"
+#include "AreaTask.h"
+
+AreaTask::AreaTask(eTutorial_State state, Tutorial *tutorial, vector<TutorialConstraint *> *inConstraints, int descriptionId, EAreaTaskCompletionStates completionState)
+ : TutorialTask( tutorial, descriptionId, false, inConstraints, false, false, false )
+{
+ m_tutorialState = state;
+ if(m_tutorialState == e_Tutorial_State_Gameplay)
+ {
+ enableConstraints(true);
+ }
+ m_completionState = completionState;
+}
+
+bool AreaTask::isCompleted()
+{
+ if(bIsCompleted) return true;
+
+ bool complete = false;
+ switch(m_completionState)
+ {
+ case eAreaTaskCompletion_CompleteOnConstraintsSatisfied:
+ {
+ bool allSatisfied = true;
+ for(AUTO_VAR(it, constraints.begin()); it != constraints.end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ if(!constraint->isConstraintSatisfied(tutorial->getPad()))
+ {
+ allSatisfied = false;
+ break;
+ }
+ }
+ complete = allSatisfied;
+ }
+ break;
+ case eAreaTaskCompletion_CompleteOnActivation:
+ complete = bHasBeenActivated;
+ break;
+ };
+ bIsCompleted = complete;
+ return complete;
+}
+
+void AreaTask::setAsCurrentTask(bool active)
+{
+ TutorialTask::setAsCurrentTask(active);
+
+ if(m_completionState == eAreaTaskCompletion_CompleteOnConstraintsSatisfied)
+ {
+ enableConstraints(active);
+ }
+}
+
+void AreaTask::onStateChange(eTutorial_State newState)
+{
+ if(m_completionState == eAreaTaskCompletion_CompleteOnActivation)
+ {
+ if(m_tutorialState == newState)
+ {
+ enableConstraints(true);
+ }
+ else if(m_tutorialState != e_Tutorial_State_Gameplay)
+ {
+ //enableConstraints(false);
+ }
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/AreaTask.h b/Minecraft.Client/Common/Tutorial/AreaTask.h
new file mode 100644
index 00000000..0d20bd7a
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/AreaTask.h
@@ -0,0 +1,24 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+// A task that creates an maintains an area constraint until it is activated
+class AreaTask : public TutorialTask
+{
+public:
+ enum EAreaTaskCompletionStates
+ {
+ eAreaTaskCompletion_CompleteOnActivation,
+ eAreaTaskCompletion_CompleteOnConstraintsSatisfied,
+ };
+private:
+ EAreaTaskCompletionStates m_completionState;
+ eTutorial_State m_tutorialState;
+public:
+ AreaTask(eTutorial_State state, Tutorial *tutorial, vector<TutorialConstraint *> *inConstraints, int descriptionId = -1, EAreaTaskCompletionStates completionState = eAreaTaskCompletion_CompleteOnActivation);
+ virtual bool isCompleted();
+ virtual void setAsCurrentTask(bool active = true);
+ virtual void onStateChange(eTutorial_State newState);
+
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ChangeStateConstraint.cpp b/Minecraft.Client/Common/Tutorial/ChangeStateConstraint.cpp
new file mode 100644
index 00000000..f01db84e
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ChangeStateConstraint.cpp
@@ -0,0 +1,136 @@
+#include "stdafx.h"
+
+#include "Tutorial.h"
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
+#include "ChangeStateConstraint.h"
+#include "..\..\..\Minecraft.World\AABB.h"
+#include "..\..\ClientConnection.h"
+#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h"
+
+ChangeStateConstraint::ChangeStateConstraint( Tutorial *tutorial, eTutorial_State targetState, eTutorial_State sourceStates[], DWORD sourceStatesCount,
+ double x0, double y0, double z0, double x1, double y1, double z1, bool contains /*= true*/, bool changeGameMode /*= false*/, GameType *targetGameMode /*= 0*/ )
+ : TutorialConstraint( -1 )
+{
+ movementArea = AABB::newPermanent(x0, y0, z0, x1, y1, z1);
+
+ this->contains = contains;
+
+ m_changeGameMode = changeGameMode;
+ m_targetGameMode = targetGameMode;
+ m_changedFromGameMode = 0;
+
+ m_tutorial = tutorial;
+ m_targetState = targetState;
+ m_sourceStatesCount = sourceStatesCount;
+
+ m_bHasChanged = false;
+ m_changedFromState = e_Tutorial_State_None;
+
+ m_bComplete = false;
+
+ m_sourceStates = new eTutorial_State [m_sourceStatesCount];
+ for(unsigned int i=0;i<m_sourceStatesCount;i++)
+ {
+ m_sourceStates[i]=sourceStates[i];
+ }
+}
+
+ChangeStateConstraint::~ChangeStateConstraint()
+{
+ delete movementArea;
+ if(m_sourceStatesCount>0) delete [] m_sourceStates;
+}
+
+void ChangeStateConstraint::tick(int iPad)
+{
+ if(m_bComplete) return;
+
+ if(m_tutorial->isStateCompleted(m_targetState))
+ {
+ Minecraft *minecraft = Minecraft::GetInstance();
+ if(m_changeGameMode)
+ {
+ unsigned int playerPrivs = minecraft->localplayers[iPad]->getAllPlayerGamePrivileges();
+ Player::setPlayerGamePrivilege(playerPrivs,Player::ePlayerGamePrivilege_CreativeMode,m_changedFromGameMode == GameType::CREATIVE);
+
+ unsigned int originalPrivileges = minecraft->localplayers[iPad]->getAllPlayerGamePrivileges();
+ if(originalPrivileges != playerPrivs)
+ {
+ // Send update settings packet to server
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ shared_ptr<MultiplayerLocalPlayer> player = minecraft->localplayers[iPad];
+ if(player != NULL && player->connection && player->connection->getNetworkPlayer() != NULL)
+ {
+ player->connection->send( shared_ptr<PlayerInfoPacket>( new PlayerInfoPacket( player->connection->getNetworkPlayer()->GetSmallId(), -1, playerPrivs) ) );
+ }
+ }
+ }
+ m_bComplete = true;
+ return;
+ }
+
+ bool inASourceState = false;
+ Minecraft *minecraft = Minecraft::GetInstance();
+ for(DWORD i = 0; i < m_sourceStatesCount; ++i)
+ {
+ if(m_sourceStates[i] == m_tutorial->getCurrentState())
+ {
+ inASourceState = true;
+ break;
+ }
+ }
+ if( !m_bHasChanged && inASourceState && movementArea->contains( minecraft->localplayers[iPad]->getPos(1) ) == contains )
+ {
+ m_bHasChanged = true;
+ m_changedFromState = m_tutorial->getCurrentState();
+ m_tutorial->changeTutorialState(m_targetState);
+
+ if(m_changeGameMode)
+ {
+ if(minecraft->localgameModes[iPad] != NULL)
+ {
+ m_changedFromGameMode = minecraft->localplayers[iPad]->abilities.instabuild ? GameType::CREATIVE : GameType::SURVIVAL;
+
+ unsigned int playerPrivs = minecraft->localplayers[iPad]->getAllPlayerGamePrivileges();
+ Player::setPlayerGamePrivilege(playerPrivs,Player::ePlayerGamePrivilege_CreativeMode,m_targetGameMode == GameType::CREATIVE);
+
+ unsigned int originalPrivileges = minecraft->localplayers[iPad]->getAllPlayerGamePrivileges();
+ if(originalPrivileges != playerPrivs)
+ {
+ // Send update settings packet to server
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ shared_ptr<MultiplayerLocalPlayer> player = minecraft->localplayers[iPad];
+ if(player != NULL && player->connection && player->connection->getNetworkPlayer() != NULL)
+ {
+ player->connection->send( shared_ptr<PlayerInfoPacket>( new PlayerInfoPacket( player->connection->getNetworkPlayer()->GetSmallId(), -1, playerPrivs) ) );
+ }
+ }
+ }
+ }
+ }
+ else if( m_bHasChanged && movementArea->contains( minecraft->localplayers[iPad]->getPos(1) ) != contains )
+ {
+ m_bHasChanged = false;
+ m_tutorial->changeTutorialState(m_changedFromState);
+
+ if(m_changeGameMode)
+ {
+ unsigned int playerPrivs = minecraft->localplayers[iPad]->getAllPlayerGamePrivileges();
+ Player::setPlayerGamePrivilege(playerPrivs,Player::ePlayerGamePrivilege_CreativeMode,m_changedFromGameMode == GameType::CREATIVE);
+
+ unsigned int originalPrivileges = minecraft->localplayers[iPad]->getAllPlayerGamePrivileges();
+ if(originalPrivileges != playerPrivs)
+ {
+ // Send update settings packet to server
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ shared_ptr<MultiplayerLocalPlayer> player = minecraft->localplayers[iPad];
+ if(player != NULL && player->connection && player->connection->getNetworkPlayer() != NULL)
+ {
+ player->connection->send( shared_ptr<PlayerInfoPacket>( new PlayerInfoPacket( player->connection->getNetworkPlayer()->GetSmallId(), -1, playerPrivs) ) );
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ChangeStateConstraint.h b/Minecraft.Client/Common/Tutorial/ChangeStateConstraint.h
new file mode 100644
index 00000000..2156870d
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ChangeStateConstraint.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "TutorialEnum.h"
+#include "TutorialConstraint.h"
+
+class AABB;
+class Tutorial;
+class GameType;
+
+class ChangeStateConstraint : public TutorialConstraint
+{
+private:
+ AABB *movementArea;
+ bool contains; // If true we must stay in this area, if false must stay out of this area
+ bool m_changeGameMode;
+ GameType *m_targetGameMode;
+ GameType *m_changedFromGameMode;
+
+ eTutorial_State m_targetState;
+ eTutorial_State *m_sourceStates;
+ DWORD m_sourceStatesCount;
+
+ bool m_bHasChanged;
+ eTutorial_State m_changedFromState;
+
+ bool m_bComplete;
+
+ Tutorial *m_tutorial;
+
+public:
+ virtual ConstraintType getType() { return e_ConstraintChangeState; }
+
+ ChangeStateConstraint( Tutorial *tutorial, eTutorial_State targetState, eTutorial_State sourceStates[], DWORD sourceStatesCount, double x0, double y0, double z0, double x1, double y1, double z1, bool contains = true, bool changeGameMode = false, GameType *targetGameMode = NULL );
+ ~ChangeStateConstraint();
+
+ virtual void tick(int iPad);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp b/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp
new file mode 100644
index 00000000..c03166b5
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp
@@ -0,0 +1,135 @@
+#include "stdafx.h"
+#include <string>
+#include <unordered_map>
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "Tutorial.h"
+#include "TutorialConstraints.h"
+#include "ChoiceTask.h"
+#include "..\..\..\Minecraft.World\Material.h"
+
+ChoiceTask::ChoiceTask(Tutorial *tutorial, int descriptionId, int promptId /*= -1*/, bool requiresUserInput /*= false*/,
+ int iConfirmMapping /*= 0*/, int iCancelMapping /*= 0*/,
+ eTutorial_CompletionAction cancelAction /*= e_Tutorial_Completion_None*/, ETelemetryChallenges telemetryEvent /*= eTelemetryTutorial_NoEvent*/)
+ : TutorialTask( tutorial, descriptionId, false, NULL, true, false, false )
+{
+ if(requiresUserInput == true)
+ {
+ constraints.push_back( new InputConstraint( iConfirmMapping ) );
+ constraints.push_back( new InputConstraint( iCancelMapping ) );
+ }
+ m_iConfirmMapping = iConfirmMapping;
+ m_iCancelMapping = iCancelMapping;
+ m_bConfirmMappingComplete = false;
+ m_bCancelMappingComplete = false;
+
+ m_cancelAction = cancelAction;
+
+ m_promptId = promptId;
+ tutorial->addMessage( m_promptId );
+
+ m_eTelemetryEvent = telemetryEvent;
+}
+
+bool ChoiceTask::isCompleted()
+{
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ if( m_bConfirmMappingComplete || m_bCancelMappingComplete )
+ {
+ sendTelemetry();
+ enableConstraints(false, true);
+ return true;
+ }
+
+ if(ui.GetMenuDisplayed(tutorial->getPad()))
+ {
+ // If a menu is displayed, then we use the handleUIInput to complete the task
+ }
+ else
+ {
+ // If the player is under water then allow all keypresses so they can jump out
+ if( pMinecraft->localplayers[tutorial->getPad()]->isUnderLiquid(Material::water) ) return false;
+
+ if(!m_bConfirmMappingComplete && InputManager.GetValue(pMinecraft->player->GetXboxPad(), m_iConfirmMapping) > 0 )
+ {
+ m_bConfirmMappingComplete = true;
+ }
+ if(!m_bCancelMappingComplete && InputManager.GetValue(pMinecraft->player->GetXboxPad(), m_iCancelMapping) > 0 )
+ {
+ m_bCancelMappingComplete = true;
+ }
+ }
+
+ if(m_bConfirmMappingComplete || m_bCancelMappingComplete)
+ {
+ sendTelemetry();
+ enableConstraints(false, true);
+ }
+ return m_bConfirmMappingComplete || m_bCancelMappingComplete;
+}
+
+eTutorial_CompletionAction ChoiceTask::getCompletionAction()
+{
+ if(m_bCancelMappingComplete)
+ {
+ return m_cancelAction;
+ }
+ else
+ {
+ return e_Tutorial_Completion_None;
+ }
+}
+
+int ChoiceTask::getPromptId()
+{
+ if( m_bShownForMinimumTime )
+ return m_promptId;
+ else
+ return -1;
+}
+
+void ChoiceTask::setAsCurrentTask(bool active /*= true*/)
+{
+ enableConstraints( active );
+ TutorialTask::setAsCurrentTask(active);
+}
+
+void ChoiceTask::handleUIInput(int iAction)
+{
+ if(bHasBeenActivated && m_bShownForMinimumTime)
+ {
+ if( iAction == m_iConfirmMapping )
+ {
+ m_bConfirmMappingComplete = true;
+ }
+ else if(iAction == m_iCancelMapping )
+ {
+ m_bCancelMappingComplete = true;
+ }
+ }
+}
+
+void ChoiceTask::sendTelemetry()
+{
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ if( m_eTelemetryEvent != eTelemetryChallenges_Unknown )
+ {
+ bool firstPlay = true;
+ // We only store first play for some of the events
+ switch(m_eTelemetryEvent)
+ {
+ case eTelemetryTutorial_TrialStart:
+ firstPlay = !tutorial->getCompleted( eTutorial_Telemetry_TrialStart );
+ tutorial->setCompleted( eTutorial_Telemetry_TrialStart );
+ break;
+ case eTelemetryTutorial_Halfway:
+ firstPlay = !tutorial->getCompleted( eTutorial_Telemetry_Halfway );
+ tutorial->setCompleted( eTutorial_Telemetry_Halfway );
+ break;
+ };
+
+ TelemetryManager->RecordEnemyKilledOrOvercome(pMinecraft->player->GetXboxPad(), 0, 0, 0, 0, 0, 0, m_eTelemetryEvent);
+ }
+}
diff --git a/Minecraft.Client/Common/Tutorial/ChoiceTask.h b/Minecraft.Client/Common/Tutorial/ChoiceTask.h
new file mode 100644
index 00000000..79c2ba42
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ChoiceTask.h
@@ -0,0 +1,27 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+// Information messages with a choice
+class ChoiceTask : public TutorialTask
+{
+private:
+ int m_iConfirmMapping, m_iCancelMapping;
+ bool m_bConfirmMappingComplete, m_bCancelMappingComplete;
+ eTutorial_CompletionAction m_cancelAction;
+
+ ETelemetryChallenges m_eTelemetryEvent;
+
+ bool CompletionMaskIsValid();
+public:
+ ChoiceTask(Tutorial *tutorial, int descriptionId, int promptId = -1, bool requiresUserInput = false, int iConfirmMapping = 0, int iCancelMapping = 0, eTutorial_CompletionAction cancelAction = e_Tutorial_Completion_None, ETelemetryChallenges telemetryEvent = eTelemetryChallenges_Unknown);
+ virtual bool isCompleted();
+ virtual eTutorial_CompletionAction getCompletionAction();
+ virtual int getPromptId();
+ virtual void setAsCurrentTask(bool active = true);
+ virtual void handleUIInput(int iAction);
+
+private:
+ void sendTelemetry();
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.cpp b/Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.cpp
new file mode 100644
index 00000000..43b2f7f3
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.cpp
@@ -0,0 +1,37 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\ItemInstance.h"
+#include "CompleteUsingItemTask.h"
+
+CompleteUsingItemTask::CompleteUsingItemTask(Tutorial *tutorial, int descriptionId, int itemIds[], unsigned int itemIdsLength, bool enablePreCompletion)
+ : TutorialTask( tutorial, descriptionId, enablePreCompletion, NULL)
+{
+ m_iValidItemsA= new int [itemIdsLength];
+ for(int i=0;i<itemIdsLength;i++)
+ {
+ m_iValidItemsA[i]=itemIds[i];
+ }
+ m_iValidItemsCount = itemIdsLength;
+}
+
+CompleteUsingItemTask::~CompleteUsingItemTask()
+{
+ delete [] m_iValidItemsA;
+}
+
+bool CompleteUsingItemTask::isCompleted()
+{
+ return bIsCompleted;
+}
+
+void CompleteUsingItemTask::completeUsingItem(shared_ptr<ItemInstance> item)
+{
+ if(!hasBeenActivated() && !isPreCompletionEnabled()) return;
+ for(int i=0;i<m_iValidItemsCount;i++)
+ {
+ if( item->id == m_iValidItemsA[i] )
+ {
+ bIsCompleted = true;
+ break;
+ }
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.h b/Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.h
new file mode 100644
index 00000000..a905bead
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/CompleteUsingItemTask.h
@@ -0,0 +1,20 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+class Level;
+
+class CompleteUsingItemTask : public TutorialTask
+{
+private:
+ int *m_iValidItemsA;
+ int m_iValidItemsCount;
+ bool completed;
+
+public:
+ CompleteUsingItemTask(Tutorial *tutorial, int descriptionId, int itemIds[], unsigned int itemIdsLength, bool enablePreCompletion = false);
+ virtual ~CompleteUsingItemTask();
+ virtual bool isCompleted();
+ virtual void completeUsingItem(shared_ptr<ItemInstance> item);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ControllerTask.cpp b/Minecraft.Client/Common/Tutorial/ControllerTask.cpp
new file mode 100644
index 00000000..c5fe071b
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ControllerTask.cpp
@@ -0,0 +1,123 @@
+#include "stdafx.h"
+#include <string>
+#include <unordered_map>
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "Tutorial.h"
+#include "TutorialConstraints.h"
+#include "ControllerTask.h"
+
+ControllerTask::ControllerTask(Tutorial *tutorial, int descriptionId, bool enablePreCompletion, bool showMinimumTime,
+ int mappings[], unsigned int mappingsLength, int iCompletionMaskA[], int iCompletionMaskACount, int iSouthpawMappings[], unsigned int uiSouthpawMappingsCount)
+ : TutorialTask( tutorial, descriptionId, enablePreCompletion, NULL, showMinimumTime )
+{
+ for(unsigned int i = 0; i < mappingsLength; ++i)
+ {
+ constraints.push_back( new InputConstraint( mappings[i] ) );
+ completedMappings[mappings[i]] = false;
+ }
+ if(uiSouthpawMappingsCount > 0 ) m_bHasSouthpaw = true;
+ for(unsigned int i = 0; i < uiSouthpawMappingsCount; ++i)
+ {
+ southpawCompletedMappings[iSouthpawMappings[i]] = false;
+ }
+
+ m_iCompletionMaskA= new int [iCompletionMaskACount];
+ for(int i=0;i<iCompletionMaskACount;i++)
+ {
+ m_iCompletionMaskA[i]=iCompletionMaskA[i];
+ }
+ m_iCompletionMaskACount=iCompletionMaskACount;
+ m_uiCompletionMask=0;
+
+ // If we don't want to be able to complete it early..then assume we want the constraints active
+ //if( !enablePreCompletion )
+ // enableConstraints( true );
+}
+
+ControllerTask::~ControllerTask()
+{
+ delete[] m_iCompletionMaskA;
+}
+
+bool ControllerTask::isCompleted()
+{
+ if( bIsCompleted )
+ return true;
+
+ bool bAllComplete = true;
+
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ int iCurrent=0;
+
+ if(m_bHasSouthpaw && app.GetGameSettings(pMinecraft->player->GetXboxPad(),eGameSetting_ControlSouthPaw))
+ {
+ for(AUTO_VAR(it, southpawCompletedMappings.begin()); it != southpawCompletedMappings.end(); ++it)
+ {
+ bool current = (*it).second;
+ if(!current)
+ {
+ // TODO Use a different pad
+ if( InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 )
+ {
+ (*it).second = true;
+ m_uiCompletionMask|=1<<iCurrent;
+ }
+ else
+ {
+ bAllComplete = false;
+ }
+ }
+ iCurrent++;
+ }
+ }
+ else
+ {
+ for(AUTO_VAR(it, completedMappings.begin()); it != completedMappings.end(); ++it)
+ {
+ bool current = (*it).second;
+ if(!current)
+ {
+ // TODO Use a different pad
+ if( InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 )
+ {
+ (*it).second = true;
+ m_uiCompletionMask|=1<<iCurrent;
+ }
+ else
+ {
+ bAllComplete = false;
+ }
+ }
+ iCurrent++;
+ }
+ }
+
+ // If this has a list of completion masks then check if there is a matching one to mark the task as complete
+ if(m_iCompletionMaskA && CompletionMaskIsValid())
+ {
+ bIsCompleted = true;
+ }
+ else
+ {
+ bIsCompleted = bAllComplete;
+ }
+
+ return bIsCompleted;
+}
+
+bool ControllerTask::CompletionMaskIsValid()
+{
+ for(int i=0;i<m_iCompletionMaskACount;i++)
+ {
+ if(m_uiCompletionMask==m_iCompletionMaskA[i]) return true;
+ }
+
+ return false;
+}
+void ControllerTask::setAsCurrentTask(bool active /*= true*/)
+{
+ TutorialTask::setAsCurrentTask(active);
+ enableConstraints(!active);
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ControllerTask.h b/Minecraft.Client/Common/Tutorial/ControllerTask.h
new file mode 100644
index 00000000..1ee6746f
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ControllerTask.h
@@ -0,0 +1,24 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+// 4J Stu - Tasks that involve using the controller
+class ControllerTask : public TutorialTask
+{
+private:
+ unordered_map<int, bool> completedMappings;
+ unordered_map<int, bool> southpawCompletedMappings;
+ bool m_bHasSouthpaw;
+ unsigned int m_uiCompletionMask;
+ int *m_iCompletionMaskA;
+ int m_iCompletionMaskACount;
+ bool CompletionMaskIsValid();
+public:
+ ControllerTask(Tutorial *tutorial, int descriptionId, bool enablePreCompletion, bool showMinimumTime,
+ int mappings[], unsigned int mappingsLength, int iCompletionMaskA[]=NULL, int iCompletionMaskACount=0, int iSouthpawMappings[]=NULL, unsigned int uiSouthpawMappingsCount=0);
+ ~ControllerTask();
+ virtual bool isCompleted();
+ virtual void setAsCurrentTask(bool active = true);
+
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/CraftTask.cpp b/Minecraft.Client/Common/Tutorial/CraftTask.cpp
new file mode 100644
index 00000000..6749d030
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/CraftTask.cpp
@@ -0,0 +1,66 @@
+#include "stdafx.h"
+#include "CraftTask.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+
+CraftTask::CraftTask( int itemId, int auxValue, int quantity,
+ Tutorial *tutorial, int descriptionId, bool enablePreCompletion /*= true*/, vector<TutorialConstraint *> *inConstraints /*= NULL*/,
+ bool bShowMinimumTime /*=false*/, bool bAllowFade /*=true*/, bool m_bTaskReminders /*=true*/ )
+ : TutorialTask(tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, m_bTaskReminders ),
+ m_quantity( quantity ),
+ m_count( 0 )
+{
+ m_numItems = 1;
+ m_items = new int[1];
+ m_items[0] = itemId;
+ m_auxValues = new int[1];
+ m_auxValues[0] = auxValue;
+}
+
+CraftTask::CraftTask( int *items, int *auxValues, int numItems, int quantity,
+ Tutorial *tutorial, int descriptionId, bool enablePreCompletion /*= true*/, vector<TutorialConstraint *> *inConstraints /*= NULL*/,
+ bool bShowMinimumTime /*=false*/, bool bAllowFade /*=true*/, bool m_bTaskReminders /*=true*/ )
+ : TutorialTask(tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, m_bTaskReminders ),
+ m_quantity( quantity ),
+ m_count( 0 )
+{
+ m_numItems = numItems;
+ m_items = new int[m_numItems];
+ m_auxValues = new int[m_numItems];
+
+ for(int i = 0; i < m_numItems; ++i)
+ {
+ m_items[i] = items[i];
+ m_auxValues[i] = auxValues[i];
+ }
+}
+
+CraftTask::~CraftTask()
+{
+ delete[] m_items;
+ delete[] m_auxValues;
+}
+
+void CraftTask::onCrafted(shared_ptr<ItemInstance> item)
+{
+#ifndef _CONTENT_PACKAGE
+ wprintf(L"CraftTask::onCrafted - %ls\n", item->toString().c_str() );
+#endif
+ bool itemFound = false;
+ for(int i = 0; i < m_numItems; ++i)
+ {
+ if(m_items[i] == item->id && (m_auxValues[i] == -1 || m_auxValues[i] == item->getAuxValue()))
+ {
+ itemFound = true;
+ break;
+ }
+ }
+
+ if(itemFound)
+ {
+ ++m_count;
+ }
+ if( m_count >= m_quantity)
+ {
+ bIsCompleted = true;
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/CraftTask.h b/Minecraft.Client/Common/Tutorial/CraftTask.h
new file mode 100644
index 00000000..1496f07a
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/CraftTask.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "TutorialTask.h"
+
+class CraftTask : public TutorialTask
+{
+public:
+ CraftTask( int itemId, int auxValue, int quantity,
+ Tutorial *tutorial, int descriptionId, bool enablePreCompletion = true, vector<TutorialConstraint *> *inConstraints = NULL,
+ bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true );
+ CraftTask( int *items, int *auxValues, int numItems, int quantity,
+ Tutorial *tutorial, int descriptionId, bool enablePreCompletion = true, vector<TutorialConstraint *> *inConstraints = NULL,
+ bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true );
+
+ ~CraftTask();
+
+ virtual bool isCompleted() { return bIsCompleted; }
+ virtual void onCrafted(shared_ptr<ItemInstance> item);
+
+private:
+ int *m_items;
+ int *m_auxValues;
+ int m_numItems;
+ int m_quantity;
+ int m_count;
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/DiggerItemHint.cpp b/Minecraft.Client/Common/Tutorial/DiggerItemHint.cpp
new file mode 100644
index 00000000..1367f411
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/DiggerItemHint.cpp
@@ -0,0 +1,76 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.entity.h"
+#include "Tutorial.h"
+#include "DiggerItemHint.h"
+
+
+DiggerItemHint::DiggerItemHint(eTutorial_Hint id, Tutorial *tutorial, int descriptionId, int items[], unsigned int itemsLength)
+ : TutorialHint(id, tutorial, descriptionId, e_Hint_DiggerItem)
+{
+ m_iItemsCount = itemsLength;
+
+ m_iItems= new int [m_iItemsCount];
+ for(unsigned int i=0;i<m_iItemsCount;i++)
+ {
+ m_iItems[i]=items[i];
+ }
+ tutorial->addMessage(IDS_TUTORIAL_HINT_ATTACK_WITH_TOOL, true);
+}
+
+int DiggerItemHint::startDestroyBlock(shared_ptr<ItemInstance> item, Tile *tile)
+{
+ if(item != NULL)
+ {
+ bool itemFound = false;
+ for(unsigned int i=0;i<m_iItemsCount;i++)
+ {
+ if(item->id == m_iItems[i])
+ {
+ itemFound = true;
+ break;
+ }
+ }
+ if(itemFound)
+ {
+ float speed = item->getDestroySpeed(tile);
+ if(speed == 1)
+ {
+ // Display hint
+ return m_descriptionId;
+ }
+ }
+ }
+ return -1;
+}
+
+int DiggerItemHint::attack(shared_ptr<ItemInstance> item, shared_ptr<Entity> entity)
+{
+ if(item != NULL)
+ {
+ bool itemFound = false;
+ for(unsigned int i=0;i<m_iItemsCount;i++)
+ {
+ if(item->id == m_iItems[i])
+ {
+ itemFound = true;
+ break;
+ }
+ }
+ if(itemFound)
+ {
+ // It's also possible that we could hit TileEntities (eg falling sand) so don't want to give this hint then
+ if( dynamic_pointer_cast<Mob>( entity ) != NULL )
+ {
+ return IDS_TUTORIAL_HINT_ATTACK_WITH_TOOL;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/DiggerItemHint.h b/Minecraft.Client/Common/Tutorial/DiggerItemHint.h
new file mode 100644
index 00000000..cb71742e
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/DiggerItemHint.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "TutorialHint.h"
+
+class DiggerItem;
+class Level;
+
+class DiggerItemHint : public TutorialHint
+{
+private:
+ int *m_iItems;
+ unsigned int m_iItemsCount;
+
+public:
+ DiggerItemHint(eTutorial_Hint id, Tutorial *tutorial, int descriptionId, int items[], unsigned int itemsLength);
+ virtual int startDestroyBlock(shared_ptr<ItemInstance> item, Tile *tile);
+ virtual int attack(shared_ptr<ItemInstance> item, shared_ptr<Entity> entity);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/EffectChangedTask.cpp b/Minecraft.Client/Common/Tutorial/EffectChangedTask.cpp
new file mode 100644
index 00000000..5f1b5b20
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/EffectChangedTask.cpp
@@ -0,0 +1,31 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.effect.h"
+#include "EffectChangedTask.h"
+
+EffectChangedTask::EffectChangedTask(Tutorial *tutorial, int descriptionId, MobEffect *effect, bool apply,
+ bool enablePreCompletion, bool bShowMinimumTime, bool bAllowFade, bool bTaskReminders )
+ : TutorialTask(tutorial,descriptionId,enablePreCompletion,NULL,bShowMinimumTime,bAllowFade,bTaskReminders)
+{
+ m_effect = effect;
+ m_apply = apply;
+}
+
+bool EffectChangedTask::isCompleted()
+{
+ return bIsCompleted;
+}
+
+void EffectChangedTask::onEffectChanged(MobEffect *effect, bool bRemoved /*=false*/)
+{
+ if(effect == m_effect)
+ {
+ if(m_apply == !bRemoved)
+ {
+ bIsCompleted = true;
+ }
+ else
+ {
+ bIsCompleted = false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/EffectChangedTask.h b/Minecraft.Client/Common/Tutorial/EffectChangedTask.h
new file mode 100644
index 00000000..23563f39
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/EffectChangedTask.h
@@ -0,0 +1,19 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+class MobEffect;
+
+class EffectChangedTask : public TutorialTask
+{
+private:
+ MobEffect *m_effect;
+ bool m_apply;
+
+public:
+ EffectChangedTask(Tutorial *tutorial, int descriptionId, MobEffect *effect, bool apply = true,
+ bool enablePreCompletion = true, bool bShowMinimumTime = false, bool bAllowFade = true, bool bTaskReminders = true );
+ virtual bool isCompleted();
+ virtual void onEffectChanged(MobEffect *effect, bool bRemoved=false);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/FullTutorial.cpp b/Minecraft.Client/Common/Tutorial/FullTutorial.cpp
new file mode 100644
index 00000000..123ab9de
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/FullTutorial.cpp
@@ -0,0 +1,653 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.phys.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.effect.h"
+#include "..\GameRules\ConsoleGameRules.h"
+#include "DiggerItemHint.h"
+#include "TutorialTasks.h"
+#include "AreaHint.h"
+#include "FullTutorial.h"
+#include "TutorialConstraints.h"
+
+FullTutorial::FullTutorial(int iPad, bool isTrial /*= false*/)
+ : Tutorial(iPad, true)
+{
+ m_isTrial = isTrial;
+ m_freezeTime = true;
+ m_progressFlags = 0;
+
+ for(unsigned int i = 0; i < e_Tutorial_State_Max; ++i)
+ {
+ m_completedStates[i] = false;
+ }
+
+ addMessage(IDS_TUTORIAL_COMPLETED);
+
+ /*
+ *
+ *
+ * GAMEPLAY
+ *
+ */
+ // START OF BASIC TUTORIAL
+ if( m_isTrial )
+ {
+ addTask(e_Tutorial_State_Gameplay, new ChoiceTask(this, IDS_TUTORIAL_TASK_OVERVIEW, IDS_TUTORIAL_PROMPT_START_TUTORIAL, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Jump_To_Last_Task, eTelemetryTutorial_TrialStart) );
+ }
+ else
+ {
+#ifdef _XBOX
+ if(getCompleted(eTutorial_Telemetry_Halfway) && !isStateCompleted(e_Tutorial_State_Redstone_And_Piston) )
+ {
+ addTask(e_Tutorial_State_Gameplay, new ChoiceTask(this, IDS_TUTORIAL_NEW_FEATURES_CHOICE, IDS_TUTORIAL_PROMPT_NEW_FEATURES_CHOICE, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Jump_To_Last_Task, eTelemetryTutorial_TrialStart) );
+ }
+
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_OVERVIEW, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+#else
+ if(getCompleted(eTutorial_Telemetry_Halfway))
+ {
+ addTask(e_Tutorial_State_Gameplay, new ChoiceTask(this, IDS_TUTORIAL_TASK_OVERVIEW, IDS_TUTORIAL_PROMPT_START_TUTORIAL, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Jump_To_Last_Task, eTelemetryTutorial_TrialStart) );
+ }
+ else
+ {
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_OVERVIEW, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+#endif
+ }
+
+ int lookMappings[] = {MINECRAFT_ACTION_LOOK_UP, MINECRAFT_ACTION_LOOK_DOWN, MINECRAFT_ACTION_LOOK_LEFT, MINECRAFT_ACTION_LOOK_RIGHT};
+ int moveMappings[] = {MINECRAFT_ACTION_FORWARD, MINECRAFT_ACTION_BACKWARD, MINECRAFT_ACTION_LEFT, MINECRAFT_ACTION_RIGHT};
+ int iLookCompletionMaskA[]= { 10, // 1010
+ 9, // 1001
+ 6, // 0110
+ 5 // 0101
+ };
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_LOOK, false, false, lookMappings, 4, iLookCompletionMaskA, 4, moveMappings, 4) );
+
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_MOVE, false, false, moveMappings, 4, iLookCompletionMaskA, 4, lookMappings, 4) );
+
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_SPRINT, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+ int jumpMappings[] = {MINECRAFT_ACTION_JUMP};
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_JUMP, false, true, jumpMappings, 1) );
+
+ int mineMappings[] = {MINECRAFT_ACTION_ACTION};
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_MINE, false, true, mineMappings, 1) );
+ addTask(e_Tutorial_State_Gameplay, new PickupTask( Tile::treeTrunk_Id, 4, -1, this, IDS_TUTORIAL_TASK_CHOP_WOOD ) );
+
+ int scrollMappings[] = {MINECRAFT_ACTION_LEFT_SCROLL,MINECRAFT_ACTION_RIGHT_SCROLL};
+ //int scrollMappings[] = {ACTION_MENU_LEFT_SCROLL,ACTION_MENU_RIGHT_SCROLL};
+ int iScrollCompletionMaskA[]= { 2, // 10
+ 1};// 01
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_SCROLL, false, false, scrollMappings, 2,iScrollCompletionMaskA,2) );
+
+ int invMappings[] = {MINECRAFT_ACTION_INVENTORY};
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_INVENTORY, false, false, invMappings, 1) );
+ addTask(e_Tutorial_State_Gameplay, new StateChangeTask( e_Tutorial_State_Inventory_Menu, this) );
+
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_DEPLETE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_HEAL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_FEED, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+ // While they should only eat the item we give them, includ the ability to complete this task with different items
+ int foodItems[] = {Item::mushroomStew_Id, Item::apple_Id, Item::bread_Id, Item::porkChop_raw_Id, Item::porkChop_cooked_Id,
+ Item::apple_gold_Id, Item::fish_raw_Id, Item::fish_cooked_Id, Item::cookie_Id, Item::beef_cooked_Id,
+ Item::beef_raw_Id, Item::chicken_cooked_Id, Item::chicken_raw_Id, Item::melon_Id, Item::rotten_flesh_Id};
+ addTask(e_Tutorial_State_Gameplay, new CompleteUsingItemTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_EAT_STEAK, foodItems, 15, true) );
+
+ int crftMappings[] = {MINECRAFT_ACTION_CRAFTING};
+ addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_CRAFTING, false, false, crftMappings, 1) );
+
+ addTask(e_Tutorial_State_Gameplay, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_2_X_2_Crafting, ProgressFlagTask::e_Progress_Set_Flag, this ) );
+ addTask(e_Tutorial_State_Gameplay, new StateChangeTask( e_Tutorial_State_2x2Crafting_Menu, this) );
+
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Tile::wood_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_PLANKS) );
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Tile::workBench_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_CRAFTING_TABLE) );
+
+ //int useMappings[] = {MINECRAFT_ACTION_USE};
+ //addTask(e_Tutorial_State_Gameplay, new ControllerTask( this, IDS_TUTORIAL_TASK_USE, false, false, useMappings, 1) );
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_USE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Gameplay, new UseItemTask( Tile::workBench_Id, this, IDS_TUTORIAL_TASK_PLACE_WORKBENCH, true ) );
+
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_NIGHT_DANGER, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_NEARBY_SHELTER, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Gameplay, new InfoTask(this, IDS_TUTORIAL_TASK_COLLECT_RESOURCES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+ // END OF BASIC TUTORIAL
+
+ addTask(e_Tutorial_State_Gameplay, new ChoiceTask(this, IDS_TUTORIAL_TASK_BASIC_COMPLETE, IDS_TUTORIAL_PROMPT_BASIC_COMPLETE, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Jump_To_Last_Task, eTelemetryTutorial_Halfway) );
+
+ // START OF FULL TUTORIAL
+
+ addTask(e_Tutorial_State_Gameplay, new UseTileTask( Tile::workBench_Id, this, IDS_TUTORIAL_TASK_OPEN_WORKBENCH, false ) );
+
+ addTask(e_Tutorial_State_Gameplay, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_3_X_3_Crafting, ProgressFlagTask::e_Progress_Set_Flag, this ) );
+ addTask(e_Tutorial_State_Gameplay, new StateChangeTask( e_Tutorial_State_3x3Crafting_Menu, this) );
+
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Item::stick->id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_STICKS) );
+
+ int shovelItems[] = {Item::shovel_wood->id, Item::shovel_stone->id, Item::shovel_iron->id, Item::shovel_gold->id, Item::shovel_diamond->id};
+ int shovelAuxVals[] = {-1,-1,-1,-1,-1};
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( shovelItems, shovelAuxVals, 5, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_SHOVEL) );
+
+ int hatchetItems[] = {Item::hatchet_wood->id, Item::hatchet_stone->id, Item::hatchet_iron->id, Item::hatchet_gold->id, Item::hatchet_diamond->id};
+ int hatchetAuxVals[] = {-1,-1,-1,-1,-1};
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( hatchetItems, hatchetAuxVals, 5, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_HATCHET) );
+
+ int pickaxeItems[] = {Item::pickAxe_wood->id, Item::pickAxe_stone->id, Item::pickAxe_iron->id, Item::pickAxe_gold->id, Item::pickAxe_diamond->id};
+ int pickaxeAuxVals[] = {-1,-1,-1,-1,-1};
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( pickaxeItems, pickaxeAuxVals, 5, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_PICKAXE) );
+
+ addTask(e_Tutorial_State_Gameplay, new PickupTask( Tile::stoneBrick_Id, 8, -1, this, IDS_TUTORIAL_TASK_MINE_STONE ) );
+
+ addTask(e_Tutorial_State_Gameplay, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_CRAFT_FURNACE, ProgressFlagTask::e_Progress_Set_Flag, this ) );
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Tile::furnace_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_FURNACE ) );
+ addTask(e_Tutorial_State_Gameplay, new UseTileTask(Tile::furnace_Id, this, IDS_TUTORIAL_TASK_PLACE_AND_OPEN_FURNACE) );
+
+ addTask(e_Tutorial_State_Gameplay, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_USE_FURNACE, ProgressFlagTask::e_Progress_Set_Flag, this ) );
+ addTask(e_Tutorial_State_Gameplay, new StateChangeTask( e_Tutorial_State_Furnace_Menu, this) );
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Item::coal->id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_CHARCOAL) );
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Tile::glass_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_GLASS) );
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Item::door_wood->id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_DOOR) );
+ addTask(e_Tutorial_State_Gameplay, new UseItemTask(Item::door_wood->id, this, IDS_TUTORIAL_TASK_PLACE_DOOR) );
+ addTask(e_Tutorial_State_Gameplay, new CraftTask( Tile::torch_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_TORCH) );
+
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"tutorialArea");
+ if(area != NULL)
+ {
+ vector<TutorialConstraint *> *areaConstraints = new vector<TutorialConstraint *>();
+ areaConstraints->push_back( new AreaConstraint( IDS_TUTORIAL_CONSTRAINT_TUTORIAL_AREA, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+ addTask(e_Tutorial_State_Gameplay, new AreaTask(e_Tutorial_State_Gameplay,this, areaConstraints) );
+ }
+ }
+
+ // This MUST be the last task in the e_Tutorial_State_Gameplay state. Some of the earlier tasks will skip to the last
+ // task when complete, and this is the one that we want the player to see.
+ ProcedureCompoundTask *finalTask = new ProcedureCompoundTask( this );
+ finalTask->AddTask( new InfoTask(this, IDS_TUTORIAL_COMPLETED, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A, eTelemetryTutorial_Complete) );
+ // 4J Stu - Remove this string as it refers to things that don't exist in the current tutorial world!
+ //finalTask->AddTask( new InfoTask(this, IDS_TUTORIAL_FEATURES_IN_THIS_AREA, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ finalTask->AddTask( new InfoTask(this, IDS_TUTORIAL_FEATURES_OUTSIDE_THIS_AREA, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ finalTask->AddTask( new InfoTask(this, IDS_TUTORIAL_COMPLETED_EXPLORE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Gameplay, finalTask);
+ // END OF FULL TUTORIAL
+
+
+ /*
+ *
+ *
+ * INVENTORY
+ *
+ */
+ // Some tasks already added in the super class ctor
+ addTask(e_Tutorial_State_Inventory_Menu, new FullTutorialActiveTask( this, e_Tutorial_Completion_Complete_State) );
+ addTask(e_Tutorial_State_Inventory_Menu, new InfoTask(this, IDS_TUTORIAL_TASK_INV_EXIT, -1, false, ACTION_MENU_B) );
+
+ /*
+ *
+ *
+ * CRAFTING
+ *
+ */
+ // Some tasks already added in the super class ctor
+
+ addTask(e_Tutorial_State_2x2Crafting_Menu, new FullTutorialActiveTask( this, e_Tutorial_Completion_Complete_State) );
+ // To block progress
+ addTask(e_Tutorial_State_2x2Crafting_Menu, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_2_X_2_Crafting, ProgressFlagTask::e_Progress_Flag_On, this ) );
+
+ addTask(e_Tutorial_State_2x2Crafting_Menu, new FullTutorialActiveTask( this, e_Tutorial_Completion_Complete_State) );
+
+ addTask(e_Tutorial_State_2x2Crafting_Menu, new CraftTask( Tile::wood_Id, -1, 1, this, IDS_TUTORIAL_TASK_CRAFT_CREATE_PLANKS) );
+
+ ProcedureCompoundTask *workbenchCompound = new ProcedureCompoundTask( this );
+ workbenchCompound->AddTask( new XuiCraftingTask( this, IDS_TUTORIAL_TASK_CRAFT_SELECT_STRUCTURES, Recipy::eGroupType_Structure) );
+ workbenchCompound->AddTask( new XuiCraftingTask( this, IDS_TUTORIAL_TASK_CRAFT_SELECT_CRAFTING_TABLE, Tile::workBench_Id) );
+ workbenchCompound->AddTask( new CraftTask( Tile::workBench_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_CRAFTING_TABLE) );
+ addTask(e_Tutorial_State_2x2Crafting_Menu, workbenchCompound );
+ addTask(e_Tutorial_State_2x2Crafting_Menu, new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_EXIT_AND_PLACE_TABLE, -1, false, ACTION_MENU_B) );
+
+ // 3x3 Crafting
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new FullTutorialActiveTask( this, e_Tutorial_Completion_Complete_State) );
+
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_3_X_3_Crafting, ProgressFlagTask::e_Progress_Flag_On, this ) );
+
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new CraftTask( Item::stick->id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_STICKS) );
+
+ ProcedureCompoundTask *shovelCompound = new ProcedureCompoundTask( this );
+ shovelCompound->AddTask( new XuiCraftingTask( this, IDS_TUTORIAL_TASK_CRAFT_SELECT_TOOLS, Recipy::eGroupType_Tool) );
+ shovelCompound->AddTask( new XuiCraftingTask( this, IDS_TUTORIAL_TASK_CRAFT_SELECT_WOODEN_SHOVEL, Item::shovel_wood->id) );
+ shovelCompound->AddTask( new CraftTask( shovelItems, shovelAuxVals, 5, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_SHOVEL) );
+ addTask(e_Tutorial_State_3x3Crafting_Menu, shovelCompound );
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new CraftTask( hatchetItems, hatchetAuxVals, 5, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_HATCHET) );
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new CraftTask( pickaxeItems, pickaxeAuxVals, 5, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_PICKAXE) );
+
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_TOOLS_BUILT, -1, false, ACTION_MENU_B) );
+
+ // To block progress
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_CRAFT_FURNACE, ProgressFlagTask::e_Progress_Flag_On, this ) );
+
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new CraftTask( Tile::furnace_Id, -1, 1, this, IDS_TUTORIAL_TASK_CRAFT_CREATE_FURNACE) );
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_EXIT_AND_PLACE_FURNACE, -1, false, ACTION_MENU_B) );
+
+ // No need to block here, as it's fine if the player wants to do this out of order
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new CraftTask( Item::door_wood->id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_WOODEN_DOOR) );
+ addTask(e_Tutorial_State_3x3Crafting_Menu, new CraftTask( Tile::torch_Id, -1, 1, this, IDS_TUTORIAL_TASK_CREATE_TORCH) );
+
+ /*
+ *
+ *
+ * FURNACE
+ *
+ */
+ // Some tasks already added in the super class ctor
+
+ addTask(e_Tutorial_State_Furnace_Menu, new FullTutorialActiveTask( this, e_Tutorial_Completion_Complete_State) );
+
+ // Blocking
+ addTask(e_Tutorial_State_Furnace_Menu, new ProgressFlagTask( &m_progressFlags, FULL_TUTORIAL_PROGRESS_USE_FURNACE, ProgressFlagTask::e_Progress_Flag_On, this ) );
+
+ addTask(e_Tutorial_State_Furnace_Menu, new CraftTask( Item::coal->id, -1, 1, this, IDS_TUTORIAL_TASK_FURNACE_CREATE_CHARCOAL) );
+ addTask(e_Tutorial_State_Furnace_Menu, new InfoTask(this, IDS_TUTORIAL_TASK_FURNACE_CHARCOAL_USES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Furnace_Menu, new CraftTask( Tile::glass_Id, -1, 1, this, IDS_TUTORIAL_TASK_FURNACE_CREATE_GLASS) );
+
+ /*
+ *
+ *
+ * BREWING
+ *
+ */
+
+ // To block progress
+ addTask(e_Tutorial_State_Brewing_Menu, new ProgressFlagTask( &m_progressFlags, EXTENDED_TUTORIAL_PROGRESS_USE_BREWING_STAND, ProgressFlagTask::e_Progress_Flag_On, this ) );
+
+ int potionItems[] = {Item::potion_Id,Item::potion_Id,Item::potion_Id,Item::potion_Id,Item::potion_Id,Item::potion_Id,Item::potion_Id,Item::potion_Id};
+ int potionAuxVals[] = { MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(0, 0, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, 0, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(0, MASK_EXTENDED, MASK_FIRE_RESISTANCE),
+ MACRO_MAKEPOTION_AUXVAL(MASK_SPLASH, MASK_EXTENDED, MASK_FIRE_RESISTANCE)
+ };
+ addTask(e_Tutorial_State_Brewing_Menu, new CraftTask( potionItems, potionAuxVals, 8, 1, this, IDS_TUTORIAL_TASK_BREWING_MENU_CREATE_FIRE_POTION) );
+ addTask(e_Tutorial_State_Brewing_Menu, new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_MENU_EXIT, -1, false, ACTION_MENU_B) );
+
+ /*
+ *
+ *
+ * MINECART
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"minecartArea");
+ if(area != NULL)
+ {
+ addHint(e_Tutorial_State_Gameplay, new AreaHint(e_Tutorial_Hint_Always_On, this, e_Tutorial_State_Gameplay, e_Tutorial_State_Riding_Minecart, IDS_TUTORIAL_HINT_MINECART, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1 ) );
+ }
+ }
+
+ /*
+ *
+ *
+ * BOAT
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"boatArea");
+ if(area != NULL)
+ {
+ addHint(e_Tutorial_State_Gameplay, new AreaHint(e_Tutorial_Hint_Always_On, this, e_Tutorial_State_Gameplay, e_Tutorial_State_Riding_Boat, IDS_TUTORIAL_HINT_BOAT, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1 ) );
+ }
+ }
+
+ /*
+ *
+ *
+ * FISHING
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"fishingArea");
+ if(area != NULL)
+ {
+ addHint(e_Tutorial_State_Gameplay, new AreaHint(e_Tutorial_Hint_Always_On, this, e_Tutorial_State_Gameplay, e_Tutorial_State_Fishing, IDS_TUTORIAL_HINT_FISHING, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1 ) );
+ }
+ }
+
+ /*
+ *
+ *
+ * PISTON - SELF-REPAIRING BRIDGE
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"pistonBridgeArea");
+ if(area != NULL)
+ {
+ addHint(e_Tutorial_State_Gameplay, new AreaHint(e_Tutorial_Hint_Always_On, this, e_Tutorial_State_Gameplay, e_Tutorial_State_None, IDS_TUTORIAL_HINT_PISTON_SELF_REPAIRING_BRIDGE, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1, true ) );
+ }
+ }
+
+ /*
+ *
+ *
+ * PISTON - PISTON AND REDSTONE CIRCUITS
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"pistonArea");
+ if(area != NULL)
+ {
+ eTutorial_State redstoneAndPistonStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Redstone_And_Piston, redstoneAndPistonStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Redstone_And_Piston, new ChoiceTask(this, IDS_TUTORIAL_REDSTONE_OVERVIEW, IDS_TUTORIAL_PROMPT_REDSTONE_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Redstone_And_Pistons) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_REDSTONE_POWER_SOURCES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_REDSTONE_TRIPWIRE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_REDSTONE_POWER_SOURCES_POSITION, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_REDSTONE_DUST, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_REDSTONE_REPEATER, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_PISTONS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Redstone_And_Piston, new InfoTask(this, IDS_TUTORIAL_TASK_TRY_IT, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * PORTAL
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"portalArea");
+ if(area != NULL)
+ {
+ eTutorial_State portalStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Portal, portalStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Portal, new ChoiceTask(this, IDS_TUTORIAL_PORTAL_OVERVIEW, IDS_TUTORIAL_PROMPT_PORTAL_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Portal) );
+ addTask(e_Tutorial_State_Portal, new InfoTask(this, IDS_TUTORIAL_TASK_BUILD_PORTAL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Portal, new InfoTask(this, IDS_TUTORIAL_TASK_ACTIVATE_PORTAL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Portal, new InfoTask(this, IDS_TUTORIAL_TASK_USE_PORTAL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Portal, new InfoTask(this, IDS_TUTORIAL_TASK_NETHER, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Portal, new InfoTask(this, IDS_TUTORIAL_TASK_NETHER_FAST_TRAVEL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * CREATIVE
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"creativeArea");
+ if(area != NULL)
+ {
+ eTutorial_State creativeStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_CreativeMode, creativeStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1,true,true,GameType::CREATIVE) );
+
+ addTask(e_Tutorial_State_CreativeMode, new ChoiceTask(this, IDS_TUTORIAL_CREATIVE_OVERVIEW, IDS_TUTORIAL_PROMPT_CREATIVE_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Jump_To_Last_Task, eTelemetryTutorial_CreativeMode) );
+ addTask(e_Tutorial_State_CreativeMode, new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_MODE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_CreativeMode, new InfoTask(this, IDS_TUTORIAL_TASK_FLY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+ int crftMappings[] = {MINECRAFT_ACTION_CRAFTING};
+ addTask(e_Tutorial_State_CreativeMode, new ControllerTask( this, IDS_TUTORIAL_TASK_OPEN_CREATIVE_INVENTORY, false, false, crftMappings, 1) );
+ addTask(e_Tutorial_State_CreativeMode, new StateChangeTask( e_Tutorial_State_Creative_Inventory_Menu, this) );
+
+ // This last task ensures that the player is still in creative mode until they exit the area (but could skip the previous instructional stuff)
+ ProcedureCompoundTask *creativeFinalTask = new ProcedureCompoundTask( this );
+
+ AABB *exitArea = app.getGameRuleDefinitions()->getNamedArea(L"creativeExitArea");
+ if(exitArea != NULL)
+ {
+ vector<TutorialConstraint *> *creativeExitAreaConstraints = new vector<TutorialConstraint *>();
+ creativeExitAreaConstraints->push_back( new AreaConstraint( -1, exitArea->x0,exitArea->y0,exitArea->z0,exitArea->x1,exitArea->y1,exitArea->z1,true,false) );
+ creativeFinalTask->AddTask( new AreaTask(e_Tutorial_State_CreativeMode, this, creativeExitAreaConstraints,IDS_TUTORIAL_TASK_CREATIVE_EXIT,AreaTask::eAreaTaskCompletion_CompleteOnConstraintsSatisfied) );
+ }
+
+ vector<TutorialConstraint *> *creativeAreaConstraints = new vector<TutorialConstraint *>();
+ creativeAreaConstraints->push_back( new AreaConstraint( IDS_TUTORIAL_CONSTRAINT_TUTORIAL_AREA, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+ creativeFinalTask->AddTask( new AreaTask(e_Tutorial_State_CreativeMode, this, creativeAreaConstraints) );
+
+ creativeFinalTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_COMPLETE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+ addTask(e_Tutorial_State_CreativeMode,creativeFinalTask);
+ }
+ }
+
+ /*
+ *
+ *
+ * BREWING
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"brewingArea");
+ if(area != NULL)
+ {
+ eTutorial_State brewingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Brewing, brewingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Brewing, new ChoiceTask(this, IDS_TUTORIAL_TASK_BREWING_OVERVIEW, IDS_TUTORIAL_PROMPT_BREWING_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Brewing) );
+
+ ProcedureCompoundTask *fillWaterBottleTask = new ProcedureCompoundTask( this );
+ fillWaterBottleTask->AddTask( new PickupTask( Item::glassBottle_Id, 1, -1, this, IDS_TUTORIAL_TASK_BREWING_GET_GLASS_BOTTLE ) );
+ fillWaterBottleTask->AddTask( new PickupTask( Item::potion_Id, 1, 0, this, IDS_TUTORIAL_TASK_BREWING_FILL_GLASS_BOTTLE ) );
+ addTask(e_Tutorial_State_Brewing, fillWaterBottleTask);
+
+ addTask(e_Tutorial_State_Brewing, new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_FILL_CAULDRON, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+
+ addTask(e_Tutorial_State_Brewing, new ProgressFlagTask( &m_progressFlags, EXTENDED_TUTORIAL_PROGRESS_USE_BREWING_STAND, ProgressFlagTask::e_Progress_Set_Flag, this ) );
+ addTask(e_Tutorial_State_Brewing, new CraftTask( potionItems, potionAuxVals, 8, 1, this, IDS_TUTORIAL_TASK_BREWING_CREATE_FIRE_POTION) );
+
+ addTask(e_Tutorial_State_Brewing, new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_USE_POTION, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Brewing, new EffectChangedTask(this, IDS_TUTORIAL_TASK_BREWING_DRINK_FIRE_POTION, MobEffect::fireResistance) );
+ addTask(e_Tutorial_State_Brewing, new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_USE_EFFECTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * ENCHANTING
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"enchantingArea");
+ if(area != NULL)
+ {
+ eTutorial_State enchantingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Enchanting, enchantingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Enchanting, new ChoiceTask(this, IDS_TUTORIAL_TASK_ENCHANTING_OVERVIEW, IDS_TUTORIAL_PROMPT_ENCHANTING_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Enchanting) );
+
+ addTask(e_Tutorial_State_Enchanting, new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_SUMMARY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enchanting, new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_BOOKS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enchanting, new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_BOOKCASES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enchanting, new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_EXPERIENCE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enchanting, new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_BOTTLE_O_ENCHANTING, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enchanting, new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_USE_CHESTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * ANVIL
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"anvilArea");
+ if(area != NULL)
+ {
+ eTutorial_State enchantingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Anvil, enchantingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Anvil, new ChoiceTask(this, IDS_TUTORIAL_TASK_ANVIL_OVERVIEW, IDS_TUTORIAL_PROMPT_ANVIL_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Anvil) );
+
+ addTask(e_Tutorial_State_Anvil, new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_SUMMARY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Anvil, new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_ENCHANTED_BOOKS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Anvil, new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_COST, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Anvil, new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_COST2, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Anvil, new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_RENAMING, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Anvil, new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_USE_CHESTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * TRADING
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"tradingArea");
+ if(area != NULL)
+ {
+ eTutorial_State enchantingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Trading, enchantingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Trading, new ChoiceTask(this, IDS_TUTORIAL_TASK_TRADING_OVERVIEW, IDS_TUTORIAL_PROMPT_TRADING_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Trading) );
+
+ addTask(e_Tutorial_State_Trading, new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_SUMMARY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Trading, new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_TRADES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Trading, new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_INCREASE_TRADES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Trading, new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_DECREASE_TRADES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Trading, new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_USE_CHESTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * ENDERCHEST
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"enderchestArea");
+ if(area != NULL)
+ {
+ eTutorial_State enchantingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Enderchests, enchantingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Enderchests, new ChoiceTask(this, IDS_TUTORIAL_TASK_ENDERCHEST_OVERVIEW, IDS_TUTORIAL_PROMPT_ENDERCHEST_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Enderchest) );
+
+ addTask(e_Tutorial_State_Enderchests, new InfoTask(this, IDS_TUTORIAL_TASK_ENDERCHEST_SUMMARY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enderchests, new InfoTask(this, IDS_TUTORIAL_TASK_ENDERCHEST_PLAYERS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enderchests, new InfoTask(this, IDS_TUTORIAL_TASK_ENDERCHEST_FUNCTION, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * FARMING
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"farmingArea");
+ if(area != NULL)
+ {
+ eTutorial_State farmingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Farming, farmingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Farming, new ChoiceTask(this, IDS_TUTORIAL_FARMING_OVERVIEW, IDS_TUTORIAL_PROMPT_FARMING_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Farming) );
+
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_SEEDS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_FARMLAND, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_WHEAT, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_PUMPKIN_AND_MELON, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_CARROTS_AND_POTATOES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_SUGARCANE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_CACTUS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_MUSHROOM, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_BONEMEAL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Farming, new InfoTask(this, IDS_TUTORIAL_TASK_FARMING_COMPLETE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * BREEDING
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"breedingArea");
+ if(area != NULL)
+ {
+ eTutorial_State breedingStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Breeding, breedingStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Breeding, new ChoiceTask(this, IDS_TUTORIAL_BREEDING_OVERVIEW, IDS_TUTORIAL_PROMPT_BREEDING_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Breeding) );
+
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_FEED, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_FEED_FOOD, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_BABY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_DELAY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_FOLLOW, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_RIDING_PIGS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_WOLF_TAMING, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_WOLF_COLLAR, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Breeding, new InfoTask(this, IDS_TUTORIAL_TASK_BREEDING_COMPLETE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+ }
+
+ /*
+ *
+ *
+ * SNOW AND IRON GOLEM
+ *
+ */
+ if(app.getGameRuleDefinitions() != NULL)
+ {
+ AABB *area = app.getGameRuleDefinitions()->getNamedArea(L"golemArea");
+ if(area != NULL)
+ {
+ eTutorial_State golemStates[] = {e_Tutorial_State_Gameplay};
+ AddGlobalConstraint( new ChangeStateConstraint(this, e_Tutorial_State_Golem, golemStates, 1, area->x0,area->y0,area->z0,area->x1,area->y1,area->z1) );
+
+ addTask(e_Tutorial_State_Golem, new ChoiceTask(this, IDS_TUTORIAL_GOLEM_OVERVIEW, IDS_TUTORIAL_PROMPT_GOLEM_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Golem) );
+
+ addTask(e_Tutorial_State_Golem, new InfoTask(this, IDS_TUTORIAL_TASK_GOLEM_PUMPKIN, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Golem, new InfoTask(this, IDS_TUTORIAL_TASK_GOLEM_SNOW, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Golem, new InfoTask(this, IDS_TUTORIAL_TASK_GOLEM_IRON, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Golem, new InfoTask(this, IDS_TUTORIAL_TASK_GOLEM_IRON_VILLAGE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+
+ }
+ }
+
+}
+
+// 4J Stu - All tutorials are onby default in the full tutorial whether the player has previously completed them or not
+bool FullTutorial::isStateCompleted( eTutorial_State state )
+{
+ return m_completedStates[state];
+}
+
+void FullTutorial::setStateCompleted( eTutorial_State state )
+{
+ m_completedStates[state] = true;
+ Tutorial::setStateCompleted(state);
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/FullTutorial.h b/Minecraft.Client/Common/Tutorial/FullTutorial.h
new file mode 100644
index 00000000..da2641d2
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/FullTutorial.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "Tutorial.h"
+
+#define FULL_TUTORIAL_PROGRESS_2_X_2_Crafting 1
+#define FULL_TUTORIAL_PROGRESS_3_X_3_Crafting 2
+#define FULL_TUTORIAL_PROGRESS_CRAFT_FURNACE 4
+#define FULL_TUTORIAL_PROGRESS_USE_FURNACE 8
+#define EXTENDED_TUTORIAL_PROGRESS_USE_BREWING_STAND 16
+
+class FullTutorial : public Tutorial
+{
+private:
+ bool m_isTrial;
+ char m_progressFlags;
+ bool m_completedStates[e_Tutorial_State_Max];
+public:
+ FullTutorial(int iPad, bool isTrial = false);
+
+ virtual bool isStateCompleted( eTutorial_State state );
+ virtual void setStateCompleted( eTutorial_State state );
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.cpp b/Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.cpp
new file mode 100644
index 00000000..54985d21
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.cpp
@@ -0,0 +1,26 @@
+#include "stdafx.h"
+#include "Tutorial.h"
+#include "FullTutorialActiveTask.h"
+
+FullTutorialActiveTask::FullTutorialActiveTask(Tutorial *tutorial, eTutorial_CompletionAction completeAction /*= e_Tutorial_Completion_None*/)
+ : TutorialTask( tutorial, -1, false, NULL, false, false, false )
+{
+ m_completeAction = completeAction;
+}
+
+bool FullTutorialActiveTask::isCompleted()
+{
+ return bHasBeenActivated;
+}
+
+eTutorial_CompletionAction FullTutorialActiveTask::getCompletionAction()
+{
+ if( tutorial->m_fullTutorialComplete )
+ {
+ return m_completeAction;
+ }
+ else
+ {
+ return e_Tutorial_Completion_None;
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.h b/Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.h
new file mode 100644
index 00000000..5aa05610
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/FullTutorialActiveTask.h
@@ -0,0 +1,18 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+// Information messages with a choice
+class FullTutorialActiveTask : public TutorialTask
+{
+private:
+ eTutorial_CompletionAction m_completeAction;
+
+ bool CompletionMaskIsValid();
+public:
+ FullTutorialActiveTask(Tutorial *tutorial, eTutorial_CompletionAction completeAction = e_Tutorial_Completion_None);
+ virtual bool isCompleted();
+ virtual eTutorial_CompletionAction getCompletionAction();
+
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/FullTutorialMode.cpp b/Minecraft.Client/Common/Tutorial/FullTutorialMode.cpp
new file mode 100644
index 00000000..a5ee85b8
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/FullTutorialMode.cpp
@@ -0,0 +1,16 @@
+#include "stdafx.h"
+#include "..\..\Minecraft.h"
+#include "FullTutorial.h"
+#include "FullTutorialMode.h"
+
+FullTutorialMode::FullTutorialMode(int iPad, Minecraft *minecraft, ClientConnection *connection)
+ : TutorialMode(iPad, minecraft, connection)
+{
+ tutorial = new FullTutorial( iPad );
+ minecraft->playerStartedTutorial( iPad );
+}
+
+bool FullTutorialMode::isTutorial()
+{
+ return !tutorial->m_fullTutorialComplete;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/FullTutorialMode.h b/Minecraft.Client/Common/Tutorial/FullTutorialMode.h
new file mode 100644
index 00000000..ce6f1819
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/FullTutorialMode.h
@@ -0,0 +1,12 @@
+#pragma once
+#include "TutorialMode.h"
+
+class FullTutorialMode : public TutorialMode
+{
+public:
+ FullTutorialMode(int iPad, Minecraft *minecraft, ClientConnection *connection);
+
+ virtual bool isImplemented() { return true; }
+
+ virtual bool isTutorial();
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/InfoTask.cpp b/Minecraft.Client/Common/Tutorial/InfoTask.cpp
new file mode 100644
index 00000000..5330841f
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/InfoTask.cpp
@@ -0,0 +1,137 @@
+#include "stdafx.h"
+#include <string>
+#include <unordered_map>
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "Tutorial.h"
+#include "TutorialConstraints.h"
+#include "InfoTask.h"
+#include "..\..\..\Minecraft.World\Material.h"
+
+InfoTask::InfoTask(Tutorial *tutorial, int descriptionId, int promptId /*= -1*/, bool requiresUserInput /*= false*/,
+ int iMapping /*= 0*/, ETelemetryChallenges telemetryEvent /*= eTelemetryTutorial_NoEvent*/)
+ : TutorialTask( tutorial, descriptionId, false, NULL, true, false, false )
+{
+ if(requiresUserInput == true)
+ {
+ constraints.push_back( new InputConstraint( iMapping ) );
+ }
+ completedMappings[iMapping]=false;
+
+ m_promptId = promptId;
+ tutorial->addMessage( m_promptId );
+
+ m_eTelemetryEvent = telemetryEvent;
+}
+
+bool InfoTask::isCompleted()
+{
+ if( bIsCompleted )
+ return true;
+
+ if( tutorial->m_hintDisplayed )
+ return false;
+
+ if( !bHasBeenActivated || !m_bShownForMinimumTime )
+ return false;
+
+ bool bAllComplete = true;
+
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ // If the player is under water then allow all keypresses so they can jump out
+ if( pMinecraft->localplayers[tutorial->getPad()]->isUnderLiquid(Material::water) ) return false;
+
+ if(ui.GetMenuDisplayed(tutorial->getPad()))
+ {
+ // If a menu is displayed, then we use the handleUIInput to complete the task
+ bAllComplete = true;
+ for(AUTO_VAR(it, completedMappings.begin()); it != completedMappings.end(); ++it)
+ {
+ bool current = (*it).second;
+ if(!current)
+ {
+ bAllComplete = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ int iCurrent=0;
+
+ for(AUTO_VAR(it, completedMappings.begin()); it != completedMappings.end(); ++it)
+ {
+ bool current = (*it).second;
+ if(!current)
+ {
+ if( InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 )
+ {
+ (*it).second = true;
+ bAllComplete=true;
+ }
+ else
+ {
+ bAllComplete = false;
+ }
+ }
+ iCurrent++;
+ }
+ }
+
+ if(bAllComplete==true)
+ {
+ sendTelemetry();
+ enableConstraints(false, true);
+ }
+ bIsCompleted = bAllComplete;
+ return bAllComplete;
+}
+
+int InfoTask::getPromptId()
+{
+ if( m_bShownForMinimumTime )
+ return m_promptId;
+ else
+ return -1;
+}
+
+void InfoTask::setAsCurrentTask(bool active /*= true*/)
+{
+ enableConstraints( active );
+ TutorialTask::setAsCurrentTask(active);
+}
+
+void InfoTask::handleUIInput(int iAction)
+{
+ if(bHasBeenActivated)
+ {
+ for(AUTO_VAR(it, completedMappings.begin()); it != completedMappings.end(); ++it)
+ {
+ if( iAction == (*it).first )
+ {
+ (*it).second = true;
+ }
+ }
+ }
+}
+
+
+void InfoTask::sendTelemetry()
+{
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+
+ if( m_eTelemetryEvent != eTelemetryChallenges_Unknown )
+ {
+ bool firstPlay = true;
+ // We only store first play for some of the events
+ switch(m_eTelemetryEvent)
+ {
+ case eTelemetryTutorial_Complete:
+ firstPlay = !tutorial->getCompleted( eTutorial_Telemetry_Complete );
+ tutorial->setCompleted( eTutorial_Telemetry_Complete );
+ break;
+ };
+ TelemetryManager->RecordEnemyKilledOrOvercome(pMinecraft->player->GetXboxPad(), 0, 0, 0, 0, 0, 0, m_eTelemetryEvent);
+ }
+}
diff --git a/Minecraft.Client/Common/Tutorial/InfoTask.h b/Minecraft.Client/Common/Tutorial/InfoTask.h
new file mode 100644
index 00000000..e072038b
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/InfoTask.h
@@ -0,0 +1,25 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+// Information messages
+class InfoTask : public TutorialTask
+{
+private:
+ unordered_map<int, bool> completedMappings;
+
+ ETelemetryChallenges m_eTelemetryEvent;
+
+ bool CompletionMaskIsValid();
+public:
+ InfoTask(Tutorial *tutorial, int descriptionId, int promptId = -1, bool requiresUserInput = false, int iMapping = 0, ETelemetryChallenges telemetryEvent = eTelemetryChallenges_Unknown);
+ virtual bool isCompleted();
+ virtual int getPromptId();
+ virtual void setAsCurrentTask(bool active = true);
+ virtual void handleUIInput(int iAction);
+
+private:
+ void sendTelemetry();
+
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/InputConstraint.cpp b/Minecraft.Client/Common/Tutorial/InputConstraint.cpp
new file mode 100644
index 00000000..a26d3eb1
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/InputConstraint.cpp
@@ -0,0 +1,18 @@
+#include "stdafx.h"
+#include "InputConstraint.h"
+
+bool InputConstraint::isMappingConstrained(int iPad, int mapping)
+{
+ // If it's a menu button, then we ignore all inputs
+ if((m_inputMapping == mapping) || (mapping < ACTION_MAX_MENU))
+ {
+ return true;
+ }
+
+ // Otherwise see if they map to the same actual button
+ unsigned char layoutMapping = InputManager.GetJoypadMapVal( iPad );
+
+ // 4J HEG - Replaced the equivalance test with bitwise AND, important in some mapping configurations
+ // (e.g. when comparing two action map values and one has extra buttons mapped)
+ return (InputManager.GetGameJoypadMaps(layoutMapping,m_inputMapping) & InputManager.GetGameJoypadMaps(layoutMapping,mapping)) > 0;
+}
diff --git a/Minecraft.Client/Common/Tutorial/InputConstraint.h b/Minecraft.Client/Common/Tutorial/InputConstraint.h
new file mode 100644
index 00000000..3d6bee61
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/InputConstraint.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "TutorialConstraint.h"
+
+class InputConstraint : public TutorialConstraint
+{
+private:
+ int m_inputMapping; // Should be one of the EControllerActions
+public:
+ virtual ConstraintType getType() { return e_ConstraintInput; }
+
+ InputConstraint(int mapping) : TutorialConstraint(-1), m_inputMapping( mapping ) {}
+
+ virtual bool isMappingConstrained(int iPad, int mapping);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/LookAtEntityHint.cpp b/Minecraft.Client/Common/Tutorial/LookAtEntityHint.cpp
new file mode 100644
index 00000000..3b4680ce
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/LookAtEntityHint.cpp
@@ -0,0 +1,25 @@
+#include "stdafx.h"
+#include "Tutorial.h"
+#include "LookAtEntityHint.h"
+
+
+LookAtEntityHint::LookAtEntityHint(eTutorial_Hint id, Tutorial *tutorial, int descriptionId, int titleId, eINSTANCEOF type)
+ : TutorialHint(id, tutorial, descriptionId, e_Hint_LookAtEntity)
+{
+ m_type = type;
+ m_titleId = titleId;
+}
+
+bool LookAtEntityHint::onLookAtEntity(eINSTANCEOF type)
+{
+ if(m_type == type)
+ {
+ // Display hint
+ Tutorial::PopupMessageDetails *message = new Tutorial::PopupMessageDetails();
+ message->m_messageId = m_descriptionId;
+ message->m_titleId = m_titleId;
+ message->m_delay = true;
+ return m_tutorial->setMessage(this, message);
+ }
+ return false;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/LookAtEntityHint.h b/Minecraft.Client/Common/Tutorial/LookAtEntityHint.h
new file mode 100644
index 00000000..99136691
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/LookAtEntityHint.h
@@ -0,0 +1,20 @@
+#pragma once
+using namespace std;
+
+#include "..\..\..\Minecraft.World\Class.h"
+#include "TutorialHint.h"
+
+class ItemInstance;
+
+class LookAtEntityHint : public TutorialHint
+{
+private:
+ eINSTANCEOF m_type;
+ int m_titleId;
+
+public:
+ LookAtEntityHint(eTutorial_Hint id, Tutorial *tutorial, int descriptionId, int titleId, eINSTANCEOF type);
+ ~LookAtEntityHint();
+
+ virtual bool onLookAtEntity(eINSTANCEOF type);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/LookAtTileHint.cpp b/Minecraft.Client/Common/Tutorial/LookAtTileHint.cpp
new file mode 100644
index 00000000..0a953a7b
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/LookAtTileHint.cpp
@@ -0,0 +1,68 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "Tutorial.h"
+#include "LookAtTileHint.h"
+
+
+LookAtTileHint::LookAtTileHint(eTutorial_Hint id, Tutorial *tutorial, int tiles[], unsigned int tilesLength, int iconOverride /*= -1*/, int iData /* = -1 */, int iDataOverride /*= -1*/)
+ : TutorialHint(id, tutorial, -1, e_Hint_LookAtTile)
+{
+ m_iTilesCount = tilesLength;
+
+ m_iTiles= new int [m_iTilesCount];
+ for(unsigned int i=0;i<m_iTilesCount;i++)
+ {
+ m_iTiles[i]=tiles[i];
+ }
+
+ m_iconOverride = iconOverride;
+ m_iData = iData;
+ m_iDataOverride = iDataOverride;
+}
+
+bool LookAtTileHint::onLookAt(int id,int iData)
+{
+ if(id > 0 && id < 256 && (m_iData == -1 || m_iData == iData) )
+ {
+ bool itemFound = false;
+ for(unsigned int i=0;i<m_iTilesCount;i++)
+ {
+ if(id == m_iTiles[i])
+ {
+ itemFound = true;
+ break;
+ }
+ }
+ if(itemFound)
+ {
+ // Display hint
+ Tutorial::PopupMessageDetails *message = new Tutorial::PopupMessageDetails();
+ message->m_delay = true;
+ if( m_iconOverride >= 0 )
+ {
+ message->m_icon = m_iconOverride;
+ }
+ else if(m_iconOverride == -2)
+ {
+ message->m_icon = TUTORIAL_NO_ICON;
+ }
+ else
+ {
+ message->m_icon = id;
+ if(m_iDataOverride > -1)
+ {
+ message->m_iAuxVal = m_iDataOverride;
+ }
+ else
+ {
+ message->m_iAuxVal = iData;
+ }
+ }
+ message->m_messageId = Item::items[id]->getUseDescriptionId();
+ message->m_titleId = Item::items[id]->getDescriptionId(message->m_iAuxVal);
+ return m_tutorial->setMessage(this, message);
+ }
+ }
+ return false;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/LookAtTileHint.h b/Minecraft.Client/Common/Tutorial/LookAtTileHint.h
new file mode 100644
index 00000000..34ec1b95
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/LookAtTileHint.h
@@ -0,0 +1,22 @@
+#pragma once
+using namespace std;
+
+#include "TutorialHint.h"
+
+class ItemInstance;
+
+class LookAtTileHint : public TutorialHint
+{
+private:
+ int *m_iTiles;
+ unsigned int m_iTilesCount;
+ int m_iconOverride;
+ int m_iData;
+ int m_iDataOverride;
+
+public:
+ LookAtTileHint(eTutorial_Hint id, Tutorial *tutorial, int tiles[], unsigned int tilesLength, int iconOverride = -1, int iData=-1, int iDataOverride = -1);
+ ~LookAtTileHint();
+
+ virtual bool onLookAt(int id, int iData=0);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/PickupTask.cpp b/Minecraft.Client/Common/Tutorial/PickupTask.cpp
new file mode 100644
index 00000000..00bc9d1f
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/PickupTask.cpp
@@ -0,0 +1,17 @@
+#include "stdafx.h"
+#include "PickupTask.h"
+
+void PickupTask::onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux)
+{
+ if(item->id == m_itemId)
+ {
+ if(m_auxValue == -1 && invItemCountAnyAux >= m_quantity)
+ {
+ bIsCompleted = true;
+ }
+ else if( m_auxValue == item->getAuxValue() && invItemCountThisAux >= m_quantity)
+ {
+ bIsCompleted = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/PickupTask.h b/Minecraft.Client/Common/Tutorial/PickupTask.h
new file mode 100644
index 00000000..68e1d479
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/PickupTask.h
@@ -0,0 +1,26 @@
+#pragma once
+using namespace std;
+#include "TutorialTask.h"
+
+class ItemInstance;
+
+class PickupTask : public TutorialTask
+{
+public:
+ PickupTask( int itemId, unsigned int quantity, int auxValue,
+ Tutorial *tutorial, int descriptionId, bool enablePreCompletion = true, vector<TutorialConstraint *> *inConstraints = NULL,
+ bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true )
+ : TutorialTask(tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, m_bTaskReminders ),
+ m_itemId( itemId),
+ m_quantity( quantity ),
+ m_auxValue( auxValue )
+ {}
+
+ virtual bool isCompleted() { return bIsCompleted; }
+ virtual void onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux);
+
+private:
+ int m_itemId;
+ unsigned int m_quantity;
+ int m_auxValue;
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.cpp b/Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.cpp
new file mode 100644
index 00000000..8603f765
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.cpp
@@ -0,0 +1,263 @@
+#include "stdafx.h"
+#include "ProcedureCompoundTask.h"
+
+ProcedureCompoundTask::~ProcedureCompoundTask()
+{
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < m_taskSequence.end(); ++it)
+ {
+ delete (*it);
+ }
+}
+
+void ProcedureCompoundTask::AddTask(TutorialTask *task)
+{
+ if(task != NULL)
+ {
+ m_taskSequence.push_back(task);
+ }
+}
+
+int ProcedureCompoundTask::getDescriptionId()
+{
+ if(bIsCompleted)
+ return -1;
+
+ // Return the id of the first task not completed
+ int descriptionId = -1;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(!task->isCompleted())
+ {
+ task->setAsCurrentTask(true);
+ descriptionId = task->getDescriptionId();
+ break;
+ }
+ else if(task->getCompletionAction() == e_Tutorial_Completion_Complete_State)
+ {
+ bIsCompleted = true;
+ break;
+ }
+ }
+ return descriptionId;
+}
+
+int ProcedureCompoundTask::getPromptId()
+{
+ if(bIsCompleted)
+ return -1;
+
+ // Return the id of the first task not completed
+ int promptId = -1;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(!task->isCompleted())
+ {
+ promptId = task->getPromptId();
+ break;
+ }
+ }
+ return promptId;
+}
+
+bool ProcedureCompoundTask::isCompleted()
+{
+ // Return whether all tasks are completed
+
+ bool allCompleted = true;
+ bool isCurrentTask = true;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+
+ if(allCompleted && isCurrentTask)
+ {
+ if(task->isCompleted())
+ {
+ if(task->getCompletionAction() == e_Tutorial_Completion_Complete_State)
+ {
+ allCompleted = true;
+ break;
+ }
+ }
+ else
+ {
+ task->setAsCurrentTask(true);
+ allCompleted = false;
+ isCurrentTask = false;
+ }
+ }
+ else if (!allCompleted)
+ {
+ task->setAsCurrentTask(false);
+ }
+ }
+
+ if(allCompleted)
+ {
+ //Disable all constraints
+ itEnd = m_taskSequence.end();
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->enableConstraints(false);
+ }
+ }
+ bIsCompleted = allCompleted;
+ return allCompleted;
+}
+
+void ProcedureCompoundTask::onCrafted(shared_ptr<ItemInstance> item)
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->onCrafted(item);
+ }
+}
+
+void ProcedureCompoundTask::handleUIInput(int iAction)
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->handleUIInput(iAction);
+ }
+}
+
+
+void ProcedureCompoundTask::setAsCurrentTask(bool active /*= true*/)
+{
+ bool allCompleted = true;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(allCompleted && !task->isCompleted())
+ {
+ task->setAsCurrentTask(true);
+ allCompleted = false;
+ }
+ else if (!allCompleted)
+ {
+ task->setAsCurrentTask(false);
+ }
+ }
+}
+
+bool ProcedureCompoundTask::ShowMinimumTime()
+{
+ if(bIsCompleted)
+ return false;
+
+ bool showMinimumTime = false;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(!task->isCompleted())
+ {
+ showMinimumTime = task->ShowMinimumTime();
+ break;
+ }
+ }
+ return showMinimumTime;
+}
+
+bool ProcedureCompoundTask::hasBeenActivated()
+{
+ if(bIsCompleted)
+ return true;
+
+ bool hasBeenActivated = false;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(!task->isCompleted())
+ {
+ hasBeenActivated = task->hasBeenActivated();
+ break;
+ }
+ }
+ return hasBeenActivated;
+}
+
+void ProcedureCompoundTask::setShownForMinimumTime()
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(!task->isCompleted())
+ {
+ task->setShownForMinimumTime();
+ break;
+ }
+ }
+}
+
+bool ProcedureCompoundTask::AllowFade()
+{
+ if(bIsCompleted)
+ return true;
+
+ bool allowFade = true;
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ if(!task->isCompleted())
+ {
+ allowFade = task->AllowFade();
+ break;
+ }
+ }
+ return allowFade;
+}
+
+void ProcedureCompoundTask::useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z,bool bTestUseOnly)
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->useItemOn(level, item, x, y, z, bTestUseOnly);
+ }
+}
+
+void ProcedureCompoundTask::useItem(shared_ptr<ItemInstance> item, bool bTestUseOnly)
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->useItem(item, bTestUseOnly);
+ }
+}
+
+void ProcedureCompoundTask::onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux)
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->onTake(item, invItemCountAnyAux, invItemCountThisAux);
+ }
+}
+
+void ProcedureCompoundTask::onStateChange(eTutorial_State newState)
+{
+ AUTO_VAR(itEnd, m_taskSequence.end());
+ for(AUTO_VAR(it, m_taskSequence.begin()); it < itEnd; ++it)
+ {
+ TutorialTask *task = *it;
+ task->onStateChange(newState);
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.h b/Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.h
new file mode 100644
index 00000000..36b32798
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ProcedureCompoundTask.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "TutorialTask.h"
+
+// A tutorial task that requires each of the task to be completed in order until the last one is complete.
+// If an earlier task that was complete is now not complete then it's hint should be shown.
+class ProcedureCompoundTask : public TutorialTask
+{
+public:
+ ProcedureCompoundTask(Tutorial *tutorial )
+ : TutorialTask(tutorial, -1, false, NULL, false, true, false )
+ {}
+
+ ~ProcedureCompoundTask();
+
+ void AddTask(TutorialTask *task);
+
+ virtual int getDescriptionId();
+ virtual int getPromptId();
+ virtual bool isCompleted();
+ virtual void onCrafted(shared_ptr<ItemInstance> item);
+ virtual void handleUIInput(int iAction);
+ virtual void setAsCurrentTask(bool active = true);
+ virtual bool ShowMinimumTime();
+ virtual bool hasBeenActivated();
+ virtual void setShownForMinimumTime();
+ virtual bool AllowFade();
+
+ virtual void useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z, bool bTestUseOnly=false);
+ virtual void useItem(shared_ptr<ItemInstance> item, bool bTestUseOnly=false);
+ virtual void onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux);
+ virtual void onStateChange(eTutorial_State newState);
+
+private:
+ vector<TutorialTask *> m_taskSequence;
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ProgressFlagTask.cpp b/Minecraft.Client/Common/Tutorial/ProgressFlagTask.cpp
new file mode 100644
index 00000000..ea224ca3
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ProgressFlagTask.cpp
@@ -0,0 +1,17 @@
+#include "stdafx.h"
+#include "ProgressFlagTask.h"
+
+bool ProgressFlagTask::isCompleted()
+{
+ switch( m_type )
+ {
+ case e_Progress_Set_Flag:
+ (*flags) |= m_mask;
+ bIsCompleted = true;
+ break;
+ case e_Progress_Flag_On:
+ bIsCompleted = ((*flags) & m_mask) == m_mask;
+ break;
+ }
+ return bIsCompleted;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/ProgressFlagTask.h b/Minecraft.Client/Common/Tutorial/ProgressFlagTask.h
new file mode 100644
index 00000000..b96e1bc0
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/ProgressFlagTask.h
@@ -0,0 +1,25 @@
+#pragma once
+using namespace std;
+#include "Tutorial.h"
+#include "TutorialTask.h"
+
+class ProgressFlagTask : public TutorialTask
+{
+public:
+ enum EProgressFlagType
+ {
+ e_Progress_Set_Flag,
+ e_Progress_Flag_On,
+ };
+private:
+ char *flags; // Not a member of this object
+ char m_mask;
+ EProgressFlagType m_type;
+public:
+ ProgressFlagTask(char *flags, char mask, EProgressFlagType type, Tutorial *tutorial ) :
+ TutorialTask(tutorial, -1, false, NULL ),
+ flags( flags ), m_mask( mask ), m_type( type )
+ {}
+
+ virtual bool isCompleted();
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/StatTask.cpp b/Minecraft.Client/Common/Tutorial/StatTask.cpp
new file mode 100644
index 00000000..5f8b215e
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/StatTask.cpp
@@ -0,0 +1,25 @@
+#include "stdafx.h"
+#include "..\..\Minecraft.h"
+#include "..\..\LocalPlayer.h"
+#include "..\..\StatsCounter.h"
+#include "..\..\..\Minecraft.World\net.minecraft.stats.h"
+#include "StatTask.h"
+
+StatTask::StatTask(Tutorial *tutorial, int descriptionId, bool enablePreCompletion, Stat *stat, int variance /*= 1*/)
+ : TutorialTask( tutorial, descriptionId, enablePreCompletion, NULL )
+{
+ this->stat = stat;
+
+ Minecraft *minecraft = Minecraft::GetInstance();
+ targetValue = minecraft->stats[ProfileManager.GetPrimaryPad()]->getTotalValue( stat ) + variance;
+}
+
+bool StatTask::isCompleted()
+{
+ if( bIsCompleted )
+ return true;
+
+ Minecraft *minecraft = Minecraft::GetInstance();
+ bIsCompleted = minecraft->stats[ProfileManager.GetPrimaryPad()]->getTotalValue( stat ) >= (unsigned int)targetValue;
+ return bIsCompleted;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/StatTask.h b/Minecraft.Client/Common/Tutorial/StatTask.h
new file mode 100644
index 00000000..ba38f00a
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/StatTask.h
@@ -0,0 +1,18 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+class Stat;
+
+// 4J Stu - Tutorial tasks that can use the current stat trackin code. This is things like blocks mined/items crafted.
+class StatTask : public TutorialTask
+{
+private:
+ Stat *stat;
+ int targetValue;
+
+public:
+ StatTask(Tutorial *tutorial, int descriptionId, bool enablePreCompletion, Stat *stat, int variance = 1);
+ virtual bool isCompleted();
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/StateChangeTask.h b/Minecraft.Client/Common/Tutorial/StateChangeTask.h
new file mode 100644
index 00000000..fb9e6396
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/StateChangeTask.h
@@ -0,0 +1,27 @@
+#pragma once
+using namespace std;
+#include "Tutorial.h"
+#include "TutorialTask.h"
+
+class StateChangeTask : public TutorialTask
+{
+private:
+ eTutorial_State m_state;
+public:
+ StateChangeTask(eTutorial_State state,
+ Tutorial *tutorial, int descriptionId = -1, bool enablePreCompletion = false, vector<TutorialConstraint *> *inConstraints = NULL,
+ bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true ) :
+ TutorialTask(tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, m_bTaskReminders ),
+ m_state( state )
+ {}
+
+ virtual bool isCompleted() { return bIsCompleted; }
+
+ virtual void onStateChange(eTutorial_State newState)
+ {
+ if(newState == m_state)
+ {
+ bIsCompleted = true;
+ }
+ }
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TakeItemHint.cpp b/Minecraft.Client/Common/Tutorial/TakeItemHint.cpp
new file mode 100644
index 00000000..a1a5c37a
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TakeItemHint.cpp
@@ -0,0 +1,45 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "Tutorial.h"
+#include "TakeItemHint.h"
+
+
+TakeItemHint::TakeItemHint(eTutorial_Hint id, Tutorial *tutorial, int items[], unsigned int itemsLength)
+ : TutorialHint(id, tutorial, -1, e_Hint_TakeItem)
+{
+ m_iItemsCount = itemsLength;
+
+ m_iItems= new int [m_iItemsCount];
+ for(unsigned int i=0;i<m_iItemsCount;i++)
+ {
+ m_iItems[i]=items[i];
+ }
+}
+
+bool TakeItemHint::onTake(shared_ptr<ItemInstance> item)
+{
+ if(item != NULL)
+ {
+ bool itemFound = false;
+ for(unsigned int i=0;i<m_iItemsCount;i++)
+ {
+ if(item->id == m_iItems[i])
+ {
+ itemFound = true;
+ break;
+ }
+ }
+ if(itemFound)
+ {
+ // Display hint
+ Tutorial::PopupMessageDetails *message = new Tutorial::PopupMessageDetails();
+ message->m_messageId = item->getUseDescriptionId();
+ message->m_titleId = item->getDescriptionId();
+ message->m_icon = item->id;
+ message->m_delay = true;
+ return m_tutorial->setMessage(this, message);
+ }
+ }
+ return false;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TakeItemHint.h b/Minecraft.Client/Common/Tutorial/TakeItemHint.h
new file mode 100644
index 00000000..f001d4c7
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TakeItemHint.h
@@ -0,0 +1,19 @@
+#pragma once
+using namespace std;
+
+#include "TutorialHint.h"
+
+class ItemInstance;
+
+class TakeItemHint : public TutorialHint
+{
+private:
+ int *m_iItems;
+ unsigned int m_iItemsCount;
+
+public:
+ TakeItemHint(eTutorial_Hint id, Tutorial *tutorial, int items[], unsigned int itemsLength);
+ ~TakeItemHint();
+
+ virtual bool onTake( shared_ptr<ItemInstance> item );
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/Tutorial b/Minecraft.Client/Common/Tutorial/Tutorial
new file mode 100644
index 00000000..db585813
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/Tutorial
Binary files differ
diff --git a/Minecraft.Client/Common/Tutorial/Tutorial.cpp b/Minecraft.Client/Common/Tutorial/Tutorial.cpp
new file mode 100644
index 00000000..b0a0d665
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/Tutorial.cpp
@@ -0,0 +1,2160 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.stats.h"
+#include "..\..\LocalPlayer.h"
+#include "..\..\..\Minecraft.World\Entity.h"
+#include "..\..\..\Minecraft.World\Level.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.entity.player.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "..\..\MinecraftServer.h"
+#include "..\..\Minecraft.h"
+#include "..\..\MultiPlayerLocalPlayer.h"
+#include "..\..\MultiPlayerLevel.h"
+#include "..\..\SurvivalMode.h"
+#include "Tutorial.h"
+#include "TutorialMessage.h"
+#include "TutorialTasks.h"
+#include "TutorialConstraints.h"
+#include "TutorialHints.h"
+
+vector<int> Tutorial::s_completableTasks;
+
+
+int Tutorial::m_iTutorialHintDelayTime = 14000;
+int Tutorial::m_iTutorialDisplayMessageTime = 7000;
+int Tutorial::m_iTutorialMinimumDisplayMessageTime = 2000;
+int Tutorial::m_iTutorialExtraReminderTime = 13000;
+int Tutorial::m_iTutorialReminderTime = m_iTutorialDisplayMessageTime + m_iTutorialExtraReminderTime;
+int Tutorial::m_iTutorialConstraintDelayRemoveTicks = 15;
+int Tutorial::m_iTutorialFreezeTimeValue = 8000;
+
+bool Tutorial::PopupMessageDetails::isSameContent(PopupMessageDetails *other)
+{
+ if(other == NULL) return false;
+
+ bool textTheSame = (m_messageId == other->m_messageId) && (m_messageString.compare(other->m_messageString) == 0);
+ bool titleTheSame = (m_titleId == other->m_titleId) && (m_titleString.compare(other->m_titleString) == 0);
+ bool promptTheSame = (m_promptId == other->m_promptId) && (m_promptString.compare(other->m_promptString) == 0);
+ return textTheSame && titleTheSame && promptTheSame;
+}
+
+void Tutorial::staticCtor()
+{
+ //
+ /*
+ *****
+ *****
+ THE ORDERING OF THESE SHOULD NOT CHANGE - Although the ordering may not be totally logical due to the order tasks were added, these map
+ to bits in the profile data in this order. New tasks/hints should be added at the end.
+ *****
+ *****
+ */
+ s_completableTasks.push_back( e_Tutorial_State_Inventory_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_2x2Crafting_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_3x3Crafting_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Furnace_Menu );
+
+ s_completableTasks.push_back( e_Tutorial_State_Riding_Minecart );
+ s_completableTasks.push_back( e_Tutorial_State_Riding_Boat );
+ s_completableTasks.push_back( e_Tutorial_State_Fishing );
+ s_completableTasks.push_back( e_Tutorial_State_Bed );
+
+ s_completableTasks.push_back( e_Tutorial_State_Container_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Trap_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Redstone_And_Piston );
+ s_completableTasks.push_back( e_Tutorial_State_Portal );
+ s_completableTasks.push_back( e_Tutorial_State_Creative_Inventory_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Food_Bar );
+ s_completableTasks.push_back( e_Tutorial_State_CreativeMode );
+ s_completableTasks.push_back( e_Tutorial_State_Brewing );
+ s_completableTasks.push_back( e_Tutorial_State_Brewing_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Enchanting );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Hold_To_Mine );
+ s_completableTasks.push_back( e_Tutorial_Hint_Tool_Damaged );
+ s_completableTasks.push_back( e_Tutorial_Hint_Swim_Up );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_2 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_3 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_4 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_5 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_6 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_7 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_8 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_9 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unused_10 );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Rock );
+ s_completableTasks.push_back( e_Tutorial_Hint_Stone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Planks );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sapling );
+ s_completableTasks.push_back( e_Tutorial_Hint_Unbreakable );
+ s_completableTasks.push_back( e_Tutorial_Hint_Water );
+ s_completableTasks.push_back( e_Tutorial_Hint_Lava );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sand );
+ s_completableTasks.push_back( e_Tutorial_Hint_Gravel );
+ s_completableTasks.push_back( e_Tutorial_Hint_Gold_Ore );
+ s_completableTasks.push_back( e_Tutorial_Hint_Iron_Ore );
+ s_completableTasks.push_back( e_Tutorial_Hint_Coal_Ore );
+ s_completableTasks.push_back( e_Tutorial_Hint_Tree_Trunk );
+ s_completableTasks.push_back( e_Tutorial_Hint_Glass );
+ s_completableTasks.push_back( e_Tutorial_Hint_Leaves );
+ s_completableTasks.push_back( e_Tutorial_Hint_Lapis_Ore );
+ s_completableTasks.push_back( e_Tutorial_Hint_Lapis_Block );
+ s_completableTasks.push_back( e_Tutorial_Hint_Dispenser );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sandstone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Note_Block );
+ s_completableTasks.push_back( e_Tutorial_Hint_Powered_Rail );
+ s_completableTasks.push_back( e_Tutorial_Hint_Detector_Rail );
+ s_completableTasks.push_back( e_Tutorial_Hint_Tall_Grass );
+ s_completableTasks.push_back( e_Tutorial_Hint_Wool );
+ s_completableTasks.push_back( e_Tutorial_Hint_Flower );
+ s_completableTasks.push_back( e_Tutorial_Hint_Mushroom );
+ s_completableTasks.push_back( e_Tutorial_Hint_Gold_Block );
+ s_completableTasks.push_back( e_Tutorial_Hint_Iron_Block );
+ s_completableTasks.push_back( e_Tutorial_Hint_Stone_Slab );
+ s_completableTasks.push_back( e_Tutorial_Hint_Red_Brick );
+ s_completableTasks.push_back( e_Tutorial_Hint_Tnt );
+ s_completableTasks.push_back( e_Tutorial_Hint_Bookshelf );
+ s_completableTasks.push_back( e_Tutorial_Hint_Moss_Stone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Obsidian );
+ s_completableTasks.push_back( e_Tutorial_Hint_Torch );
+ s_completableTasks.push_back( e_Tutorial_Hint_MobSpawner );
+ s_completableTasks.push_back( e_Tutorial_Hint_Chest );
+ s_completableTasks.push_back( e_Tutorial_Hint_Redstone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Diamond_Ore );
+ s_completableTasks.push_back( e_Tutorial_Hint_Diamond_Block );
+ s_completableTasks.push_back( e_Tutorial_Hint_Crafting_Table );
+ s_completableTasks.push_back( e_Tutorial_Hint_Crops );
+ s_completableTasks.push_back( e_Tutorial_Hint_Farmland );
+ s_completableTasks.push_back( e_Tutorial_Hint_Furnace );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sign );
+ s_completableTasks.push_back( e_Tutorial_Hint_Door_Wood );
+ s_completableTasks.push_back( e_Tutorial_Hint_Ladder );
+ s_completableTasks.push_back( e_Tutorial_Hint_Rail );
+ s_completableTasks.push_back( e_Tutorial_Hint_Stairs_Stone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Lever );
+ s_completableTasks.push_back( e_Tutorial_Hint_PressurePlate );
+ s_completableTasks.push_back( e_Tutorial_Hint_Door_Iron );
+ s_completableTasks.push_back( e_Tutorial_Hint_Redstone_Ore );
+ s_completableTasks.push_back( e_Tutorial_Hint_Redstone_Torch );
+ s_completableTasks.push_back( e_Tutorial_Hint_Button );
+ s_completableTasks.push_back( e_Tutorial_Hint_Snow );
+ s_completableTasks.push_back( e_Tutorial_Hint_Ice );
+ s_completableTasks.push_back( e_Tutorial_Hint_Cactus );
+ s_completableTasks.push_back( e_Tutorial_Hint_Clay );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sugarcane );
+ s_completableTasks.push_back( e_Tutorial_Hint_Record_Player );
+ s_completableTasks.push_back( e_Tutorial_Hint_Pumpkin );
+ s_completableTasks.push_back( e_Tutorial_Hint_Hell_Rock );
+ s_completableTasks.push_back( e_Tutorial_Hint_Hell_Sand );
+ s_completableTasks.push_back( e_Tutorial_Hint_Glowstone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Portal );
+ s_completableTasks.push_back( e_Tutorial_Hint_Pumpkin_Lit );
+ s_completableTasks.push_back( e_Tutorial_Hint_Cake );
+ s_completableTasks.push_back( e_Tutorial_Hint_Redstone_Repeater );
+ s_completableTasks.push_back( e_Tutorial_Hint_Trapdoor );
+ s_completableTasks.push_back( e_Tutorial_Hint_Piston );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sticky_Piston );
+ s_completableTasks.push_back( e_Tutorial_Hint_Monster_Stone_Egg );
+ s_completableTasks.push_back( e_Tutorial_Hint_Stone_Brick_Smooth );
+ s_completableTasks.push_back( e_Tutorial_Hint_Huge_Mushroom );
+ s_completableTasks.push_back( e_Tutorial_Hint_Iron_Fence );
+ s_completableTasks.push_back( e_Tutorial_Hint_Thin_Glass );
+ s_completableTasks.push_back( e_Tutorial_Hint_Melon );
+ s_completableTasks.push_back( e_Tutorial_Hint_Vine );
+ s_completableTasks.push_back( e_Tutorial_Hint_Fence_Gate );
+ s_completableTasks.push_back( e_Tutorial_Hint_Mycel );
+ s_completableTasks.push_back( e_Tutorial_Hint_Water_Lily );
+ s_completableTasks.push_back( e_Tutorial_Hint_Nether_Brick );
+ s_completableTasks.push_back( e_Tutorial_Hint_Nether_Fence );
+ s_completableTasks.push_back( e_Tutorial_Hint_Nether_Stalk );
+ s_completableTasks.push_back( e_Tutorial_Hint_Enchant_Table );
+ s_completableTasks.push_back( e_Tutorial_Hint_Brewing_Stand );
+ s_completableTasks.push_back( e_Tutorial_Hint_Cauldron );
+ s_completableTasks.push_back( e_Tutorial_Hint_End_Portal );
+ s_completableTasks.push_back( e_Tutorial_Hint_End_Portal_Frame );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Squid );
+ s_completableTasks.push_back( e_Tutorial_Hint_Cow );
+ s_completableTasks.push_back( e_Tutorial_Hint_Sheep );
+ s_completableTasks.push_back( e_Tutorial_Hint_Chicken );
+ s_completableTasks.push_back( e_Tutorial_Hint_Pig );
+ s_completableTasks.push_back( e_Tutorial_Hint_Wolf );
+ s_completableTasks.push_back( e_Tutorial_Hint_Creeper );
+ s_completableTasks.push_back( e_Tutorial_Hint_Skeleton );
+ s_completableTasks.push_back( e_Tutorial_Hint_Spider );
+ s_completableTasks.push_back( e_Tutorial_Hint_Zombie );
+ s_completableTasks.push_back( e_Tutorial_Hint_Pig_Zombie );
+ s_completableTasks.push_back( e_Tutorial_Hint_Ghast );
+ s_completableTasks.push_back( e_Tutorial_Hint_Slime );
+ s_completableTasks.push_back( e_Tutorial_Hint_Enderman );
+ s_completableTasks.push_back( e_Tutorial_Hint_Silverfish );
+ s_completableTasks.push_back( e_Tutorial_Hint_Cave_Spider );
+ s_completableTasks.push_back( e_Tutorial_Hint_MushroomCow );
+ s_completableTasks.push_back( e_Tutorial_Hint_SnowMan );
+ s_completableTasks.push_back( e_Tutorial_Hint_IronGolem );
+ s_completableTasks.push_back( e_Tutorial_Hint_EnderDragon );
+ s_completableTasks.push_back( e_Tutorial_Hint_Blaze );
+ s_completableTasks.push_back( e_Tutorial_Hint_Lava_Slime );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Ozelot );
+ s_completableTasks.push_back( e_Tutorial_Hint_Villager );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Shovel );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Hatchet );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Pickaxe );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Flint_And_Steel );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Apple );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bow );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Arrow );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Coal );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Diamond );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Iron_Ingot );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Gold_Ingot );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Sword );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Stick );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bowl );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Mushroom_Stew );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_String );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Feather );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Sulphur );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Hoe );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Seeds );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Wheat );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bread );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Helmet );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Chestplate );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Leggings );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Boots );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Flint );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Porkchop_Raw );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Porkchop_Cooked );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Painting );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Apple_Gold );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Sign );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Door_Wood );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bucket_Empty );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bucket_Water );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bucket_Lava );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Minecart );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Saddle );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Door_Iron );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Redstone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Snowball );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Boat );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Leather );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Milk );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Brick );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Clay );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Reeds );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Paper );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Book );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Slimeball );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Minecart_Chest );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Minecart_Furnace );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Egg );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Compass );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Clock );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Yellow_Dust );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Fish_Raw );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Fish_Cooked );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Dye_Powder );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Bone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Sugar );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Cake );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Diode );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Cookie );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Map );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Record );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_White_Stone );
+ s_completableTasks.push_back( e_Tutorial_Hint_Dragon_Egg );
+ s_completableTasks.push_back( e_Tutorial_Hint_RedstoneLamp );
+ s_completableTasks.push_back( e_Tutorial_Hint_Cocoa);
+
+ s_completableTasks.push_back( e_Tutorial_Hint_EmeraldOre );
+ s_completableTasks.push_back( e_Tutorial_Hint_EmeraldBlock );
+ s_completableTasks.push_back( e_Tutorial_Hint_EnderChest );
+ s_completableTasks.push_back( e_Tutorial_Hint_TripwireSource );
+ s_completableTasks.push_back( e_Tutorial_Hint_Tripwire );
+ s_completableTasks.push_back( e_Tutorial_Hint_CobblestoneWall );
+ s_completableTasks.push_back( e_Tutorial_Hint_Flowerpot );
+ s_completableTasks.push_back( e_Tutorial_Hint_Anvil );
+ s_completableTasks.push_back( e_Tutorial_Hint_QuartzOre );
+ s_completableTasks.push_back( e_Tutorial_Hint_QuartzBlock );
+ s_completableTasks.push_back( e_Tutorial_Hint_WoolCarpet );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Potato );
+ s_completableTasks.push_back( e_Tutorial_Hint_Carrot );
+
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Unused_18 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Unused_19 );
+ s_completableTasks.push_back( e_Tutorial_Hint_Item_Unused_20 );
+
+ s_completableTasks.push_back( eTutorial_Telemetry_TrialStart );
+ s_completableTasks.push_back( eTutorial_Telemetry_Halfway );
+ s_completableTasks.push_back( eTutorial_Telemetry_Complete );
+
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_1 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_2 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_3 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_4 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_5 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_6 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_7 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_8 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_9 );
+ s_completableTasks.push_back( eTutorial_Telemetry_Unused_10 );
+
+ s_completableTasks.push_back( e_Tutorial_State_Enchanting_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Farming );
+ s_completableTasks.push_back( e_Tutorial_State_Breeding );
+ s_completableTasks.push_back( e_Tutorial_State_Golem );
+ s_completableTasks.push_back( e_Tutorial_State_Trading );
+ s_completableTasks.push_back( e_Tutorial_State_Trading_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Anvil );
+ s_completableTasks.push_back( e_Tutorial_State_Anvil_Menu );
+ s_completableTasks.push_back( e_Tutorial_State_Enderchests );
+
+ s_completableTasks.push_back( e_Tutorial_State_Unused_9 );
+ s_completableTasks.push_back( e_Tutorial_State_Unused_10 );
+
+ if( s_completableTasks.size() > TUTORIAL_PROFILE_STORAGE_BITS )
+ {
+ app.DebugPrintf("Warning: Too many tutorial completable tasks added, not enough bits allocated to stored them in the profile data");
+ assert(false);
+ }
+}
+
+Tutorial::Tutorial(int iPad, bool isFullTutorial /*= false*/) : m_iPad( iPad )
+{
+ m_isFullTutorial = isFullTutorial;
+ m_fullTutorialComplete = false;
+ m_allTutorialsComplete = false;
+ hasRequestedUI = false;
+ uiTempDisabled = false;
+ m_hintDisplayed = false;
+ m_freezeTime = false;
+ m_timeFrozen = false;
+ m_UIScene = NULL;
+ m_allowShow = true;
+ m_bHasTickedOnce = false;
+ m_firstTickTime = 0;
+
+ m_lastMessage = NULL;
+
+ lastMessageTime = 0;
+ m_iTaskReminders = 0;
+ m_lastMessageState = e_Tutorial_State_Gameplay;
+
+ m_CurrentState = e_Tutorial_State_Gameplay;
+ m_hasStateChanged = false;
+#ifdef _XBOX
+ m_hTutorialScene=NULL;
+#endif
+
+ for(unsigned int i = 0; i < e_Tutorial_State_Max; ++i)
+ {
+ currentTask[i] = NULL;
+ currentFailedConstraint[i] = NULL;
+ }
+
+ // DEFAULT TASKS THAT ALL TUTORIALS SHARE
+ /*
+ *
+ *
+ * GAMEPLAY
+ *
+ */
+
+ if(!isHintCompleted(e_Tutorial_Hint_Hold_To_Mine)) addHint(e_Tutorial_State_Gameplay, new TutorialHint(e_Tutorial_Hint_Hold_To_Mine, this, IDS_TUTORIAL_HINT_HOLD_TO_MINE, TutorialHint::e_Hint_HoldToMine) );
+ if(!isHintCompleted(e_Tutorial_Hint_Tool_Damaged)) addHint(e_Tutorial_State_Gameplay, new TutorialHint(e_Tutorial_Hint_Tool_Damaged, this, IDS_TUTORIAL_HINT_TOOL_DAMAGED, TutorialHint::e_Hint_ToolDamaged) );
+ if(!isHintCompleted(e_Tutorial_Hint_Swim_Up)) addHint(e_Tutorial_State_Gameplay, new TutorialHint(e_Tutorial_Hint_Swim_Up, this, IDS_TUTORIAL_HINT_SWIM_UP, TutorialHint::e_Hint_SwimUp) );
+
+ /*
+ * TILE HINTS
+ */
+ int rockItems[] = {Tile::rock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Rock)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Rock, this, rockItems, 1 ) );
+
+ int stoneItems[] = {Tile::stoneBrick_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Stone)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone, this, stoneItems, 1 ) );
+
+ int plankItems[] = {Tile::wood_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Planks)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Planks, this, plankItems, 1 ) );
+
+ int saplingItems[] = {Tile::sapling_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Sapling)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sapling, this, saplingItems, 1 ) );
+
+ int unbreakableItems[] = {Tile::unbreakable_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Unbreakable)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Unbreakable, this, unbreakableItems, 1 ) );
+
+ int waterItems[] = {Tile::water_Id, Tile::calmWater_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Water)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Water, this, waterItems, 2 ) );
+
+ int lavaItems[] = {Tile::lava_Id, Tile::calmLava_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Lava)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Lava, this, lavaItems, 2 ) );
+
+ int sandItems[] = {Tile::sand_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Sand)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sand, this, sandItems, 1 ) );
+
+ int gravelItems[] = {Tile::gravel_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Gravel)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Gravel, this, gravelItems, 1 ) );
+
+ int goldOreItems[] = {Tile::goldOre_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Gold_Ore)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Gold_Ore, this, goldOreItems, 1 ) );
+
+ int ironOreItems[] = {Tile::ironOre_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Iron_Ore)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Iron_Ore, this, ironOreItems, 1 ) );
+
+ int coalOreItems[] = {Tile::coalOre_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Coal_Ore)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Coal_Ore, this, coalOreItems, 1 ) );
+
+ int treeTrunkItems[] = {Tile::treeTrunk_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Tree_Trunk)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Tree_Trunk, this, treeTrunkItems, 1 ) );
+
+ int leavesItems[] = {Tile::leaves_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Leaves)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Leaves, this, leavesItems, 1 ) );
+
+ int glassItems[] = {Tile::glass_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Glass)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Glass, this, glassItems, 1 ) );
+
+ int lapisOreItems[] = {Tile::lapisOre_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Lapis_Ore)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Lapis_Ore, this, lapisOreItems, 1 ) );
+
+ int lapisBlockItems[] = {Tile::lapisBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Lapis_Block)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Lapis_Block, this, lapisBlockItems, 1 ) );
+
+ int dispenserItems[] = {Tile::dispenser_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Dispenser)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Dispenser, this, dispenserItems, 1 ) );
+
+ int sandstoneItems[] = {Tile::sandStone_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Sandstone))
+ {
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sandstone, this, sandstoneItems, 1, -1, SandStoneTile::TYPE_DEFAULT ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sandstone, this, sandstoneItems, 1, -1, SandStoneTile::TYPE_HEIROGLYPHS ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sandstone, this, sandstoneItems, 1, -1, SandStoneTile::TYPE_SMOOTHSIDE ) );
+ }
+
+ int noteBlockItems[] = {Tile::musicBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Note_Block)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Note_Block, this, noteBlockItems, 1 ) );
+
+ int poweredRailItems[] = {Tile::goldenRail_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Powered_Rail)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Powered_Rail, this, poweredRailItems, 1 ) );
+
+ int detectorRailItems[] = {Tile::detectorRail_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Detector_Rail)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Detector_Rail, this, detectorRailItems, 1 ) );
+
+ int tallGrassItems[] = {Tile::tallgrass_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Tall_Grass))
+ {
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Tall_Grass, this, tallGrassItems, 1, -1, TallGrass::DEAD_SHRUB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Tall_Grass, this, tallGrassItems, 1, -1, TallGrass::TALL_GRASS ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Tall_Grass, this, tallGrassItems, 1, -1, TallGrass::FERN ) );
+ }
+
+ int woolItems[] = {Tile::cloth_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Wool)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Wool, this, woolItems, 1 ) );
+
+ int flowerItems[] = {Tile::flower_Id, Tile::rose_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Flower)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Flower, this, flowerItems, 2 ) );
+
+ int mushroomItems[] = {Tile::mushroom1_Id, Tile::mushroom2_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Mushroom)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Mushroom, this, mushroomItems, 2 ) );
+
+ int goldBlockItems[] = {Tile::goldBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Gold_Block)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Gold_Block, this, goldBlockItems, 1 ) );
+
+ int ironBlockItems[] = {Tile::ironBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Iron_Block)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Iron_Block, this, ironBlockItems, 1 ) );
+
+ int stoneSlabItems[] = {Tile::stoneSlabHalf_Id, Tile::stoneSlab_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Stone_Slab))
+ {
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::STONE_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::SAND_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::WOOD_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::COBBLESTONE_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::BRICK_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::SMOOTHBRICK_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::NETHERBRICK_SLAB ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, stoneSlabItems, 2, -1, StoneSlabTile::QUARTZ_SLAB ) );
+ }
+
+ int woodSlabItems[] = {Tile::woodSlabHalf_Id, Tile::woodSlab_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Stone_Slab))
+ {
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, woodSlabItems, 2, -1, TreeTile::BIRCH_TRUNK ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Slab, this, woodSlabItems, 2, -1, TreeTile::DARK_TRUNK ) );
+ }
+
+ int redBrickItems[] = {Tile::redBrick_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Red_Brick)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Red_Brick, this, redBrickItems, 1 ) );
+
+ int tntItems[] = {Tile::tnt_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Tnt)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Tnt, this, tntItems, 1 ) );
+
+ int bookshelfItems[] = {Tile::bookshelf_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Bookshelf)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Bookshelf, this, bookshelfItems, 1 ) );
+
+ int mossStoneItems[] = {Tile::mossStone_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Moss_Stone)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Moss_Stone, this, mossStoneItems, 1 ) );
+
+ int obsidianItems[] = {Tile::obsidian_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Obsidian)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Obsidian, this, obsidianItems, 1 ) );
+
+ int torchItems[] = {Tile::torch_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Torch)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Torch, this, torchItems, 1 ) );
+
+ int mobSpawnerItems[] = {Tile::mobSpawner_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_MobSpawner)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_MobSpawner, this, mobSpawnerItems, 1 ) );
+
+ int chestItems[] = {Tile::chest_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Chest)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Chest, this, chestItems, 1 ) );
+
+ int redstoneItems[] = {Tile::redStoneDust_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Redstone)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Redstone, this, redstoneItems, 1, Item::redStone_Id ) );
+
+ int diamondOreItems[] = {Tile::diamondOre_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Diamond_Ore)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Diamond_Ore, this, diamondOreItems, 1 ) );
+
+ int diamondBlockItems[] = {Tile::diamondBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Diamond_Block)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Diamond_Block, this, diamondBlockItems, 1 ) );
+
+ int craftingTableItems[] = {Tile::workBench_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Crafting_Table)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Crafting_Table, this, craftingTableItems, 1 ) );
+
+ int cropsItems[] = {Tile::crops_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Crops)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Crops, this, cropsItems, 1, -1, -1, 7 ) );
+
+ int farmlandItems[] = {Tile::farmland_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Farmland)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Farmland, this, farmlandItems, 1 ) );
+
+ int furnaceItems[] = {Tile::furnace_Id, Tile::furnace_lit_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Furnace)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Furnace, this, furnaceItems, 2 ) );
+
+ int signItems[] = {Tile::sign_Id, Tile::wallSign_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Sign)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sign, this, signItems, 2, Item::sign_Id ) );
+
+ int doorWoodItems[] = {Tile::door_wood_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Door_Wood)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Door_Wood, this, doorWoodItems, 1, Item::door_wood->id ) );
+
+ int ladderItems[] = {Tile::ladder_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Ladder)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Ladder, this, ladderItems, 1 ) );
+
+ int stairsStoneItems[] = {Tile::stairs_stone_Id,Tile::stairs_bricks_Id,Tile::stairs_stoneBrickSmooth_Id,Tile::stairs_wood_Id,Tile::stairs_sprucewood_Id,Tile::stairs_birchwood_Id,Tile::stairs_netherBricks_Id,Tile::stairs_sandstone_Id,Tile::stairs_quartz_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Stairs_Stone)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stairs_Stone, this, stairsStoneItems, 9 ) );
+
+ int railItems[] = {Tile::rail_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Rail)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Rail, this, railItems, 1 ) );
+
+ int leverItems[] = {Tile::lever_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Lever)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Lever, this, leverItems, 1 ) );
+
+ int pressurePlateItems[] = {Tile::pressurePlate_stone_Id, Tile::pressurePlate_wood_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_PressurePlate)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_PressurePlate, this, pressurePlateItems, 2 ) );
+
+ int doorIronItems[] = {Tile::door_iron_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Door_Iron)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Door_Iron, this, doorIronItems, 1, Item::door_iron->id ) );
+
+ int redstoneOreItems[] = {Tile::redStoneOre_Id, Tile::redStoneOre_lit_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Redstone_Ore)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Redstone_Ore, this, redstoneOreItems, 2 ) );
+
+ int redstoneTorchItems[] = {Tile::notGate_off_Id, Tile::notGate_on_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Redstone_Torch)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Redstone_Torch, this, redstoneTorchItems, 2 ) );
+
+ int buttonItems[] = {Tile::button_stone_Id, Tile::button_wood_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Button)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Button, this, buttonItems, 2 ) );
+
+ int snowItems[] = {Tile::snow_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Snow)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Snow, this, snowItems, 1 ) );
+
+ int iceItems[] = {Tile::ice_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Ice)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Ice, this, iceItems, 1 ) );
+
+ int cactusItems[] = {Tile::cactus_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Cactus)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Cactus, this, cactusItems, 1 ) );
+
+ int clayItems[] = {Tile::clay_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Clay)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Clay, this, clayItems, 1 ) );
+
+ int sugarCaneItems[] = {Tile::reeds_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Sugarcane)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sugarcane, this, sugarCaneItems, 1 ) );
+
+ int recordPlayerItems[] = {Tile::recordPlayer_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Record_Player)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Record_Player, this, recordPlayerItems, 1 ) );
+
+ int pumpkinItems[] = {Tile::pumpkin_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Pumpkin)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Pumpkin, this, pumpkinItems, 1, -1, -1, 0 ) );
+
+ int hellRockItems[] = {Tile::hellRock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Hell_Rock)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Hell_Rock, this, hellRockItems, 1 ) );
+
+ int hellSandItems[] = {Tile::hellSand_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Hell_Sand)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Hell_Sand, this, hellSandItems, 1 ) );
+
+ int glowstoneItems[] = {Tile::lightGem_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Glowstone)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Glowstone, this, glowstoneItems, 1 ) );
+
+ int portalItems[] = {Tile::portalTile_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Portal)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Portal, this, portalItems, 1 ) );
+
+ int pumpkinLitItems[] = {Tile::litPumpkin_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Pumpkin_Lit)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Pumpkin_Lit, this, pumpkinLitItems, 1, -1, -1, 0 ) );
+
+ int cakeItems[] = {Tile::cake_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Cake)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Cake, this, cakeItems, 1 ) );
+
+ int redstoneRepeaterItems[] = {Tile::diode_on_Id, Tile::diode_off_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Redstone_Repeater)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Redstone_Repeater, this, redstoneRepeaterItems, 2, Item::diode_Id ) );
+
+ int trapdoorItems[] = {Tile::trapdoor_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Trapdoor)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Trapdoor, this, trapdoorItems, 1 ) );
+
+ int pistonItems[] = {Tile::pistonBase_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Piston)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Piston, this, pistonItems, 1 ) );
+
+ int stickyPistonItems[] = {Tile::pistonStickyBase_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Sticky_Piston)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Sticky_Piston, this, stickyPistonItems, 1 ) );
+
+ int monsterStoneEggItems[] = {Tile::monsterStoneEgg_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Monster_Stone_Egg)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Monster_Stone_Egg, this, monsterStoneEggItems, 1 ) );
+
+ int stoneBrickSmoothItems[] = {Tile::stoneBrickSmooth_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Stone_Brick_Smooth)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Stone_Brick_Smooth, this, stoneBrickSmoothItems, 1 ) );
+
+ int hugeMushroomItems[] = {Tile::hugeMushroom1_Id,Tile::hugeMushroom2_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Huge_Mushroom)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Huge_Mushroom, this, hugeMushroomItems, 2 ) );
+
+ int ironFenceItems[] = {Tile::ironFence_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Iron_Fence)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Iron_Fence, this, ironFenceItems, 1 ) );
+
+ int thisGlassItems[] = {Tile::thinGlass_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Thin_Glass)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Thin_Glass, this, thisGlassItems, 1 ) );
+
+ int melonItems[] = {Tile::melon_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Melon)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Melon, this, melonItems, 1 ) );
+
+ int vineItems[] = {Tile::vine_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Vine)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Vine, this, vineItems, 1 ) );
+
+ int fenceGateItems[] = {Tile::fenceGate_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Fence_Gate)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Fence_Gate, this, fenceGateItems, 1 ) );
+
+ int mycelItems[] = {Tile::mycel_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Mycel)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Mycel, this, mycelItems, 1 ) );
+
+ int waterLilyItems[] = {Tile::waterLily_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Water_Lily)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Water_Lily, this, waterLilyItems, 1 ) );
+
+ int netherBrickItems[] = {Tile::netherBrick_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Nether_Brick)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Nether_Brick, this, netherBrickItems, 1 ) );
+
+ int netherFenceItems[] = {Tile::netherFence_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Nether_Fence)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Nether_Fence, this, netherFenceItems, 1 ) );
+
+ int netherStalkItems[] = {Tile::netherStalk_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Nether_Stalk)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Nether_Stalk, this, netherStalkItems, 1 ) );
+
+ int enchantTableItems[] = {Tile::enchantTable_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Enchant_Table)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Enchant_Table, this, enchantTableItems, 1 ) );
+
+ int brewingStandItems[] = {Tile::brewingStand_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Brewing_Stand)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Brewing_Stand, this, brewingStandItems, 1, Item::brewingStand_Id ) );
+
+ int cauldronItems[] = {Tile::cauldron_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Cauldron)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Cauldron, this, cauldronItems, 1, Item::cauldron_Id ) );
+
+ int endPortalItems[] = {Tile::endPortalTile_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_End_Portal)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_End_Portal, this, endPortalItems, 1, -2 ) );
+
+ int endPortalFrameItems[] = {Tile::endPortalFrameTile_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_End_Portal_Frame)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_End_Portal_Frame, this, endPortalFrameItems, 1 ) );
+
+ int whiteStoneItems[] = {Tile::whiteStone_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_White_Stone)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_White_Stone, this, whiteStoneItems, 1 ) );
+
+ int dragonEggItems[] = {Tile::dragonEgg_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Dragon_Egg)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Dragon_Egg, this, dragonEggItems, 1 ) );
+
+ int redstoneLampItems[] = {Tile::redstoneLight_Id, Tile::redstoneLight_lit_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_RedstoneLamp)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_RedstoneLamp, this, redstoneLampItems, 2 ) );
+
+ int cocoaItems[] = {Tile::cocoa_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Cocoa)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Cocoa, this, cocoaItems, 1 ) );
+
+ int emeraldOreItems[] = {Tile::emeraldOre_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_EmeraldOre)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_EmeraldOre, this, emeraldOreItems, 1 ) );
+
+ int emeraldBlockItems[] = {Tile::emeraldBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_EmeraldBlock)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_EmeraldBlock, this, emeraldBlockItems, 1 ) );
+
+ int enderChestItems[] = {Tile::enderChest_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_EnderChest)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_EnderChest, this, enderChestItems, 1 ) );
+
+ int tripwireSourceItems[] = {Tile::tripWireSource_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_TripwireSource)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_TripwireSource, this, tripwireSourceItems, 1 ) );
+
+ int tripwireItems[] = {Tile::tripWire_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Tripwire)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Tripwire, this, tripwireItems, 1, Item::string_Id ) );
+
+ int cobblestoneWallItems[] = {Tile::cobbleWall_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_CobblestoneWall))
+ {
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_CobblestoneWall, this, cobblestoneWallItems, 1, -1, WallTile::TYPE_NORMAL ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_CobblestoneWall, this, cobblestoneWallItems, 1, -1, WallTile::TYPE_MOSSY ) );
+ }
+
+ int flowerpotItems[] = {Tile::flowerPot_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Flowerpot)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Flowerpot, this, flowerpotItems, 1, Item::flowerPot_Id ) );
+
+ int anvilItems[] = {Tile::anvil_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Anvil)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Anvil, this, anvilItems, 1 ) );
+
+ int quartzOreItems[] = {Tile::netherQuartz_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_QuartzOre)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_QuartzOre, this, quartzOreItems, 1 ) );
+
+ int quartzBlockItems[] = {Tile::quartzBlock_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_QuartzBlock))
+ {
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_QuartzBlock, this, quartzBlockItems, 1, -1, QuartzBlockTile::TYPE_DEFAULT ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_QuartzBlock, this, quartzBlockItems, 1, -1, QuartzBlockTile::TYPE_CHISELED ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_QuartzBlock, this, quartzBlockItems, 1, -1, QuartzBlockTile::TYPE_LINES_Y ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_QuartzBlock, this, quartzBlockItems, 1, -1, QuartzBlockTile::TYPE_LINES_X ) );
+ addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_QuartzBlock, this, quartzBlockItems, 1, -1, QuartzBlockTile::TYPE_LINES_Z ) );
+ }
+
+ int carpetItems[] = {Tile::woolCarpet_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_WoolCarpet)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_WoolCarpet, this, carpetItems, 1 ) );
+
+ int potatoItems[] = {Tile::potatoes_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Potato)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Potato, this, potatoItems, 1, -1, -1, 7 ) );
+
+ int carrotItems[] = {Tile::carrots_Id};
+ if(!isHintCompleted(e_Tutorial_Hint_Carrot)) addHint(e_Tutorial_State_Gameplay, new LookAtTileHint(e_Tutorial_Hint_Carrot, this, carrotItems, 1, -1, -1, 7 ) );
+
+ /*
+ * ENTITY HINTS
+ */
+ if(!isHintCompleted(e_Tutorial_Hint_Squid)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Squid, this, IDS_DESC_SQUID, IDS_SQUID, eTYPE_SQUID ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Cow)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Cow, this, IDS_DESC_COW, IDS_COW, eTYPE_COW ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Sheep)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Sheep, this, IDS_DESC_SHEEP, IDS_SHEEP, eTYPE_SHEEP ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Chicken)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Chicken, this, IDS_DESC_CHICKEN, IDS_CHICKEN, eTYPE_CHICKEN ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Pig)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Pig, this, IDS_DESC_PIG, IDS_PIG, eTYPE_PIG ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Wolf)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Wolf, this, IDS_DESC_WOLF, IDS_WOLF, eTYPE_WOLF ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Creeper)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Creeper, this, IDS_DESC_CREEPER, IDS_CREEPER, eTYPE_CREEPER ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Skeleton)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Skeleton, this, IDS_DESC_SKELETON, IDS_SKELETON, eTYPE_SKELETON ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Spider)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Spider, this, IDS_DESC_SPIDER, IDS_SPIDER, eTYPE_SPIDER ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Zombie)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Zombie, this, IDS_DESC_ZOMBIE, IDS_ZOMBIE, eTYPE_ZOMBIE ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Pig_Zombie)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Pig_Zombie, this, IDS_DESC_PIGZOMBIE, IDS_PIGZOMBIE, eTYPE_PIGZOMBIE ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Ghast)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Ghast, this, IDS_DESC_GHAST, IDS_GHAST, eTYPE_GHAST ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Slime)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Slime, this, IDS_DESC_SLIME, IDS_SLIME, eTYPE_SLIME ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Enderman)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Enderman, this, IDS_DESC_ENDERMAN, IDS_ENDERMAN, eTYPE_ENDERMAN ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Silverfish)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Silverfish, this, IDS_DESC_SILVERFISH, IDS_SILVERFISH, eTYPE_SILVERFISH ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Cave_Spider)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Cave_Spider, this, IDS_DESC_CAVE_SPIDER, IDS_CAVE_SPIDER, eTYPE_CAVESPIDER ) );
+ if(!isHintCompleted(e_Tutorial_Hint_MushroomCow)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_MushroomCow, this, IDS_DESC_MUSHROOM_COW, IDS_MUSHROOM_COW, eTYPE_MUSHROOMCOW) );
+ if(!isHintCompleted(e_Tutorial_Hint_SnowMan)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_SnowMan, this, IDS_DESC_SNOWMAN, IDS_SNOWMAN, eTYPE_SNOWMAN ) );
+ if(!isHintCompleted(e_Tutorial_Hint_IronGolem)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_IronGolem, this, IDS_DESC_IRONGOLEM, IDS_IRONGOLEM, eTYPE_VILLAGERGOLEM ) );
+ if(!isHintCompleted(e_Tutorial_Hint_EnderDragon)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_EnderDragon, this, IDS_DESC_ENDERDRAGON, IDS_ENDERDRAGON, eTYPE_ENDERDRAGON ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Blaze)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Blaze, this, IDS_DESC_BLAZE, IDS_BLAZE, eTYPE_BLAZE ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Lava_Slime)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Lava_Slime, this, IDS_DESC_LAVA_SLIME, IDS_LAVA_SLIME, eTYPE_LAVASLIME ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Ozelot)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Ozelot, this, IDS_DESC_OZELOT, IDS_OZELOT, eTYPE_OZELOT ) );
+ if(!isHintCompleted(e_Tutorial_Hint_Villager)) addHint(e_Tutorial_State_Gameplay, new LookAtEntityHint(e_Tutorial_Hint_Villager, this, IDS_DESC_VILLAGER, IDS_VILLAGER, eTYPE_VILLAGER) );
+
+
+ /*
+ * ITEM HINTS
+ */
+ int shovelItems[] = {Item::shovel_wood->id, Item::shovel_stone->id, Item::shovel_iron->id, Item::shovel_gold->id, Item::shovel_diamond->id};
+ if(!isHintCompleted(e_Tutorial_Hint_Item_Shovel)) addHint(e_Tutorial_State_Gameplay, new DiggerItemHint(e_Tutorial_Hint_Item_Shovel, this, IDS_TUTORIAL_HINT_DIGGER_ITEM_SHOVEL, shovelItems, 5) );
+
+ int hatchetItems[] = {Item::hatchet_wood->id, Item::hatchet_stone->id, Item::hatchet_iron->id, Item::hatchet_gold->id, Item::hatchet_diamond->id};
+ if(!isHintCompleted(e_Tutorial_Hint_Item_Hatchet)) addHint(e_Tutorial_State_Gameplay, new DiggerItemHint(e_Tutorial_Hint_Item_Hatchet, this, IDS_TUTORIAL_HINT_DIGGER_ITEM_HATCHET, hatchetItems, 5 ) );
+
+ int pickaxeItems[] = {Item::pickAxe_wood->id, Item::pickAxe_stone->id, Item::pickAxe_iron->id, Item::pickAxe_gold->id, Item::pickAxe_diamond->id};
+ if(!isHintCompleted(e_Tutorial_Hint_Item_Pickaxe)) addHint(e_Tutorial_State_Gameplay, new DiggerItemHint(e_Tutorial_Hint_Item_Pickaxe, this, IDS_TUTORIAL_HINT_DIGGER_ITEM_PICKAXE, pickaxeItems, 5 ) );
+
+ /*
+ *
+ *
+ * INVENTORY
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Inventory_Menu) )
+ {
+ ProcedureCompoundTask *inventoryOverviewTask = new ProcedureCompoundTask( this );
+ inventoryOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_INV_OVERVIEW, IDS_TUTORIAL_PROMPT_INV_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_Inventory) );
+ inventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_INV_PICK_UP, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ inventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_INV_MOVE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ inventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_INV_DROP, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ inventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_INV_INFO, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Inventory_Menu, inventoryOverviewTask );
+ }
+
+ /*
+ *
+ *
+ * CREATIVE INVENTORY
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Creative_Inventory_Menu) )
+ {
+ ProcedureCompoundTask *creativeInventoryOverviewTask = new ProcedureCompoundTask( this );
+ creativeInventoryOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_CREATIVE_INV_OVERVIEW, IDS_TUTORIAL_PROMPT_CREATIVE_INV_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_CreativeInventory) );
+ creativeInventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_INV_PICK_UP, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ creativeInventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_INV_MOVE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ creativeInventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_INV_DROP, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ creativeInventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_INV_NAV, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ creativeInventoryOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CREATIVE_INV_INFO, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Creative_Inventory_Menu, creativeInventoryOverviewTask );
+ }
+
+ /*
+ *
+ *
+ * CRAFTING
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_2x2Crafting_Menu ) )
+ {
+ ProcedureCompoundTask *craftingOverviewTask = new ProcedureCompoundTask( this );
+ craftingOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_CRAFT_OVERVIEW, IDS_TUTORIAL_PROMPT_CRAFT_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_Crafting) );
+ craftingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_NAV, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ craftingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_CREATE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ craftingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_CRAFT_TABLE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ craftingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_INVENTORY, IDS_TUTORIAL_PROMPT_PRESS_X_TO_TOGGLE_DESCRIPTION, false, ACTION_MENU_X) );
+ craftingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_DESCRIPTION, IDS_TUTORIAL_PROMPT_PRESS_X_TO_TOGGLE_INGREDIENTS, false, ACTION_MENU_X) );
+ craftingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_CRAFT_INGREDIENTS, IDS_TUTORIAL_PROMPT_PRESS_X_TO_TOGGLE_INVENTORY, false, ACTION_MENU_X) );
+ addTask(e_Tutorial_State_2x2Crafting_Menu, craftingOverviewTask );
+ }
+ // Other tasks can be added in the derived classes
+
+ addHint(e_Tutorial_State_2x2Crafting_Menu, new TutorialHint(e_Tutorial_Hint_Always_On, this, IDS_TUTORIAL_HINT_CRAFT_NO_INGREDIENTS, TutorialHint::e_Hint_NoIngredients) );
+
+ addHint(e_Tutorial_State_3x3Crafting_Menu, new TutorialHint(e_Tutorial_Hint_Always_On, this, IDS_TUTORIAL_HINT_CRAFT_NO_INGREDIENTS, TutorialHint::e_Hint_NoIngredients) );
+
+ /*
+ *
+ *
+ * FURNACE
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Furnace_Menu ) )
+ {
+ ProcedureCompoundTask *furnaceOverviewTask = new ProcedureCompoundTask( this );
+ furnaceOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_FURNACE_OVERVIEW, IDS_TUTORIAL_PROMPT_FURNACE_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_Furnace) );
+ furnaceOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_FURNACE_METHOD, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ furnaceOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_FURNACE_FUELS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ furnaceOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_FURNACE_INGREDIENTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Furnace_Menu, furnaceOverviewTask );
+ }
+ // Other tasks can be added in the derived classes
+
+ /*
+ *
+ *
+ * BREWING MENU
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Brewing_Menu ) )
+ {
+ ProcedureCompoundTask *brewingOverviewTask = new ProcedureCompoundTask( this );
+ brewingOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_BREWING_MENU_OVERVIEW, IDS_TUTORIAL_PROMPT_BREWING_MENU_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_BrewingMenu) );
+ brewingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_MENU_METHOD, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ brewingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_MENU_BASIC_INGREDIENTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ brewingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_MENU_EXTENDED_INGREDIENTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ brewingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_BREWING_MENU_EXTENDED_INGREDIENTS_2, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Brewing_Menu, brewingOverviewTask );
+ }
+ // Other tasks can be added in the derived classes
+
+ /*
+ *
+ *
+ * ENCHANTING MENU
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Enchanting_Menu ) )
+ {
+ ProcedureCompoundTask *enchantingOverviewTask = new ProcedureCompoundTask( this );
+ enchantingOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_ENCHANTING_MENU_OVERVIEW, IDS_TUTORIAL_PROMPT_ENCHANTING_MENU_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_EnchantingMenu) );
+ enchantingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_MENU_START, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ enchantingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_MENU_ENCHANTMENTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ enchantingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_MENU_COST, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ enchantingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_MENU_ENCHANT, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ enchantingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ENCHANTING_MENU_BETTER_ENCHANTMENTS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Enchanting_Menu, enchantingOverviewTask );
+ }
+ // Other tasks can be added in the derived classes
+
+ /*
+ *
+ *
+ * ANVIL MENU
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Anvil_Menu ) )
+ {
+ ProcedureCompoundTask *anvilOverviewTask = new ProcedureCompoundTask( this );
+ anvilOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_OVERVIEW, IDS_TUTORIAL_PROMPT_ANVIL_MENU_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_AnvilMenu) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_START, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_REPAIR, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_SACRIFICE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_ENCHANT, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_COST, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_RENAMING, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ anvilOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_ANVIL_MENU_SMITH, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Anvil_Menu, anvilOverviewTask );
+ }
+ // Other tasks can be added in the derived classes
+
+ /*
+ *
+ *
+ * TRADING MENU
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Trading_Menu ) )
+ {
+ ProcedureCompoundTask *tradingOverviewTask = new ProcedureCompoundTask( this );
+ tradingOverviewTask->AddTask( new ChoiceTask(this, IDS_TUTORIAL_TASK_TRADING_MENU_OVERVIEW, IDS_TUTORIAL_PROMPT_TRADING_MENU_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State, eTelemetryTutorial_TradingMenu) );
+ tradingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_MENU_START, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ tradingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_MENU_UNAVAILABLE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ tradingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_MENU_DETAILS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ tradingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_MENU_INVENTORY, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ tradingOverviewTask->AddTask( new InfoTask(this, IDS_TUTORIAL_TASK_TRADING_MENU_TRADE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Trading_Menu, tradingOverviewTask );
+ }
+ // Other tasks can be added in the derived classes
+
+ /*
+ *
+ *
+ * MINECART
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Riding_Minecart ) )
+ {
+ addTask(e_Tutorial_State_Riding_Minecart, new ChoiceTask(this, IDS_TUTORIAL_TASK_MINECART_OVERVIEW, IDS_TUTORIAL_PROMPT_MINECART_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Minecart) );
+ addTask(e_Tutorial_State_Riding_Minecart, new InfoTask(this, IDS_TUTORIAL_TASK_MINECART_RAILS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Riding_Minecart, new InfoTask(this, IDS_TUTORIAL_TASK_MINECART_POWERED_RAILS, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Riding_Minecart, new InfoTask(this, IDS_TUTORIAL_TASK_MINECART_PUSHING, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+
+ /*
+ *
+ *
+ * BOAT
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Riding_Boat ) )
+ {
+ addTask(e_Tutorial_State_Riding_Boat, new ChoiceTask(this, IDS_TUTORIAL_TASK_BOAT_OVERVIEW, IDS_TUTORIAL_PROMPT_BOAT_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Boat) );
+ addTask(e_Tutorial_State_Riding_Boat, new InfoTask(this, IDS_TUTORIAL_TASK_BOAT_STEER, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+
+ /*
+ *
+ *
+ * FISHING
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Fishing ) )
+ {
+ addTask(e_Tutorial_State_Fishing, new ChoiceTask(this, IDS_TUTORIAL_TASK_FISHING_OVERVIEW, IDS_TUTORIAL_PROMPT_FISHING_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Fishing) );
+ addTask(e_Tutorial_State_Fishing, new InfoTask(this, IDS_TUTORIAL_TASK_FISHING_CAST, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Fishing, new InfoTask(this, IDS_TUTORIAL_TASK_FISHING_FISH, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Fishing, new InfoTask(this, IDS_TUTORIAL_TASK_FISHING_USES, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+
+ /*
+ *
+ *
+ * BED
+ *
+ */
+ if(isFullTutorial || !isStateCompleted( e_Tutorial_State_Bed ) )
+ {
+ addTask(e_Tutorial_State_Bed, new ChoiceTask(this, IDS_TUTORIAL_TASK_BED_OVERVIEW, IDS_TUTORIAL_PROMPT_BED_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_Bed) );
+ addTask(e_Tutorial_State_Bed, new InfoTask(this, IDS_TUTORIAL_TASK_BED_PLACEMENT, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Bed, new InfoTask(this, IDS_TUTORIAL_TASK_BED_MULTIPLAYER, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+
+ /*
+ *
+ *
+ * FOOD BAR
+ *
+ */
+ if(!isFullTutorial && !isStateCompleted( e_Tutorial_State_Food_Bar ) )
+ {
+ addTask(e_Tutorial_State_Food_Bar, new ChoiceTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_OVERVIEW, IDS_TUTORIAL_PROMPT_FOOD_BAR_OVERVIEW, true, ACTION_MENU_A, ACTION_MENU_B, e_Tutorial_Completion_Complete_State_Gameplay_Constraints, eTelemetryTutorial_FoodBar) );
+ addTask(e_Tutorial_State_Food_Bar, new InfoTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_DEPLETE, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Food_Bar, new InfoTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_HEAL, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ addTask(e_Tutorial_State_Food_Bar, new InfoTask(this, IDS_TUTORIAL_TASK_FOOD_BAR_FEED, IDS_TUTORIAL_PROMPT_PRESS_A_TO_CONTINUE, true, ACTION_MENU_A) );
+ }
+}
+
+Tutorial::~Tutorial()
+{
+ for(AUTO_VAR(it, m_globalConstraints.begin()); it != m_globalConstraints.end(); ++it)
+ {
+ delete (*it);
+ }
+ for(unordered_map<int, TutorialMessage *>::iterator it = messages.begin(); it != messages.end(); ++it)
+ {
+ delete (*it).second;
+ }
+ for(unsigned int i = 0; i < e_Tutorial_State_Max; ++i)
+ {
+ for(AUTO_VAR(it, activeTasks[i].begin()); it < activeTasks[i].end(); ++it)
+ {
+ delete (*it);
+ }
+ for(AUTO_VAR(it, hints[i].begin()); it < hints[i].end(); ++it)
+ {
+ delete (*it);
+ }
+
+ currentTask[i] = NULL;
+ currentFailedConstraint[i] = NULL;
+ }
+}
+
+void Tutorial::debugResetPlayerSavedProgress(int iPad)
+{
+#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
+ GAME_SETTINGS *pGameSettings = (GAME_SETTINGS *)StorageManager.GetGameDefinedProfileData(iPad);
+#else
+ GAME_SETTINGS *pGameSettings = (GAME_SETTINGS *)ProfileManager.GetGameDefinedProfileData(iPad);
+#endif
+ ZeroMemory( pGameSettings->ucTutorialCompletion, TUTORIAL_PROFILE_STORAGE_BYTES );
+ pGameSettings->uiSpecialTutorialBitmask = 0;
+}
+
+void Tutorial::setCompleted( int completableId )
+{
+ //if(app.GetGameSettingsDebugMask(m_iPad) && app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_TipsAlwaysOn))
+ //{
+ // return;
+ //}
+
+
+ int completableIndex = -1;
+ for( AUTO_VAR(it, s_completableTasks.begin()); it < s_completableTasks.end(); ++it)
+ {
+ ++completableIndex;
+ if( *it == completableId )
+ {
+ break;
+ }
+ }
+ if( completableIndex >= 0 && completableIndex < TUTORIAL_PROFILE_STORAGE_BITS )
+ {
+ // Set the bit for this position
+#if (defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
+ GAME_SETTINGS *pGameSettings = (GAME_SETTINGS *)StorageManager.GetGameDefinedProfileData(m_iPad);
+#else
+ GAME_SETTINGS *pGameSettings = (GAME_SETTINGS *)ProfileManager.GetGameDefinedProfileData(m_iPad);
+#endif
+ int arrayIndex = completableIndex >> 3;
+ int bitIndex = 7 - (completableIndex % 8);
+ pGameSettings->ucTutorialCompletion[arrayIndex] |= 1<<bitIndex;
+ // flag a profile write needed
+ pGameSettings->bSettingsChanged=true;
+ }
+}
+
+bool Tutorial::getCompleted( int completableId )
+{
+ //if(app.GetGameSettingsDebugMask(m_iPad) && app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_TipsAlwaysOn))
+ //{
+ // return false;
+ //}
+
+ int completableIndex = -1;
+ for( AUTO_VAR(it, s_completableTasks.begin()); it < s_completableTasks.end(); ++it)
+ {
+ ++completableIndex;
+ if( *it == completableId )
+ {
+ break;
+ }
+ }
+ if( completableIndex >= 0 && completableIndex < TUTORIAL_PROFILE_STORAGE_BITS )
+ {
+ // Read the bit for this position
+ //Retrieve the data pointer from the profile
+#if ( defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__)
+ GAME_SETTINGS *pGameSettings = (GAME_SETTINGS *)StorageManager.GetGameDefinedProfileData(m_iPad);
+#else
+ GAME_SETTINGS *pGameSettings = (GAME_SETTINGS *)ProfileManager.GetGameDefinedProfileData(m_iPad);
+#endif
+ int arrayIndex = completableIndex >> 3;
+ int bitIndex = 7 - (completableIndex % 8);
+ return (pGameSettings->ucTutorialCompletion[arrayIndex] & 1<<bitIndex) == (1<<bitIndex);
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool Tutorial::isStateCompleted( eTutorial_State state )
+{
+ return getCompleted(state);
+}
+
+void Tutorial::setStateCompleted( eTutorial_State state )
+{
+ setCompleted( state );
+}
+
+bool Tutorial::isHintCompleted( eTutorial_Hint hint )
+{
+ return getCompleted(hint);
+}
+
+void Tutorial::setHintCompleted( eTutorial_Hint hint )
+{
+ //if(app.GetGameSettingsDebugMask(m_iPad) && app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_TipsAlwaysOn))
+ //{
+ // return;
+ //}
+
+ setCompleted( hint );
+}
+
+void Tutorial::setHintCompleted( TutorialHint *hint )
+{
+ //if(app.GetGameSettingsDebugMask(m_iPad) && app.GetGameSettingsDebugMask()&(1L<<eDebugSetting_TipsAlwaysOn))
+ //{
+ // return;
+ //}
+
+ eTutorial_Hint hintId = hint->getId();
+
+ if( hintId != e_Tutorial_Hint_Always_On )
+ {
+ setHintCompleted( hint->getId() );
+ hints[m_CurrentState].erase( find(hints[m_CurrentState].begin(), hints[m_CurrentState].end(), hint) );
+ delete hint;
+ }
+ // else
+ // {
+ // find(hints[m_CurrentState].begin(), hints[m_CurrentState].end(), hint);
+ // }
+}
+
+void Tutorial::tick()
+{
+ // Don't do anything for the first 2 seconds so that the loading screen is gone
+ if(!m_bHasTickedOnce)
+ {
+ int time = GetTickCount();
+ if(m_firstTickTime == 0)
+ {
+ m_firstTickTime = time;
+ }
+ else if ( time - m_firstTickTime > 1500 )
+ {
+ m_bHasTickedOnce = true;
+ }
+ }
+ if(!m_bHasTickedOnce)
+ {
+ return;
+ }
+
+ bool constraintChanged = false;
+ bool taskChanged = false;
+
+ for(unsigned int state = 0; state < e_Tutorial_State_Max; ++state)
+ {
+ AUTO_VAR(it, constraintsToRemove[state].begin());
+ while(it < constraintsToRemove[state].end() )
+ {
+ ++(*it).second;
+ if( (*it).second > m_iTutorialConstraintDelayRemoveTicks )
+ {
+ TutorialConstraint *c = (*it).first;
+ constraints[state].erase( find( constraints[state].begin(), constraints[state].end(), c) );
+ c->setQueuedForRemoval(false);
+ it = constraintsToRemove[state].erase( it );
+
+ if( c->getDeleteOnDeactivate() )
+ {
+ delete c;
+ }
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ }
+
+ // 4J Stu TODO - Make this a constraint
+ Minecraft *pMinecraft = Minecraft::GetInstance();
+ if(m_freezeTime && !m_timeFrozen && !m_fullTutorialComplete )
+ {
+ // Need to set the time on both levels to stop the flickering as the local level
+ // tries to predict the time
+ MinecraftServer::SetTimeOfDay(m_iTutorialFreezeTimeValue);
+ pMinecraft->level->setOverrideTimeOfDay(m_iTutorialFreezeTimeValue); // Always daytime
+ m_timeFrozen = true;
+ }
+ else if(m_freezeTime && m_timeFrozen && m_fullTutorialComplete)
+ {
+ __int64 currentTime = pMinecraft->level->getTime();
+ int currentDayTime = (currentTime % Level::TICKS_PER_DAY);
+ int timeToAdd = 0;
+ if(currentDayTime > m_iTutorialFreezeTimeValue)
+ {
+ timeToAdd = (Level::TICKS_PER_DAY - currentDayTime) + m_iTutorialFreezeTimeValue;
+ }
+ else
+ {
+ timeToAdd = m_iTutorialFreezeTimeValue - currentDayTime;
+ }
+ __int64 targetTime = currentTime + timeToAdd;
+ MinecraftServer::SetTimeOfDay(-1);
+ MinecraftServer::SetTime(targetTime);
+ pMinecraft->level->setOverrideTimeOfDay(-1);
+ pMinecraft->level->setTime(targetTime);
+ m_timeFrozen = false;
+ }
+
+ if(!m_allowShow)
+ {
+ if( currentTask[m_CurrentState] != NULL && (!currentTask[m_CurrentState]->AllowFade() || (lastMessageTime + m_iTutorialDisplayMessageTime ) > GetTickCount() ) )
+ {
+ uiTempDisabled = true;
+ }
+ ui.SetTutorialVisible( m_iPad, false );
+ return;
+ }
+
+
+ if(!hasRequestedUI )
+ {
+#ifdef _XBOX
+ m_bSceneIsSplitscreen=app.GetLocalPlayerCount()>1;
+ if(m_bSceneIsSplitscreen)
+ {
+ app.NavigateToScene(m_iPad, eUIComponent_TutorialPopup,(void *)this, false, false, &m_hTutorialScene);
+ }
+ else
+ {
+ app.NavigateToScene(m_iPad, eUIComponent_TutorialPopup,(void *)this, false, false, &m_hTutorialScene);
+ }
+#else
+ ui.SetTutorial(m_iPad, this);
+#endif
+ hasRequestedUI = true;
+ }
+ else
+ {
+ // if we've changed mode, we may need to change scene
+ if(m_bSceneIsSplitscreen!=(app.GetLocalPlayerCount()>1))
+ {
+#ifdef _XBOX
+ app.TutorialSceneNavigateBack(m_iPad);
+ m_bSceneIsSplitscreen=app.GetLocalPlayerCount()>1;
+ if(m_bSceneIsSplitscreen)
+ {
+ app.NavigateToScene(m_iPad, eUIComponent_TutorialPopup,(void *)this, false, false, &m_hTutorialScene);
+ }
+ else
+ {
+ app.NavigateToScene(m_iPad, eUIComponent_TutorialPopup,(void *)this, false, false, &m_hTutorialScene);
+ }
+#else
+ ui.SetTutorial(m_iPad, this);
+#endif
+ }
+ }
+
+ if(ui.IsPauseMenuDisplayed( m_iPad ) )
+ {
+ if( currentTask[m_CurrentState] != NULL && (!currentTask[m_CurrentState]->AllowFade() || (lastMessageTime + m_iTutorialDisplayMessageTime ) > GetTickCount() ) )
+ {
+ uiTempDisabled = true;
+ }
+ ui.SetTutorialVisible( m_iPad, false );
+ return;
+ }
+ if( uiTempDisabled )
+ {
+ ui.SetTutorialVisible( m_iPad, true );
+ lastMessageTime = GetTickCount();
+ uiTempDisabled = false;
+ }
+
+ // Check constraints
+ for(AUTO_VAR(it, m_globalConstraints.begin()); it < m_globalConstraints.end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ constraint->tick(m_iPad);
+ }
+
+ // Check hints
+ int hintNeeded = -1;
+ if(!m_hintDisplayed)
+ {
+ // 4J Stu - TU-1 interim
+ // Allow turning off all the hints
+ bool hintsOn = m_isFullTutorial || app.GetGameSettings(m_iPad,eGameSetting_Hints);
+
+ if(hintsOn)
+ {
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->tick();
+ if(hintNeeded >= 0)
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = hintNeeded;
+ message->m_allowFade = hint->allowFade();
+ message->m_forceDisplay = true;
+ setMessage( hint, message );
+ break;
+ }
+ }
+ }
+ }
+
+ // Check constraints
+ // Only need to update these if we aren't already failing something
+ if( !m_allTutorialsComplete && (currentFailedConstraint[m_CurrentState] == NULL || currentFailedConstraint[m_CurrentState]->isConstraintSatisfied(m_iPad)) )
+ {
+ if( currentFailedConstraint[m_CurrentState] != NULL && currentFailedConstraint[m_CurrentState]->isConstraintSatisfied(m_iPad) )
+ {
+ constraintChanged = true;
+ currentFailedConstraint[m_CurrentState] = NULL;
+ }
+ for(AUTO_VAR(it, constraints[m_CurrentState].begin()); it < constraints[m_CurrentState].end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ if( !constraint->isConstraintSatisfied(m_iPad) && constraint->isConstraintRestrictive(m_iPad) )
+ {
+ constraintChanged = true;
+ currentFailedConstraint[m_CurrentState] = constraint;
+ }
+ }
+ }
+
+ if( !m_allTutorialsComplete && currentFailedConstraint[m_CurrentState] == NULL )
+ {
+ // Update tasks
+ bool isCurrentTask = true;
+ AUTO_VAR(it, activeTasks[m_CurrentState].begin());
+ while(activeTasks[m_CurrentState].size() > 0 && it < activeTasks[m_CurrentState].end())
+ {
+ TutorialTask *task = *it;
+ if( isCurrentTask || task->isPreCompletionEnabled() )
+ {
+ isCurrentTask = false;
+ if(
+ ( !task->ShowMinimumTime() || ( task->hasBeenActivated() && (lastMessageTime + m_iTutorialMinimumDisplayMessageTime ) < GetTickCount() ) )
+ && task->isCompleted()
+ )
+ {
+ eTutorial_CompletionAction compAction = task->getCompletionAction();
+ it = activeTasks[m_CurrentState].erase( it );
+ delete task;
+ task = NULL;
+
+ if( activeTasks[m_CurrentState].size() > 0 )
+ {
+ switch( compAction )
+ {
+ case e_Tutorial_Completion_Complete_State_Gameplay_Constraints:
+ {
+ // 4J Stu - Move the delayed constraints to the gameplay state so that they are in
+ // effect for a bit longer
+ AUTO_VAR(itCon, constraintsToRemove[m_CurrentState].begin());
+ while(itCon != constraintsToRemove[m_CurrentState].end() )
+ {
+ constraints[e_Tutorial_State_Gameplay].push_back(itCon->first);
+ constraintsToRemove[e_Tutorial_State_Gameplay].push_back( pair<TutorialConstraint *, unsigned char>(itCon->first, itCon->second) );
+
+ constraints[m_CurrentState].erase( find( constraints[m_CurrentState].begin(), constraints[m_CurrentState].end(), itCon->first) );
+ itCon = constraintsToRemove[m_CurrentState].erase(itCon);
+ }
+ }
+ // Fall through the the normal complete state
+ case e_Tutorial_Completion_Complete_State:
+ for(AUTO_VAR(itRem, activeTasks[m_CurrentState].begin()); itRem < activeTasks[m_CurrentState].end(); ++itRem)
+ {
+ delete (*itRem);
+ }
+ activeTasks[m_CurrentState].clear();
+ break;
+ case e_Tutorial_Completion_Jump_To_Last_Task:
+ {
+ TutorialTask *lastTask = activeTasks[m_CurrentState].at( activeTasks[m_CurrentState].size() - 1 );
+ activeTasks[m_CurrentState].pop_back();
+ for(AUTO_VAR(itRem, activeTasks[m_CurrentState].begin()); itRem < activeTasks[m_CurrentState].end(); ++itRem)
+ {
+ delete (*itRem);
+ }
+ activeTasks[m_CurrentState].clear();
+ activeTasks[m_CurrentState].push_back( lastTask );
+ it = activeTasks[m_CurrentState].begin();
+ }
+ break;
+ case e_Tutorial_Completion_None:
+ default:
+ break;
+ }
+ }
+
+ if( activeTasks[m_CurrentState].size() > 0 )
+ {
+ currentTask[m_CurrentState] = activeTasks[m_CurrentState][0];
+ currentTask[m_CurrentState]->setAsCurrentTask();
+ }
+ else
+ {
+ setStateCompleted( m_CurrentState );
+
+ currentTask[m_CurrentState] = NULL;
+ }
+ taskChanged = true;
+
+ // If we can complete this early, check if we can complete it right now
+ if( currentTask[m_CurrentState] != NULL && currentTask[m_CurrentState]->isPreCompletionEnabled() )
+ {
+ isCurrentTask = true;
+ }
+ }
+ else
+ {
+ ++it;
+ }
+ if( task != NULL && task->ShowMinimumTime() && task->hasBeenActivated() && (lastMessageTime + m_iTutorialMinimumDisplayMessageTime ) < GetTickCount() )
+ {
+ task->setShownForMinimumTime();
+
+ if( !m_hintDisplayed )
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = task->getDescriptionId();
+ message->m_promptId = task->getPromptId();
+ message->m_allowFade = task->AllowFade();
+ message->m_replaceCurrent = true;
+ setMessage( message );
+ }
+ }
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ if( currentTask[m_CurrentState] == NULL && activeTasks[m_CurrentState].size() > 0 )
+ {
+ currentTask[m_CurrentState] = activeTasks[m_CurrentState][0];
+ currentTask[m_CurrentState]->setAsCurrentTask();
+ taskChanged = true;
+ }
+ }
+
+ if(!m_allTutorialsComplete && (taskChanged || m_hasStateChanged) )
+ {
+ bool allComplete = true;
+ for(unsigned int state = 0; state < e_Tutorial_State_Max; ++state)
+ {
+ if(activeTasks[state].size() > 0 )
+ {
+ allComplete = false;
+ break;
+ }
+ if(state==e_Tutorial_State_Gameplay)
+ {
+ m_fullTutorialComplete = true;
+ Minecraft::GetInstance()->playerLeftTutorial(m_iPad);
+ }
+ }
+ if(allComplete)
+ m_allTutorialsComplete = true;
+ }
+
+ if( constraintChanged || taskChanged || m_hasStateChanged ||
+ (currentFailedConstraint[m_CurrentState] == NULL && currentTask[m_CurrentState] != NULL && (m_lastMessage == NULL || currentTask[m_CurrentState]->getDescriptionId() != m_lastMessage->m_messageId) && !m_hintDisplayed)
+ )
+ {
+ if( currentFailedConstraint[m_CurrentState] != NULL )
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = currentFailedConstraint[m_CurrentState]->getDescriptionId();
+ message->m_allowFade = false;
+ setMessage( message );
+ }
+ else if( currentTask[m_CurrentState] != NULL )
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = currentTask[m_CurrentState]->getDescriptionId();
+ message->m_promptId = currentTask[m_CurrentState]->getPromptId();
+ message->m_allowFade = currentTask[m_CurrentState]->AllowFade();
+ setMessage( message );
+ currentTask[m_CurrentState]->TaskReminders()? m_iTaskReminders = 1 : m_iTaskReminders = 0;
+ }
+ else
+ {
+ setMessage( NULL );
+ }
+ }
+
+ if(m_hintDisplayed && (lastMessageTime + m_iTutorialDisplayMessageTime ) < GetTickCount() )
+ {
+ m_hintDisplayed = false;
+ }
+
+ if( currentFailedConstraint[m_CurrentState] == NULL && currentTask[m_CurrentState] != NULL && (m_iTaskReminders!=0) && (lastMessageTime + (m_iTaskReminders * m_iTutorialReminderTime) ) < GetTickCount() )
+ {
+ // Reminder
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = currentTask[m_CurrentState]->getDescriptionId();
+ message->m_promptId = currentTask[m_CurrentState]->getPromptId();
+ message->m_allowFade = currentTask[m_CurrentState]->AllowFade();
+ message->m_isReminder = true;
+ setMessage( message );
+ ++m_iTaskReminders;
+ if( m_iTaskReminders > 1 )
+ m_iTaskReminders = 1;
+ }
+
+ m_hasStateChanged = false;
+
+ // If we have completed this state, and it is one that occurs during normal gameplay then change back to the gameplay track
+ if( m_CurrentState != e_Tutorial_State_Gameplay && activeTasks[m_CurrentState].size() == 0 && (isSelectedItemState() || !ui.GetMenuDisplayed(m_iPad) ) )
+ {
+ this->changeTutorialState( e_Tutorial_State_Gameplay );
+ }
+}
+
+bool Tutorial::setMessage(PopupMessageDetails *message)
+{
+ if(message != NULL && !message->m_forceDisplay &&
+ m_lastMessageState == m_CurrentState &&
+ message->isSameContent(m_lastMessage) &&
+ ( !message->m_isReminder || ( (lastMessageTime + m_iTutorialReminderTime ) > GetTickCount() && message->m_isReminder ) )
+ )
+ {
+ delete message;
+ return false;
+ }
+
+ if(message != NULL && (message->m_messageId > 0 || !message->m_messageString.empty()) )
+ {
+ m_lastMessageState = m_CurrentState;
+
+ if(!message->m_replaceCurrent) lastMessageTime = GetTickCount();
+
+ wstring text;
+ if(!message->m_messageString.empty())
+ {
+ text = message->m_messageString;
+ }
+ else
+ {
+ AUTO_VAR(it, messages.find(message->m_messageId));
+ if( it != messages.end() && it->second != NULL )
+ {
+ TutorialMessage *messageString = it->second;
+ text = wstring( messageString->getMessageForDisplay() );
+ }
+ else
+ {
+ text = wstring( app.GetString(message->m_messageId) );
+ }
+ }
+
+ if(!message->m_promptString.empty())
+ {
+ text.append(message->m_promptString);
+ }
+ else if(message->m_promptId >= 0)
+ {
+ AUTO_VAR(it, messages.find(message->m_promptId));
+ if(it != messages.end() && it->second != NULL)
+ {
+ TutorialMessage *prompt = it->second;
+ text.append( prompt->getMessageForDisplay() );
+ }
+ }
+
+ wstring title;
+ TutorialPopupInfo popupInfo;
+ popupInfo.interactScene = m_UIScene;
+ popupInfo.desc = text.c_str();
+ popupInfo.icon = message->m_icon;
+ popupInfo.iAuxVal = message->m_iAuxVal;
+ popupInfo.allowFade = message->m_allowFade;
+ popupInfo.isReminder = message->m_isReminder;
+ popupInfo.tutorial = this;
+ if( !message->m_titleString.empty() || message->m_titleId > 0 )
+ {
+ if(message->m_titleString.empty()) title = wstring( app.GetString(message->m_titleId) );
+ else title = message->m_titleString;
+
+ popupInfo.title = title.c_str();
+ ui.SetTutorialDescription( m_iPad, &popupInfo );
+ }
+ else
+ {
+ ui.SetTutorialDescription( m_iPad, &popupInfo );
+ }
+ }
+ else if( (m_lastMessage != NULL && m_lastMessage->m_messageId != -1) ) //&& (lastMessageTime + m_iTutorialReminderTime ) > GetTickCount() )
+ {
+ // This should cause the popup to dissappear
+ TutorialPopupInfo popupInfo;
+ popupInfo.interactScene = m_UIScene;
+ popupInfo.tutorial = this;
+ ui.SetTutorialDescription( m_iPad, &popupInfo );
+ }
+
+ if(m_lastMessage != NULL) delete m_lastMessage;
+ m_lastMessage = message;
+
+ return true;
+}
+
+bool Tutorial::setMessage(TutorialHint *hint, PopupMessageDetails *message)
+{
+ // 4J Stu - TU-1 interim
+ // Allow turning off all the hints
+ bool hintsOn = m_isFullTutorial || (app.GetGameSettings(m_iPad,eGameSetting_Hints) && app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD));
+
+ bool messageShown = false;
+ DWORD time = GetTickCount();
+ if(message != NULL && (message->m_forceDisplay || hintsOn) &&
+ (!message->m_delay ||
+ (
+ (m_hintDisplayed && (time - m_lastHintDisplayedTime) > m_iTutorialHintDelayTime ) ||
+ (!m_hintDisplayed && (time - lastMessageTime) > m_iTutorialMinimumDisplayMessageTime )
+ )
+ )
+ )
+ {
+ messageShown = setMessage( message );
+
+ if(messageShown)
+ {
+ m_lastHintDisplayedTime = time;
+ m_hintDisplayed = true;
+ if(hint!=NULL) setHintCompleted( hint );
+ }
+ }
+ return messageShown;
+}
+
+bool Tutorial::setMessage(const wstring &messageString, int icon, int auxValue)
+{
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageString = messageString;
+ message->m_icon = icon;
+ message->m_iAuxVal = auxValue;
+ message->m_forceDisplay = true;
+
+ return setMessage(message);
+}
+
+void Tutorial::showTutorialPopup(bool show)
+{
+ m_allowShow = show;
+
+ if(!show)
+ {
+ if( currentTask[m_CurrentState] != NULL && (!currentTask[m_CurrentState]->AllowFade() || (lastMessageTime + m_iTutorialDisplayMessageTime ) > GetTickCount() ) )
+ {
+ uiTempDisabled = true;
+ }
+ ui.SetTutorialVisible( m_iPad, show );
+ }
+}
+
+void Tutorial::useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z, bool bTestUseOnly)
+{
+ for(AUTO_VAR(it, activeTasks[m_CurrentState].begin()); it < activeTasks[m_CurrentState].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->useItemOn(level, item, x, y, z, bTestUseOnly);
+ }
+}
+
+void Tutorial::useItemOn(shared_ptr<ItemInstance> item, bool bTestUseOnly)
+{
+ for(AUTO_VAR(it, activeTasks[m_CurrentState].begin()); it < activeTasks[m_CurrentState].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->useItem(item, bTestUseOnly);
+ }
+}
+
+void Tutorial::completeUsingItem(shared_ptr<ItemInstance> item)
+{
+ for(AUTO_VAR(it, activeTasks[m_CurrentState].begin()); it < activeTasks[m_CurrentState].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->completeUsingItem(item);
+ }
+
+ // Fix for #46922 - TU5: UI: Player receives a reminder that he is hungry while "hunger bar" is full (triggered in split-screen mode)
+ if(m_CurrentState != e_Tutorial_State_Gameplay)
+ {
+ for(AUTO_VAR(it, activeTasks[e_Tutorial_State_Gameplay].begin()); it < activeTasks[e_Tutorial_State_Gameplay].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->completeUsingItem(item);
+ }
+ }
+}
+
+void Tutorial::startDestroyBlock(shared_ptr<ItemInstance> item, Tile *tile)
+{
+ int hintNeeded = -1;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->startDestroyBlock(item, tile);
+ if(hintNeeded >= 0)
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = hintNeeded;
+ setMessage( hint, message );
+ break;
+ }
+
+ }
+}
+
+void Tutorial::destroyBlock(Tile *tile)
+{
+ int hintNeeded = -1;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->destroyBlock(tile);
+ if(hintNeeded >= 0)
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = hintNeeded;
+ setMessage( hint, message );
+ break;
+ }
+
+ }
+}
+
+void Tutorial::attack(shared_ptr<Player> player, shared_ptr<Entity> entity)
+{
+ int hintNeeded = -1;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->attack(player->inventory->getSelected(), entity);
+ if(hintNeeded >= 0)
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = hintNeeded;
+ setMessage( hint, message );
+ break;
+ }
+
+ }
+}
+
+void Tutorial::itemDamaged(shared_ptr<ItemInstance> item)
+{
+ int hintNeeded = -1;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->itemDamaged(item);
+ if(hintNeeded >= 0)
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = hintNeeded;
+ setMessage( hint, message );
+ break;
+ }
+
+ }
+}
+
+void Tutorial::handleUIInput(int iAction)
+{
+ if( m_hintDisplayed ) return;
+
+ //for(AUTO_VAR(it, activeTasks[m_CurrentState].begin()); it < activeTasks[m_CurrentState].end(); ++it)
+ //{
+ // TutorialTask *task = *it;
+ // task->handleUIInput(iAction);
+ //}
+ if(currentTask[m_CurrentState] != NULL)
+ currentTask[m_CurrentState]->handleUIInput(iAction);
+}
+
+void Tutorial::createItemSelected(shared_ptr<ItemInstance> item, bool canMake)
+{
+ int hintNeeded = -1;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->createItemSelected(item, canMake);
+ if(hintNeeded >= 0)
+ {
+ PopupMessageDetails *message = new PopupMessageDetails();
+ message->m_messageId = hintNeeded;
+ setMessage( hint, message );
+ break;
+ }
+
+ }
+}
+
+void Tutorial::onCrafted(shared_ptr<ItemInstance> item)
+{
+ for(unsigned int state = 0; state < e_Tutorial_State_Max; ++state)
+ {
+ for(AUTO_VAR(it, activeTasks[state].begin()); it < activeTasks[state].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->onCrafted(item);
+ }
+ }
+}
+
+void Tutorial::onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux)
+{
+ if( !m_hintDisplayed )
+ {
+ bool hintNeeded = false;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->onTake(item);
+ if(hintNeeded)
+ {
+ break;
+ }
+
+ }
+ }
+
+ for(unsigned int state = 0; state < e_Tutorial_State_Max; ++state)
+ {
+ for(AUTO_VAR(it, activeTasks[state].begin()); it < activeTasks[state].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->onTake(item, invItemCountAnyAux, invItemCountThisAux);
+ }
+ }
+}
+
+void Tutorial::onSelectedItemChanged(shared_ptr<ItemInstance> item)
+{
+ // We only handle this if we are in a state that allows changing based on the selected item
+ // Menus and states like riding in a minecart will NOT allow this
+ if( isSelectedItemState() )
+ {
+ if(item != NULL)
+ {
+ switch(item->id)
+ {
+ case Item::fishingRod_Id:
+ changeTutorialState(e_Tutorial_State_Fishing);
+ break;
+ default:
+ changeTutorialState(e_Tutorial_State_Gameplay);
+ break;
+ }
+ }
+ else
+ {
+ changeTutorialState(e_Tutorial_State_Gameplay);
+ }
+ }
+}
+
+void Tutorial::onLookAt(int id, int iData)
+{
+ if( m_hintDisplayed ) return;
+
+ bool hintNeeded = false;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->onLookAt(id, iData);
+ if(hintNeeded)
+ {
+ break;
+ }
+ }
+
+ if( m_CurrentState == e_Tutorial_State_Gameplay )
+ {
+ if(id > 0)
+ {
+ switch(id)
+ {
+ case Tile::bed_Id:
+ changeTutorialState(e_Tutorial_State_Bed);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void Tutorial::onLookAtEntity(eINSTANCEOF type)
+{
+ if( m_hintDisplayed ) return;
+
+ bool hintNeeded = false;
+ for(AUTO_VAR(it, hints[m_CurrentState].begin()); it < hints[m_CurrentState].end(); ++it)
+ {
+ TutorialHint *hint = *it;
+ hintNeeded = hint->onLookAtEntity(type);
+ if(hintNeeded)
+ {
+ break;
+ }
+ }
+}
+
+void Tutorial::onEffectChanged(MobEffect *effect, bool bRemoved)
+{
+ for(AUTO_VAR(it, activeTasks[m_CurrentState].begin()); it < activeTasks[m_CurrentState].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->onEffectChanged(effect,bRemoved);
+ }
+}
+
+bool Tutorial::canMoveToPosition(double xo, double yo, double zo, double xt, double yt, double zt)
+{
+ bool allowed = true;
+ for(AUTO_VAR(it, constraints[m_CurrentState].begin()); it < constraints[m_CurrentState].end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ if( !constraint->isConstraintSatisfied(m_iPad) && !constraint->canMoveToPosition(xo,yo,zo,xt,yt,zt) )
+ {
+ allowed = false;
+ break;
+ }
+ }
+ return allowed;
+}
+
+bool Tutorial::isInputAllowed(int mapping)
+{
+ if( m_hintDisplayed ) return true;
+
+ // If the player is under water then allow all keypresses so they can jump out
+ if( Minecraft::GetInstance()->localplayers[m_iPad]->isUnderLiquid(Material::water) ) return true;
+
+ bool allowed = true;
+ for(AUTO_VAR(it, constraints[m_CurrentState].begin()); it < constraints[m_CurrentState].end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ if( constraint->isMappingConstrained( m_iPad, mapping ) )
+ {
+ allowed = false;
+ break;
+ }
+ }
+ return allowed;
+}
+
+vector<TutorialTask *> *Tutorial::getTasks()
+{
+ return &tasks;
+}
+
+unsigned int Tutorial::getCurrentTaskIndex()
+{
+ unsigned int index = 0;
+ for(AUTO_VAR(it, tasks.begin()); it < tasks.end(); ++it)
+ {
+ if(*it == currentTask[e_Tutorial_State_Gameplay])
+ break;
+
+ ++index;
+ }
+ return index;
+}
+
+void Tutorial::AddGlobalConstraint(TutorialConstraint *c)
+{
+ m_globalConstraints.push_back(c);
+}
+
+void Tutorial::AddConstraint(TutorialConstraint *c)
+{
+ constraints[m_CurrentState].push_back(c);
+}
+
+void Tutorial::RemoveConstraint(TutorialConstraint *c, bool delayedRemove /*= false*/)
+{
+ if( currentFailedConstraint[m_CurrentState] == c )
+ currentFailedConstraint[m_CurrentState] = NULL;
+
+ if( c->getQueuedForRemoval() )
+ {
+ // If it is already queued for removal, remove it on the next tick
+ /*for(AUTO_VAR(it, constraintsToRemove[m_CurrentState].begin()); it < constraintsToRemove[m_CurrentState].end(); ++it)
+ {
+ if( it->first == c )
+ {
+ it->second = m_iTutorialConstraintDelayRemoveTicks;
+ break;
+ }
+ }*/
+ }
+ else if(delayedRemove)
+ {
+ c->setQueuedForRemoval(true);
+ constraintsToRemove[m_CurrentState].push_back( pair<TutorialConstraint *, unsigned char>(c, 0) );
+ }
+ else
+ {
+ for( AUTO_VAR(it, constraintsToRemove[m_CurrentState].begin()); it < constraintsToRemove[m_CurrentState].end(); ++it)
+ {
+ if( it->first == c )
+ {
+ constraintsToRemove[m_CurrentState].erase( it );
+ break;
+ }
+ }
+
+ AUTO_VAR(it, find( constraints[m_CurrentState].begin(), constraints[m_CurrentState].end(), c));
+ if( it != constraints[m_CurrentState].end() ) constraints[m_CurrentState].erase( find( constraints[m_CurrentState].begin(), constraints[m_CurrentState].end(), c) );
+
+ // It may be in the gameplay list, so remove it from there if it is
+ it = find( constraints[e_Tutorial_State_Gameplay].begin(), constraints[e_Tutorial_State_Gameplay].end(), c);
+ if( it != constraints[e_Tutorial_State_Gameplay].end() ) constraints[e_Tutorial_State_Gameplay].erase( find( constraints[e_Tutorial_State_Gameplay].begin(), constraints[e_Tutorial_State_Gameplay].end(), c) );
+ }
+}
+
+void Tutorial::addTask(eTutorial_State state, TutorialTask *t)
+{
+ if( state == e_Tutorial_State_Gameplay )
+ {
+ tasks.push_back(t);
+ }
+ activeTasks[state].push_back(t);
+}
+
+void Tutorial::addHint(eTutorial_State state, TutorialHint *h)
+{
+ hints[state].push_back(h);
+}
+
+void Tutorial::addMessage(int messageId, bool limitRepeats /*= false*/, unsigned char numRepeats /*= TUTORIAL_MESSAGE_DEFAULT_SHOW*/)
+{
+ if(messageId >= 0 && messages.find(messageId)==messages.end())
+ messages[messageId] = new TutorialMessage(messageId, limitRepeats, numRepeats);
+}
+
+#ifdef _XBOX
+void Tutorial::changeTutorialState(eTutorial_State newState, CXuiScene *scene /*= NULL*/)
+#else
+void Tutorial::changeTutorialState(eTutorial_State newState, UIScene *scene /*= NULL*/)
+#endif
+{
+ if(newState == m_CurrentState)
+ {
+ // If clearing the scene, make sure that the tutorial popup has its reference to this scene removed
+#ifndef _XBOX
+ if( scene == NULL )
+ {
+ ui.RemoveInteractSceneReference(m_iPad, m_UIScene);
+ }
+#endif
+ m_UIScene = scene;
+ return;
+ }
+ // 4J Stu - TU-1 interim
+ // Allow turning off all the hints
+ bool hintsOn = m_isFullTutorial || app.GetGameSettings(m_iPad,eGameSetting_Hints);
+
+ if(hintsOn)
+ {
+ // If we have completed this state, and it is one that occurs during normal gameplay then change back to the gameplay track
+ if( newState != e_Tutorial_State_Gameplay && activeTasks[newState].size() == 0 && !ui.GetMenuDisplayed(m_iPad) )
+ {
+ return;
+ }
+
+ // The action that caused the change of state may also have completed the current task
+ if( currentTask[m_CurrentState] != NULL && currentTask[m_CurrentState]->isCompleted() )
+ {
+ activeTasks[m_CurrentState].erase( find( activeTasks[m_CurrentState].begin(), activeTasks[m_CurrentState].end(), currentTask[m_CurrentState]) );
+
+ if( activeTasks[m_CurrentState].size() > 0 )
+ {
+ currentTask[m_CurrentState] = activeTasks[m_CurrentState][0];
+ currentTask[m_CurrentState]->setAsCurrentTask();
+ }
+ else
+ {
+ currentTask[m_CurrentState] = NULL;
+ }
+ }
+
+ if( currentTask[m_CurrentState] != NULL )
+ {
+ currentTask[m_CurrentState]->onStateChange(newState);
+ }
+
+ // Make sure that the current message is cleared
+ setMessage( NULL );
+
+ // If clearing the scene, make sure that the tutorial popup has its reference to this scene removed
+#ifndef _XBOX
+ if( scene == NULL )
+ {
+ ui.RemoveInteractSceneReference(m_iPad, m_UIScene);
+ }
+#endif
+ m_UIScene = scene;
+
+
+ if( m_CurrentState != newState )
+ {
+ for(AUTO_VAR(it, activeTasks[newState].begin()); it < activeTasks[newState].end(); ++it)
+ {
+ TutorialTask *task = *it;
+ task->onStateChange(newState);
+ }
+ m_CurrentState = newState;
+ m_hasStateChanged = true;
+ m_hintDisplayed = false;
+ }
+ }
+}
+
+bool Tutorial::isSelectedItemState()
+{
+ bool isSelectedItemState = false;
+ switch(m_CurrentState)
+ {
+ case e_Tutorial_State_Gameplay:
+ case e_Tutorial_State_Fishing:
+ isSelectedItemState = true;
+ break;
+ default:
+ break;
+ }
+ return isSelectedItemState;
+}
diff --git a/Minecraft.Client/Common/Tutorial/Tutorial.h b/Minecraft.Client/Common/Tutorial/Tutorial.h
new file mode 100644
index 00000000..aaaaba0a
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/Tutorial.h
@@ -0,0 +1,199 @@
+#pragma once
+using namespace std;
+#include "TutorialTask.h"
+#include "TutorialConstraint.h"
+#include "TutorialHint.h"
+#include "TutorialMessage.h"
+#include "TutorialEnum.h"
+
+// #define TUTORIAL_HINT_DELAY_TIME 14000 // How long we should wait from displaying one hint to the next
+// #define TUTORIAL_DISPLAY_MESSAGE_TIME 7000
+// #define TUTORIAL_MINIMUM_DISPLAY_MESSAGE_TIME 2000
+// #define TUTORIAL_REMINDER_TIME (TUTORIAL_DISPLAY_MESSAGE_TIME + 20000)
+// #define TUTORIAL_CONSTRAINT_DELAY_REMOVE_TICKS 15
+//
+// // 0-24000
+// #define TUTORIAL_FREEZE_TIME_VALUE 8000
+
+class Level;
+class CXuiScene;
+
+class Tutorial
+{
+public:
+ class PopupMessageDetails
+ {
+ public:
+ int m_messageId;
+ int m_promptId;
+ int m_titleId;
+ wstring m_messageString;
+ wstring m_promptString;
+ wstring m_titleString;
+ int m_icon;
+ int m_iAuxVal;
+ bool m_allowFade;
+ bool m_isReminder;
+ bool m_replaceCurrent;
+ bool m_forceDisplay;
+ bool m_delay;
+
+ PopupMessageDetails()
+ {
+ m_messageId = -1;
+ m_promptId = -1;
+ m_titleId = -1;
+ m_messageString = L"";
+ m_promptString = L"";
+ m_titleString = L"";
+ m_icon = TUTORIAL_NO_ICON;
+ m_iAuxVal = 0;
+ m_allowFade = true;
+ m_isReminder = false;
+ m_replaceCurrent = false;
+ m_forceDisplay = false;
+ m_delay = false;
+ }
+
+ bool isSameContent(PopupMessageDetails *other);
+
+ };
+
+private:
+ static int m_iTutorialHintDelayTime;
+ static int m_iTutorialDisplayMessageTime;
+ static int m_iTutorialMinimumDisplayMessageTime;
+ static int m_iTutorialExtraReminderTime;
+ static int m_iTutorialReminderTime;
+ static int m_iTutorialConstraintDelayRemoveTicks;
+ static int m_iTutorialFreezeTimeValue;
+ eTutorial_State m_CurrentState;
+ bool m_hasStateChanged;
+#ifdef _XBOX
+ HXUIOBJ m_hTutorialScene; // to store the popup scene (splitscreen or normal)
+#endif
+ bool m_bSceneIsSplitscreen;
+
+ bool m_bHasTickedOnce;
+ int m_firstTickTime;
+
+protected:
+ unordered_map<int, TutorialMessage *> messages;
+ vector<TutorialConstraint *> m_globalConstraints;
+ vector<TutorialConstraint *> constraints[e_Tutorial_State_Max];
+ vector< pair<TutorialConstraint *, unsigned char> > constraintsToRemove[e_Tutorial_State_Max];
+ vector<TutorialTask *> tasks; // We store a copy of the tasks for the main gameplay tutorial so that we could display an overview menu
+ vector<TutorialTask *> activeTasks[e_Tutorial_State_Max];
+ vector<TutorialHint *> hints[e_Tutorial_State_Max];
+ TutorialTask *currentTask[e_Tutorial_State_Max];
+ TutorialConstraint *currentFailedConstraint[e_Tutorial_State_Max];
+
+ bool m_freezeTime;
+ bool m_timeFrozen;
+ //D3DXVECTOR3 m_OriginalPosition;
+
+public:
+ DWORD lastMessageTime;
+ DWORD m_lastHintDisplayedTime;
+private:
+ PopupMessageDetails *m_lastMessage;
+
+ eTutorial_State m_lastMessageState;
+ unsigned int m_iTaskReminders;
+
+ bool m_allowShow;
+
+public:
+ bool m_hintDisplayed;
+
+private:
+ bool hasRequestedUI;
+ bool uiTempDisabled;
+
+#ifdef _XBOX
+ CXuiScene *m_UIScene;
+#else
+ UIScene *m_UIScene;
+#endif
+
+ int m_iPad;
+public:
+ bool m_allTutorialsComplete;
+ bool m_fullTutorialComplete;
+ bool m_isFullTutorial;
+public:
+ Tutorial(int iPad, bool isFullTutorial = false);
+ ~Tutorial();
+ void tick();
+
+ int getPad() { return m_iPad; }
+
+ virtual bool isStateCompleted( eTutorial_State state );
+ virtual void setStateCompleted( eTutorial_State state );
+ bool isHintCompleted( eTutorial_Hint hint );
+ void setHintCompleted( eTutorial_Hint hint );
+ void setHintCompleted( TutorialHint *hint );
+
+ // completableId will be either a eTutorial_State value or eTutorial_Hint
+ void setCompleted( int completableId );
+ bool getCompleted( int completableId );
+
+#ifdef _XBOX
+ void changeTutorialState(eTutorial_State newState, CXuiScene *scene = NULL);
+#else
+ void changeTutorialState(eTutorial_State newState, UIScene *scene = NULL);
+#endif
+ bool isSelectedItemState();
+
+ bool setMessage(PopupMessageDetails *message);
+ bool setMessage(TutorialHint *hint, PopupMessageDetails *message);
+ bool setMessage(const wstring &message, int icon, int auxValue);
+
+ void showTutorialPopup(bool show);
+
+ void useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z,bool bTestUseOnly=false);
+ void useItemOn(shared_ptr<ItemInstance> item, bool bTestUseOnly=false);
+ void completeUsingItem(shared_ptr<ItemInstance> item);
+ void startDestroyBlock(shared_ptr<ItemInstance> item, Tile *tile);
+ void destroyBlock(Tile *tile);
+ void attack(shared_ptr<Player> player, shared_ptr<Entity> entity);
+ void itemDamaged(shared_ptr<ItemInstance> item);
+
+ void handleUIInput(int iAction);
+ void createItemSelected(shared_ptr<ItemInstance> item, bool canMake);
+ void onCrafted(shared_ptr<ItemInstance> item);
+ void onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux);
+ void onSelectedItemChanged(shared_ptr<ItemInstance> item);
+ void onLookAt(int id, int iData=0);
+ void onLookAtEntity(eINSTANCEOF type);
+ void onEffectChanged(MobEffect *effect, bool bRemoved=false);
+
+ bool canMoveToPosition(double xo, double yo, double zo, double xt, double yt, double zt);
+ bool isInputAllowed(int mapping);
+
+ void AddGlobalConstraint(TutorialConstraint *c);
+ void AddConstraint(TutorialConstraint *c);
+ void RemoveConstraint(TutorialConstraint *c, bool delayedRemove = false);
+ void addTask(eTutorial_State state, TutorialTask *t);
+ void addHint(eTutorial_State state, TutorialHint *h);
+ void addMessage(int messageId, bool limitRepeats = false, unsigned char numRepeats = TUTORIAL_MESSAGE_DEFAULT_SHOW);
+
+ int GetTutorialDisplayMessageTime() {return m_iTutorialDisplayMessageTime;}
+
+ // Only for the main gameplay tutorial
+ vector<TutorialTask *> *getTasks();
+ unsigned int getCurrentTaskIndex();
+
+#ifdef _XBOX
+ CXuiScene *getScene() { return m_UIScene; }
+#else
+ UIScene *getScene() { return m_UIScene; }
+#endif
+ eTutorial_State getCurrentState() { return m_CurrentState; }
+
+ // These are required so that we have a consistent mapping of the completion bits stored in the profile data
+ static void staticCtor();
+ static vector<int> s_completableTasks;
+
+ static void debugResetPlayerSavedProgress(int iPad);
+};
diff --git a/Minecraft.Client/Common/Tutorial/TutorialConstraint.h b/Minecraft.Client/Common/Tutorial/TutorialConstraint.h
new file mode 100644
index 00000000..877fd57e
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialConstraint.h
@@ -0,0 +1,41 @@
+#pragma once
+
+// 4J Stu - An abstract class that represents a constraint on what the user is able to do
+class TutorialConstraint
+{
+private:
+ int descriptionId;
+ bool m_deleteOnDeactivate;
+ bool m_queuedForRemoval;
+public:
+ enum ConstraintType
+ {
+ e_ConstraintInput = 0, // Constraint on controller input
+ e_ConstraintArea,
+ e_ConstraintAllInput,
+ e_ConstraintXuiInput,
+ e_ConstraintChangeState,
+ };
+
+ TutorialConstraint(int descriptionId) : descriptionId( descriptionId ), m_deleteOnDeactivate( false ), m_queuedForRemoval( false ) {}
+ virtual ~TutorialConstraint() {}
+
+ int getDescriptionId() { return descriptionId; }
+
+ virtual ConstraintType getType() = 0;
+
+ virtual void tick(int iPad) {}
+ virtual bool isConstraintSatisfied(int iPad) { return true; }
+ virtual bool isConstraintRestrictive(int iPad) { return true; }
+
+ virtual bool isMappingConstrained(int iPad, int mapping) { return false;}
+ virtual bool isXuiInputConstrained(int vk) { return false;}
+
+ void setDeleteOnDeactivate(bool deleteOnDeactivated) { m_deleteOnDeactivate = deleteOnDeactivated; }
+ bool getDeleteOnDeactivate() { return m_deleteOnDeactivate; }
+
+ void setQueuedForRemoval(bool queued) { m_queuedForRemoval = queued; }
+ bool getQueuedForRemoval() { return m_queuedForRemoval; }
+
+ virtual bool canMoveToPosition(double xo, double yo, double zo, double xt, double yt, double zt) { return true; }
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialConstraints.h b/Minecraft.Client/Common/Tutorial/TutorialConstraints.h
new file mode 100644
index 00000000..74bb8935
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialConstraints.h
@@ -0,0 +1,4 @@
+#include "TutorialConstraint.h"
+#include "AreaConstraint.h"
+#include "ChangeStateConstraint.h"
+#include "InputConstraint.h" \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialEnum.h b/Minecraft.Client/Common/Tutorial/TutorialEnum.h
new file mode 100644
index 00000000..33f2e67d
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialEnum.h
@@ -0,0 +1,329 @@
+#pragma once
+
+typedef struct {
+ WORD index;
+ DWORD diffsSize;
+ BYTE *diffs;
+ DWORD lastByteChanged;
+} TutorialDiff_Chunk;
+
+typedef struct {
+ DWORD diffCount;
+ TutorialDiff_Chunk *diffs;
+} TutorialDiff_File;
+
+#define TUTORIAL_NO_TEXT -1
+#define TUTORIAL_NO_ICON -1
+
+// If you want to make these bigger, be aware that that will affect what is stored after the tutorial data in the profile data
+// See Xbox_App.h for the struct
+#define TUTORIAL_PROFILE_STORAGE_BITS 512
+#define TUTORIAL_PROFILE_STORAGE_BYTES (TUTORIAL_PROFILE_STORAGE_BITS/8)
+
+// 4J Stu - The total number of eTutorial_State and eTutorial_Hint must be less than 512, as we only have 512 bits of profile
+// data to flag whether or not the player has seen them
+// In general a block or tool will have one each. We have a state if we need more than one message, or a hint if just once
+// message will suffice
+// Tasks added here should also be added in the Tutorial::staticCtor() if you wish to store completion in the profile data
+enum eTutorial_State
+{
+ e_Tutorial_State_Any = -2,
+ e_Tutorial_State_None = -1,
+
+ e_Tutorial_State_Gameplay = 0,
+
+ e_Tutorial_State_Inventory_Menu,
+ e_Tutorial_State_2x2Crafting_Menu,
+ e_Tutorial_State_3x3Crafting_Menu,
+ e_Tutorial_State_Furnace_Menu,
+
+ e_Tutorial_State_Riding_Minecart,
+ e_Tutorial_State_Riding_Boat,
+ e_Tutorial_State_Fishing,
+
+ e_Tutorial_State_Bed,
+
+ e_Tutorial_State_Container_Menu,
+ e_Tutorial_State_Trap_Menu,
+ e_Tutorial_State_Redstone_And_Piston,
+ e_Tutorial_State_Portal,
+ e_Tutorial_State_Creative_Inventory_Menu, // Added TU5
+ e_Tutorial_State_Food_Bar, // Added TU5
+ e_Tutorial_State_CreativeMode, // Added TU7
+ e_Tutorial_State_Brewing,
+ e_Tutorial_State_Brewing_Menu,
+ e_Tutorial_State_Enchanting,
+ e_Tutorial_State_Enchanting_Menu,
+ e_Tutorial_State_Farming,
+ e_Tutorial_State_Breeding,
+ e_Tutorial_State_Golem,
+ e_Tutorial_State_Trading,
+ e_Tutorial_State_Trading_Menu,
+ e_Tutorial_State_Anvil,
+ e_Tutorial_State_Anvil_Menu,
+ e_Tutorial_State_Enderchests,
+
+ e_Tutorial_State_Unused_9,
+ e_Tutorial_State_Unused_10,
+
+ e_Tutorial_State_Max
+};
+
+// Hints added here should also be added in the Tutorial::staticCtor() if you wish to store completion in the profile data
+enum eTutorial_Hint
+{
+ e_Tutorial_Hint_Always_On = e_Tutorial_State_Max,
+
+ e_Tutorial_Hint_Hold_To_Mine,
+ e_Tutorial_Hint_Tool_Damaged,
+ e_Tutorial_Hint_Swim_Up,
+
+ e_Tutorial_Hint_Unused_2,
+ e_Tutorial_Hint_Unused_3,
+ e_Tutorial_Hint_Unused_4,
+ e_Tutorial_Hint_Unused_5,
+ e_Tutorial_Hint_Unused_6,
+ e_Tutorial_Hint_Unused_7,
+ e_Tutorial_Hint_Unused_8,
+ e_Tutorial_Hint_Unused_9,
+ e_Tutorial_Hint_Unused_10,
+
+ e_Tutorial_Hint_Rock,
+ e_Tutorial_Hint_Stone,
+ e_Tutorial_Hint_Planks,
+ e_Tutorial_Hint_Sapling,
+ e_Tutorial_Hint_Unbreakable,
+ e_Tutorial_Hint_Water,
+ e_Tutorial_Hint_Lava,
+ e_Tutorial_Hint_Sand,
+ e_Tutorial_Hint_Gravel,
+ e_Tutorial_Hint_Gold_Ore,
+ e_Tutorial_Hint_Iron_Ore,
+ e_Tutorial_Hint_Coal_Ore,
+ e_Tutorial_Hint_Tree_Trunk,
+ e_Tutorial_Hint_Leaves,
+ e_Tutorial_Hint_Glass,
+ e_Tutorial_Hint_Lapis_Ore,
+ e_Tutorial_Hint_Lapis_Block,
+ e_Tutorial_Hint_Dispenser,
+ e_Tutorial_Hint_Sandstone,
+ e_Tutorial_Hint_Note_Block,
+ e_Tutorial_Hint_Powered_Rail,
+ e_Tutorial_Hint_Detector_Rail,
+ e_Tutorial_Hint_Tall_Grass,
+ e_Tutorial_Hint_Wool,
+ e_Tutorial_Hint_Flower,
+ e_Tutorial_Hint_Mushroom,
+ e_Tutorial_Hint_Gold_Block,
+ e_Tutorial_Hint_Iron_Block,
+ e_Tutorial_Hint_Stone_Slab,
+ e_Tutorial_Hint_Red_Brick,
+ e_Tutorial_Hint_Tnt,
+ e_Tutorial_Hint_Bookshelf,
+ e_Tutorial_Hint_Moss_Stone,
+ e_Tutorial_Hint_Obsidian,
+ e_Tutorial_Hint_Torch,
+ e_Tutorial_Hint_MobSpawner,
+ e_Tutorial_Hint_Chest,
+ e_Tutorial_Hint_Redstone,
+ e_Tutorial_Hint_Diamond_Ore,
+ e_Tutorial_Hint_Diamond_Block,
+ e_Tutorial_Hint_Crafting_Table,
+ e_Tutorial_Hint_Crops,
+ e_Tutorial_Hint_Farmland,
+ e_Tutorial_Hint_Furnace,
+ e_Tutorial_Hint_Sign,
+ e_Tutorial_Hint_Door_Wood,
+ e_Tutorial_Hint_Ladder,
+ e_Tutorial_Hint_Stairs_Stone,
+ e_Tutorial_Hint_Rail,
+ e_Tutorial_Hint_Lever,
+ e_Tutorial_Hint_PressurePlate,
+ e_Tutorial_Hint_Door_Iron,
+ e_Tutorial_Hint_Redstone_Ore,
+ e_Tutorial_Hint_Redstone_Torch,
+ e_Tutorial_Hint_Button,
+ e_Tutorial_Hint_Snow,
+ e_Tutorial_Hint_Ice,
+ e_Tutorial_Hint_Cactus,
+ e_Tutorial_Hint_Clay,
+ e_Tutorial_Hint_Sugarcane,
+ e_Tutorial_Hint_Record_Player,
+ e_Tutorial_Hint_Pumpkin,
+ e_Tutorial_Hint_Hell_Rock,
+ e_Tutorial_Hint_Hell_Sand,
+ e_Tutorial_Hint_Glowstone,
+ e_Tutorial_Hint_Portal,
+ e_Tutorial_Hint_Pumpkin_Lit,
+ e_Tutorial_Hint_Cake,
+ e_Tutorial_Hint_Redstone_Repeater,
+ e_Tutorial_Hint_Trapdoor,
+ e_Tutorial_Hint_Piston,
+ e_Tutorial_Hint_Sticky_Piston,
+ e_Tutorial_Hint_Monster_Stone_Egg,
+ e_Tutorial_Hint_Stone_Brick_Smooth,
+ e_Tutorial_Hint_Huge_Mushroom,
+ e_Tutorial_Hint_Iron_Fence,
+ e_Tutorial_Hint_Thin_Glass,
+ e_Tutorial_Hint_Melon,
+ e_Tutorial_Hint_Vine,
+ e_Tutorial_Hint_Fence_Gate,
+ e_Tutorial_Hint_Mycel,
+ e_Tutorial_Hint_Water_Lily,
+ e_Tutorial_Hint_Nether_Brick,
+ e_Tutorial_Hint_Nether_Fence,
+ e_Tutorial_Hint_Nether_Stalk,
+ e_Tutorial_Hint_Enchant_Table,
+ e_Tutorial_Hint_Brewing_Stand,
+ e_Tutorial_Hint_Cauldron,
+ e_Tutorial_Hint_End_Portal,
+ e_Tutorial_Hint_End_Portal_Frame,
+
+ e_Tutorial_Hint_Squid,
+ e_Tutorial_Hint_Cow,
+ e_Tutorial_Hint_Sheep,
+ e_Tutorial_Hint_Chicken,
+ e_Tutorial_Hint_Pig,
+ e_Tutorial_Hint_Wolf,
+ e_Tutorial_Hint_Creeper,
+ e_Tutorial_Hint_Skeleton,
+ e_Tutorial_Hint_Spider,
+ e_Tutorial_Hint_Zombie,
+ e_Tutorial_Hint_Pig_Zombie,
+ e_Tutorial_Hint_Ghast,
+ e_Tutorial_Hint_Slime,
+ e_Tutorial_Hint_Enderman,
+ e_Tutorial_Hint_Silverfish,
+ e_Tutorial_Hint_Cave_Spider,
+ e_Tutorial_Hint_MushroomCow,
+ e_Tutorial_Hint_SnowMan,
+ e_Tutorial_Hint_IronGolem,
+ e_Tutorial_Hint_EnderDragon,
+ e_Tutorial_Hint_Blaze,
+ e_Tutorial_Hint_Lava_Slime,
+
+ e_Tutorial_Hint_Ozelot,
+ e_Tutorial_Hint_Villager,
+
+ e_Tutorial_Hint_Item_Shovel,
+ e_Tutorial_Hint_Item_Hatchet,
+ e_Tutorial_Hint_Item_Pickaxe,
+ e_Tutorial_Hint_Item_Flint_And_Steel,
+ e_Tutorial_Hint_Item_Apple,
+ e_Tutorial_Hint_Item_Bow,
+ e_Tutorial_Hint_Item_Arrow,
+ e_Tutorial_Hint_Item_Coal,
+ e_Tutorial_Hint_Item_Diamond,
+ e_Tutorial_Hint_Item_Iron_Ingot,
+ e_Tutorial_Hint_Item_Gold_Ingot,
+ e_Tutorial_Hint_Item_Sword,
+ e_Tutorial_Hint_Item_Stick,
+ e_Tutorial_Hint_Item_Bowl,
+ e_Tutorial_Hint_Item_Mushroom_Stew,
+ e_Tutorial_Hint_Item_String,
+ e_Tutorial_Hint_Item_Feather,
+ e_Tutorial_Hint_Item_Sulphur,
+ e_Tutorial_Hint_Item_Hoe,
+ e_Tutorial_Hint_Item_Seeds,
+ e_Tutorial_Hint_Item_Wheat,
+ e_Tutorial_Hint_Item_Bread,
+ e_Tutorial_Hint_Item_Helmet,
+ e_Tutorial_Hint_Item_Chestplate,
+ e_Tutorial_Hint_Item_Leggings,
+ e_Tutorial_Hint_Item_Boots,
+ e_Tutorial_Hint_Item_Flint,
+ e_Tutorial_Hint_Item_Porkchop_Raw,
+ e_Tutorial_Hint_Item_Porkchop_Cooked,
+ e_Tutorial_Hint_Item_Painting,
+ e_Tutorial_Hint_Item_Apple_Gold,
+ e_Tutorial_Hint_Item_Sign,
+ e_Tutorial_Hint_Item_Door_Wood,
+ e_Tutorial_Hint_Item_Bucket_Empty,
+ e_Tutorial_Hint_Item_Bucket_Water,
+ e_Tutorial_Hint_Item_Bucket_Lava,
+ e_Tutorial_Hint_Item_Minecart,
+ e_Tutorial_Hint_Item_Saddle,
+ e_Tutorial_Hint_Item_Door_Iron,
+ e_Tutorial_Hint_Item_Redstone,
+ e_Tutorial_Hint_Item_Snowball,
+ e_Tutorial_Hint_Item_Boat,
+ e_Tutorial_Hint_Item_Leather,
+ e_Tutorial_Hint_Item_Milk,
+ e_Tutorial_Hint_Item_Brick,
+ e_Tutorial_Hint_Item_Clay,
+ e_Tutorial_Hint_Item_Reeds,
+ e_Tutorial_Hint_Item_Paper,
+ e_Tutorial_Hint_Item_Book,
+ e_Tutorial_Hint_Item_Slimeball,
+ e_Tutorial_Hint_Item_Minecart_Chest,
+ e_Tutorial_Hint_Item_Minecart_Furnace,
+ e_Tutorial_Hint_Item_Egg,
+ e_Tutorial_Hint_Item_Compass,
+ e_Tutorial_Hint_Item_Clock,
+ e_Tutorial_Hint_Item_Yellow_Dust,
+ e_Tutorial_Hint_Item_Fish_Raw,
+ e_Tutorial_Hint_Item_Fish_Cooked,
+ e_Tutorial_Hint_Item_Dye_Powder,
+ e_Tutorial_Hint_Item_Bone,
+ e_Tutorial_Hint_Item_Sugar,
+ e_Tutorial_Hint_Item_Cake,
+ e_Tutorial_Hint_Item_Diode,
+ e_Tutorial_Hint_Item_Cookie,
+ e_Tutorial_Hint_Item_Map,
+ e_Tutorial_Hint_Item_Record,
+
+ e_Tutorial_Hint_White_Stone,
+ e_Tutorial_Hint_Dragon_Egg,
+ e_Tutorial_Hint_RedstoneLamp,
+ e_Tutorial_Hint_Cocoa,
+
+ e_Tutorial_Hint_EmeraldOre,
+ e_Tutorial_Hint_EmeraldBlock,
+ e_Tutorial_Hint_EnderChest,
+ e_Tutorial_Hint_TripwireSource,
+ e_Tutorial_Hint_Tripwire,
+ e_Tutorial_Hint_CobblestoneWall,
+ e_Tutorial_Hint_Flowerpot,
+ e_Tutorial_Hint_Anvil,
+ e_Tutorial_Hint_QuartzOre,
+ e_Tutorial_Hint_QuartzBlock,
+ e_Tutorial_Hint_WoolCarpet,
+
+ e_Tutorial_Hint_Potato,
+ e_Tutorial_Hint_Carrot,
+
+ e_Tutorial_Hint_Item_Unused_18,
+ e_Tutorial_Hint_Item_Unused_19,
+ e_Tutorial_Hint_Item_Unused_20,
+
+ e_Tutorial_Hint_Item_Max,
+};
+
+// We store the first time that we complete these tasks to be used in telemetry
+enum eTutorial_Telemetry
+{
+ eTutorial_Telemetry_None = e_Tutorial_Hint_Item_Max,
+
+ eTutorial_Telemetry_TrialStart,
+ eTutorial_Telemetry_Halfway,
+ eTutorial_Telemetry_Complete,
+
+ eTutorial_Telemetry_Unused_1,
+ eTutorial_Telemetry_Unused_2,
+ eTutorial_Telemetry_Unused_3,
+ eTutorial_Telemetry_Unused_4,
+ eTutorial_Telemetry_Unused_5,
+ eTutorial_Telemetry_Unused_6,
+ eTutorial_Telemetry_Unused_7,
+ eTutorial_Telemetry_Unused_8,
+ eTutorial_Telemetry_Unused_9,
+ eTutorial_Telemetry_Unused_10,
+};
+
+enum eTutorial_CompletionAction
+{
+ e_Tutorial_Completion_None,
+ e_Tutorial_Completion_Complete_State, // This will make the current tutorial state complete
+ e_Tutorial_Completion_Complete_State_Gameplay_Constraints, // This will make the current tutorial state complete, and move the delayed constraints to the gameplay state
+ e_Tutorial_Completion_Jump_To_Last_Task,
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialHint.cpp b/Minecraft.Client/Common/Tutorial/TutorialHint.cpp
new file mode 100644
index 00000000..5f0808bf
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialHint.cpp
@@ -0,0 +1,128 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "Tutorial.h"
+#include "TutorialHint.h"
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+
+TutorialHint::TutorialHint(eTutorial_Hint id, Tutorial *tutorial, int descriptionId, eHintType type, bool allowFade /*= true*/)
+ : m_id( id ), m_tutorial(tutorial), m_descriptionId( descriptionId ), m_type( type ), m_counter( 0 ),
+ m_lastTile( NULL ), m_hintNeeded( true ), m_allowFade(allowFade)
+{
+ tutorial->addMessage(descriptionId, type != e_Hint_NoIngredients);
+}
+
+int TutorialHint::startDestroyBlock(shared_ptr<ItemInstance> item, Tile *tile)
+{
+ int returnVal = -1;
+ switch(m_type)
+ {
+ case e_Hint_HoldToMine:
+ if( tile == m_lastTile && m_hintNeeded )
+ {
+ ++m_counter;
+ if(m_counter > TUTORIAL_HINT_MAX_MINE_REPEATS)
+ {
+ returnVal = m_descriptionId;
+ }
+ }
+ else
+ {
+ m_counter = 0;
+ }
+ m_lastTile = tile;
+ break;
+ default:
+ break;
+ }
+
+ return returnVal;
+}
+
+int TutorialHint::destroyBlock(Tile *tile)
+{
+ int returnVal = -1;
+ switch(m_type)
+ {
+ case e_Hint_HoldToMine:
+ if(tile == m_lastTile && m_counter > 0)
+ {
+ m_hintNeeded = false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return returnVal;
+}
+
+int TutorialHint::attack(shared_ptr<ItemInstance> item, shared_ptr<Entity> entity)
+{
+ /*
+ switch(m_type)
+ {
+ default:
+ return -1;
+ }
+ */
+ return -1;
+}
+
+int TutorialHint::createItemSelected(shared_ptr<ItemInstance> item, bool canMake)
+{
+ int returnVal = -1;
+ switch(m_type)
+ {
+ case e_Hint_NoIngredients:
+ if(!canMake)
+ returnVal = m_descriptionId;
+ break;
+ default:
+ break;
+ }
+ return returnVal;
+}
+
+int TutorialHint::itemDamaged(shared_ptr<ItemInstance> item)
+{
+ int returnVal = -1;
+ switch(m_type)
+ {
+ case e_Hint_ToolDamaged:
+ returnVal = m_descriptionId;
+ break;
+ default:
+ break;
+ }
+ return returnVal;
+}
+
+bool TutorialHint::onTake( shared_ptr<ItemInstance> item )
+{
+ return false;
+}
+
+bool TutorialHint::onLookAt(int id, int iData)
+{
+ return false;
+}
+
+bool TutorialHint::onLookAtEntity(eINSTANCEOF type)
+{
+ return false;
+}
+
+int TutorialHint::tick()
+{
+ int returnVal = -1;
+ switch(m_type)
+ {
+ case e_Hint_SwimUp:
+ if( Minecraft::GetInstance()->localplayers[m_tutorial->getPad()]->isUnderLiquid(Material::water) ) returnVal = m_descriptionId;
+ break;
+ }
+ return returnVal;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialHint.h b/Minecraft.Client/Common/Tutorial/TutorialHint.h
new file mode 100644
index 00000000..8ca543cc
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialHint.h
@@ -0,0 +1,53 @@
+#pragma once
+using namespace std;
+
+#include "TutorialEnum.h"
+
+#define TUTORIAL_HINT_MAX_MINE_REPEATS 20
+
+class Level;
+class Tutorial;
+
+class TutorialHint
+{
+public:
+ enum eHintType
+ {
+ e_Hint_DiggerItem,
+ e_Hint_HoldToMine,
+ e_Hint_NoIngredients,
+ e_Hint_ToolDamaged,
+ e_Hint_TakeItem,
+ e_Hint_Area,
+ e_Hint_LookAtTile,
+ e_Hint_LookAtEntity,
+ e_Hint_SwimUp,
+ };
+
+protected:
+ eHintType m_type;
+ int m_descriptionId;
+ Tutorial *m_tutorial;
+ eTutorial_Hint m_id;
+
+ int m_counter;
+ Tile *m_lastTile;
+ bool m_hintNeeded;
+ bool m_allowFade;
+
+public:
+ TutorialHint(eTutorial_Hint id, Tutorial *tutorial, int descriptionId, eHintType type, bool allowFade = true);
+
+ eTutorial_Hint getId() { return m_id; }
+
+ virtual int startDestroyBlock(shared_ptr<ItemInstance> item, Tile *tile);
+ virtual int destroyBlock(Tile *tile);
+ virtual int attack(shared_ptr<ItemInstance> item, shared_ptr<Entity> entity);
+ virtual int createItemSelected(shared_ptr<ItemInstance> item, bool canMake);
+ virtual int itemDamaged(shared_ptr<ItemInstance> item);
+ virtual bool onTake( shared_ptr<ItemInstance> item );
+ virtual bool onLookAt(int id, int iData=0);
+ virtual bool onLookAtEntity(eINSTANCEOF type);
+ virtual int tick();
+ virtual bool allowFade() { return m_allowFade; }
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialHints.h b/Minecraft.Client/Common/Tutorial/TutorialHints.h
new file mode 100644
index 00000000..5c7381ab
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialHints.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "AreaHint.h"
+#include "DiggerItemHint.h"
+#include "LookAtTileHint.h"
+#include "TakeItemHint.h"
+#include "LookAtEntityHint.h" \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialMessage.cpp b/Minecraft.Client/Common/Tutorial/TutorialMessage.cpp
new file mode 100644
index 00000000..1f007035
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialMessage.cpp
@@ -0,0 +1,23 @@
+#include "stdafx.h"
+#include "TutorialMessage.h"
+
+TutorialMessage::TutorialMessage(int messageId, bool limitRepeats /*= false*/, unsigned char numRepeats /*= TUTORIAL_MESSAGE_DEFAULT_SHOW*/)
+ : messageId( messageId ), limitRepeats( limitRepeats ), numRepeats( numRepeats ), timesShown( 0 )
+{
+}
+
+bool TutorialMessage::canDisplay()
+{
+ return !limitRepeats || (timesShown < numRepeats);
+}
+
+LPCWSTR TutorialMessage::getMessageForDisplay()
+{
+ if(!canDisplay())
+ return L"";
+
+ if(limitRepeats)
+ ++timesShown;
+
+ return app.GetString( messageId );
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialMessage.h b/Minecraft.Client/Common/Tutorial/TutorialMessage.h
new file mode 100644
index 00000000..6a0b4d46
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialMessage.h
@@ -0,0 +1,20 @@
+#pragma once
+
+// The default number of times any message should be shown
+#define TUTORIAL_MESSAGE_DEFAULT_SHOW 3
+
+class TutorialMessage
+{
+private:
+ int messageId;
+ bool limitRepeats;
+ unsigned char numRepeats;
+ unsigned char timesShown;
+ DWORD lastDisplayed;
+
+public:
+ TutorialMessage(int messageId, bool limitRepeats = false, unsigned char numRepeats = TUTORIAL_MESSAGE_DEFAULT_SHOW);
+
+ bool canDisplay();
+ LPCWSTR getMessageForDisplay();
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialMode.cpp b/Minecraft.Client/Common/Tutorial/TutorialMode.cpp
new file mode 100644
index 00000000..82c81598
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialMode.cpp
@@ -0,0 +1,124 @@
+#include "stdafx.h"
+#include <memory>
+#include "..\..\Minecraft.h"
+#include "..\..\MultiplayerLocalPlayer.h"
+#include "..\..\MultiPlayerLevel.h"
+#include "..\..\..\Minecraft.World\Inventory.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
+#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
+#include "TutorialMode.h"
+
+TutorialMode::TutorialMode(int iPad, Minecraft *minecraft, ClientConnection *connection) : MultiPlayerGameMode( minecraft, connection ), m_iPad( iPad )
+{
+}
+
+TutorialMode::~TutorialMode()
+{
+ if(tutorial != NULL)
+ delete tutorial;
+}
+
+void TutorialMode::startDestroyBlock(int x, int y, int z, int face)
+{
+ if(!tutorial->m_allTutorialsComplete)
+ {
+ int t = minecraft->level->getTile(x, y, z);
+ tutorial->startDestroyBlock(minecraft->player->inventory->getSelected(), Tile::tiles[t]);
+ }
+ MultiPlayerGameMode::startDestroyBlock( x, y, z, face );
+}
+
+bool TutorialMode::destroyBlock(int x, int y, int z, int face)
+{
+ if(!tutorial->m_allTutorialsComplete)
+ {
+ int t = minecraft->level->getTile(x, y, z);
+ tutorial->destroyBlock(Tile::tiles[t]);
+ }
+ shared_ptr<ItemInstance> item = minecraft->player->getSelectedItem();
+ int damageBefore;
+ if(item != NULL)
+ {
+ damageBefore = item->getDamageValue();
+ }
+ bool changed = MultiPlayerGameMode::destroyBlock( x, y, z, face );
+
+ if(!tutorial->m_allTutorialsComplete)
+ {
+ if ( item != NULL && item->isDamageableItem() )
+ {
+ int max = item->getMaxDamage();
+ int damageNow = item->getDamageValue();
+
+ if(damageNow > damageBefore && damageNow > (max/2) )
+ {
+ tutorial->itemDamaged( item );
+ }
+ }
+ }
+
+ return changed;
+}
+
+void TutorialMode::tick()
+{
+ MultiPlayerGameMode::tick();
+
+ if(!tutorial->m_allTutorialsComplete)
+ tutorial->tick();
+
+ /*
+ if( tutorial.m_allTutorialsComplete && (tutorial.lastMessageTime + m_iTutorialDisplayMessageTime) < GetTickCount() )
+ {
+ // Exit tutorial
+ minecraft->gameMode = new SurvivalMode( this );
+ delete this;
+ }
+ */
+}
+
+bool TutorialMode::useItemOn(shared_ptr<Player> player, Level *level, shared_ptr<ItemInstance> item, int x, int y, int z, int face, Vec3 *hit, bool bTestUseOnly, bool *pbUsedItem)
+{
+ bool haveItem = false;
+ int itemCount = 0;
+ if(!tutorial->m_allTutorialsComplete)
+ {
+ tutorial->useItemOn(level, item, x, y, z, bTestUseOnly);
+
+ if(!bTestUseOnly)
+ {
+ if(item != NULL)
+ {
+ haveItem = true;
+ itemCount = item->count;
+ }
+ }
+ }
+ bool result = MultiPlayerGameMode::useItemOn( player, level, item, x, y, z, face, hit, bTestUseOnly, pbUsedItem );
+
+ if(!bTestUseOnly)
+ {
+ if(!tutorial->m_allTutorialsComplete)
+ {
+ if( result && haveItem && itemCount > item->count )
+ {
+ tutorial->useItemOn(item);
+ }
+ }
+ }
+ return result;
+}
+
+void TutorialMode::attack(shared_ptr<Player> player, shared_ptr<Entity> entity)
+{
+ if(!tutorial->m_allTutorialsComplete)
+ tutorial->attack(player, entity);
+
+ MultiPlayerGameMode::attack( player, entity );
+}
+
+bool TutorialMode::isInputAllowed(int mapping)
+{
+ return tutorial->m_allTutorialsComplete || tutorial->isInputAllowed( mapping );
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialMode.h b/Minecraft.Client/Common/Tutorial/TutorialMode.h
new file mode 100644
index 00000000..75e24edf
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialMode.h
@@ -0,0 +1,28 @@
+#pragma once
+using namespace std;
+
+#include "..\..\MultiPlayerGameMode.h"
+#include "Tutorial.h"
+
+class TutorialMode : public MultiPlayerGameMode
+{
+protected:
+ Tutorial *tutorial;
+ int m_iPad;
+
+ // Function to make this an abstract class
+ virtual bool isImplemented() = 0;
+public:
+ TutorialMode(int iPad, Minecraft *minecraft, ClientConnection *connection);
+ virtual ~TutorialMode();
+
+ virtual void startDestroyBlock(int x, int y, int z, int face);
+ virtual bool destroyBlock(int x, int y, int z, int face);
+ virtual void tick();
+ virtual bool useItemOn(shared_ptr<Player> player, Level *level, shared_ptr<ItemInstance> item, int x, int y, int z, int face, Vec3 *hit, bool bTestUseOnly=false, bool *pbUsedItem=NULL);
+ virtual void attack(shared_ptr<Player> player, shared_ptr<Entity> entity);
+
+ virtual bool isInputAllowed(int mapping);
+
+ Tutorial *getTutorial() { return tutorial; }
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialTask.cpp b/Minecraft.Client/Common/Tutorial/TutorialTask.cpp
new file mode 100644
index 00000000..2251ab07
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialTask.cpp
@@ -0,0 +1,78 @@
+#include "stdafx.h"
+#include "Tutorial.h"
+#include "TutorialConstraints.h"
+#include "TutorialTask.h"
+
+TutorialTask::TutorialTask(Tutorial *tutorial, int descriptionId, bool enablePreCompletion, vector<TutorialConstraint *> *inConstraints,
+ bool bShowMinimumTime, bool bAllowFade, bool bTaskReminders)
+ : tutorial( tutorial ), descriptionId( descriptionId ), m_promptId( -1 ), enablePreCompletion( enablePreCompletion ),
+ areConstraintsEnabled( false ), bIsCompleted( false ), bHasBeenActivated( false ),
+ m_bAllowFade(bAllowFade), m_bTaskReminders(bTaskReminders), m_bShowMinimumTime( bShowMinimumTime), m_bShownForMinimumTime( false )
+{
+ if(inConstraints != NULL)
+ {
+ for(AUTO_VAR(it, inConstraints->begin()); it < inConstraints->end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ constraints.push_back( constraint );
+ }
+ delete inConstraints;
+ }
+
+ tutorial->addMessage(descriptionId);
+}
+
+TutorialTask::~TutorialTask()
+{
+ enableConstraints(false);
+
+ for(AUTO_VAR(it, constraints.begin()); it < constraints.end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+
+ if( constraint->getQueuedForRemoval() )
+ {
+ constraint->setDeleteOnDeactivate(true);
+ }
+ else
+ {
+ delete constraint;
+ }
+ }
+}
+
+void TutorialTask::taskCompleted()
+{
+ if( areConstraintsEnabled == true )
+ enableConstraints( false );
+}
+
+void TutorialTask::enableConstraints(bool enable, bool delayRemove /*= false*/)
+{
+ if( !enable && (areConstraintsEnabled || !delayRemove) )
+ {
+ // Remove
+ for(AUTO_VAR(it, constraints.begin()); it != constraints.end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ //app.DebugPrintf(">>>>>>>> %i\n", constraints.size());
+ tutorial->RemoveConstraint( constraint, delayRemove );
+ }
+ areConstraintsEnabled = false;
+ }
+ else if( !areConstraintsEnabled && enable )
+ {
+ // Add
+ for(AUTO_VAR(it, constraints.begin()); it != constraints.end(); ++it)
+ {
+ TutorialConstraint *constraint = *it;
+ tutorial->AddConstraint( constraint );
+ }
+ areConstraintsEnabled = true;
+ }
+}
+
+void TutorialTask::setAsCurrentTask(bool active /*= true*/)
+{
+ bHasBeenActivated = active;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialTask.h b/Minecraft.Client/Common/Tutorial/TutorialTask.h
new file mode 100644
index 00000000..92cb5999
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialTask.h
@@ -0,0 +1,63 @@
+#pragma once
+using namespace std;
+#include "TutorialEnum.h"
+
+class Level;
+class Tutorial;
+class TutorialConstraint;
+class MobEffect;
+
+// A class that represents each individual task in the tutorial.
+//
+// Members:
+// enablePreCompletion - If this is true, then the player can complete this task out of sequence.
+// This stops us asking them to do things they have already done
+// constraints - A list of constraints which can be activated (as a whole).
+// If they are active, then the constraints are removed when the task is completed
+// areConstraintsEnabled- A flag which records whether or not we have added the constraints to the tutorial
+class TutorialTask
+{
+protected:
+ int descriptionId;
+ int m_promptId;
+ Tutorial *tutorial;
+ bool enablePreCompletion;
+ bool bHasBeenActivated;
+ bool m_bAllowFade;
+ bool m_bTaskReminders;
+ bool m_bShowMinimumTime;
+
+protected:
+ bool bIsCompleted;
+ bool m_bShownForMinimumTime;
+ vector<TutorialConstraint *> constraints;
+ bool areConstraintsEnabled;
+public:
+ TutorialTask(Tutorial *tutorial, int descriptionId, bool enablePreCompletion, vector<TutorialConstraint *> *inConstraints, bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true );
+ virtual ~TutorialTask();
+
+ virtual int getDescriptionId() { return descriptionId; }
+ virtual int getPromptId() { return m_promptId; }
+
+ virtual bool isCompleted() = 0;
+ virtual eTutorial_CompletionAction getCompletionAction() { return e_Tutorial_Completion_None; }
+ virtual bool isPreCompletionEnabled() { return enablePreCompletion; }
+ virtual void taskCompleted();
+ virtual void enableConstraints(bool enable, bool delayRemove = false);
+ virtual void setAsCurrentTask(bool active = true);
+
+ virtual void setShownForMinimumTime() { m_bShownForMinimumTime = true; }
+ virtual bool hasBeenActivated() { return bHasBeenActivated; }
+ virtual bool AllowFade() { return m_bAllowFade;}
+ bool TaskReminders() { return m_bTaskReminders;}
+ virtual bool ShowMinimumTime() { return m_bShowMinimumTime;}
+
+ virtual void useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z, bool bTestUseOnly=false) { }
+ virtual void useItem(shared_ptr<ItemInstance> item,bool bTestUseOnly=false) { }
+ virtual void completeUsingItem(shared_ptr<ItemInstance> item) { }
+ virtual void handleUIInput(int iAction) { }
+ virtual void onCrafted(shared_ptr<ItemInstance> item) { }
+ virtual void onTake(shared_ptr<ItemInstance> item, unsigned int invItemCountAnyAux, unsigned int invItemCountThisAux) { }
+ virtual void onStateChange(eTutorial_State newState) { }
+ virtual void onEffectChanged(MobEffect *effect, bool bRemoved=false) { }
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/TutorialTasks.h b/Minecraft.Client/Common/Tutorial/TutorialTasks.h
new file mode 100644
index 00000000..591e9564
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/TutorialTasks.h
@@ -0,0 +1,16 @@
+#include "StatTask.h"
+#include "CraftTask.h"
+#include "PickupTask.h"
+#include "UseTileTask.h"
+#include "UseItemTask.h"
+#include "InfoTask.h"
+#include "ControllerTask.h"
+#include "ProcedureCompoundTask.h"
+#include "XuiCraftingTask.h"
+#include "StateChangeTask.h"
+#include "ChoiceTask.h"
+#include "FullTutorialActiveTask.h"
+#include "AreaTask.h"
+#include "ProgressFlagTask.h"
+#include "CompleteUsingItemTask.h"
+#include "EffectChangedTask.h" \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/UseItemTask.cpp b/Minecraft.Client/Common/Tutorial/UseItemTask.cpp
new file mode 100644
index 00000000..09bac4d1
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/UseItemTask.cpp
@@ -0,0 +1,25 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\Entity.h"
+#include "..\..\..\Minecraft.World\Level.h"
+#include "..\..\..\Minecraft.World\ItemInstance.h"
+#include "UseItemTask.h"
+
+UseItemTask::UseItemTask(const int itemId, Tutorial *tutorial, int descriptionId,
+ bool enablePreCompletion, vector<TutorialConstraint *> *inConstraints, bool bShowMinimumTime, bool bAllowFade, bool bTaskReminders)
+ : TutorialTask( tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, bTaskReminders ),
+ itemId( itemId )
+{
+}
+
+bool UseItemTask::isCompleted()
+{
+ return bIsCompleted;
+}
+
+void UseItemTask::useItem(shared_ptr<ItemInstance> item,bool bTestUseOnly)
+{
+ if(bTestUseOnly) return;
+
+ if( item->id == itemId )
+ bIsCompleted = true;
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/UseItemTask.h b/Minecraft.Client/Common/Tutorial/UseItemTask.h
new file mode 100644
index 00000000..46d71be4
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/UseItemTask.h
@@ -0,0 +1,20 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+class Level;
+
+// 4J Stu - Tasks that involve placing a tile
+class UseItemTask : public TutorialTask
+{
+private:
+ const int itemId;
+ bool completed;
+
+public:
+ UseItemTask(const int itemId, Tutorial *tutorial, int descriptionId,
+ bool enablePreCompletion = false, vector<TutorialConstraint *> *inConstraints = NULL, bool bShowMinimumTime = false, bool bAllowFade = true, bool bTaskReminders = true );
+ virtual bool isCompleted();
+ virtual void useItem(shared_ptr<ItemInstance> item, bool bTestUseOnly=false);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/UseTileTask.cpp b/Minecraft.Client/Common/Tutorial/UseTileTask.cpp
new file mode 100644
index 00000000..1f4ed4cb
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/UseTileTask.cpp
@@ -0,0 +1,40 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\Entity.h"
+#include "..\..\..\Minecraft.World\Level.h"
+#include "..\..\..\Minecraft.World\ItemInstance.h"
+#include "UseTileTask.h"
+
+UseTileTask::UseTileTask(const int tileId, int x, int y, int z, Tutorial *tutorial, int descriptionId,
+ bool enablePreCompletion, vector<TutorialConstraint *> *inConstraints, bool bShowMinimumTime, bool bAllowFade, bool bTaskReminders)
+ : TutorialTask( tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, bTaskReminders ),
+ x( x ), y( y ), z( z ), tileId( tileId )
+{
+ useLocation = true;
+}
+
+UseTileTask::UseTileTask(const int tileId, Tutorial *tutorial, int descriptionId,
+ bool enablePreCompletion, vector<TutorialConstraint *> *inConstraints, bool bShowMinimumTime, bool bAllowFade, bool bTaskReminders)
+ : TutorialTask( tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, bTaskReminders ),
+ tileId( tileId )
+{
+ useLocation = false;
+}
+
+bool UseTileTask::isCompleted()
+{
+ return bIsCompleted;
+}
+
+void UseTileTask::useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z,bool bTestUseOnly)
+{
+ if(bTestUseOnly) return;
+
+ if( !enablePreCompletion && !bHasBeenActivated) return;
+
+ if( !useLocation || ( x == this->x && y == this->y && z == this->z ) )
+ {
+ int t = level->getTile(x, y, z);
+ if( t == tileId )
+ bIsCompleted = true;
+ }
+} \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/UseTileTask.h b/Minecraft.Client/Common/Tutorial/UseTileTask.h
new file mode 100644
index 00000000..74b3a40c
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/UseTileTask.h
@@ -0,0 +1,24 @@
+#pragma once
+using namespace std;
+
+#include "TutorialTask.h"
+
+class Level;
+
+// 4J Stu - Tasks that involve using a tile, with or without an item. e.g. Opening a chest
+class UseTileTask : public TutorialTask
+{
+private:
+ int x,y,z;
+ const int tileId;
+ bool useLocation;
+ bool completed;
+
+public:
+ UseTileTask(const int tileId, int x, int y, int z, Tutorial *tutorial, int descriptionId,
+ bool enablePreCompletion = false, vector<TutorialConstraint *> *inConstraints = NULL, bool bShowMinimumTime = false, bool bAllowFade = true, bool bTaskReminders = true );
+ UseTileTask(const int tileId, Tutorial *tutorial, int descriptionId,
+ bool enablePreCompletion = false, vector<TutorialConstraint *> *inConstraints = NULL, bool bShowMinimumTime = false, bool bAllowFade = true, bool bTaskReminders = true);
+ virtual bool isCompleted();
+ virtual void useItemOn(Level *level, shared_ptr<ItemInstance> item, int x, int y, int z, bool bTestUseOnly=false);
+}; \ No newline at end of file
diff --git a/Minecraft.Client/Common/Tutorial/XuiCraftingTask.cpp b/Minecraft.Client/Common/Tutorial/XuiCraftingTask.cpp
new file mode 100644
index 00000000..71b88479
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/XuiCraftingTask.cpp
@@ -0,0 +1,42 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\ItemInstance.h"
+#if !(defined _XBOX) && !(defined __PSVITA__)
+#include "..\UI\UI.h"
+#endif
+#include "Tutorial.h"
+#include "XuiCraftingTask.h"
+
+bool XuiCraftingTask::isCompleted()
+{
+#ifndef __PSVITA__
+ // This doesn't seem to work
+ //IUIScene_CraftingMenu *craftScene = reinterpret_cast<IUIScene_CraftingMenu *>(tutorial->getScene());
+#ifdef _XBOX
+ CXuiSceneCraftingPanel *craftScene = (CXuiSceneCraftingPanel *)(tutorial->getScene());
+#else
+ UIScene_CraftingMenu *craftScene = reinterpret_cast<UIScene_CraftingMenu *>(tutorial->getScene());
+#endif
+
+ bool completed = false;
+
+ switch(m_type)
+ {
+ case e_Crafting_SelectGroup:
+ if(craftScene != NULL && craftScene->getCurrentGroup() == m_group)
+ {
+ completed = true;
+ }
+ break;
+ case e_Crafting_SelectItem:
+ if(craftScene != NULL && craftScene->isItemSelected(m_item))
+ {
+ completed = true;
+ }
+ break;
+ }
+
+ return completed;
+#else
+ return true;
+#endif
+}
diff --git a/Minecraft.Client/Common/Tutorial/XuiCraftingTask.h b/Minecraft.Client/Common/Tutorial/XuiCraftingTask.h
new file mode 100644
index 00000000..2dc48709
--- /dev/null
+++ b/Minecraft.Client/Common/Tutorial/XuiCraftingTask.h
@@ -0,0 +1,36 @@
+#pragma once
+#include "TutorialTask.h"
+#include "..\..\..\Minecraft.World\Recipy.h"
+
+class XuiCraftingTask : public TutorialTask
+{
+public:
+ enum eCraftingTaskType
+ {
+ e_Crafting_SelectGroup,
+ e_Crafting_SelectItem,
+ };
+
+ // Select group
+ XuiCraftingTask(Tutorial *tutorial, int descriptionId, Recipy::_eGroupType groupToSelect, bool enablePreCompletion = false, vector<TutorialConstraint *> *inConstraints = NULL,
+ bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true )
+ : TutorialTask(tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, m_bTaskReminders ),
+ m_group(groupToSelect),
+ m_type( e_Crafting_SelectGroup )
+ {}
+
+ // Select Item
+ XuiCraftingTask(Tutorial *tutorial, int descriptionId, int itemId, bool enablePreCompletion = false, vector<TutorialConstraint *> *inConstraints = NULL,
+ bool bShowMinimumTime=false, bool bAllowFade=true, bool m_bTaskReminders=true )
+ : TutorialTask(tutorial, descriptionId, enablePreCompletion, inConstraints, bShowMinimumTime, bAllowFade, m_bTaskReminders ),
+ m_item(itemId),
+ m_type( e_Crafting_SelectItem )
+ {}
+
+ virtual bool isCompleted();
+
+private:
+ eCraftingTaskType m_type;
+ Recipy::_eGroupType m_group;
+ int m_item;
+}; \ No newline at end of file