first commit

This commit is contained in:
murdle
2026-03-01 02:38:58 +02:00
commit 19250b9db4
19111 changed files with 4358159 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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;
}
}

View File

@@ -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();
};

View File

@@ -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);
}
}
}

View File

@@ -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);
};

View File

@@ -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) ) );
}
}
}
}
}

View File

@@ -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);
};

View File

@@ -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);
}
}

View File

@@ -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();
};

View File

@@ -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;
}
}
}

View File

@@ -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);
};

View File

@@ -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);
}

View File

@@ -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);
};

View File

@@ -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;
}
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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;
}
}
}

View File

@@ -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);
};

View File

@@ -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);
}

View File

@@ -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 );
};

View File

@@ -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;
}
}

View File

@@ -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();
};

View File

@@ -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;
}

View File

@@ -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();
};

View File

@@ -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);
}
}

View File

@@ -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();
};

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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;
}
}
}

View File

@@ -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;
};

View File

@@ -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);
}
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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();
};

View File

@@ -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;
}

View File

@@ -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();
};

View File

@@ -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;
}
}
};

View File

@@ -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;
}

View File

@@ -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 );
};

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -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);
};

View File

@@ -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; }
};

View File

@@ -0,0 +1,4 @@
#include "TutorialConstraint.h"
#include "AreaConstraint.h"
#include "ChangeStateConstraint.h"
#include "InputConstraint.h"

View File

@@ -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,
};

View File

@@ -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;
}

View File

@@ -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; }
};

View File

@@ -0,0 +1,7 @@
#pragma once
#include "AreaHint.h"
#include "DiggerItemHint.h"
#include "LookAtTileHint.h"
#include "TakeItemHint.h"
#include "LookAtEntityHint.h"

View File

@@ -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 );
}

View File

@@ -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();
};

View File

@@ -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 );
}

View File

@@ -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; }
};

View File

@@ -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;
}

View File

@@ -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) { }
};

View File

@@ -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"

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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;
}
}

View File

@@ -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);
};

View File

@@ -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
}

View File

@@ -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;
};