thug/Code/Sk/Modules/Skate/skate.cpp

3526 lines
115 KiB
C++
Raw Normal View History

2016-02-13 21:39:12 +00:00
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: PS2 **
** **
** Module: Skate Module (SKATE) **
** **
** File name: modules/skate.cpp **
** **
** Created by: 06/07/2000 - spg **
** **
** Description: Skate Module **
** **
*****************************************************************************/
// start autoduck documentation
// @DOC skate
// @module skate | None
// @subindex Scripting Database
// @index script | skate
// define this to call the movie updatign from the Skate::Mdl update, instead of the fronend up[date
#define __MOVIES_FROM_SKATE_UPDATE__
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <sk/modules/skate/skate.h>
#ifndef __PLAT_XBOX__
#ifndef __PLAT_NGC__
#include <sifdev.h>
#endif
#endif
#include <core/defines.h>
#include <core/math.h>
#include <core/singleton.h>
#include <core/task.h>
#include <core/string/stringutils.h>
#include <gfx/gfxman.h>
#include <gfx/nx.h>
#include <gfx/nxmiscfx.h>
#include <gfx/nxparticlemgr.h>
#include <gfx/2D/ScreenElement2.h>
#include <gfx/2D/ScreenElemMan.h>
#include <gel/objman.h>
#include <gel/module.h>
#include <gel/mainloop.h>
#include <gel/components/suspendcomponent.h>
#include <gel/components/vibrationcomponent.h>
#include <gel/components/inputcomponent.h>
#include <gel/components/trickcomponent.h>
#include <gel/components/shadowcomponent.h>
#include <gel/components/railmanagercomponent.h>
#include <gel/music/music.h>
#include <gel/net/server/netserv.h>
#include <gel/net/client/netclnt.h>
#include <gel/object/compositeobjectmanager.h>
#include <gel/prefs/prefs.h>
#include <gel/scripting/checksum.h>
#include <gel/scripting/script.h>
#include <gel/scripting/array.h>
#include <gel/scripting/string.h>
#include <gel/scripting/symboltable.h>
#include <gel/soundfx/soundfx.h>
#include <sk/engine/sounds.h>
#include <sk/gamenet/gamenet.h>
#include <sk/scripting/cfuncs.h>
#include <sk/scripting/nodearray.h>
#include <sk/modules/FrontEnd/FrontEnd.h>
#include <sk/modules/skate/gameflow.h>
#include <sk/modules/skate/gamemode.h>
#include <sk/modules/skate/goalmanager.h>
#include <sk/modules/skate/competition.h>
#include <sk/modules/skate/horse.h>
#include <sk/modules/Viewer/Viewer.h>
#include <sk/objects/crown.h>
#include <sk/objects/moviecam.h>
#include <sk/objects/playerprofilemanager.h>
#include <sk/objects/emitter.h>
#include <sk/objects/proxim.h>
#include <sk/objects/rail.h>
#include <sk/objects/records.h>
#include <sk/objects/restart.h>
#include <sk/objects/skater.h>
#include <sk/objects/skatercareer.h>
#include <sk/objects/skaterprofile.h>
#include <sk/objects/skatertricks.h>
#include <sk/objects/trickObject.h>
#ifdef TESTING_GUNSLINGER
#include <sk/objects/navigation.h>
#endif
#include <sk/components/skatercorephysicscomponent.h>
#include <sk/components/skaterstatehistorycomponent.h>
#include <sk/components/skaterendruncomponent.h>
#include <sk/components/skaterbalancetrickcomponent.h>
#include <sk/components/RailEditorComponent.h>
#include <sk/parkEditor2/edmap.h>
#include <sys/sys.h>
#include <sys/mem/memman.h>
#include <sys/timer.h>
#include <sys/file/filesys.h>
#include <sys/file/pre.h>
#include <sys/config/config.h>
#include <sys/replay/replay.h>
extern bool skip_startup;
namespace Front
{
extern void SetTimeTHPS4(int minutes, int seconds);
extern void HideTimeTHPS4();
}
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Mdl
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
DefineSingletonClass( Skate, "Skate Module" );
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Classes **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
// When going into observer mode the local skater gets destroyed, and is later
// restored from his profile. The created tricks are not stored in the profile,
// so we are storing them out seperately.
static Script::CStruct *spCATData=NULL;
static Script::CStruct *spStatData=NULL;
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::s_logic_code ( const Tsk::Task< Skate >& task )
{
GameNet::Manager* gamenet_man = GameNet::Manager::Instance();
Dbg_AssertType ( &task, Tsk::Task< Skate > );
Skate& mdl = task.GetData();
mdl.DoUpdate();
if( gamenet_man->OnServer() && ( mdl.GetNumSkaters() > 0 ))
{
mdl.CheckSkaterCollisions();
}
if ( mdl.GetGameMode()->IsFrontEnd() )
{
}
else if( ( mdl.GetGameMode()->GetNameChecksum() == CRCD(0x6ef8fda0,"netking") ) ||
( mdl.GetGameMode()->GetNameChecksum() == CRCD(0x5d32129c,"king") ))
{
if( !mdl.GetGameMode()->EndConditionsMet())
{
GameNet::PlayerInfo* king;
king = gamenet_man->GetKingOfTheHill();
if( king && !king->m_Skater->IsPaused())
{
Mdl::Score* score;
int current_score, total_score, goal_score;
score = king->m_Skater->GetScoreObject();
current_score = score->GetTotalScore();
total_score = current_score + (int) ( ( Tmr::FrameLength() * 60.0f ) *
( Tmr::vRESOLUTION / 60.0f ));
score->SetTotalScore( total_score );
goal_score = mdl.GetGameMode()->GetTargetScore();
if( mdl.GetGameMode()->IsTeamGame())
{
total_score = gamenet_man->GetTeamScore( king->m_Team );
}
else
{
total_score = score->GetTotalScore();
}
// When within 10 seconds of victory, play a timer sound periodically
mdl.BeepTimer( (float) ( goal_score - total_score) / 1000.0f,
10.0f,
10.0f,
"timer_runout_beep");
}
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::v_start_cb ( void )
{
// TODO: Should assert that the top-down heap is empty
// before the permanent prefiles are loaded
// Script::RunScript( "DumpHeaps" );
// these prefiles will sit on the top-down heap permanently
// this is done before other stuff gets put on the top-down
// heap
Script::RunScript( "load_permanent_prefiles" );
m_stat_override = 0.0f;
Mlp::Manager * mlp_manager = Mlp::Manager::Instance();
Obj::Proxim_Init(); //
Obj::CEmitterManager::sInit();
m_logic_task->SetMask(1<<1);
// Initialise logic and display tasks
mlp_manager->AddLogicTask ( *m_logic_task );
GetGameMode()->Reset();
Script::RunScript("init_loading_bar");
Script::RunScript("startup_loading_screen");
// By default we are both client and server
//gamenet_manager->m_Flags.SetMask( GameNet::mSERVER | GameNet::mCLIENT );
// Run the script for loading sounds that are permanently loaded into sound RAM...
Script::RunScript("LoadPermSounds");
// Run the script for loading the skater animations
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
Mem::PushMemProfile("Permanent Assets");
Script::RunScript( "load_permanent_assets" );
Mem::PopMemProfile(/*"Permanent Assets"*/);
Mem::Manager::sHandle().PopContext();
// initialize the pro skater profiles here
GetPlayerProfileManager()->Init();
// add the trick checksums used to the lookup table
mp_trickChecksumTable->Init();
Script::RunScript("default_system_startup");
if ( !Config::CD() )
{
if ( !skip_startup )
{
// Run the personal startup script.
Script::RunScript("Call_Personal_StartUp_Script");
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::v_stop_cb ( void )
{
m_logic_task->Remove();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::HideSkater( Obj::CSkater* skater, bool should_hide )
{
if( should_hide )
{
skater->Pause();
}
else
{
skater->UnPause();
}
skater->Hide( should_hide );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int Skate::GetNextUnusedSkaterHeapIndex( bool for_local_skater )
{
int start_index, heap_index, num_tested;
bool taken;
// Ok... kinda complicated, but it was the simplest solution I could come up with that solves the problem.
// The issue is that we only have vMAX_SKATERS skater heaps. And we always want to reserve skater heap 0
// for our local skater. But we might be observing a game that has vMAX_SKATERS, in which case you will
// not have a heap for the local skater at all. But if we observe a server that has ( vMAX_SKATERS - 1 )
// skaters and join late, we want to make sure that our skater (the last one to be loaded) gets skater
// heap 0
start_index = 1;
if( for_local_skater )
{
start_index = 0;
}
heap_index = start_index;
for( num_tested = 0; num_tested < (int) GetGameMode()->GetMaximumNumberOfPlayers(); num_tested ++ )
{
taken = false;
for( uint i = 0; i < GetNumSkaters(); i++ )
{
if( m_skaters.GetItem(i) != NULL )
{
Obj::CSkater *pSkater = m_skaters.GetItem(i)->GetData();
if( pSkater->GetHeapIndex() == heap_index )
{
taken = true;
break;
}
}
}
if( taken == false )
{
break;
}
heap_index = ( heap_index + 1 ) % GetGameMode()->GetMaximumNumberOfPlayers();
}
// We assume that these skater heaps are totally empty
// so if something is aleft on them, then assert
#ifdef __NOPT_ASSERT__
Mem::Heap *skater_heap = Mem::Manager::sHandle().SkaterHeap(heap_index);
Dbg_MsgAssert( skater_heap != NULL, ( "Invalid skater heap : %d\n", heap_index ));
if (skater_heap->mUsedBlocks.m_count)
{
printf ("Skater heap has %d used blocks still on it, it should be empty\n",skater_heap->mUsedBlocks.m_count);
#ifndef __PLAT_NGC__
MemView_AnalyzeHeap(skater_heap);
MemView_DumpHeap(skater_heap);
#endif // __PLAT_NGC__
Dbg_MsgAssert(0,("Skater heap has %d used blocks still on it, it should be empty\n",skater_heap->mUsedBlocks.m_count));
}
Mem::Heap *geom_heap = Mem::Manager::sHandle().SkaterGeomHeap(heap_index);
if (geom_heap->mUsedBlocks.m_count)
{
printf ("SkaterGeom heap has %d used blocks still on it, it should be empty\n",geom_heap->mUsedBlocks.m_count);
#ifndef __PLAT_NGC__
MemView_AnalyzeHeap(geom_heap);
MemView_DumpHeap(geom_heap);
#endif // __PLAT_NGC__
Dbg_MsgAssert(0,("SkaterGeom heap has %d used blocks still on it, it should be empty\n",geom_heap->mUsedBlocks.m_count));
}
#endif
return heap_index;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CSkater* Skate::add_skater ( Obj::CSkaterProfile* pSkaterProfile, bool local_client, int obj_id, int player_num )
{
Lst::Node< Obj::CSkater > *node;
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
int heap_index;
// GJ: copy the face texture (if it has one) from the local client's skater profile
// we need to do this because the code that sends the face texture data as a separate
// network message hasn't been implemented yet.
//Dbg_MsgAssert( local_client, ( "Gary's kludge for face textures only works on local client" ) );
if ( local_client )
{
Gfx::CModelAppearance* pModelAppearance = pSkaterProfile->GetAppearance();
Obj::CSkaterProfile* pOriginalProfile;
if (CFuncs::ScriptInSplitScreenGame( NULL, NULL ))
{
// (Mick) Kluge modified for 2 players
// get the correct profile
pOriginalProfile = mp_PlayerProfileManager->GetProfile( player_num );
}
else
{
// Otherwise, use the old kluge
pOriginalProfile = mp_PlayerProfileManager->GetProfile( 0 );
}
Gfx::CModelAppearance* pOriginalAppearance = pOriginalProfile->GetAppearance();
*pModelAppearance = *pOriginalAppearance;
}
// Change our ID to what the server says it should be to avoid ID collision amongs clients
if( local_client )
{
Obj::CSkater* skater;
Script::RunScript( "show_panel_stuff" );
skater = GetLocalSkater();
if( skater )
{
// In Split-screen games, we'll have two local skaters
if( CFuncs::ScriptInSplitScreenGame( NULL, NULL ))
{
if( skater->GetID() == (uint32) obj_id )
{
return skater;
}
#ifdef __PLAT_NGC__
else
{
File::PreMgr* pre_mgr = File::PreMgr::Instance();
pre_mgr->LoadPre( "skaterparts.pre", false);
}
#endif
}
else
{
// In Net games, we'll only have one, but his ID can change in order to avoid
// ID collision over the net. So, if someone is trying to add another local skater with a different
// ID, assume that they just want to assign a new ID to our already-existing local skater
if( skater->GetID() != (uint32) obj_id )
{
Score* score;
node = skater->GetLinkNode();
node->SetPri( obj_id );
node->Remove();
m_skaters.AddUniqueSequence( node );
////////////////////////////////////////////////////////////////////////////////////
// Changing the id means we have to destroy and re-create the particle systems
// as they are referenced by the id of the skater.
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(skater->GetHeapIndex()));
Script::RunScript( "DestroySkaterParticles", NULL, skater );
skater->SetID( obj_id );
Script::RunScript( "InitSkaterParticles", NULL, skater );
Mem::Manager::sHandle().PopContext();
////////////////////////////////////////////////////////////////////////////////////
score = skater->GetScoreObject();
score->SetSkaterId( obj_id );
}
return skater;
}
}
else
{
Obj::CCompositeObject* cam_obj;
// If we're about to re-create the skater, delete the skatercam as it is about to
// be re-created. This is to handle the case where someone goes into observer mode.
// In this case, we destroy the skater, but leave the camera. So now we're going back
// to the front end and it's re-creating the skater.
cam_obj = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x967c138c,"skatercam0"));
if( cam_obj )
{
cam_obj->SetLockOff();
delete cam_obj;
}
}
}
else
{
// Stop vibration when loading client skaters in net games
if ( gamenet_man->InNetGame() )
{
Obj::CSkater* p_skater;
p_skater = GetLocalSkater();
if( p_skater )
{
Obj::CVibrationComponent* p_vibration_component = GetVibrationComponentFromObject(p_skater);
if (p_vibration_component)
{
p_vibration_component->StopAllVibration();
}
}
}
}
if ( gamenet_man->InNetGame() )
{
Dbg_MsgAssert( GetNumSkaters() < GetGameMode()->GetMaximumNumberOfPlayers(),( "Trying to add too many players %d : %d", GetNumSkaters(), GetGameMode()->GetMaximumNumberOfPlayers()));
}
Mem::PushMemProfile("Skater"); // Could possibly replace this with the name of the skater, when we have one, so can compare in multi player
Dbg_MsgAssert(( obj_id >= 0 ) && ( obj_id < vMAX_SKATERS ),( "Invalid skater object id\n" ));
heap_index = GetNextUnusedSkaterHeapIndex( local_client );
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterHeap(heap_index));
Obj::CSkater* skater;
Dbg_MsgAssert( pSkaterProfile,( "No profile specified" ));
// Garrett: We may need to pause the music here if we get glitches on the network server
//Pcm::PauseMusic(1);
skater = new Obj::CSkater ( player_num, GetObjectManager(),
local_client, obj_id, heap_index, !GetGameMode()->IsFrontEnd() );
//Pcm::PauseMusic(0);
skater->Init(pSkaterProfile);
// Initialize the skater's special items
if( !skater->IsLocalClient())
{
Script::RunScript( "ClientSkaterInit", NULL, skater );
}
// This bit of code will order our skaters in the linked list according to their object id
// so the order will be consistent across all clients
node = skater->GetLinkNode();
node->SetPri( skater->GetID() );
m_skaters.AddUniqueSequence( node );
if ( GetGameMode()->IsFrontEnd() )
{
// front end doesn't have a server, so we need
// to treat it as a special case.
skip_to_restart_point( skater );
Script::RunScript("reset_skateshop_skater");
}
// check if we should bind this skater to a different controller
// printf("skaterIndex = %i, player_num = %i\n", mp_controller_preferences[player_num].skaterIndex, player_num);
UpdateSkaterInputHandlers();
// restore CAT's
if( skater->IsLocalClient() && ( skater->GetSkaterNumber() == 0 ))
{
if (spCATData)
{
printf("CAT: Restoring Created Tricks\n");
skater->LoadCATInfo(spCATData);
delete spCATData;
spCATData=NULL;
}
// restore stat goal data too!
if (spStatData)
{
printf("CAT: Restoring Stat Goal data\n");
skater->LoadStatGoalInfo(spStatData);
delete spStatData;
spStatData=NULL;
}
}
// update trick mappings if this is the second skater in a split screen game
if ( skater->GetID() == 0x00000001 && CFuncs::ScriptInSplitScreenGame( NULL, NULL ) )
{
// Obj::CPlayerProfileManager* pProfileMan = GetPlayerProfileManager();
// Obj::CSkaterProfile* pProfile = pProfileMan->GetProfile( 1 );
Obj::CTrickComponent* p_trick_component = GetTrickComponentFromObject(skater);
Dbg_Assert(p_trick_component);
p_trick_component->UpdateTrickMappings( pSkaterProfile );
}
Mem::PopMemProfile(/*"Skater"*/);
Mem::Manager::sHandle().PopContext();
return skater;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::GetNextStartingPointData( Mth::Vector* pos, Mth::Matrix* matrix, int obj_id )
{
int node;
pos->Set( 0.0f, 0.0f, 0.0f, 0.0f );
matrix->Ident();
node = find_restart_node( obj_id );
// ...and jump to it
if (node != -1)
{
Mth::Vector rot;
printf ("Got restart node %d\n",node);
SkateScript::GetAngles( node, &rot );
if ( rot[ X ] || rot[ Y ] || rot[ Z ] )
{
// 3DSMAX_ANGLES Mick: 3/19/03 - Changed all rotation orders to X,Y,Z
matrix->RotateX( rot[ X ] );
matrix->RotateY( rot[ Y ] );
matrix->RotateZ( rot[ Z ] );
}
SkateScript::GetPosition( node, pos );
}
}
/******************************************************************/
/* Find the zero-based restart node. So index 0 is Player1 */
/* */
/******************************************************************/
int Skate::find_restart_node( int index )
{
int node = -1;
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
// get appropriate restart point...
if( IsMultiplayerGame())
{
if( GetGameMode()->IsTeamGame())
{
if( GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netlobby" ))
{
node = Obj::GetRestartNode( Script::GenerateCRC( "team" ), 0 );
}
else if( GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netctf" ))
{
GameNet::PlayerInfo* player;
player = gamenet_man->GetLocalPlayer();
if( player )
{
switch( player->m_Team )
{
case GameNet::vTEAM_RED:
node = SkateScript::FindNamedNode( "TRG_CTF_Restart_Red" );
break;
case GameNet::vTEAM_BLUE:
node = SkateScript::FindNamedNode( "TRG_CTF_Restart_Blue" );
break;
case GameNet::vTEAM_GREEN:
node = SkateScript::FindNamedNode( "TRG_CTF_Restart_Green" );
break;
case GameNet::vTEAM_YELLOW:
node = SkateScript::FindNamedNode( "TRG_CTF_Restart_Yellow" );
break;
}
}
}
else
{
index = gamenet_man->GetSkaterStartingPoint( index );
node = Obj::GetRestartNode( Script::GenerateCRC( "Multiplayer" ), index );
// if we did not find one, then try the first generic restart
if (node == -1)
{
printf ("\n\nWARNING - no multiplayer restart point, trying player1\n\n");
// If no Playern, then try player1
node = Obj::GetRestartNode( Script::GenerateCRC( "Player1" ), 0 );
}
}
}
// In the skateshop, use the Player1, Player2 restart points
else if( GetGameMode()->IsFrontEnd())
{
char buff[32];
sprintf( buff, "Player%d", index + 1 );
node = Obj::GetRestartNode( Script::GenerateCRC( buff ), 0 );
}
else if ( GetGameMode()->IsTrue( "is_horse" ) )
{
// grab the current horse node
node = Obj::GetRestartNode( Script::GenerateCRC( "horse" ), GetHorse()->GetCurrentRestartIndex() );
}
else
{
index = gamenet_man->GetSkaterStartingPoint( index );
node = Obj::GetRestartNode( Script::GenerateCRC( "Multiplayer" ), index );
// if we did not find one, then try the first generic restart
if (node == -1)
{
printf ("\n\nWARNING - no multiplayer restart point, trying player1\n\n");
// If no Playern, then try player1
node = Obj::GetRestartNode( Script::GenerateCRC( "Player1" ), 0 );
}
}
}
else
{
node = Obj::GetRestartNode( Script::GenerateCRC( "Player1" ), index );
}
// If No player 1, then use generic
if (node == -1)
{
printf ("\n\nWARNING - no Player1 restart point, trying Generic\n\n");
node = Obj::GetRestartNode( 0, 0 );
}
// If No player 1, then use generic
if( node == -1 )
{
printf( "\n\nWARNING - No restart points found\n\n" );
}
return node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::skip_to_restart_point( Obj::CSkater* skater, int node, bool walk )
{
if (node == -1)
{
node = find_restart_node( skater->GetID() );
}
// ...and jump to it
if (node != -1)
{
skater->SkipToRestart( node, walk );
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::move_to_restart_point( Obj::CSkater* skater )
{
skip_to_restart_point(skater, -1);
/* Dan: MoveToRestart is deprecated. We'll use skip instead.
int node;
node = find_restart_node( skater->GetID() );
if (node != -1)
{
skater->MoveToRestart(node);
}
*/
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::remove_skater( Obj::CSkater* skater )
{
Dbg_Assert( skater );
// (Mick) Now check for bailboard, and kill it
// Bit of a patch really, but a fairly safe high level one.
// (need a more general solution for killing model that has
// instances...)
Obj::CCompositeObject*p_bailboard = (Obj::CCompositeObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID(CRCD(0x884ef81b, "bailboard") + skater->GetID());
if( p_bailboard )
{
p_bailboard->MarkAsDead();
Obj::CCompositeObjectManager::Instance()->FlushDeadObjects();
}
// destroy any car the non-local skater might have
if( !skater->IsLocalClient() )
{
Script::CStruct* p_params = new Script::CStruct;
p_params->AddChecksum(CRCD(0x5b24faaa, "SkaterId"), skater->GetID());
Script::RunScript(CRCD(0x5b3fdccb, "remove_car_from_non_local_skater"), p_params);
delete p_params;
}
// save off CAT params
if( skater->IsLocalClient() && ( skater->GetSkaterNumber() == 0 ))
{
if (spCATData)
{
Dbg_Assert( 0 );
delete spCATData;
spCATData=NULL;
}
printf("CAT: Storing Created Trick data\n");
spCATData=new Script::CStruct;
skater->AddCATInfo(spCATData);
// save stat goal info too...
if (spStatData)
{
Dbg_Assert( 0 );
delete spStatData;
spStatData=NULL;
}
printf("CAT: Storing Stat Goal data\n");
spStatData=new Script::CStruct;
skater->AddStatGoalInfo(spStatData);
}
skater->GetLinkNode()->Remove();
//Obj::Unlock( skater );
//Obj::Destroy( skater );
delete skater;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::SkatersAreIdle()
{
//GameNet::Manager* gamenet_man = GameNet::Manager::Instance();
#ifdef __USER_GARY__
// GJ: this assert was firing off for some reason.
// it doesn't seem to have any negative impact, but i'd
// like to look at it later, when i've got more time
// Dbg_Assert( GetGameMode()->EndConditionsMet() );
#endif
bool all_idle = true;
for ( uint32 i = 0; i < GetNumSkaters(); i++ )
{
Obj::CSkater* pSkater = GetSkater( i );
Dbg_Assert( pSkater );
if ( GetGameMode()->IsTrue( "is_horse" ) )
{
// only need to check the current horse skater
if ( GetHorse()->GetCurrentSkaterId() != (int) pSkater->GetID() )
{
continue;
}
}
Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(pSkater);
Dbg_Assert(p_skater_endrun_component);
if ( !p_skater_endrun_component->RunHasEnded() )
{
all_idle = false;
if( pSkater->IsLocalClient())
{
p_skater_endrun_component->EndRun();
}
}
}
// In network games, don't base it on whether skater objects are idle as this is unreliable.
// Instead, base it on "GameIsOver()" which uses reliable transport messages
/*if( gamenet_man->InNetGame())
{
return gamenet_man->GameIsOver();
}*/
return all_idle;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::FirstTrickStarted()
{
// you should only call this function in horse mode
Dbg_Assert( GetGameMode()->IsTrue("is_horse") );
Obj::CSkater* pSkater = GetSkaterById( GetHorse()->GetCurrentSkaterId() );
Dbg_Assert( pSkater );
Obj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);
Dbg_Assert( pTrickComponent );
if ( pTrickComponent->FirstTrickStarted() )
{
// if the trick has started, then end the run, yo!
Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(pSkater);
Dbg_Assert(p_skater_endrun_component);
p_skater_endrun_component->EndRun();
}
return pTrickComponent->FirstTrickStarted();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::FirstTrickCompleted()
{
// you should only call this function in horse mode
Dbg_Assert( GetGameMode()->IsTrue("is_horse") );
Obj::CSkater* pSkater = GetSkaterById( GetHorse()->GetCurrentSkaterId() );
Dbg_Assert( pSkater );
Obj::CTrickComponent* pTrickComponent = GetTrickComponentFromObject(pSkater);
Dbg_Assert( pTrickComponent );
return pTrickComponent->FirstTrickCompleted();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::PauseGameFlow( bool paused )
{
Dbg_AssertPtr( mp_gameFlow );
mp_gameFlow->Pause( paused );
}
//////////////////////////////////////////////////////////////////////
// void Skate::BeepTimer(float time, float beep_time, float beep_speed, const char *p_script_name)
// given a time, run a script if that time is less than beep_time, and again, with increasing
// frequency. Note use of static vars, means this is a single use fn. Intetended for a single timer
// time = time remaining in seconds
// beep_time = time at which to start beeping
// beep_speed = relative speed at whcih beeps increase 10.0 is good
// p_script_name = script to run for each beep
//
// example:
//
// BeepTimer(time,10.0f, 10.0f,"timer_runout_beep");
//
void Skate::BeepTimer(float time, float beep_time, float beep_speed, const char *p_script_name)
{
static float next_beep_time;
if (time > 0.01f && time <= beep_time)
{
if (time<next_beep_time)
{
Script::RunScript( p_script_name, NULL, NULL );
float sub = next_beep_time/beep_speed;
if (sub<0.2f) // limit the delay between beeps
{
sub=0.2f;
}
next_beep_time -= sub; // Make Urgent smaller, but less so as time remain, so frequency rises
}
}
else
{
next_beep_time = beep_time;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
static void do_CheckModelActive(Obj::CObject *pOb, void *pVoidData)
{
Obj::CCompositeObject* pCompositeObject = (Obj::CCompositeObject*)pOb;
Obj::CSuspendComponent* pSuspendComponent = GetSuspendComponentFromObject( pCompositeObject );
if ( pSuspendComponent )
{
pSuspendComponent->CheckModelActive();
}
}
void Skate::DoUpdate()
{
#ifdef __MOVIES_FROM_SKATE_UPDATE__
if ( !Mdl::FrontEnd::Instance()->GamePaused() && !Mdl::CViewer::sGetViewMode() )
{
if ( mp_movieManager->IsRolling() )
{
if ( mp_movieManager->GetActiveCamera() )
{
// hardcoded to viewport 0... if we need the other
// viewports to play movies then we can store it
// in the details...
Nx::CViewportManager::sSetCamera( 0, mp_movieManager->GetActiveCamera() );
}
// hides the loading screen, if any
if ( m_lastFrameWasMovieCamera )
{
Script::RunScript( CRCD(0xc5c9373a,"hide_loading_screen") );
}
mp_movieManager->Update();
m_lastFrameWasMovieCamera = true;
}
else
{
// the camera just finished
if ( m_lastFrameWasMovieCamera )
{
Script::RunScript( CRCD(0x15674315,"restore_skater_camera") );
m_lastFrameWasMovieCamera = false;
}
}
// play any extra object anims that might be playing
// (this might be phased out later)
if ( mp_objectAnimManager->IsRolling() )
{
mp_objectAnimManager->Update();
}
}
#endif
// Fills in a little structure with some stuff so that SkipLogic is really fast.
pre_calculate_object_update_info();
// called once per frame
Script::RunScript( CRCD(0x1aef674f,"Game_Update") );
// Mick: PATCH
// if the game is paused, then manually update the visibility of the game object
// as we might be moving the camera around (Like in the view-goals screen)
if ( Mdl::FrontEnd::Instance()->GamePaused())
{
GetObjectManager()->ProcessAllObjects(do_CheckModelActive);
}
//
#if 1
// Temp hack, for each viewport, run proxim-update on it, hooking it up to the appropiate camera
// Perhaps a better solution would be to have a non-suspendable component
// that is attached to the skater, and grabs the viewport/camera itself
// But what about when the game is paused?
if( GetLocalSkater())
{
int viewports = Nx::CViewportManager::sGetNumActiveViewports();
switch (viewports)
{
case 1:
if (Nx::CViewportManager::sGetActiveCamera(0))
{
Proxim_Update(1<<0, GetLocalSkater(), Nx::CViewportManager::sGetActiveCamera(0)->GetPos());
}
else
{
#ifdef __NOPT_ASSERT__
printf ("WARNING: 1 viewport, but no active camera 0\n");
#endif
}
break;
case 2:
if (Nx::CViewportManager::sGetCamera(0))
{
Proxim_Update(1<<0, Obj::CCompositeObjectManager::Instance()->GetObjectByID(0), Nx::CViewportManager::sGetCamera(0)->GetPos());
}
// Need to check that the second skater exists, as well as the viewport
if (Nx::CViewportManager::sGetCamera(1) && Obj::CCompositeObjectManager::Instance()->GetObjectByID(1))
{
Proxim_Update(1<<1, Obj::CCompositeObjectManager::Instance()->GetObjectByID(1), Nx::CViewportManager::sGetCamera(1)->GetPos());
}
break;
default:
Dbg_MsgAssert(0,("Don't handle %d viewport proxim updating",viewports));
}
}
else if (CFuncs::ScriptIsObserving(NULL, NULL)) // TT12029: Run without object in observer mode
{
int viewports = Nx::CViewportManager::sGetNumActiveViewports();
switch (viewports)
{
case 1:
if (Nx::CViewportManager::sGetActiveCamera(0))
{
Obj::Proxim_Update(1<<0, NULL, Nx::CViewportManager::sGetActiveCamera(0)->GetPos());
}
else
{
#ifdef __NOPT_ASSERT__
printf ("WARNING: 1 viewport, but no active camera 0\n");
#endif
}
break;
default:
Dbg_MsgAssert(0,("Don't handle %d viewport proxim updating in observer mode",viewports));
}
}
else
{
#ifdef __NOPT_ASSERT__
// printf ("WARNING: No local skater, so no Proxim updates\n");
#endif
}
#endif
if ( m_levelChanged )
{
#ifdef __DEFERRED_CLEANUP_TEST__
CFuncs::ScriptPrintMemInfo( NULL, NULL );
#endif
m_levelChanged = false;
}
// don't think i need this anymore
if (GetGameMode()->IsFrontEnd())
{
// if the front end is active, then don't update
return;
}
// =================== TIMER STUFF ===========================
// display the appropriate time if necessary
// (we don't use or show a clock in certain game modes)
Game::CGoalManager* pGoalManager = Game::GetGoalManager();
if ( !Replay::RunningReplay() && pGoalManager->ShouldUseTimer() )
{
Tmr::Time time_left = (pGoalManager->GetGoalTime() + 999) / 1000;
// int time_left = m_time_limit - Tmr::InSeconds( front_end->GetGameTime());
if( time_left < 1 )
{
time_left = 0;
}
int seconds = time_left % 60;
int minutes = time_left / 60;
Front::SetTimeTHPS4(minutes, seconds);
//m_panelMgr->SetTime(minutes, seconds);
/* if (GetGameMode()->ShouldTimerBeep())
{
//float time = (float)m_time_limit - front_end->GetGameTime()/1000.0f;
float time = float(time_left);
BeepTimer(time,10.0f, 10.0f,"timer_runout_beep");
}
*/
}
else
{
Front::HideTimeTHPS4();
}
// make sure everyone's controller is still plugged in
#ifdef __PLAT_XBOX__
int is_changing_levels = Script::GetInteger( CRCD(0xe997db9f,"is_changing_levels"), Script::ASSERT );
int check_controllers = Script::GetInteger( CRCD(0x77a5662c,"check_for_unplugged_controllers"), Script::ASSERT );
if ( check_controllers && !is_changing_levels )
{
if ( m_first_input_received )
{
Front::CScreenElementManager* p_screen_elem_man = Front::CScreenElementManager::Instance();
Front::CScreenElement* p_root_window = p_screen_elem_man->GetElement( CRCD(0x56a1eae3,"root_window") , Front::CScreenElementManager::DONT_ASSERT );
if ( p_root_window )
{
// check that the box isn't already up
Front::CScreenElement* p_error_box = p_screen_elem_man->GetElement( CRCD(0x2edb780f,"controller_unplugged_dialog_anchor") , Front::CScreenElementManager::DONT_ASSERT );
if ( !p_error_box )
{
bool controller_unplugged = false;
for ( int i = 0; i < vMAX_SKATERS; i++ )
{
Obj::CSkater* pSkater = GetSkater( i );
if ( pSkater && pSkater->IsLocalClient() )
{
Inp::Handler< Obj::CInputComponent >* pHandler = pSkater->mp_input_component->GetInputHandler();
if ( !pHandler->m_Device->IsPluggedIn() )
{
// m_controller_unplugged_frame_count++;
controller_unplugged = true;
if ( m_controller_unplugged_frame_count > Script::GetInteger( CRCD(0xf7fabb50,"controller_unplugged_frame_count"), Script::ASSERT ) )
{
m_controller_unplugged_frame_count = 0;
Script::CStruct* pScriptParams = new Script::CStruct();
GameNet::Manager* gamenet_man = GameNet::Manager::Instance();
if ( gamenet_man->InNetGame() )
{
Game::CGoalManager* pGoalManager = Game::GetGoalManager();
Dbg_Assert( pGoalManager );
pGoalManager->DeactivateAllGoals();
pGoalManager->UninitializeAllGoals();
pScriptParams->AddChecksum( NONAME, CRCD(0xeaa48e14,"leaving_net_game") );
Skate::LeaveServer();
if ( gamenet_man->OnClient() )
{
gamenet_man->CleanupPlayers();
gamenet_man->ClientShutdown();
}
}
// get the device that's unplugged
int device_num = pHandler->m_Device->GetPort();
pScriptParams->AddInteger( CRCD(0xc9428a08,"device_num"), device_num );
Script::RunScript( CRCD(0xf77aca62,"controller_unplugged"), pScriptParams );
delete pScriptParams;
break;
}
}
}
}
if ( controller_unplugged )
m_controller_unplugged_frame_count++;
else
m_controller_unplugged_frame_count = 0;
}
}
}
}
#endif // __PLAT_NGC__
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetTimeLimit( int seconds )
{
m_time_limit = seconds;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | SetTimeLimit | sets the time limit
// @parmopt int | seconds | 120 | number of seconds for time limit
bool ScriptSetTimeLimit(Script::CStruct *pParams, Script::CScript *pScript) {
int seconds = 120;
pParams->GetInteger( "seconds", &seconds );
Skate* skate = Skate::Instance();
skate->SetTimeLimit( seconds );
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int Skate::GetTimeLimit( void )
{
return m_time_limit;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::UpdateGameFlow()
{
Dbg_Assert( mp_movieManager );
#ifndef __MOVIES_FROM_SKATE_UPDATE__
if ( !Mdl::FrontEnd::Instance()->GamePaused() && !Mdl::CViewer::sGetViewMode() )
{
if ( mp_movieManager->IsRolling() )
{
if ( mp_movieManager->GetActiveCamera() )
{
// hardcoded to viewport 0... if we need the other
// viewports to play movies then we can store it
// in the details...
Nx::CViewportManager::sSetCamera( 0, mp_movieManager->GetActiveCamera() );
}
// hides the loading screen, if any
if ( m_lastFrameWasMovieCamera )
{
Script::RunScript( CRCD(0xc5c9373a,"hide_loading_screen") );
}
mp_movieManager->Update();
m_lastFrameWasMovieCamera = true;
}
else
{
// the camera just finished
if ( m_lastFrameWasMovieCamera )
{
Script::RunScript( CRCD(0x15674315,"restore_skater_camera") );
m_lastFrameWasMovieCamera = false;
}
}
// play any extra object anims that might be playing
// (this might be phased out later)
if ( mp_objectAnimManager->IsRolling() )
{
mp_objectAnimManager->Update();
}
}
#endif
Dbg_AssertPtr( mp_gameFlow );
mp_gameFlow->Update();
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
Skate::Skate ( void )
{
m_first_input_received = false;
m_controller_unplugged_frame_count = 0;
m_logic_task = new Tsk::Task< Skate > ( Skate::s_logic_code, *this );
net_setup();
mp_PlayerProfileManager = new Obj::CPlayerProfileManager;
mp_PlayerProfileManager->Reset();
mp_gameFlow = new CGameFlow;
mp_goalManager = new Game::CGoalManager;
// mp_obj_manager = new Obj::CGeneralManager;
// Bit of a patch, but the engine now needs to be told what is managing the moving objects
// When Skate.cpp is broken up, then the mp_obj_manager needs extracting into some more generic "game object" manager
// which Nx can query, if it really needs to
Nx::CEngine::sSetMovableObjectManager(GetObjectManager());
mp_gameMode = new Game::CGameMode;
mp_career = new Obj::CSkaterCareer; // new local careeer
mp_railManager = new Obj::CRailManager;
# ifdef TESTING_GUNSLINGER
mp_navManager = new Obj::CNavManager;
# endif
mp_trickChecksumTable = new Obj::CTrickChecksumTable;
mp_trickObjectManager = new Obj::CTrickObjectManager;
mp_trickObjectManager->DeleteAllTrickObjects();
m_recording = false;
m_playing = false;
m_fd = 0;
m_gameInProgress = false;
m_levelLoaded = false;
SetGameType( Script::GenerateCRC("freeskate") );
// initialize the splitscreen preferences
mp_splitscreen_preferences = new Prefs::Preferences;
mp_splitscreen_preferences->Load( Script::GenerateCRC("default_splitscreen_preferences" ) );
mp_competition = new CCompetition;
mp_horse = new CHorse;
mp_movieManager = new Obj::CMovieManager;
mp_objectAnimManager = new Obj::CMovieManager;
mp_gameRecords = new Records::CGameRecords(Obj::CSkaterCareer::vMAX_CAREER_LEVELS);
m_shadow_mode = Gfx::vSIMPLE_SHADOW;
// Initialise the controller preferences.
// These might get changed by an autoload off the memory card.
for (int i=0; i<vMAX_SKATERS; ++i)
{
m_device_server_map[i] = -1;
mp_controller_preferences[i].skaterIndex = i;
mp_controller_preferences[i].VibrationOn=true;
SetAutoKick(i,true);
SetSpinTaps(i,false);
}
// so that autolaunch works
m_device_server_map[0] = 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Skate::~Skate ( void )
{
delete mp_gameRecords;
delete mp_competition;
delete mp_horse;
delete mp_movieManager;
delete mp_objectAnimManager;
delete mp_railManager;
delete mp_career;
// delete mp_obj_manager;
net_shutdown();
Dbg_Assert( mp_gameFlow );
delete mp_gameFlow;
Dbg_Assert( mp_gameMode );
delete mp_gameMode;
Dbg_Assert( mp_goalManager );
delete mp_goalManager;
Dbg_Assert( mp_PlayerProfileManager );
delete mp_PlayerProfileManager;
delete m_logic_task;
delete mp_splitscreen_preferences;
delete mp_trickChecksumTable;
delete mp_trickObjectManager;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetSpinTaps(int index, bool state)
{
Dbg_MsgAssert(index>=0 && index<vMAX_SKATERS,("Bad index"));
mp_controller_preferences[index].SpinTapsOn=state;
Obj::CSkater *p_skater = GetSkater(index);
if (p_skater)
{
GetSkaterCorePhysicsComponentFromObject(p_skater)->m_spin_taps=state;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetAutoKick(int index, bool state)
{
Dbg_MsgAssert(index>=0 && index<vMAX_SKATERS,("Bad index"));
mp_controller_preferences[index].AutoKickOn=state;
Obj::CSkater *p_skater = GetSkater(index);
if (p_skater)
{
GetSkaterCorePhysicsComponentFromObject(p_skater)->m_auto_kick=state;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetVibration(int index, bool state)
{
Dbg_MsgAssert(index>=0 && index<vMAX_SKATERS,("Bad index"));
mp_controller_preferences[index].VibrationOn=state;
Obj::CSkater *p_skater = GetSkater(index);
if (p_skater)
{
Obj::CVibrationComponent* p_vibration_component = GetVibrationComponentFromObject(p_skater);
if (p_vibration_component)
{
p_vibration_component->SetActiveState(state);
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CSkater* Skate::GetLocalSkater( void )
{
unsigned int i;
for( i = 0; i < GetNumSkaters(); i++ )
{
if( m_skaters.GetItem(i) != NULL )
{
Obj::CSkater *pSkater = m_skaters.GetItem(i)->GetData();
if( pSkater->IsLocalClient())
{
return pSkater;
}
}
}
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CSkater *Skate::GetSkater( uint num )
{
if( GetNumSkaters() <= num )
{
return NULL;
}
else
{
Dbg_Assert( m_skaters.GetItem( num ) );
return m_skaters.GetItem( num )->GetData();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CSkater *Skate::GetSkaterById( uint32 id )
{
for (uint i = 0; i < GetNumSkaters(); i++)
{
if( m_skaters.GetItem(i) != NULL )
{
Obj::CSkater *pSkater = m_skaters.GetItem(i)->GetData();
if (pSkater->GetID() == id)
return pSkater;
}
}
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CGeneralManager* Skate::GetObjectManager( void )
{
// return mp_obj_manager;
return Obj::CCompositeObjectManager::Instance();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CTrickObjectManager* Skate::GetTrickObjectManager( void )
{
return mp_trickObjectManager;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CPlayerProfileManager* Skate::GetPlayerProfileManager( void )
{
return mp_PlayerProfileManager;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Prefs::Preferences* Skate::GetSplitScreenPreferences( void )
{
return mp_splitscreen_preferences;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
float Skate::GetHandicap( int id )
{
Prefs::Preferences* pPreferences = GetSplitScreenPreferences();
Script::CStruct* pStructure = NULL;
switch ( id )
{
case 0:
pStructure = pPreferences->GetPreference( Script::GenerateCRC("player1_handicap") );
break;
case 1:
pStructure = pPreferences->GetPreference( Script::GenerateCRC("player2_handicap") );
break;
default:
Dbg_MsgAssert( 0, ( "Out of range handicap id %d", id ) );
break;
}
Dbg_Assert( pStructure );
int val = 0;
pStructure->GetInteger( "time", &val ); // stored in the time field... ugly!
return val;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// The Skate::Cleanup function is essentially cleaning up
// the "Session" objects.
// It does not unload any assets, just deletes objects that were valid for the session
void Skate::Cleanup()
{
uint32 i;
printf("Skate::Cleanup() - Deleting all session specific objects\n");
// Resetting the skater is complicated
// in that we have to lock him, to make sure he is not deleted
// and then reset him manually, as we can't just delete and re-create him (yet)
for (i=0;i<GetNumSkaters();i++)
{
Obj::CSkater* skater;
skater = GetSkater(i);
if (skater)
{
skater->SetLockOn(); // Sets the "lock" flag, so he won't get deleted by DestroyAllObjects
if( skater->IsLocalClient())
{
skater->ResetPhysics(false, true);
// stop any movies associated with each skater
this->GetMovieManager()->ClearMovieQueue();
}
skater->DeleteResources(); // blood, gap checkslistm shodow
//skater->SwitchOffShadow();
skater->RemoveFromCurrentWorld();
}
}
// Clear the movies used for moving object anims
GetMovieManager()->ClearMovieQueue();
GetObjectAnimManager()->ClearMovieQueue();
// clear out the viewer object, if any
Mdl::CViewer* pViewer = Mdl::CViewer::sGetViewer();
if ( pViewer )
{
pViewer->RemoveViewerObject();
}
// Destroy all level objects. Basically anything created with the node array
GetObjectManager()->DestroyAllObjects();
GetObjectManager()->FlushDeadObjects();
// For now we destory all the composite objects here as well
// Obj::CCompositeObjectManager::Instance()->UnlockAllObjects();
// Obj::CCompositeObjectManager::Instance()->DestroyAllObjects();
// Obj::CCompositeObjectManager::Instance()->FlushDeadObjects();
// Now remove the lock on the skaters' objects
for (i=0;i<GetNumSkaters();i++)
{
Obj::CSkater* skater;
skater = GetSkater(i);
if (skater)
{
skater->SetLockOff(); // Clears the "lock" flag
skater->AddToCurrentWorld();
}
}
// The gamenet managers objects (crown, compass... )
// have now been destroyed so Nullify references to them
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
gamenet_man->CleanupObjects();
// Little sanity check, to make sure everyhting except the skater is gone
// sint pTypes[]={SKATE_TYPE_SKATER,-1};
// GetObjectManager()->AssertIfObjectsRemainApartFrom(pTypes);
// unlock the skaters, as they will be the only remaining objects
//GetObjectManager()->UnlockAllObjects();
// Delete any leftover spawned scripts.
// (NB, might not want to do this, if the gameflow has spawned scripts?
// but we probably do, as most of it will be session specific scripts
Script::DeleteSpawnedScripts();
// Delete all the trick objects that were created for this session
mp_trickObjectManager->DeleteAllTrickObjects();
// destroy the list of gapchecks (checklist of all gaps in the level)
// (maybe we would keep this from session to session?)
// m_gapcheck_list.DestroyAllNodes();
// Destroy the new style particle systems....
// or not, as they are now all destroyed by the controlling objects, or the object manager
// so, if we did destroy them here, then the blood splat would stop working.
Nx::destroy_all_temp_particles( );
// Destroy rails, they get re-created from the node array
GetRailManager()->Cleanup();
// Destroy Proximity nodes, similar to rails
Obj::Proxim_Cleanup();
// Destroy EmitterObjects
Obj::CEmitterManager::sCleanup();
// cleanup particles
Dbg_Printf( "Destroying particle systems..." );
Nx::CEngine::sGetParticleManager()->Cleanup();
// This is a debugging function to see what's
// currently in the anim cache (at this point,
// only a handful of skater anims should be
// in the cache)
// Nx::PrintAnimCache();
}
// Cleaup stuff that might have been created in the park editor test play
void Skate::CleanupForParkEditor()
{
mp_trickObjectManager->DeleteAllTrickObjects();
Nx::KillAllTextureSplats();
Nx::destroy_all_temp_particles( );
GetRailManager()->Cleanup();
Obj::Proxim_Cleanup();
Obj::CEmitterManager::sCleanup();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::Pause( bool pause )
{
if ( pause )
{
Sfx::CSfxManager * sfx_manager = Sfx::CSfxManager::Instance();
sfx_manager->PauseSounds( );
// Pcm::PauseMusic( 1 );
// Pcm::PauseStream( 1 );
}
else
{
// unpause music if game is active:
if ( IsGameInProgress( ) )
{
// Pcm::PauseMusic( 0 );
// Pcm::PauseStream( 0 );
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::RequestGameEnd()
{
m_gameInProgress = false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Game::CGameMode *Skate::GetGameMode(void)
{
return mp_gameMode;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Game::CGoalManager* Skate::GetGoalManager(void)
{
return mp_goalManager;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CSkaterProfile* Skate::GetCurrentProfile( Script::CStruct *pParams )
{
Dbg_MsgAssert( mp_PlayerProfileManager,( "No skater profile manager\n" ));
int skaterNum;
if ( pParams && pParams->GetInteger( "skater", &skaterNum ) )
{
return mp_PlayerProfileManager->GetProfile( skaterNum );
}
else
{
return mp_PlayerProfileManager->GetCurrentProfile();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Obj::CSkaterProfile* Skate::GetProfile( int skaterNum )
{
Dbg_MsgAssert( mp_PlayerProfileManager,( "No skater profile manager\n" ));
return mp_PlayerProfileManager->GetProfile( skaterNum );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetGameType(uint32 gameType)
{
// Don't set this right away...
// GetGameMode()->LoadGameType( gameType );
m_requested_game_type = gameType;
// Instead, remember it, and
// commit the change when we do the "setgamestate on"
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetCurrentGameType()
{
printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Changing Game Mode\n");
GetGameMode()->LoadGameType( m_requested_game_type );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::OpenLevel(uint32 level_script)
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
// CloseLevel();
Mem::PushMemProfile("LaunchLevel");
if( gamenet_man->InNetGame())
{
if( gamenet_man->OnServer())
{
Lst::Search< GameNet::PlayerInfo > sh;
GameNet::PlayerInfo* player;
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))
{
player->MarkAsNotReady( 0 );
}
}
}
if (level_script == Script::GenerateCRC("custom_park"))
{
;
}
else
{
#ifdef __NOPT_ASSERT__
// Make sure it exists, otherwise we crash obscurely...
Script::CSymbolTableEntry *p_entry=Script::Resolve(level_script);
Dbg_MsgAssert(p_entry,("Level script %x (%s) not found",level_script,Script::FindChecksumName(level_script)));
#endif
Script::RunScript(level_script);
}
m_levelLoaded = true;
m_cur_level = level_script;
if( gamenet_man->InNetGame())
{
int i;
for( i = 0; i < GameNet::vMAX_LOCAL_CLIENTS; i++ )
{
Lst::Search< Net::Conn > sh;
Net::Conn* server_conn;
Net::Client* client;
client = gamenet_man->GetClient( i );
if( client )
{
server_conn = client->FirstConnection( &sh );
if( server_conn )
{
server_conn->UpdateCommTime( Tmr::Seconds( 12 )); // update the current comm time so it doesn't time out after
// loading the skater
}
}
}
if( gamenet_man->OnServer())
{
Lst::Search< Net::Conn > sh;
Net::Conn* conn;
Net::Server* server;
server = gamenet_man->GetServer();
if( server )
{
for( conn = server->FirstConnection( &sh ); conn;
conn = server->NextConnection( &sh ))
{
conn->UpdateCommTime( Tmr::Seconds( 8 )); // update the current comm time so it doesn't time out after
// loading the skater
}
}
}
else
{
// If we have some queued up new players, we'll respond to the ready query
// after we finish loading them. Otherwise, if this is just a standard change level
// call, tell the server we're finished loading it and ready to communicate
Lst::Search< GameNet::NewPlayerInfo > sh;
if( gamenet_man->FirstNewPlayerInfo( sh ) == NULL )
{
gamenet_man->RespondToReadyQuery();
}
}
}
Mem::PopMemProfile(/*"LaunchLevel"*/);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// RestartLevel is just intended to be called when a level is restarted
// it does not actually restart the level, it just sets a few flags
// and does something with disabling the the viewer log that's only related to screenshot mode
void Skate::RestartLevel()
{
// clear the end run flag
ClearEndRun();
// GJ: in a network lobby, the skater is loaded AFTER the
// level so this return wouldn't work... come to think
// of it, what's it needed for?
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
if ( !GetNumSkaters() && !gamenet_man->InNetGame() )
{
Ryan("BAD BAD BAD\n");
return;
}
if (!m_levelLoaded)
{
Ryan("BAD BAD BAD\n");
return;
}
// the game is now on
if ( GetGameMode()->IsFrontEnd() )
{
// don't let the career timer go until
// we're actually in a real level,
// otherwise, we'll get "Requested MenuScreen
// not active" asserts
m_gameInProgress = false;
}
else
{
m_gameInProgress = true;
// Mdl::RwViewer * rwviewer_mod = Mdl::RwViewer::Instance();
// rwviewer_mod->DisableMainLogic( false ); // reset
}
if ( gamenet_man->InNetGame() )
{
#if 0
// unpause the game if we're in the network lobby
Mdl::FrontEnd* frontend = Mdl::FrontEnd::Instance();
frontend->SetActive(false);
#endif
}
// Mick: tell the career mode that we are just starting this level
// so it will remember what the flags were at the start of the level
GetCareer()->StartLevel();
// print debug info
GetTrickObjectManager()->PrintContents();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::ChangeLevel( uint32 level_id )
{
//GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
// changes level while preserving the skaters
// Mick - moved this in ScriptCleanup
// Game::CGoalManager* p_GoalManager = Game::GetGoalManager();
// Dbg_MsgAssert( p_GoalManager, ( "couldn't get GoalManager\n" ) );
// p_GoalManager->LevelUnload();
// p_GoalManager->DeactivateAllGoals();
// p_GoalManager->RemoveAllGoals();
printf ("-----------------------------------------Skate::ChangeLevel(%d)\n",level_id);
//uint32 i;
Script::CStruct* pTempStructure;
// TODO: is this necessary? since we push individual heaps below
// maybe, if there is anyhting else that might allocate stuff
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().SkaterInfoHeap());
// requests the new level...
pTempStructure = new Script::CStruct;
pTempStructure->Clear();
pTempStructure->AddComponent( Script::GenerateCRC("level"), ESYMBOLTYPE_NAME, (int)level_id );
Script::RunScript( "request_level", pTempStructure );
delete pTempStructure;
m_prev_level = m_cur_level;
m_cur_level=level_id;
// removes the skaters from the existing world
// (skate::cleanup func used to take care of this
// but now it's in ScriptCleanup
/*if( !gamenet_man->InNetGame())
{
for ( i = 0; i < GetNumSkaters(); i++ )
{
Obj::CSkater* pSkater = GetSkater( i );
pSkater->RemoveFromCurrentWorld();
}
}*/
// cleans up everything but the skaters
pTempStructure = new Script::CStruct;
pTempStructure->Clear();
// If we're going back to the skateshop, clean up any extra skater heaps we may have allocated
if( level_id != Script::GenerateCRC( "load_skateshop" ))
{
pTempStructure->AddComponent( NONAME, ESYMBOLTYPE_NAME, (int)Script::GenerateCRC("preserve_skaters") );
}
CFuncs::ScriptCleanup( pTempStructure, NULL );
delete pTempStructure;
m_levelChanged = true;
//if( gamenet_man->InNetGame())
//{
//Script::RunScript( "create_score_menu" );
//}
// restarts the gameflow
Dbg_AssertPtr( mp_gameFlow );
mp_gameFlow->Reset( Script::GenerateCRC( "ChangeLevelGameFlow" ) );
Mem::Manager::sHandle().PopContext();
}
void Skate::ResetLevel()
{
GameNet::Manager* gamenet_man = GameNet::Manager::Instance();
// Cleanup existing level specific stuff
Cleanup();
// Re-trigger all the objects in the level
CFuncs::ScriptParseNodeArray(NULL,NULL);
// clear the end run flag
ClearEndRun();
// now that the trick object database is set,
// we can apply any graffiti state queued up in the trick
// object manager
GetTrickObjectManager()->ApplyObserverGraffitiState();
Game::CGoalManager* pGoalManager = Game::GetGoalManager();
if( gamenet_man->InNetGame())
{
pGoalManager->InitializeAllMinigames();
pGoalManager->UnBeatAllGoals();
}
else
{
pGoalManager->InitializeAllGoals();
}
pGoalManager->CreateGoalLevelObjects();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::ResetSkaters(int node, bool walk)
{
// Skip skaters to restart points (will also reset their physics states)
for (uint32 i=0;i<GetNumSkaters();i++)
{
Obj::CSkater* pSkater = GetSkater( i );
Dbg_MsgAssert ( pSkater,( "No skater" ));
if ( pSkater->IsLocalClient() )
{
skip_to_restart_point( pSkater, node, walk );
}
// We Resync() the skater here, as he has just restarted
// he also moves on the client
// however, the client does not know he has to restart yet
// so will still be sending old positions
// we need to tell the clients all the restart
// and then not take any positions from them until they acknowledge
// that they have carried out this restart
// This would involved calling Resync each frame until they acknowledge having restarted
// or we could just resync every frame for a period of time
// however, that seems rather dodgy, as you have no way of knowing
// how long you should resync for
pSkater->Resync();
// So... how do we do that then Steve?
}
ClearEndRun();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::LaunchGame()
{
Mdl::FrontEnd * front = Mdl::FrontEnd::Instance();
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
front->PauseGame(false);
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
printf ("\nLAUNCH GAME CALLED with %d skaters \n\n",GetNumSkaters());
//if (!GetNumSkaters())
if( !gamenet_man->GetLocalPlayer())
{
Dbg_Printf( "*** NO LOCAL PLAYER\n" );
// If we are starting a game with possibly more than two players
// then we want to allocate
Dbg_Printf( "*** Max players: %d\n", GetGameMode()->GetMaximumNumberOfPlayers());
if (GetGameMode()->GetMaximumNumberOfPlayers() > NUM_PERM_SKATER_HEAPS)
{
Mem::Manager::sHandle().InitSkaterHeaps(GetGameMode()->GetMaximumNumberOfPlayers());
}
// start the game flow
Dbg_AssertPtr( mp_gameFlow );
mp_gameFlow->Reset( Script::GenerateCRC( "InitializeGameFlow" ) );
mp_gameFlow->Update();
printf( "\nLeaving Update\n" );
}
else
{
// Reset everything in the level to its initial state
ResetLevel();
// GJ: we are intentionally not rerunning the intro script here
m_gameInProgress = true;
// start the game flow
Dbg_AssertPtr( mp_gameFlow );
mp_gameFlow->Reset( Script::GenerateCRC( "StandardGameFlow" ) );
printf("Restarting game flow\n");
}
// Clear the king of the hill
GameNet::PlayerInfo* player;
Lst::Search< GameNet::PlayerInfo > sh;
if(( player = gamenet_man->GetKingOfTheHill()))
{
player->MarkAsKing( false );
}
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player; player = gamenet_man->NextPlayerInfo( sh, true ))
{
player->ClearCTFState();
}
if( GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netlobby" ))
{
gamenet_man->CreateTeamFlags( GetGameMode()->NumTeams());
}
Mem::Manager::sHandle().PopContext();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::CheckSkaterCollisions( void )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
Obj::CSkater* subject;
int i;
if( gamenet_man->GameIsOver())
{
return;
}
// Only perform the collision logic if player collision is enabled
if( ( gamenet_man->PlayerCollisionEnabled() == false ) &&
( GetGameMode()->GetNameChecksum() != CRCD(0xbff33600,"netfirefight")) &&
( GetGameMode()->GetNameChecksum() != CRCD(0x3d6d444f,"firefight")) &&
( GetGameMode()->GetNameChecksum() != CRCD( 0x6ef8fda0, "netking" )) &&
( GetGameMode()->GetNameChecksum() != CRCD( 0x5d32129c, "king" )) &&
( GetGameMode()->GetNameChecksum() != CRCD( 0x6c5ff266, "netctf" )))
{
return;
}
// Loop through all other skaters and check for collisions
for( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )
{
subject = GetSkater( i );
if( subject == NULL )
{
continue;
}
subject->mp_skater_state_history_component->CollideWithOtherSkaters( 0 );
}
// If we're in king of the hill mode and the crown is on the ground
// perform collision checks to see if someone snags it
if( ( GetGameMode()->GetNameChecksum() == CRCD( 0x6ef8fda0, "netking" )) ||
( GetGameMode()->GetNameChecksum() == CRCD( 0x5d32129c, "king" )))
{
Obj::CCrown* crown;
crown = gamenet_man->GetCrown();
if( crown && !crown->OnKing())
{
for( i = 0; i < Mdl::Skate::vMAX_SKATERS; i++ )
{
subject = GetSkater( i );
if( subject == NULL )
{
continue;
}
if( subject->mp_skater_state_history_component->CheckForCrownCollision())
{
GameNet::PlayerInfo* player;
Lst::Search< GameNet::PlayerInfo > sh;
player = gamenet_man->GetPlayerByObjectID( subject->GetID() );
Dbg_Assert( player );
// It is important that we mark the king immediately (rather than through a
// network message) since we do logic based on the "current" king
player->MarkAsKing( true );
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player;
player = gamenet_man->NextPlayerInfo( sh, true ))
{
// Already marked the king for the local player (above)
if( player->IsLocalPlayer())
{
continue;
}
GameNet::MsgByteInfo msg;
Net::MsgDesc msg_desc;
Net::Server* server;
server = gamenet_man->GetServer();
Dbg_Assert( server );
msg.m_Data = subject->GetID();
msg_desc.m_Data = &msg;
msg_desc.m_Length = sizeof( GameNet::MsgByteInfo );
msg_desc.m_Id = GameNet::MSG_ID_NEW_KING;
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
server->EnqueueMessage( player->GetConnHandle(), &msg_desc );
}
break;
}
}
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::ObserveNextSkater( void )
{
GameNet::PlayerInfo* player;
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
player = gamenet_man->GetNextPlayerToObserve();
gamenet_man->ObservePlayer( player );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
const char* Skate::GetSkaterDisplayName( int id )
{
for ( uint32 j = 0; j < GetNumSkaters(); j++ )
{
if ( (int) GetSkater(j)->GetID() == id )
{
return GetSkater(j)->GetDisplayName();
}
}
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::ShouldBeAbsentNode( Script::CStruct* pNode )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
Dbg_Assert( pNode );
return ( pNode->ContainsFlag( 0x68910ac6 /*"AbsentInNetGames"*/ ) &&
( IsMultiplayerGame() || gamenet_man->InNetMode()));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::IsMultiplayerGame( void )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
return ( gamenet_man->InNetGame() || GetGameMode()->GetInitialNumberOfPlayers() > 1 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::SetShadowMode( Gfx::EShadowType shadowMode )
{
Obj::CSkater* skater;
Lst::Search< Obj::CSkater > sh;
m_shadow_mode = shadowMode;
for( skater = sh.FirstItem( m_skaters ); skater; skater = sh.NextItem())
{
Obj::CShadowComponent* p_shadow_component = GetShadowComponentFromObject(skater);
Dbg_Assert(p_shadow_component);
p_shadow_component->SwitchOnSkaterShadow();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Gfx::EShadowType Skate::GetShadowMode( void ) const
{
return m_shadow_mode;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | SetGameType | Sets the type of game to be played. Examples: <nl>
// SetGameType FreeSkate <nl>
// SetGameType SingleSession
// @uparm name | Game type
bool ScriptSetGameType(Script::CStruct *pParams, Script::CScript *pScript)
{
Skate* skate = Skate::Instance();
uint32 game_type;
pParams->GetChecksum(NONAME, &game_type, true);
skate->SetGameType(game_type);
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | TestGameType | Tests if current game type is equal to the
// game type specified as the first parameter
// @uparm name | Game type
bool ScriptTestGameType(Script::CStruct *pParams, Script::CScript *pScript)
{
uint32 game_type;
pParams->GetChecksum(NONAME, &game_type, true);
Skate* skate = Skate::Instance();
return (game_type == skate->GetGameMode()->GetNameChecksum());
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool ScriptInTeamGame(Script::CStruct *pParams, Script::CScript *pScript)
{
Skate* skate = Skate::Instance();
return skate->GetGameMode()->IsTeamGame();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | TestRequestedGameType |
// This is so that I can tell what the last value sent to SetGameType
// was, since SetGameType will not set the game type straight away,
// so TestGameType will not work.
// @uparm name | Game type
bool ScriptTestRequestedGameType(Script::CStruct *pParams, Script::CScript *pScript)
{
uint32 game_type;
pParams->GetChecksum(NONAME, &game_type, true);
Skate* skate = Skate::Instance();
return (game_type == skate->GetGameType());
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | ChangeLevel |
// @parm string | level | The level to change to
bool ScriptChangeLevel(Script::CStruct *pParams, Script::CScript *pScript)
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
bool show_warning;
uint32 level;
pParams->GetChecksum(Script::GenerateCRC("level"), &level, true);
if( level == Script::GenerateCRC("use_preferences") )
{
level = gamenet_man->GetLevelFromPreferences();
}
gamenet_man->SetLevel( level );
show_warning = pParams->ContainsComponentNamed( "show_warning" );
#ifdef __NOPT_ASSERT__
printf("Send message to ChangeLevel level=%s here!\n", Script::FindChecksumName(level) );
#endif
Pcm::StopMusic();
Net::Server* server;
GameNet::MsgChangeLevel msg;
GameNet::PlayerInfo* player;
Lst::Search< GameNet::PlayerInfo > sh;
server = gamenet_man->GetServer();
Dbg_Assert( server );
msg.m_Level = level;
msg.m_ShowWarning = (char) show_warning;
for( player = gamenet_man->FirstPlayerInfo( sh, true ); player;
player = gamenet_man->NextPlayerInfo( sh, true ))
{
GameNet::MsgReady ready_msg;
Net::MsgDesc msg_desc;
ready_msg.m_Time = Tmr::GetTime();
if( player->IsLocalPlayer() == false )
{
if( level == CRCD(0xb664035d,"Load_Sk5Ed_gameplay"))
{
server->StreamMessage( player->GetConnHandle(), GameNet::MSG_ID_LEVEL_DATA, Ed::CParkManager::COMPRESSED_MAP_SIZE,
Ed::CParkManager::sInstance()->GetCompressedMapBuffer(), "level data",
GameNet::vSEQ_GROUP_PLAYER_MSGS, false, true );
server->StreamMessage( player->GetConnHandle(), GameNet::MSG_ID_RAIL_DATA, Obj::GetRailEditor()->GetCompressedRailsBufferSize(),
Obj::GetRailEditor()->GetCompressedRailsBuffer(), "rail data",
GameNet::vSEQ_GROUP_PLAYER_MSGS, false, true );
}
}
msg_desc.m_Data = &msg;
msg_desc.m_Length = sizeof(GameNet::MsgChangeLevel);
msg_desc.m_Id = GameNet::MSG_ID_CHANGE_LEVEL;
msg_desc.m_Queue = Net::QUEUE_SEQUENCED;
msg_desc.m_GroupId = GameNet::vSEQ_GROUP_PLAYER_MSGS;
server->EnqueueMessage( player->GetConnHandle(), &msg_desc );
if( player->IsLocalPlayer() == false )
{
if( gamenet_man->UsingCreatedGoals())
{
gamenet_man->LoadGoals( level );
server->StreamMessage( player->GetConnHandle(), GameNet::MSG_ID_GOALS_DATA, gamenet_man->GetGoalsDataSize(),
gamenet_man->GetGoalsData(), "goals data", GameNet::vSEQ_GROUP_PLAYER_MSGS, false, true );
}
}
// Don't send them any non-important messages until they're finished loading
msg_desc.m_Data = &ready_msg;
msg_desc.m_Length = sizeof( GameNet::MsgReady );
msg_desc.m_Id = GameNet::MSG_ID_READY_QUERY;
server->EnqueueMessage( player->GetConnHandle(), &msg_desc );
player->SetReadyQueryTime( ready_msg.m_Time );
}
// In net games, the changing of levels is deferred. No need to send immediately - we can
// wait until the enqueued message is naturally added to the outgoing stream. In 2p mode,
// however, the scripts expect this message to be sent and handled in a one-frame window
// so we need to send it immediately
if ( ! gamenet_man->InNetGame())
{
server->SendData(); // Mick, (true) because we want to send it immediatly
}
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | LaunchLevel | launches currently requested level
bool ScriptLaunchLevel(Script::CStruct *pParams, Script::CScript *pScript)
{
Skate* skate_mod = Skate::Instance();
uint32 level = skate_mod->m_requested_level;
skate_mod->OpenLevel(level);
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | RequestLevel |
// @uparm name | level to request
bool ScriptRequestLevel(Script::CStruct *pParams, Script::CScript *pScript)
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
Skate* skate_mod = Skate::Instance();
uint32 level;
// printf ("\n%s\n",pScript->GetScriptInfo());
if( !pParams->GetChecksum(NONAME, &level, false))
{
const char* level_name;
char checksum_name[128];
if( pParams->GetString( NONAME, &level_name, Script::ASSERT ))
{
sprintf( checksum_name, "load_%s", level_name );
Dbg_Printf( "Got checksum name of %s\n", checksum_name );
level = Script::GenerateCRC( checksum_name );
}
}
if( level == Script::GenerateCRC("use_preferences") )
{
level = gamenet_man->GetLevelFromPreferences();
gamenet_man->SetLevel( level );
}
skate_mod->m_requested_level = level;
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | Retry | retry current level
bool ScriptRetry(Script::CStruct *pParams, Script::CScript *pScript)
{
Skate* skate_mod = Skate::Instance();
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
skate_mod->LaunchGame();
Mem::Manager::sHandle().PopContext();
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | LaunchGame |
bool ScriptLaunchGame(Script::CStruct *pParams, Script::CScript *pScript)
{
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
Skate::Instance()->LaunchGame();
Mem::Manager::sHandle().PopContext();
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool ScriptFillRankingScreen(Script::CStruct *pParams, Script::CScript *pScript)
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
Lst::Search< GameNet::PlayerInfo > sh;
GameNet::PlayerInfo* player;
Lst::Head< GameNet::ScoreRank > rank_list;
Lst::Search< GameNet::ScoreRank > rank_sh;
GameNet::ScoreRank* rank, *next;
bool in_goal_attack;
int i;
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap());
in_goal_attack = skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netgoalattack" );
if( skate_mod->GetGameMode()->IsTeamGame())
{
for( i = 0; i < skate_mod->GetGameMode()->NumTeams(); i++ )
{
if( gamenet_man->NumTeamMembers( i ) == 0 )
{
continue;
}
char team_name_str[64];
rank = new GameNet::ScoreRank;
rank->m_IsKing = false;
rank->m_ColorIndex = i + 2;
rank->m_TeamId = i;
rank->m_TotalScore = gamenet_man->GetTeamScore( i );
sprintf( team_name_str, "team_%d_name", i + 1 );
sprintf( rank->m_Name, "\\c%d%s %s", rank->m_ColorIndex, Script::GetString( team_name_str ), Script::GetString( "total_str" ));
rank->SetPri( gamenet_man->GetTeamScore( i ));
rank_list.AddNode( rank );
}
// Now loop through the sorted list in order of highest to lowest score and print them out
i = 0;
for( rank = rank_sh.FirstItem( rank_list ); rank; rank = next )
{
Script::CStruct* p_item_params;
char score_str[64];
next = rank_sh.NextItem();
for( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))
{
char player_score_str[128];
int player_score;
if( player->m_Team != rank->m_TeamId )
{
continue;
}
if( in_goal_attack )
{
Game::CGoalManager* pGoalManager;
pGoalManager = Game::GetGoalManager();
player_score = pGoalManager->NumGoalsBeatenBy( player->m_Skater->GetID());
}
else
{
player_score = gamenet_man->GetPlayerScore( player->m_Skater->GetID());
}
if( player->IsLocalPlayer())
{
sprintf( player_score_str, "\\c%d> %s", rank->m_ColorIndex, player->m_Name );
}
else
{
sprintf( player_score_str, "\\c%d%s", rank->m_ColorIndex, player->m_Name );
}
p_item_params = new Script::CStruct;
p_item_params->AddString( "text", player_score_str );
// p_item_params->AddChecksum( "id", 123456 + i );
p_item_params->AddChecksum( "parent", Script::GenerateCRC( "player_list_menu" ));
Script::RunScript("player_menu_add_item", p_item_params);
delete p_item_params;
p_item_params = new Script::CStruct;
if( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netking" ) ||
skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "king" ))
{
sprintf( score_str, "%.2d:%.2d", Tmr::InSeconds( player_score ) / 60, Tmr::InSeconds( player_score ) % 60 );
}
else
{
sprintf( score_str, "%d", player_score );
}
p_item_params->AddString( "text", score_str );
p_item_params->AddChecksum( "font", Script::GenerateCRC( "dialog" ) );
p_item_params->AddChecksum( "id", 234567 + i );
p_item_params->AddChecksum( "parent", Script::GenerateCRC( "rankings_list_menu" ));
Script::RunScript("score_menu_add_item",p_item_params);
delete p_item_params;
i++;
}
p_item_params = new Script::CStruct;
p_item_params->AddString( "text", rank->m_Name );
// p_item_params->AddChecksum( "id", 123456 + i );
p_item_params->AddChecksum( NONAME, Script::GenerateCRC( "team_score" ) );
p_item_params->AddChecksum( "parent", Script::GenerateCRC( "player_list_menu" ));
Script::RunScript("player_menu_add_item",p_item_params);
delete p_item_params;
p_item_params = new Script::CStruct;
if( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netking" ) ||
skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "king" ))
{
sprintf( score_str, "\\c%d%.2d:%.2d", rank->m_ColorIndex, Tmr::InSeconds( rank->GetPri()) / 60, Tmr::InSeconds( rank->GetPri()) % 60 );
}
else
{
sprintf( score_str, "\\c%d%d", rank->m_ColorIndex, rank->GetPri());
}
p_item_params->AddString( "text", score_str );
p_item_params->AddChecksum( "id", 234567 + i );
p_item_params->AddChecksum( "font", Script::GenerateCRC( "dialog" ) );
p_item_params->AddChecksum( NONAME, Script::GenerateCRC( "team_score" ) );
p_item_params->AddChecksum( "parent", Script::GenerateCRC( "rankings_list_menu" ));
Script::RunScript("score_menu_add_item",p_item_params);
delete p_item_params;
delete rank;
i++;
}
}
else
{
for( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ))
{
int player_score;
if( in_goal_attack )
{
Game::CGoalManager* pGoalManager;
pGoalManager = Game::GetGoalManager();
player_score = pGoalManager->NumGoalsBeatenBy( player->m_Skater->GetID());
}
else
{
player_score = gamenet_man->GetPlayerScore( player->m_Skater->GetID());
}
rank = new GameNet::ScoreRank;
strcpy( rank->m_Name, player->m_Skater->GetDisplayName() );
// Lists sort based on node's priority so set the node's priority to that of
// the player's score and add him to the list
rank->SetPri( player_score );
rank_list.AddNode( rank );
}
// Now loop through the sorted list in order of highest to lowest score and print them out
i = 0;
for( rank = rank_sh.FirstItem( rank_list ); rank; rank = next )
{
Script::CStruct* p_item_params;
char score_str[64];
next = rank_sh.NextItem();
//Script::RunScript( "prepare_server_menu_for_new_children" );
p_item_params = new Script::CStruct;
p_item_params->AddString( "text", rank->m_Name );
// p_item_params->AddChecksum( "id", 123456 + i );
p_item_params->AddChecksum( "parent", Script::GenerateCRC( "player_list_menu" ));
Script::RunScript("player_menu_add_item",p_item_params);
delete p_item_params;
p_item_params = new Script::CStruct;
if( skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "netking" ) ||
skate_mod->GetGameMode()->GetNameChecksum() == Script::GenerateCRC( "king" ))
{
sprintf( score_str, "%.2d:%.2d", Tmr::InSeconds( rank->GetPri()) / 60, Tmr::InSeconds( rank->GetPri()) % 60 );
}
else
{
sprintf( score_str, "%d", rank->GetPri());
}
p_item_params->AddString( "text", score_str );
p_item_params->AddChecksum( "id", 234567 + i );
p_item_params->AddChecksum( "font", Script::GenerateCRC( "dialog" ) );
p_item_params->AddChecksum( "parent", Script::GenerateCRC( "rankings_list_menu" ));
Script::RunScript("score_menu_add_item",p_item_params);
delete p_item_params;
delete rank;
i++;
}
}
Mem::Manager::sHandle().PopContext();
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// K: This function used to use GetMaximumNumberOfPlayers,
// but I changed it to use p_gamenet_man->GetMaxPlayers so that only
// the required amount of memory is allocated, hence allowing bigger
// parks that allow fewer players.
// p_gamenet_man->GetMaxPlayers will return the num players as chosen from the Players menu
// when starting a network game.
// @script | InitSkaterHeaps |
bool ScriptInitSkaterHeaps(Script::CStruct *pParams, Script::CScript *pScript)
{
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
int num_skater_heaps_required=1;
Skate *p_skate = Skate::Instance();
if (p_skate->GetGameType()==CRCD(0x5c8f5d66,"freeskate2p"))
{
num_skater_heaps_required=2;
}
else
{
GameNet::Manager * p_gamenet_man = GameNet::Manager::Instance();
num_skater_heaps_required=p_gamenet_man->GetMaxPlayers();
}
Dbg_Printf( "\nInitializing %d Skater Heaps\n", num_skater_heaps_required);
// If we are startinga game with possibly more than two players
// then we want to allocate
if( num_skater_heaps_required > NUM_PERM_SKATER_HEAPS )
{
Mem::Manager::sHandle().DeleteSkaterHeaps();
Mem::Manager::sHandle().InitSkaterHeaps(num_skater_heaps_required);
}
Mem::Manager::sHandle().PopContext();
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// @script | ResetLevel | resets the level
bool ScriptResetLevel(Script::CStruct *pParams, Script::CScript *pScript)
{
Skate* skate_mod = Skate::Instance();
// A hacky way of preserving the running script, since skate's cleanup will destroy all
// spawned scripts.
bool was_spawned = false;
if( pScript )
{
was_spawned = pScript->mIsSpawned;
pScript->mIsSpawned = false;
}
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap());
skate_mod->ResetLevel();
Mem::Manager::sHandle().PopContext();
if( pScript )
{
pScript->mIsSpawned = was_spawned;
}
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#if 0
static char * maybe_new(int n, bool new_record)
{
char *p = Script::GetScriptString(n);
if (new_record)
{
sprintf (p,"&c1");
p+=3;
}
return p;
}
// insert a single line into the script strings
void populate_line(int &index, Records::CRecord *pRecord)
{
sprintf(maybe_new(index++,pRecord->GetNewRecord()),"%s",Str::PrintThousands(pRecord->GetValue()));
sprintf(maybe_new(index++,pRecord->GetNewRecord()),"%d",pRecord->GetNumber());
sprintf(maybe_new(index++,pRecord->GetNewRecord()),pRecord->GetInitials());
}
#ifndef __PLAT_NGC__
// insert a single line into the script strings
static void populate_line_secs(int &index, Records::CRecord *pRecord)
{
#if (ENGLISH == 0)
sprintf(maybe_new(index++,pRecord->GetNewRecord()),"%3.2f %s",(float)pRecord->GetValue()/100.0f,Script::GetLocalString( "skate_str_secs"));
#else
sprintf(maybe_new(index++,pRecord->GetNewRecord()),"%3.2f secs",(float)pRecord->GetValue()/100.0f);
#endif
sprintf(maybe_new(index++,pRecord->GetNewRecord()),"%d",pRecord->GetNumber());
sprintf(maybe_new(index++,pRecord->GetNewRecord()),pRecord->GetInitials());
}
static void populate_table(int &index, Records::CRecordTable *pRecordTable)
{
int entries = pRecordTable->GetSize();
for (int i = 0; i < entries; i++)
{
populate_line(index, pRecordTable->GetRecord(i));
}
}
#endif // __PLAT_NGC__
#endif
/******************************************************************/
/* */
/* */
/******************************************************************/
// Update the records with whatever we just did this session
void Skate::UpdateRecords()
{
m_new_record = false;
int level = GetCareer()->GetLevel();
// get the records for this level
Records::CLevelRecords *pRecords = GetGameRecords()->GetLevelRecords(level);
// find the skater, get the score landed:
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
Obj::CSkater *pSkater = skate_mod->GetLocalSkater();
if( pSkater == NULL )
{
return;
}
Mdl::Score * pScore = ( pSkater->GetScoreObject() );
/*
HUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();
HUD::Panel* pPanel;
pPanel = panel_mgr->GetPanelBySkaterId(pSkater->GetID(), false);
*/
// Insert the score into the high score table if it is high enough
m_new_record |= (-1 != pRecords->GetHighScores()->MaybeNewEntry(pScore->GetTotalScore(),0));
m_new_record |= (-1 != pRecords->GetBestCombos()->MaybeNewEntry(pScore->GetBestCombo(),0));
Obj::CSkaterBalanceTrickComponent* p_skater_balance_trick_component = GetSkaterBalanceTrickComponentFromObject(pSkater);
Dbg_Assert(p_skater_balance_trick_component);
int this_grind = (int)(p_skater_balance_trick_component->mGrind.GetMaxTime()*100);
int this_manual = (int)(p_skater_balance_trick_component->mManual.GetMaxTime()*100);
int this_lip = (int)(p_skater_balance_trick_component->mLip.GetMaxTime()*100);
// int this_combo = 0;
int this_combo = pScore->GetLongestCombo();
m_new_record |= pRecords->GetLongestGrind()->MaybeNewRecord(this_grind,0);
m_new_record |= pRecords->GetLongestManual()->MaybeNewRecord(this_manual,0);
m_new_record |= pRecords->GetLongestLipTrick()->MaybeNewRecord(this_lip,0);
m_new_record |= pRecords->GetLongestCombo()->MaybeNewRecord(this_combo,0);
}
#define MAX_COMBO_LINES 200 // more that we need...
/******************************************************************/
/* */
/* */
/******************************************************************/
#ifndef __PLAT_NGC__
#if 0
static float text_width(const char *p_string, const char *p_font)
{
Fnt::Drawer drawer;
drawer.SetFont(p_font);
drawer.SetText(p_string);
return drawer.GetWidth();
}
#endif
#endif // __PLAT_NGC__
/******************************************************************/
/* */
/* */
/******************************************************************/
// Utility function to get the info out of the level records
// and into the script strings
void Skate::GetRecordsText(int level)
{
#if 0
#ifndef __PLAT_NGC__
// get the records for this level
Records::CLevelRecords *pRecords = GetGameRecords()->GetLevelRecords(level);
int index = 0;
// find the skater, get the score landed:
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
Obj::CSkater *pSkater = skate_mod->GetLocalSkater();
Mdl::Score * pScore = ( pSkater->GetScoreObject() );
/*
HUD::PanelMgr* panel_mgr = HUD::PanelMgr::Instance();
HUD::Panel* pPanel;
pPanel = panel_mgr->GetPanelBySkaterId(pSkater->GetID(), false);
Dbg_MsgAssert(pPanel,("Could not get panel for skater on records screen"));
*/
int this_grind = (int)(pSkater->mGrind.GetMaxTime()*100);
int this_manual = (int)(pSkater->mManual.GetMaxTime()*100);
int this_lip = (int)(pSkater->mLip.GetMaxTime()*100);
// get total score for this level
sprintf(Script::GetScriptString(index++),"%s",Str::PrintThousands(pScore->GetTotalScore())); // 0
// get highest score from high score table
sprintf(Script::GetScriptString(index++),"%s",Str::PrintThousands(pRecords->GetHighScores()->GetRecord(0)->GetValue())); // 1
#if (ENGLISH == 0)
sprintf(Script::GetScriptString(index++),"%3.2f %s",(float)this_grind/100.0f,Script::GetLocalString( "skate_str_secs")); // 2
sprintf(Script::GetScriptString(index++),"%3.2f %s",(float)this_manual/100.0f,Script::GetLocalString( "skate_str_secs")); // 3
sprintf(Script::GetScriptString(index++),"%3.2f %s",(float)this_lip/100.0f,Script::GetLocalString( "skate_str_secs")); // 4
sprintf(Script::GetScriptString(index++),"%d %s",pPanel->GetNumLongestCombo(),Script::GetLocalString( "skate_str_tricks")); // 5
sprintf(Script::GetScriptString(index++),Script::GetLocalString( "skate_str_points_tricks"),Str::PrintThousands(pPanel->GetScoreBestCombo()),pPanel->GetNumBestCombo()); // 6
#else
sprintf(Script::GetScriptString(index++),"%3.2f secs",(float)this_grind/100.0f); // 2
sprintf(Script::GetScriptString(index++),"%3.2f secs",(float)this_manual/100.0f); // 3
sprintf(Script::GetScriptString(index++),"%3.2f secs",(float)this_lip/100.0f); // 4
sprintf(Script::GetScriptString(index++),"1 tricks"); // 5
sprintf(Script::GetScriptString(index++),"2 points in 2 tricks"); // 6
//sprintf(Script::GetScriptString(index++),"%d tricks",pPanel->GetNumLongestCombo()); // 5
//sprintf(Script::GetScriptString(index++),"%s points in %d tricks",Str::PrintThousands(pPanel->GetScoreBestCombo()),pPanel->GetNumBestCombo()); // 6
#endif
// What we want is to get the last N lines of combo text, word wrapped
// to the correct size for the font we will use on the statistics screen
//
// What we have is the text for the individual tricks, and the number of tricks.
//
// - Set up a textdrawer with the correct size and font
// - add text to it, and to a string, until full
// - copy string into a ScriptString, and repeat
// find font we will be using by looking in the appropiate property
Script::CStruct * p_record_font_props = Script::GetStructure("statistics_font_props");
const char *p_font;
p_record_font_props->GetText("font",&p_font);
Script::CStruct * p_record_box3_props = Script::GetStructure("statistics_box_3_props");
int box_width;
p_record_box3_props->GetInteger("box_w",&box_width);
Str::String line_table[MAX_COMBO_LINES];
int line = 0;
float current_w = 0;
int num_combos = 0;
//int num_combos = pPanel->GetNumBestCombo();
for (int trick =0; trick < num_combos; trick++)
{
const char * trick_chars = "blah";
//const char * trick_chars = pPanel->GetStringBestCombo(trick);
float trick_w = text_width(trick_chars, p_font);
float new_w = current_w + trick_w;
if (current_w > 0.0f && new_w > box_width)
{
line++;
Dbg_MsgAssert(line < MAX_COMBO_LINES,("Far to many combo lines"));
current_w = 0.0f;
}
if (current_w == 0.0f)
{
line_table[line] = trick_chars;
}
else
{
// combine the two strings into one string by sprintfing them into a temporary buffer
char temp[1024]; // good job we have a huge stack!!
sprintf (temp,"%s%s",line_table[line].getString(),trick_chars);
Dbg_MsgAssert(strlen(temp) < 1024,("line insanely too long")); // not taking any chances
line_table[line] = temp; // this will delete the old string contents
}
current_w += trick_w;
}
// int num_lines = line+1;
line = 0;
while (index < 20)
{
sprintf(Script::GetScriptString(index++),line_table[line++].getString());
}
/* functions we can use
int GetScoreBestCombo();
int GetNumBestCombo();
const char * GetStringBestCombo(int trick);
int GetScoreLongestCombo();
int GetNumLongestCombo();
*/
index = 20;
populate_table(index, pRecords->GetHighScores()); // 20-34
populate_table(index, pRecords->GetBestCombos()); // 35-49
populate_line_secs(index,pRecords->GetLongestGrind()); // 50-52
populate_line_secs(index,pRecords->GetLongestManual()); // 53-55
populate_line_secs(index,pRecords->GetLongestLipTrick()); // 56-58
populate_line(index,pRecords->GetLongestCombo()); // 59-61
#endif // __PLAT_NGC__
#endif
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::UpdateSkaterInputHandlers()
{
printf("&&&&&&&&&&&&&&&&&&&&&&&&&& UpdateSkaterInputHandlers called\n");
for ( int i = 0; i < vMAX_SKATERS; i++ )
{
Obj::CSkater* pSkater = GetSkater( i );
if ( pSkater && pSkater->IsLocalClient() )
{
printf("found a local skater - binding controller\n");
int heap_index = pSkater->GetHeapIndex();
Dbg_MsgAssert( heap_index >= 0 && heap_index < vMAX_SKATERS, ( "heap index %i out of range", heap_index ) );
Dbg_Assert(GetInputComponentFromObject(pSkater));
GetInputComponentFromObject(pSkater)->BindToController(m_device_server_map[heap_index]);
// Dan: Pretty sure this method is wrong.
//char skatecam[16];
//sprintf(skatecam,"SkaterCam%d",i);
//if (Obj::CCompositeObject *p_obj
//= static_cast< Obj::CCompositeObject* >(Obj::CCompositeObjectManager::Instance()->GetObjectByID(Script::GenerateCRC(skatecam))))
if (Obj::CCompositeObject *p_obj = pSkater->GetCamera())
{
Dbg_Assert(GetInputComponentFromObject(p_obj));
GetInputComponentFromObject(p_obj)->BindToController(m_device_server_map[heap_index]);
}
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Fills in a little structure with some stuff so that SkipLogic is really fast.
void Skate::pre_calculate_object_update_info()
{
if (Nx::CViewportManager::sGetNumActiveViewports() > 1 || ! Nx::CViewportManager::sGetActiveCamera(0))
{
// Nothing should be suspended if multiplayer, so leave the flag true.
m_precalculated_object_update_info.mDoNotSuspendAnything=true;
}
else
{
m_precalculated_object_update_info.mDoNotSuspendAnything=false;
m_precalculated_object_update_info.mActiveCameraPosition = Nx::CViewportManager::sGetActiveCamera(0)->GetPos();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Prefs::Preferences* GetPreferences( Script::CStruct* pParams, bool assert_on_fail )
{
uint32 checksum;
pParams->GetChecksum( "prefs", &checksum, true );
return GetPreferences( checksum, assert_on_fail );
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Prefs::Preferences* GetPreferences( uint32 checksum, bool assert_on_fail )
{
if ( checksum == Script::GenerateCRC("network") )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
return gamenet_man->GetNetworkPreferences();
}
else if ( checksum == Script::GenerateCRC("taunt") )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
return gamenet_man->GetTauntPreferences();
}
else if ( checksum == Script::GenerateCRC("splitscreen") )
{
Mdl::Skate * skate_mod = Mdl::Skate::Instance();
return skate_mod->GetSplitScreenPreferences();
}
if ( assert_on_fail )
{
Dbg_MsgAssert( 0, ( "Couldn't find preferences for %s", Script::FindChecksumName(checksum) ) );
}
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Just a simple debugging interface function to call the main rail
// manager's DebugRender() function
void Rail_DebugRender()
{
Mdl::Skate* skate_mod = Mdl::Skate::Instance();
if (!skate_mod->GetDrawRails())
{
return;
}
skate_mod->GetRailManager()->DebugRender();
for (Obj::CRailManagerComponent* p_rail_manager_component = static_cast< Obj::CRailManagerComponent* >(Obj::CCompositeObjectManager::Instance()->GetFirstComponentByType(CRC_RAILMANAGER));
p_rail_manager_component;
p_rail_manager_component = static_cast< Obj::CRailManagerComponent* >(p_rail_manager_component->GetNextSameType()))
{
Obj::CCompositeObject* p_movable_object = p_rail_manager_component->GetObject();
// form a transformation matrix
Mth::Matrix total_mat = p_movable_object->GetMatrix();
total_mat[X][W] = 0.0f;
total_mat[Y][W] = 0.0f;
total_mat[Z][W] = 0.0f;
total_mat[W] = p_movable_object->GetPos();
total_mat[W][W] = 1.0f;
Obj::CRailManager *p_railman = p_rail_manager_component->GetRailManager();
if (p_railman)
{
p_railman->DebugRender(&total_mat);
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// return the current gap checklist for the level that we are in
Obj::CGapChecklist* Skate::GetGapChecklist()
{
Obj::CGapChecklist* p_gap_checklist = GetCareer()->GetGapChecklist();
Dbg_Assert(p_gap_checklist);
return p_gap_checklist;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::ShouldAllocateNetMiscHeap( void )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
return ( gamenet_man->InNetGame() && ( m_cur_level != Script::GenerateCRC( "Load_Skateshop" ))) ;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool Skate::ShouldAllocateInternetHeap( void )
{
GameNet::Manager * gamenet_man = GameNet::Manager::Instance();
if( gamenet_man->InNetMode())
{
return true;
}
// GJ: need to temporarily remove LOAD_CAS, because
// the internet heap is coming in after the unloadable
// anims, and the unloadable anims need to be the last
// thing on the topdown heap
if( ( m_requested_level == Script::GenerateCRC( "load_skateshop" ) )
|| ( m_requested_level == Script::GenerateCRC( "load_CAS" )))
{
return true;
}
return false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Skate::FirstInputReceived()
{
m_first_input_received = true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Mdl