// start autoduck documentation // @DOC goal // @module goal | None // @subindex Scripting Database // @index script | goal #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Front { extern void HideTimeTHPS4(); } namespace Game { /******************************************************************/ /* */ /* */ /******************************************************************/ CGoalLink::CGoalLink() { m_relative = 0; mp_next = NULL; m_beaten = false; } CGoalLink::~CGoalLink() { // nothing yet } /******************************************************************/ /* */ /* */ /******************************************************************/ CGoal::CGoal( Script::CStruct* pParams ) : Lst::Node( this ) { mp_children = new Game::CGoalLink(); mp_parents = new Game::CGoalLink(); m_active = false; m_hasSeen = false; m_paused = false; m_unlimitedTime = true; m_isbeat = false; m_netIsBeat = false; m_beatenFlags = 0; m_teamBeatenFlags = 0; m_isselected = false; m_isInitialized = false; m_numTimesLost = 0; m_numTimesWon = 0; m_numTimesStarted = 0; m_deactivateOnExpire = true; m_timeLeft = 0; m_chapter = m_stage = -1; mp_params = new Script::CStruct; mp_params->AppendStructure( pParams ); mp_goalPed = new Game::CGoalPed( mp_params ); mp_goalFlags = new Script::CStruct; m_numflags = 0; m_flagsSet = 0; m_elapsedTime = 0; m_elapsedTimeRecord = vINT32_MAX; m_winScoreRecord = 0; m_endRunType = vGOALENDOFRUN; // set the level number Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkaterCareer* pCareer = skate_mod->GetCareer(); m_levelNum = pCareer->GetLevel(); CreateGoalFlags( pParams ); if ( pParams->ContainsFlag( CRCD( 0x4ab5f14, "single_timer" ) ) ) { // Dbg_MsgAssert( mp_children->m_relative, ( "single_timer flag used on a goal without children" ) ); m_inherited_flags |= GOAL_INHERITED_FLAGS_ONE_TIMER; } if ( pParams->ContainsFlag( CRCD( 0xc6b4258f, "retry_stage" ) ) ) { m_inherited_flags |= GOAL_INHERITED_FLAGS_RETRY_STAGE; } // TODO: make goal lock stuff work right if ( pParams->ContainsFlag( vUNLOCKED_BY_ANOTHER ) ) { m_isLocked = true; } else if ( pParams->ContainsFlag( vPRO_GOAL ) ) { m_isLocked = true; } /* else if ( pParams->ContainsFlag( vPRO_CHALLENGE ) ) { m_isLocked = true; } */ else { m_isLocked = false; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::Init() { Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap()); // overwrite any params with difficulty level params AppendDifficultyLevelParams(); // make sure there's a goal description so that the intro cam anims can // be killed and Gary will be happy Dbg_MsgAssert( mp_params->ContainsComponentNamed( CRCD(0xc5d7e6b,"goal_description") ), ( "No goal description defined for %s\n", Script::FindChecksumName( GetGoalId() ) ) ); RunCallbackScript( vINIT ); ReplaceTrickText(); m_isInitialized = true; // Dan, TT12965. If a server switched between time limit and capture limit ctf games, m_unlimitedTime was not being reset to true. Thus, ShouldExpire // was returning true during the capture limit game, if the time on the previous time limit game had been allowed to run down. int unlimited_time = 0; mp_params->GetInteger( CRCD(0xf0e712d2,"unlimited_time"), &unlimited_time ); if ( unlimited_time ) { m_unlimitedTime = true; } Mem::Manager::sHandle().PopContext(); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::AddParent( uint32 id ) { // printf("adding parents\n"); if ( mp_parents->m_relative == 0 ) { mp_parents->m_relative = id; } else { Game::CGoalLink* p_parent = new Game::CGoalLink(); p_parent->m_relative = id; p_parent->mp_next = mp_parents; mp_parents = p_parent; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::CreateGoalFlags( Script::CStruct* pParams ) { // set any goal flags specified in the params Script::CArray *pTempArray; mp_goalFlags->Clear(); m_numflags = 0; if ( pParams->GetArray( CRCD(0xcc3c4cc4,"goal_flags"), &pTempArray ) ) { for ( uint32 c = 0; c < pTempArray->GetSize(); c++) { mp_goalFlags->AddInteger( pTempArray->GetNameChecksum( c ), 0 ); m_numflags++; } } mp_params->AddInteger( CRCD(0xb3790f33,"num_flags"), m_numflags ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetInheritableFlags( int recurse_level ) { // printf("SetInheritableFlags called on %s\n", Script::FindChecksumName( GetGoalId() ) ); Dbg_MsgAssert( recurse_level < 100, ( "SetInheritableFlags recursed too much" ) ); CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); CGoalLink* p_child = mp_children; while ( p_child && p_child->m_relative != 0 ) { CGoal *pGoal = pGoalManager->GetGoal( p_child->m_relative ); if ( pGoal ) { pGoal->m_inherited_flags |= m_inherited_flags; pGoal->SetInheritableFlags( recurse_level + 1 ); } p_child = p_child->mp_next; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::AddChild( uint32 id ) { // printf("adding child\n"); // any current children? if ( mp_children->m_relative == 0 ) { mp_children->m_relative = id; } else { // make sure this child isn't already in the list bool found = false; Game::CGoalLink* p_test = mp_children; while ( p_test && p_test->m_relative != 0 ) { if ( p_test->m_relative == id ) { found = true; break; } p_test = p_test->mp_next; } if ( found ) { Dbg_MsgAssert( 0, ( "AddChild failed. %s already a child of %s\n", Script::FindChecksumName( id ), Script::FindChecksumName( GetGoalId() ) ) ); } else { // add new child to head of list Game::CGoalLink* p_child = new Game::CGoalLink(); p_child->m_relative = id; p_child->mp_next = mp_children; mp_children = p_child; } } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::ResetGoalLinks() { CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); CGoalLink* p_link = mp_children; while ( p_link && p_link->m_relative != 0 ) { p_link->m_beaten = false; CGoal* pGoal = pGoalManager->GetGoal( p_link->m_relative ); if ( pGoal ) { // recurse! pGoal->ResetGoalLinks(); } p_link = p_link->mp_next; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::DeleteLinks( CGoalLink* p_list ) { CGoalLink *p_a, *p_b; for ( p_a = p_list; p_a; p_a = p_b ) { p_b = p_a->mp_next; delete p_a; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::Uninit( bool propogate, int recurse_level ) { Dbg_MsgAssert( recurse_level < 20, ( "CGoal::Uninit recursed too deep" ) ); // uint32 trigger_obj_id = 0; if ( IsActive() ) { Deactivate( true ); } RunCallbackScript( vUNINIT ); m_isInitialized = false; /* Script::RunScript( Script::GenerateCRC( "goal_kill_proset_geom" ), mp_params ); mp_params->GetChecksum( CRCD( 0x2d7e03d, "trigger_obj_id" ), &trigger_obj_id ); if ( trigger_obj_id ) { Obj::CMovingObject* p_pos_obj = NULL; // p_pos_obj = Obj::CMovingObject::m_hash_table.GetItem( trigger_obj_id ); p_pos_obj = (Obj::CMovingObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( trigger_obj_id ); if ( p_pos_obj ) { delete p_pos_obj; } } */ if ( propogate ) { CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); CGoalLink* pGoalLink = mp_children; while ( pGoalLink && pGoalLink->m_relative != 0 ) { CGoal* pChildGoal = pGoalManager->GetGoal( pGoalLink->m_relative ); Dbg_Assert( pChildGoal ); pChildGoal->Uninit( propogate, recurse_level + 1 ); pGoalLink = pGoalLink->mp_next; } } } /******************************************************************/ /* */ /* */ /******************************************************************/ CGoal::~CGoal() { // does this really need to be run? // (you may not necessarily want to go through the // same destructor logic if we're clearing out the // goals at the end of the level) RunCallbackScript( vDESTROY ); delete mp_goalPed; Dbg_Assert( mp_params ); delete mp_params; delete mp_goalFlags; // delete all children and parent trees DeleteLinks( mp_children ); DeleteLinks( mp_parents ); } /******************************************************************/ /* */ /* */ /******************************************************************/ Script::CStruct* CGoal::GetParams() { return mp_params; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetTimer() { int unlimited_time = 0; mp_params->GetInteger( CRCD(0xf0e712d2,"unlimited_time"), &unlimited_time ); // check for unlimited time if ( unlimited_time == 1 ) { return; } // don't set default time for minigames. if ( IsMinigame() ) { if ( !mp_params->ContainsComponentNamed( CRCD(0x906b67ba,"time") ) ) return; } // default time limit of 2 minutes m_timeLeft = 120; int time; if ( mp_params->GetInteger( CRCD(0x906b67ba,"time"), &time, Script::NO_ASSERT ) ) { m_timeLeft = (Tmr::Time)time; } /* else { Script::CArray* pTimeLimits; if ( mp_params->GetArray( CRCD(0x906b67ba,"time"), &pTimeLimits, Script::NO_ASSERT ) ) { CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); uint32 difficulty_level = pGoalManager->GetDifficultyLevel(); Dbg_Assert( difficulty_level > 0 && difficulty_level < pTimeLimits->GetSize() ); m_timeLeft = (Tmr::Time)( pTimeLimits->GetInteger( difficulty_level ) ); } } */ // convert to milliseconds m_timeLeft *= 1000; // bump up timer so clock starts with expected amount of time left m_timeLeft += 20; // printf("timer set to %i\n", (int)m_timeLeft); m_unlimitedTime = false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetTimer( int time ) { m_timeLeft = (Tmr::Time)time * 1000; } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetTimeLeft( void ) { return m_timeLeft; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::AddTime( int time ) { // bump up time by 20ms so that it displays right m_timeLeft += ( (Tmr::Time)time * 1000 ) + 20; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::Activate() { if ( !IsActive() ) { Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().BottomUpHeap()); // Warning! Make sure there are no 'return's between the above pushcontext and the // popcontext below ... m_elapsedTime = 0; m_numTimesStarted++; // printf("goal is not active - now activating\n"); GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); GameNet::PlayerInfo* player; Lst::Search< GameNet::PlayerInfo > sh; // TODO: reset just this skater's score for( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh ) ) { Obj::CSkater *p_Skater = player->m_Skater; Dbg_Assert( p_Skater ); Obj::CSkaterScoreComponent* p_SkaterScoreComponent = GetSkaterScoreComponentFromObject(p_Skater); Dbg_Assert( p_SkaterScoreComponent ); Mdl::Score * p_Score = ( p_SkaterScoreComponent->GetScore() ); Dbg_Assert( p_Score ); // don't reset the score when starting a minigame if ( !IsMinigame() ) p_Score->Reset(); } // Warning! Make sure there are no 'return's between the above pushcontext and the // popcontext below ... if ( mp_parents->m_relative != 0 ) { CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); CGoal* pParentGoal = NULL; // get the root node and check the timer CGoalLink* p_parent = mp_parents; while ( p_parent && p_parent->m_relative != 0 ) { pParentGoal = pGoalManager->GetGoal( p_parent->m_relative ); p_parent = pParentGoal->GetParents(); } if ( pParentGoal ) { if ( m_inherited_flags & GOAL_INHERITED_FLAGS_ONE_TIMER ) SetTimer( pParentGoal->GetTimeLeft() / 1000.0f ); else SetTimer(); if ( pParentGoal->IsInitialized() ) { pParentGoal->Uninit(); // reinitialize the goal in case uninitializing the parent // screwed anything up. if ( IsInitialized() ) { Uninit(); Init(); } } } else { // Dbg_Message( "Goal supposed to use a single timer but couldn't find parent" ); SetTimer(); } } else { SetTimer(); } if ( !IsInitialized() ) { Init(); } m_endRunCalled = false; // Warning! Make sure there are no 'return's between the above pushcontext and the // popcontext below ... mp_params->RemoveFlag( CRCD(0x7100155d,"combo_started") ); // activate script RunCallbackScript( vACTIVATE ); if( gamenet_man->InNetGame() == false ) { m_hasSeen = true; } //if ( !mp_params->ContainsFlag( "quick_start" ) ) //PauseGoal(); SetActive(); Mem::Manager::sHandle().PopContext(); return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetActive() { m_active = true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::Deactivate( bool force, bool affect_tree ) { if ( IsActive() ) { // special case for special trick goal...get rid of // the temp key_combos array if ( IsSpecialGoal() ) mp_params->RemoveComponent( CRCD(0x79704516,"key_combos") ); Front::HideTimeTHPS4(); SetInactive(); ResetGoalFlags(); ResetGoalLinks(); RunCallbackScript( vDEACTIVATE ); if (!mp_params->ContainsFlag( CRCD( 0x38221df4, "quick_start" ) )) { // If not retrying, then remove the testing_goal flag // The presence of the testing_goal flag prevents the goal from being marked as // beaten when it is beaten during testing. mp_params->RemoveFlag(CRCD(0x54d3cac1,"testing_goal")); } if ( !mp_params->ContainsFlag( CRCD( 0xc309cad1, "just_won_goal" ) ) && !mp_params->ContainsFlag( CRCD( 0x38221df4, "quick_start" ) ) ) { Script::RunScript(CRCD(0x719ae783, "ready_skater_for_early_end_current_goal"), mp_params); if ( affect_tree && mp_parents && mp_parents->m_relative ) { Uninit(); // find parent node and reinitialize CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); CGoalLink* p_link = mp_parents; CGoal* pParentGoal = NULL; while ( p_link && p_link->m_relative ) { pParentGoal = pGoalManager->GetGoal( p_link->m_relative ); Dbg_Assert( pParentGoal ); p_link = pParentGoal->GetParents(); } if ( pParentGoal && !pParentGoal->HasWonGoal() ) { // printf("initializing goal: %s\n", Script::FindChecksumName( pParentGoal->GetGoalId() ) ); pParentGoal->Init(); } } } return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetInactive() { m_active = false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::Win( void ) { mp_params->AddInteger( CRCD(0xc22a2b72,"win_record"), 0 ); // see if it's a leaf node if ( mp_children->m_relative == 0 ) { mp_params->AddChecksum( NONAME, CRCD( 0xc309cad1, "just_won_goal" ) ); GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); m_numTimesWon++; // look for a new record if we're not in a net game bool set_new_record = false; uint32 record_type; if ( !gamenet_man->InNetGame() && mp_params->GetChecksum( CRCD(0x96963902,"record_type"), &record_type, Script::NO_ASSERT ) ) { // printf("record type is %s\n", Script::FindChecksumName( record_type ) ); if ( record_type == CRCD(0xcd66c8ae,"score") ) { // check for custom score record int custom_record; if ( mp_params->GetInteger( CRCD(0xfc9630ab,"custom_score_record"), &custom_record, Script::NO_ASSERT ) ) { if ( custom_record > m_winScoreRecord ) { m_winScoreRecord = custom_record; mp_params->AddInteger( CRCD(0xc22a2b72,"win_record"), m_winScoreRecord ); set_new_record = true; } } else { // printf("found a score record type\n"); Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater *pSkater = skate_mod->GetLocalSkater(); Dbg_Assert( pSkater ); Obj::CSkaterScoreComponent* pSkaterScoreComponent = GetSkaterScoreComponentFromObject(pSkater); Dbg_Assert( pSkaterScoreComponent ); Mdl::Score * pScore = ( pSkaterScoreComponent->GetScore() ); Dbg_Assert( pScore ); int total_score; if ( mp_params->ContainsFlag( CRCD(0xc63432a7,"high_combo") ) ) total_score = pScore->GetLastScoreLanded(); else total_score = pScore->GetTotalScore(); // printf("got a total_score of %i, had a previous record of %i\n", total_score, m_winScoreRecord ); if ( total_score > m_winScoreRecord ) { m_winScoreRecord = total_score; mp_params->AddInteger( CRCD(0xc22a2b72,"win_record"), m_winScoreRecord ); set_new_record = true; } } } else if ( record_type == CRCD(0x906b67ba,"time") ) { // printf("got a time of %i, previous record was %i\n", (int)m_elapsedTime, (int)m_elapsedTimeRecord); if ( m_elapsedTime < m_elapsedTimeRecord ) { m_elapsedTimeRecord = m_elapsedTime; mp_params->AddInteger( CRCD(0xc22a2b72,"win_record"), (int)m_elapsedTimeRecord ); set_new_record = true; } } } #ifdef __NOPT_ASSERT__ CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); #endif // __NOPT_ASSERT__ if ( !HasWonGoal() && !gamenet_man->InNetGame() ) { // printf("getting rewards struct\n"); Script::CStruct* p_reward_params = new Script::CStruct(); GetRewardsStructure( p_reward_params, true ); if ( set_new_record ) p_reward_params->AddChecksum( NONAME, CRCD(0xe7b8254f,"set_new_record") ); mp_params->AddStructurePointer( CRCD(0x128b3088,"reward_params"), p_reward_params ); UnlockRewardGoals(); } else mp_params->RemoveComponent( CRCD(0x128b3088,"reward_params") ); // update set_new_record flag if ( set_new_record ) mp_params->AddChecksum( NONAME, CRCD(0xe7b8254f,"set_new_record") ); else mp_params->RemoveFlag( CRCD(0xe7b8254f,"set_new_record") ); RunCallbackScript( vSUCCESS ); bool testing_goal=mp_params->ContainsFlag(CRCD(0x54d3cac1,"testing_goal")); if ( IsActive() ) { // add a flag so the deactivate script knows that we just beat the goal Deactivate(); } // The testing_goal flag is set when a created goal is being test played. // Don't want it to be crossed off the view goals menu in that case. (TT3366) if (!testing_goal) { MarkBeaten(); } if ( gamenet_man->InNetGame() ) { Uninit(); } mp_params->RemoveFlag( CRCD( 0xc309cad1, "just_won_goal" ) ); return true; } else { // it's a link to another goal // TODO: we need a way of deciding which child to pick // for now, we'll just take the first child Game::CGoalLink* p_link = mp_children; CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); Deactivate(); Uninit(); CGoal* pChildGoal = pGoalManager->GetGoal( p_link->m_relative ); pChildGoal->Init(); pGoalManager->ActivateGoal( p_link->m_relative, false ); // mark the link beaten p_link->m_beaten = true; return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::Lose( void ) { // Mdl::Skate * skate_mod = Mdl::Skate::Instance(); // Obj::CSkater *p_Skater = skate_mod->GetLocalSkater(); // Dbg_Assert( p_Skater ); // p_Skater->ClearAllExceptions(); if ( IsActive() ) { m_numTimesLost++; RunCallbackScript( vFAIL ); Deactivate( true ); return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsExpired() { return IsExpired( false ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::ShouldExpire() { // returns true if the goal would expire if the skater was not in a combo // Dan: this logic needs to mimic IsExpired() Mdl::Skate * skate_mod = Mdl::Skate::Instance(); GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); Obj::CSkater* p_skater; p_skater = skate_mod->GetLocalSkater(); if ( p_skater == NULL ) { return true; } #ifdef __NOPT_ASSERT__ Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater); Dbg_Assert(p_skater_endrun_component); #endif // __NOPT_ASSERT__ // If no players are left, the goal should expire if ( gamenet_man->GetNumPlayers() == 0 ) { return true; } // If it's an unlimited game, don't expire the goal if ( m_unlimitedTime ) { return false; } if ( (int)m_timeLeft <= 0 ) { // Dbg_Printf( "**** Already Expired\n" ); return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsExpired( bool force_end ) { Mdl::Skate * skate_mod = Mdl::Skate::Instance(); GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); Obj::CSkater* p_skater; p_skater = skate_mod->GetLocalSkater(); if ( p_skater == NULL ) { return true; } Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater); Dbg_Assert(p_skater_endrun_component); // If no players are left, the goal should expire if ( gamenet_man->GetNumPlayers() == 0 ) { return true; } // If it's an unlimited game, don't expire the goal if ( m_unlimitedTime ) { return false; } // check if the skaters have reached end of run BEFORE // setting the exception, or you'll never catch it! bool expired = false; switch ( m_endRunType ) { case vENDOFRUN: expired = p_skater_endrun_component->RunHasEnded(); break; case vGOALENDOFRUN: expired = p_skater_endrun_component->GoalRunHasEnded(); break; case vNONE: // if we're not supposed to use end of run, we need only check // the time return ( (int)m_timeLeft <= 0 ); break; default: Dbg_Assert( 0 ); } if ( expired && (int)m_timeLeft <= 0 ) { // Dbg_Printf( "**** Already Expired\n" ); return true; } // if time is up, set the end of run exception if ( (int)m_timeLeft <= 0 ) { // Dbg_Printf( "EXPIRING GOAL: %d\n", GetGoalId()); // printf("&&&&&&&&&&&&&&&&& calling EndRun\n"); switch ( m_endRunType ) { case vENDOFRUN: m_endRunCalled = true; // Dbg_Printf( "**** Calling End Run\n" ); p_skater_endrun_component->EndRun( force_end ); break; case vGOALENDOFRUN: // printf("reached goalendofrun\n"); m_endRunCalled = true; p_skater_endrun_component->EndGoalRun( force_end ); break; default: Dbg_Assert( 0 ); } } // printf("AtEndOfRun returned %i\n", all_expired); // return ( all_expired && ( (int)m_timeLeft <= 0 ) ); return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::AllSkatersAtEndOfRun() { // check all the goals GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); Mdl::Skate* skate_mod = Mdl::Skate::Instance(); GameNet::PlayerInfo* player; Lst::Search< GameNet::PlayerInfo > sh; for( player = gamenet_man->FirstPlayerInfo( sh ); player; player = gamenet_man->NextPlayerInfo( sh )) { Obj::CSkater *p_Skater = player->m_Skater; // int skater_num = p_Skater->GetSkaterNumber(); Dbg_Assert( p_Skater ); Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_Skater); Dbg_Assert( p_skater_endrun_component ); if( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0x9d65d0e7, "horse" )) { if( p_Skater->IsPaused() || p_Skater->IsHidden()) { continue; } } switch ( m_endRunType ) { case vENDOFRUN: if ( !p_skater_endrun_component->RunHasEnded() ) { return false; } break; case vGOALENDOFRUN: if ( !p_skater_endrun_component->GoalRunHasEnded() ) { return false; } break; default: Dbg_Assert( 0 ); } } return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::EditParams( Script::CStruct* pParams ) { mp_params->AppendStructure( pParams ); return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::Update( void ) { if ( IsActive() && !IsPaused() ) { RunCallbackScript( vACTIVE ); } // the active script may have deactivated the goal, so we check // if it's active again...don't check mini games if ( IsActive() && !IsPaused()) { if( ShouldUseTimer() ) { if ( ( (int)m_timeLeft >= 1 ) ) { int old_time_left = (int)m_timeLeft; m_timeLeft -= (Tmr::Time)( Tmr::FrameLength() * 1000 ); m_elapsedTime += (Tmr::Time)( Tmr::FrameLength() * 1000 ); if ( (int)m_timeLeft < 10000 && ( (int)( old_time_left / 1000 ) > (int)( (int)m_timeLeft / 1000 ) ) ) { if (Mdl::Skate::Instance()->GetGameMode()->ShouldTimerBeep()) { Script::RunScript( CRCD(0xcfc7c3ad,"timer_runout_beep") ); } } } } if ( ShouldRequireCombo() ) { if ( !mp_params->ContainsFlag( CRCD( 0x7100155d, "combo_started" ) ) ) { Mdl::Skate *skate_mod = Mdl::Skate::Instance(); Obj::CSkater* pSkater = skate_mod->GetLocalSkater(); if ( pSkater ) { Mdl::Score* pScore = pSkater->GetScoreObject(); if ( pScore && pScore->GetScorePotValue() > 0 ) { mp_params->AddChecksum( NONAME, CRCD(0x7100155d,"combo_started") ); } } } } // add the amount of time left // mp_params->AddInteger( "time_left", m_timeLeft ); if ( IsExpired() ) { Expire(); } } // haven't used the inactive yet /* else { if ( !IsLocked() ) { // runs its inactive script (if any) RunCallbackScript( vINACTIVE ); } } */ return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::Expire() { RunCallbackScript( vEXPIRED ); // TODO: fix after e3 // this was done to make the horse and combo letter goals work right if ( m_deactivateOnExpire ) { Deactivate(); } } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsActive( void ) { return ( m_active == true ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::HasSeenGoal( void ) { return m_hasSeen; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::PauseGoal( void ) { m_paused = true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::UnPauseGoal( void ) { m_paused = false; } /******************************************************************/ /* */ /* */ /******************************************************************/ Tmr::Time CGoal::GetTime( void ) { return m_timeLeft; } /******************************************************************/ /* */ /* */ /******************************************************************/ /*void CGoal::CreateGoalFlag( uint32 flag ) { mp_goalFlags->AddInteger( flag, 0 ); m_numflags++; }*/ /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::SetGoalFlag( uint32 flag, int value ) { if ( !IsActive() ) { return false; } if ( mp_goalFlags->ContainsComponentNamed( flag ) ) { // remember the old value int old_value; mp_goalFlags->GetInteger( flag, &old_value, Script::ASSERT ); mp_goalFlags->AddInteger( flag, value ); if ( old_value != value ) { if ( value == 0 ) m_flagsSet--; else { m_flagsSet++; if ( !mp_params->ContainsFlag( CRCD(0x524566e3,"no_midgoal_sound") ) ) Script::RunScript( CRCD(0x5ed34deb,"goal_got_flag_sound") ); } if ( mp_params->ContainsFlag( CRCD(0xfd7ae1f4,"use_hud_counter") ) ) Script::RunScript( CRCD(0xf2e85a34,"goal_update_counter"), mp_params ); mp_params->AddInteger( CRCD(0xcf6cd3c1,"num_flags_set"), m_flagsSet ); } // printf("setting goal flag %s, %i of %i set\n", Script::FindChecksumName( flag ), m_flagsSet, m_numflags ); return true; } Dbg_MsgAssert( 0, ("SetGoalFlag couldn't find flag\n" ) ); return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::GetCreatedGoalGap(int gapIndex) { Script::CArray *p_required_gaps=NULL; if (!mp_params->GetArray(CRCD(0x52d4489e,"required_gaps"),&p_required_gaps)) { return false; } const char *p_required_trick_name=""; mp_params->GetString(CRCD(0x730844a3,"required_trick_name"),&p_required_trick_name); if (p_required_trick_name[0]) { Mdl::Skate *p_skate_mod = Mdl::Skate::Instance(); Obj::CSkater *p_skater = p_skate_mod->GetLocalSkater(); if (!p_skater) { return false; } Mdl::Score *p_score = p_skater->GetScoreObject(); uint32 trick_checksum=Script::GenerateCRC(p_required_trick_name); // Also check for fs and bs versions (TT9784) uint32 bs_trick_checksum=CRCD(0x7491335e,"bs "); bs_trick_checksum=Crc::ExtendCRCWithString(bs_trick_checksum, p_required_trick_name); uint32 fs_trick_checksum=CRCD(0x73989b82,"fs "); fs_trick_checksum=Crc::ExtendCRCWithString(fs_trick_checksum, p_required_trick_name); if (p_score->GetCurrentNumberOfOccurrencesByName(trick_checksum, 0, false) == 0 && p_score->GetCurrentNumberOfOccurrencesByName(bs_trick_checksum, 0, false) == 0 && p_score->GetCurrentNumberOfOccurrencesByName(fs_trick_checksum, 0, false) == 0) { return false; } } for (uint i=0; iGetSize(); ++i) { if (gapIndex==p_required_gaps->GetInteger(i)) { char p_foo[20]; sprintf(p_foo,"got_%d",i+1); SetGoalFlag(Script::GenerateCRC(p_foo),1); return true; } } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::GoalFlagEquals( uint32 flag, int value ) { if ( mp_goalFlags->ContainsComponentNamed( flag ) ) { int f; mp_goalFlags->GetInteger( flag, &f, Script::ASSERT ); return ( value == f ); } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::ResetGoalFlags() { // reset the goal flags Script::CComponent* p_comp = mp_goalFlags->GetNextComponent( NULL ); while ( p_comp ) { Script::CComponent* p_next = mp_goalFlags->GetNextComponent( p_comp ); p_comp->mIntegerValue = 0; // SetGoalFlag( p_comp->mNameChecksum, 0 ); // printf("resetting goal flag %s\n", Script::FindChecksumName( flag_name ) ); p_comp = p_next; } m_flagsSet = 0; mp_params->AddInteger( CRCD( 0xcf6cd3c1, "num_flags_set" ), 0 ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::AllFlagsSet() { // printf("%i flags, %i set\n", m_numflags, m_flagsSet); int num_flags_to_win = m_numflags; mp_params->GetInteger( CRCD(0x1171a555,"num_flags_to_win"), &num_flags_to_win, Script::NO_ASSERT ); // K: Fix to TT9785, where created gap goals would succeed straight away if no gaps were chosen, // causing an assert. if (num_flags_to_win == 0) { return false; } return ( m_flagsSet >= num_flags_to_win ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::GoalFlagSet( uint32 flag ) { int flag_value; mp_goalFlags->GetInteger( flag, &flag_value, Script::ASSERT ); return ( flag_value != 0 ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsLocked() { return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::UnlockGoal() { if ( m_isLocked ) { m_isLocked = false; // don't initialize goals automatically in net games GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); if ( gamenet_man->InNetGame() ) return; // initialize goal Init(); // call the unlock script RunCallbackScript( vUNLOCK ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::NextTourSpot() { Script::CArray* p_waypoints; // backward compatible with the horse_spots array naming convention if ( !mp_params->GetArray( CRCD(0x160b3220,"tour_spots"), &p_waypoints, Script::NO_ASSERT ) ) mp_params->GetArray( CRCD(0x92c6e839,"horse_spots"), &p_waypoints, Script::ASSERT ); Script::CStruct* p_waypoint; for ( uint32 i = 0; i < p_waypoints->GetSize(); i++ ) { p_waypoint = p_waypoints->GetStructure( i ); // is this waypoint done? uint32 flagId; p_waypoint->GetChecksum( CRCD(0x2e0b1465,"flag"), &flagId, Script::ASSERT ); if ( GoalFlagEquals( flagId, 1 ) ) continue; // pause the goal and set the time for this tour spot PauseGoal(); int time; p_waypoint->GetInteger( CRCD(0x906b67ba,"time"), &time, Script::ASSERT ); // add time if necessary if ( mp_params->ContainsFlag( CRCD(0xfb11cb01,"cumulative_timer") ) ) { AddTime( time ); } else { mp_params->AddInteger( CRCD(0x906b67ba,"time"), time ); SetTimer(); } // add the goalId and trigger id to the params p_waypoint->AddChecksum( CRCD(0x9982e501,"goal_id"), GetGoalId() ); // send a flag if this is the first spot if ( m_flagsSet == 0 ) p_waypoint->AddChecksum( NONAME, CRCD( 0xb13f3ab8, "first_spot" ) ); // send a flag if this is a restart if ( mp_params->ContainsFlag( CRCD(0x38221df4,"quick_start") ) ) p_waypoint->AddChecksum( NONAME, CRCD(0x38221df4,"quick_start") ); else p_waypoint->RemoveFlag( CRCD(0x38221df4,"quick_start") ); #ifdef __NOPT_ASSERT__ // backward compatible with horse goal Script::CScript *p_script=NULL; if ( mp_params->ContainsFlag( CRCD(0x9d65d0e7,"horse") ) ) p_script=Script::SpawnScript( CRCD(0x681bc776,"goal_horse_next_spot"), p_waypoint ); else p_script=Script::SpawnScript( CRCD(0x4c938553,"goal_tour_next_spot"), p_waypoint ); p_script->SetCommentString("Spawned from CGoal::NextTourSpot()"); #else // backward compatible with horse goal if ( mp_params->ContainsFlag( CRCD(0x9d65d0e7,"horse") ) ) Script::SpawnScript( CRCD(0x681bc776,"goal_horse_next_spot"), p_waypoint ); else Script::SpawnScript( CRCD(0x4c938553,"goal_tour_next_spot"), p_waypoint ); #endif // remove restart flag p_waypoint->RemoveFlag( CRCD(0x38221df4,"quick_start") ); /* // move the skater to the node uint32 reset_checksum; p_waypoint->GetChecksum( "id", &reset_checksum, Script::ASSERT ); Mdl::Skate * p_skate = Mdl::Skate::Instance(); p_skate->ResetSkaters( SkateScript::FindNamedNode( reset_checksum ) ); uint32 waypoint_script; if ( p_waypoint->GetChecksum( "scr", &waypoint_script, Script::NO_ASSERT ) ) Script::SpawnScript( waypoint_script ); */ return true; } return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::InitTrickObjects() { // get the object id's Script::CArray* p_trickObjectArray = NULL; mp_params->GetArray( CRCD(0x2eb84a54,"trick_objects"), &p_trickObjectArray, Script::ASSERT ); Mdl::Skate* skate_mod = Mdl::Skate::Instance(); Obj::CTrickObjectManager* p_TrickObjectManager = skate_mod->GetTrickObjectManager(); for ( uint32 i = 0; i < p_trickObjectArray->GetSize(); i++ ) { // add the trick object uint32 goal_object; Script::CStruct* p_trickObject = p_trickObjectArray[i].GetStructure( i ); p_trickObject->GetChecksum( CRCD(0x40c698af,"id"), &goal_object, Script::ASSERT ); // p_TrickObjectManager->RequestLogTrick( 1, p_TrickObjectManager->ModulateTrickObjectColor( goal_object, 0 ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::GotTrickObject( uint32 clusterId ) { // do we care? if ( mp_params->ContainsFlag( CRCD( 0xf268c278, "SkateTheLine" ) ) ) { // we do uint32 current; mp_params->GetChecksum( CRCD(0xb03713ee,"current_cluster"), ¤t, Script::ASSERT ); if ( current == clusterId ) Script::RunScript( CRCD( 0x62b12a8e, "Goal_SkateTheLine_got_node" ), mp_params ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsGraffitiGoal() { return ( mp_params->ContainsFlag( CRCD(0xc8a82b5a,"graffiti") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::ShouldLogTrickObject() { if ( mp_params->ContainsFlag( CRCD(0xc8a82b5a,"graffiti") ) || mp_params->ContainsFlag( CRCD(0xf268c278,"SkateTheLine") ) ) { return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::GotGraffitiCluster( uint32 clusterId, int score ) { // find the cluster in our cluster array Script::CArray* pClusterArray; mp_params->GetArray( CRCD(0x191f66e9,"kill_clusters"), &pClusterArray, Script::ASSERT ); for ( uint32 i = 0; i < pClusterArray->GetSize(); i++ ) { Script::CStruct* pCluster = pClusterArray->GetStructure( i ); Dbg_MsgAssert( pCluster, ( "got null cluster from kill_cluster array\n" ) ); uint32 id; pCluster->GetChecksum( "id", &id, Script::ASSERT ); int minScore; // get the score for this cluster, or the default score if ( !pCluster->GetInteger( CRCD(0xcd66c8ae,"score"), &minScore, Script::NO_ASSERT ) ) mp_params->GetInteger( CRCD(0xcd66c8ae,"score"), &minScore, Script::ASSERT ); // printf("minScore: %i, score: %i\n", minScore, score); if ( id == clusterId && score > minScore ) { Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CTrickObjectManager* p_trickObjectMan = skate_mod->GetTrickObjectManager(); // printf("modulating color\n"); if ( !p_trickObjectMan->ModulateTrickObjectColor( clusterId, 0 ) ) printf("ModulateTrickObjectColor didn't work\n"); uint32 flag; pCluster->GetChecksum( CRCD(0x2e0b1465,"flag"), &flag, Script::ASSERT ); SetGoalFlag( flag, 1 ); return; } } } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsSpecialGoal() { return ( mp_params->ContainsFlag( CRCD(0xb394c01c,"special") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CheckSpecialGoal() { Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater *p_Skater = skate_mod->GetLocalSkater(); Dbg_Assert( p_Skater ); Obj::CSkaterScoreComponent* p_SkaterScoreComponent = GetSkaterScoreComponentFromObject(p_Skater); Dbg_Assert( p_SkaterScoreComponent ); Mdl::Score * p_Score = ( p_SkaterScoreComponent->GetScore() ); Dbg_Assert( p_Score ); const char* trick_string; mp_params->GetString( CRCD(0x3a54cc4b,"trick_string"), &trick_string, Script::ASSERT ); // if it's a grind, we need to check for the FS and BS version too uint32 trick_type; mp_params->GetChecksum( CRCD(0x3d929b66,"trick_type"), &trick_type, Script::ASSERT ); if ( trick_type == CRCD( 0x255ed86f, "grind" ) ) { char test_trick[128]; // frontside strcpy( test_trick, "FS " ); strcat( test_trick, trick_string ); // printf("testing FS version - %s\n", test_trick); if ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( test_trick ) ) ) { // printf("got it\n"); return true; } // backside strcpy( test_trick, "BS " ); strcat( test_trick, trick_string ); // printf("testing BS version - %s\n", test_trick); if ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( test_trick ) ) ) { // printf("got it\n"); return true; } } // check the bare trick string if ( mp_params->ContainsFlag( CRCD(0x8e6014f6,"create_a_trick") ) ) { // printf("testing cat version %s\n", new_string ); if ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( trick_string ) ) > 0 ) { return true; } } else { // printf("testing normal version - %s\n", trick_string); if ( p_Score->GetCurrentNumberOfOccurrencesByName( Script::GenerateCRC( trick_string ) ) > 0 ) { return true; } } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsTetrisGoal() { return ( mp_params->ContainsFlag( CRCD(0x4147922b,"tetris") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetRandomIndexFromKeyCombos( Script::CArray* p_keyCombos ) { Dbg_MsgAssert( p_keyCombos->GetType() == ESYMBOLTYPE_NAME || p_keyCombos->GetType() == ESYMBOLTYPE_STRUCTURE, ( "GetRandomIndexFromKeyCombos got array of the wrong type" ) ); // get the global trick mapping Mdl::Skate* skate_mod = Mdl::Skate::Instance(); Obj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile(); Script::CStruct* p_trickMappings = p_SkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,"trick_mapping") ); // figure number of components in mapping uint32 size = p_keyCombos->GetSize(); // safety first int max_tries = 100; uint32 trick_name_checksum = 0; uint32 key_combo; while ( !trick_name_checksum ) { int i = Mth::Rnd( size ); if ( p_keyCombos->GetType() == ESYMBOLTYPE_NAME ) { key_combo = p_keyCombos->GetChecksum( i ); } else p_keyCombos->GetStructure( i )->GetChecksum( CRCD(0xacfdb27a,"key_combo"), &key_combo, Script::ASSERT ); // see if this is a valid key_combo int cat_index; p_trickMappings->GetChecksum( key_combo, &trick_name_checksum, Script::NO_ASSERT ); if ( trick_name_checksum ) { return i; } else if ( p_trickMappings->GetInteger( key_combo, &cat_index, Script::NO_ASSERT ) ) { return i; } // reset it to 0 trick_name_checksum = 0; max_tries--; if ( max_tries == 0 ) { // they've probably un-mapped all their keys. check all the tricks in order // just to be safe for ( uint32 j = 0; j < size; j++ ) { if ( p_keyCombos->GetType() == ESYMBOLTYPE_NAME ) key_combo = p_keyCombos->GetChecksum( j ); else p_keyCombos->GetStructure( j )->GetChecksum( CRCD(0xacfdb27a,"key_combo"), &key_combo, Script::ASSERT ); p_trickMappings->GetChecksum( key_combo, &trick_name_checksum, Script::NO_ASSERT ); if ( trick_name_checksum ) { return i; } trick_name_checksum = 0; } // they did un-map all their keys. Fuck 'em NoValidKeyCombos(); break; } } return -1; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::NoValidKeyCombos() { Script::CStruct* p_temp_params = new Script::CStruct(); p_temp_params->AddChecksum( CRCD(0x9982e501,"goal_id"), GetGoalId() ); Script::RunScript( CRCD( 0xf3c20af5, "goal_no_valid_key_combos" ), p_temp_params ); delete p_temp_params; } /******************************************************************/ /* */ /* */ /******************************************************************/ uint32 CGoal::GetRootGoalId() { CGoalManager* pGoalManager = GetGoalManager(); CGoal* pParentGoal = this; Dbg_Assert( pGoalManager ); // get the root node CGoalLink* p_parent = mp_parents; while ( p_parent && p_parent->m_relative != 0 ) { pParentGoal = pGoalManager->GetGoal( p_parent->m_relative ); p_parent = pParentGoal->GetParents(); } return pParentGoal->GetGoalId(); } /******************************************************************/ /* */ /* */ /******************************************************************/ uint32 CGoal::GetGoalId() { uint32 goalId = 0; mp_params->GetChecksum( "goal_id", &goalId, Script::ASSERT ); return goalId; } bool CGoal::IsEditedGoal() { Dbg_MsgAssert(mp_params,("NULL mp_params")); return mp_params->ContainsFlag(CRCD(0x981d3ad0,"edited_goal")); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::HasWonGoal() { GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); Mdl::Skate* skate_mod = Mdl::Skate::Instance(); if ( gamenet_man->InNetGame() && ( skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0xec200eaa, "netgoalattack" )) || ( skate_mod->GetGameMode()->GetNameChecksum() == CRCD(0x1c471c60,"netlobby"))) { return m_netIsBeat; } return m_isbeat; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::HasWonStage() { if ( HasWonGoal() ) return true; else { CGoalLink* pLink = mp_children; while ( pLink ) { if ( pLink->m_beaten ) return true; else pLink = pLink->mp_next; } } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsSelected() { return m_isselected; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::GotCounterObject() { int number_collected = 0; mp_params->GetInteger( CRCD(0x129daa10,"number_collected"), &number_collected, Script::NO_ASSERT ); // printf("alredy collected %i\n", number_collected); number_collected++; mp_params->AddInteger( CRCD(0x129daa10,"number_collected"), number_collected ); if ( mp_params->ContainsFlag( CRCD(0xfd7ae1f4,"use_hud_counter") ) ) Script::RunScript( CRCD(0xf2e85a34,"goal_update_counter"), mp_params ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CounterGoalDone() { int number_collected = 0; mp_params->GetInteger( CRCD(0x129daa10,"number_collected"), &number_collected, Script::NO_ASSERT ); int number; mp_params->GetInteger( CRCD(0x696fe0ab,"number"), &number, Script::ASSERT ); return ( number_collected >= number ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::MarkInvalid() { m_invalid = true; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsInvalid() { return m_invalid; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::HasProset( const char* proset_prefix ) { const char* p_local_proset; if ( mp_params->GetString( CRCD(0x955c6305,"proset_prefix"), &p_local_proset, Script::NO_ASSERT ) ) { if ( stricmp( p_local_proset, proset_prefix ) == 0 ) return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetHasSeen() { m_hasSeen = true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::MarkBeaten() { GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); Mdl::Skate* skate_mod = Mdl::Skate::Instance(); if( gamenet_man->InNetGame() && skate_mod->GetGameMode()->GetNameChecksum() == CRCD( 0xec200eaa, "netgoalattack" ) ) { m_netIsBeat = true; } else { m_isbeat = true; } // mark all goals in the tree beaten CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); Game::CGoalLink* p_link = mp_parents; while ( p_link && p_link->m_relative != 0 ) { CGoal* pGoal = pGoalManager->GetGoal( p_link->m_relative ); pGoal->MarkBeaten(); p_link = p_link->mp_next; } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::MarkBeatenBy( int id ) { Dbg_Printf( "**** Marking goal 0x%x as beaten\n", GetGoalId()); m_beatenFlags.Set( id ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::MarkBeatenByTeam( int team_id ) { m_teamBeatenFlags.Set( team_id ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::HasWonGoal( int id ) { return m_beatenFlags.Test( id ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::HasTeamWonGoal( int team_id ) { return m_teamBeatenFlags.Test( team_id ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::Select() { m_isselected = true; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::Deselect() { m_isselected = false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetUnlocked() { m_isLocked = false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetLevelNum( int levelNum ) { m_levelNum = levelNum; } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetLevelNum() { return m_levelNum; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CheckMinigameRecord( int value ) { int record = 0; mp_params->GetInteger( CRCD(0x78ffb85c,"minigame_record"), &record, Script::NO_ASSERT ); mp_params->AddInteger( CRCD(0x819fc1d1,"last_attempt"), value ); if ( value > record ) { mp_params->AddInteger( CRCD(0x78ffb85c,"minigame_record"), value ); return true; } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetMinigameRecord() { int minigame_record = -1; mp_params->GetInteger( CRCD(0x78ffb85c,"minigame_record"), &minigame_record, Script::NO_ASSERT ); return minigame_record; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CanRetry() { return ( !mp_params->ContainsFlag( CRCD(0xa612f12c,"no_restart") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsMinigame() { return ( mp_params->ContainsFlag( CRCD(0x6bae094c,"minigame") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetStartTime() { mp_params->AddInteger( CRCD(0x5fd80edc,"current_time"), 0 ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::UpdateComboTimer() { if ( !IsPaused() ) { Tmr::Time current_time = 0; int time; mp_params->GetInteger( CRCD(0x5fd80edc,"current_time"), &time, Script::NO_ASSERT ); current_time = (Tmr::Time)time; current_time += (Tmr::Time)( Tmr::FrameLength() * 1000 ); mp_params->AddInteger( CRCD(0x5fd80edc,"current_time"), (int)current_time ); // add normal units for display mp_params->AddInteger( CRCD(0x7b1fe9a4,"current_time_seconds"), (int)( current_time / 1000 ) ); mp_params->AddInteger( CRCD(0xb4db9cb7,"current_time_fraction"), (int)( ( current_time / 10 ) % 100 ) ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetStartHeight() { Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater *p_skater = skate_mod->GetLocalSkater(); Dbg_Assert( p_skater ); int start_height = static_cast< int >(GetSkaterStateComponentFromObject(p_skater)->GetHeight()); mp_params->AddInteger( CRCD(0xc07d8d60,"start_height"), start_height ); // printf("setting start height to %i\n", start_height); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CheckHeightRecord() { if ( !IsPaused() ) { int record = 0; mp_params->GetInteger( CRCD(0x78ffb85c,"minigame_record"), &record, Script::NO_ASSERT ); Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater *p_skater = skate_mod->GetLocalSkater(); Dbg_Assert( p_skater ); int start_height = 10000; mp_params->GetInteger( CRCD(0xc07d8d60,"start_height"), &start_height, Script::NO_ASSERT ); int current_height = static_cast< int >(GetSkaterStateComponentFromObject(p_skater)->GetHeight()) - start_height; //printf("current_height: %i\n", current_height); if ( current_height < 0 ) current_height = 0; int feet = (int)( current_height / 12 ); int inches = current_height % 12; mp_params->AddInteger( CRCD(0x50815d42,"current_height_feet"), feet ); mp_params->AddInteger( CRCD(0xb0c26927,"current_height_inches"), inches ); if ( current_height > record ) { mp_params->AddInteger( CRCD(0x78ffb85c,"minigame_record"), current_height ); mp_params->AddInteger( CRCD(0x24bf3ae4,"record_feet"), feet ); mp_params->AddInteger( CRCD(0x9b49f28d,"record_inches"), inches ); return true; } } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CheckDistanceRecord() { // find the object in question uint32 objId; mp_params->GetChecksum( CRCD(0x8e18f3b3,"distance_record_object"), &objId, Script::ASSERT ); // grab the object Obj::CMovingObject* pObj = NULL; // pObj = Obj::CMovingObject::m_hash_table.GetItem( objId ); pObj = (Obj::CMovingObject*) Obj::CCompositeObjectManager::Instance()->GetObjectByID( objId); // grab the skater Obj::CSkater* pSkater = Mdl::Skate::Instance()->GetLocalSkater(); if ( pSkater && pObj ) { float distSquared = Mth::DistanceSqr( pObj->m_pos, pSkater->m_pos ); // get the height of the two float objHeight = pObj->m_pos.GetY(); float skaterHeight = pSkater->m_pos.GetY(); // get the base of the right triangle formed by the three points float distance = sqrtf( distSquared - ( Mth::Sqr( skaterHeight - objHeight ) ) ); // printf("distance = %f\n", distance); int feet = (int)( distance / 12 ); int inches = (int)distance % 12; mp_params->AddInteger( CRCD(0xcb48c8e8,"current_distance_feet"), feet ); mp_params->AddInteger( CRCD(0x644fc146,"current_distance_inches"), inches ); int record = 0; mp_params->GetInteger( CRCD(0x78ffb85c,"minigame_record"), &record, Script::NO_ASSERT ); if ( distance > record ) { mp_params->AddInteger( CRCD(0x78ffb85c,"minigame_record"), distance ); mp_params->AddInteger( CRCD(0x24bf3ae4,"record_feet"), feet ); mp_params->AddInteger( CRCD(0x9b49f28d,"record_inches"), inches ); return true; } } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetQuickStartFlag() { mp_params->AddChecksum( NONAME, CRCD( 0x38221df4, "quick_start" ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::UnsetQuickStartFlag() { mp_params->RemoveFlag( CRCD(0x38221df4,"quick_start") ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsProGoal() { return ( mp_params->ContainsComponentNamed( CRCD(0xd303a1a3,"pro_goal") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsNetGoal() { return ( mp_params->ContainsComponentNamed( CRCD(0xd15ea00,"net") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsCompetition() { return ( mp_params->ContainsFlag( CRCD(0x4af5d34e,"competition") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsPaused() { return m_paused; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::UnBeatGoal() { GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); if( gamenet_man->InNetGame() ) { m_beatenFlags = 0; m_teamBeatenFlags = 0; if( m_netIsBeat ) { m_netIsBeat = false; return true; } } else { if ( m_isbeat ) { m_isbeat = false; return true; } } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::GetViewGoalsText( const char** p_view_goals_text ) { mp_params->GetText( "view_goals_text", p_view_goals_text, Script::NO_ASSERT ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsBettingGame() { return ( mp_params->ContainsFlag( CRCD(0x8add4306,"betting_game") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsBettingGuy() { return ( mp_params->ContainsFlag( CRCD(0x8cfee956,"betting_guy") ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::EndRunCalled() { return m_endRunCalled; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::ClearEndRun( Script::CScript* pScript ) { // printf("CGoal::ClearEndRun called\n"); m_endRunCalled = false; // TODO: this should pick the right skater somehow Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater* p_skater = skate_mod->GetLocalSkater(); Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater); Dbg_Assert(p_skater_endrun_component); switch ( m_endRunType ) { case vENDOFRUN: // Mick: the way these type of exception is handled has changed // I'm not sure if it still needs to be cleared here any more // as it should have been executed immediately // I'm removing this line for now, as the ExceptionComponent has gone // GetExceptionComponentFromObject(p_skater)->ClearException( CRCD( 0x822e13a9, "RunHasEnded" )); p_skater->CallMemberFunction( CRCD( 0x4c58771e, "EndOfRunDone" ), NULL, pScript ); p_skater_endrun_component->ClearStartedEndOfRunFlag(); break; case vGOALENDOFRUN: // GetExceptionComponentFromObject(p_skater)->ClearException( CRCD( 0xab676175, "GoalHasEnded" ) ); p_skater->CallMemberFunction( CRCD( 0x69a9e37f, "Goal_EndOfRunDone" ), NULL, pScript ); p_skater_endrun_component->ClearStartedGoalEndOfRunFlag(); break; default: Dbg_Assert( 0 ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::FinishedEndOfRun() { // TODO: make this pick the right skater Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater* p_skater = skate_mod->GetLocalSkater(); Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater); Dbg_Assert(p_skater_endrun_component); switch ( m_endRunType ) { case vENDOFRUN: return p_skater_endrun_component->RunHasEnded(); break; case vGOALENDOFRUN: return p_skater_endrun_component->GoalRunHasEnded(); break; default: Dbg_Assert( 0 ); } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::StartedEndOfRun() { // TODO: make this choose the right skater Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CSkater* p_skater = skate_mod->GetLocalSkater(); Obj::CSkaterEndRunComponent* p_skater_endrun_component = GetSkaterEndRunComponentFromObject(p_skater); Dbg_Assert(p_skater_endrun_component); switch ( m_endRunType ) { case vENDOFRUN: return p_skater_endrun_component->StartedEndOfRun(); break; case vGOALENDOFRUN: // return p_skater->StartedGoalEndOfRun(); return m_endRunCalled; break; default: Dbg_Assert( 0 ); } return false; } /******************************************************************/ /* */ /* */ /******************************************************************/ // void CGoal::DisableEndOfRun() // { // m_shouldEndRun = false; // } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::AddTempSpecialTrick() { // get the new special trick name and type uint32 trickType; bool is_cat = mp_params->ContainsFlag( CRCD(0x8e6014f6,"create_a_trick") ); mp_params->GetChecksum( "trick_type", &trickType, Script::ASSERT ); uint32 trickName; if ( is_cat ) { int tempTrickName; mp_params->GetInteger( CRCD(0xb502200,"premade_cat_index"), &tempTrickName, Script::ASSERT ); trickName = (uint32)tempTrickName; } else mp_params->GetChecksum( "trick_name", &trickName, Script::ASSERT ); // get the local string version of the trick and store it if ( is_cat ) { Script::CArray* pPremadeCatArray = Script::GetArray( CRCD(0xffd7913f,"Premade_CATS"), Script::ASSERT ); Script::CStruct* pPremadeCat = pPremadeCatArray->GetStructure( trickName ); const char* pPremadeCatName; pPremadeCat->GetString( CRCD(0xa1dc81f9,"name"), &pPremadeCatName, Script::ASSERT ); mp_params->AddString( CRCD(0x3a54cc4b,"trick_string"), pPremadeCatName ); } else { const char* trickName_string; Script::CStruct* p_trick = Script::GetStructure( trickName, Script::ASSERT ); Script::CStruct* p_trick_params; p_trick->GetStructure( "Params", &p_trick_params, Script::ASSERT ); p_trick_params->GetLocalString( "Name", &trickName_string, Script::ASSERT ); mp_params->AddString( "trick_string", trickName_string ); } // get the list of valid key bindings for this trick type Script::CStruct* p_keyBindings = NULL; switch ( trickType ) { case CRCC( 0x61a1bc57, "cat" ): case CRCC( 0x439f4704, "air" ): p_keyBindings = Script::GetStructure( CRCD( 0x4764231d, "goal_special_tricks_air" ), Script::ASSERT ); break; case CRCC( 0xa549b57b, "lip" ): p_keyBindings = Script::GetStructure( CRCD( 0xa1b2d162, "goal_special_tricks_lip" ), Script::ASSERT ); break; case CRCC( 0x255ed86f, "grind" ): p_keyBindings = Script::GetStructure( CRCD( 0xf481d0cd, "goal_special_tricks_grind" ), Script::ASSERT ); break; case CRCC( 0xef24413b, "manual" ): p_keyBindings = Script::GetStructure( CRCD( 0xd72d5cf7, "goal_special_tricks_manual" ), Script::ASSERT ); break; default: Dbg_MsgAssert( p_keyBindings, ( "AddTempSpecialTrick got weird trick type\n" ) ); } Obj::CPlayerProfileManager* pPlayerProfileManager = Mdl::Skate::Instance()->GetPlayerProfileManager(); Obj::CSkaterProfile* pSkaterProfile = pPlayerProfileManager->GetCurrentProfile(); // Script::CStruct* p_trickMapping = p_SkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,"trick_mapping") ); int numTricks = pSkaterProfile->GetNumSpecialTrickSlots(); // we need to remember the key combo uint32 key_combo = 0; // search through current special tricks bool found_trick = false; for ( int i = 0; i < numTricks; i++ ) { Obj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( i ); if ( !is_cat && trick_info.m_TrickName == trickName ) { // printf("the special trick is already bound!\n"); found_trick = true; key_combo = trick_info.m_TrickSlot; break; } p_keyBindings->RemoveFlag( trick_info.m_TrickSlot ); } // if we didn't find the trick, grab the first available, unused key combo if ( !found_trick ) { // printf("binding special trick\n"); Script::CComponent* p_comp = p_keyBindings->GetNextComponent(); Dbg_MsgAssert( p_comp, ( "Could not find an open key binding\n" ) ); uint32 trickSlot = p_comp->mChecksum; Dbg_MsgAssert( trickSlot, ( "Could not find key binding in structure" ) ); // give everyone a new slot /*int num_profiles = pPlayerProfileManager->GetNumProfileTemplates(); for ( int i = 0; i < num_profiles; i++ ) { Obj::CSkaterProfile* pTempProfile = pPlayerProfileManager->GetProfileTemplateByIndex( i ); pTempProfile->AwardSpecialTrickSlot(); }*/ pSkaterProfile->AwardSpecialTrickSlot(); key_combo = trickSlot; if ( is_cat ) { // assign cat to trickslot Script::CStruct* pScriptParams = new Script::CStruct(); pScriptParams->AddChecksum( CRCD(0xa92a2280,"trickSlot"), trickSlot ); pScriptParams->AddInteger( CRCD(0x7f8c98fe,"index"), trickName ); pScriptParams->AddInteger( CRCD(0x7f264be9,"special_trick_index"), numTricks ); Script::RunScript( CRCD(0x466576c8,"load_premade_cat"), pScriptParams ); delete pScriptParams; } else { // add new trick to new slot Obj::SSpecialTrickInfo trickInfo; trickInfo.m_TrickSlot = trickSlot; trickInfo.m_TrickName = trickName; pSkaterProfile->SetSpecialTrickInfo( numTricks, trickInfo ); } // make a note of this so we can remove it later mp_params->AddInteger( CRCD( 0xbc678826, "should_remove_trick" ), 1 ); } // testing // Script::PrintContents( p_SkaterProfile->GetSpecialTricksStructure() ); // replace the key combo array mp_params->RemoveComponent( "key_combos" ); Script::CArray* p_key_combos = new Script::CArray(); p_key_combos->SetSizeAndType( 1, ESYMBOLTYPE_NAME ); p_key_combos->SetChecksum( 0, key_combo ); mp_params->AddArrayPointer( "key_combos", p_key_combos ); // printf("added special trick\n"); // Script::PrintContents( mp_params ); ReplaceTrickText(); return !found_trick; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::RemoveTempSpecialTrick() { Mdl::Skate* skate_mod = Mdl::Skate::Instance(); Obj::CPlayerProfileManager* pPlayerProfileManager = skate_mod->GetPlayerProfileManager(); Obj::CSkaterProfile* pSkaterProfile = pPlayerProfileManager->GetCurrentProfile(); // do we need to take out the trick we added? int should_remove; mp_params->GetInteger( "should_remove_trick", &should_remove, Script::ASSERT ); if ( should_remove == 1 ) { // printf("removing special trick\n"); // find it and take it out uint32 trickName; if ( mp_params->ContainsFlag( CRCD(0x8e6014f6,"create_a_trick") ) ) { // int premade_cat_index; // mp_params->GetInteger( CRCD(0xb502200,"premade_cat_index"), &premade_cat_index, Script::ASSERT ); // trickName = (uint32)premade_cat_index; // temp cat tricks are always on 0 trickName = 0; } else mp_params->GetChecksum( CRCD( 0xef6fb249, "trick_name" ), &trickName, Script::ASSERT ); // int numTricks = p_SkaterProfile->GetNumSpecialTrickSlots(); // just look through all tricks for ( int i = 0; i < Obj::CSkaterProfile::vMAXSPECIALTRICKSLOTS; i++ ) { Obj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( i ); // printf("m_TrickName: %x, trickName: %x\n", trick_info.m_TrickName, trickName ); if ( trick_info.m_TrickName == trickName ) { // printf("Removing special trick\n"); Obj::SSpecialTrickInfo new_info; new_info.m_TrickName = CRCD( 0xf60c9090, "unassigned" ); new_info.m_TrickSlot = CRCD( 0xf60c9090, "unassigned" ); pSkaterProfile->SetSpecialTrickInfo( i, new_info ); mp_params->AddInteger( CRCD( 0xbc678826, "should_remove_trick" ), 0 ); break; } } // take a slot away from everyone /*int num_profiles = pPlayerProfileManager->GetNumProfileTemplates(); for ( int i = 0; i < num_profiles; i++ ) { Obj::CSkaterProfile* pTempProfile = pPlayerProfileManager->GetProfileTemplateByIndex( i ); pTempProfile->AwardSpecialTrickSlot( -1 ); }*/ pSkaterProfile->AwardSpecialTrickSlot( -1 ); } mp_params->RemoveComponent( CRCD(0x79704516,"key_combos") ); Dbg_MsgAssert( (int)pSkaterProfile->GetNumSpecialTrickSlots() <= Script::GetInteger( CRCD(0x20297d6f,"max_number_of_special_trickslots") ), ( "You have too many trickslots!" ) ); // Script::CStruct* pTest = pSkaterProfile->GetSpecialTricksStructure(); // printf("done removing\n"); // Script::PrintContents( pTest ); // remove the display string just in case mp_params->RemoveComponent( "key_combo_string" ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::ShouldUseTimer() { int unlimited_time = 0; mp_params->GetInteger( CRCD(0xf0e712d2,"unlimited_time"), &unlimited_time ); return ( unlimited_time == 0 ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::CountAsActive() { return IsActive(); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::LoadSaveData( Script::CStruct *pFlags ) { int hasBeaten = 0; pFlags->GetInteger( "hasBeaten", &hasBeaten, Script::ASSERT ); if ( hasBeaten != 0 ) MarkBeaten(); int isLocked = 1; pFlags->GetInteger( "isLocked", &isLocked, Script::ASSERT ); if ( isLocked == 0 ) { // special case for pro challenges /* if ( mp_params->ContainsFlag( "pro_specific_challenge" ) && hasBeaten == 0 ) { if ( mp_goalPed->ProIsCurrentSkater() ) SetUnlocked(); } else */ SetUnlocked(); } int hasSeen = 0; pFlags->GetInteger( "hasSeen", &hasSeen, Script::ASSERT ); if ( hasSeen != 0 ) SetHasSeen(); // check for a completion record int record = 0; pFlags->GetInteger( CRCD( 0xc22a2b72, "win_record" ), &record, Script::ASSERT ); mp_params->AddInteger( "win_record", record ); uint32 record_type; if ( mp_params->GetChecksum( "record_type", &record_type, Script::NO_ASSERT ) ) { if ( record_type == Script::GenerateCRC( "time" ) ) m_elapsedTimeRecord = record; else if ( record_type == Script::GenerateCRC( "score" ) ) m_winScoreRecord = record; } pFlags->GetInteger( "timesLost", &m_numTimesLost, Script::ASSERT ); pFlags->GetInteger( "timesWon", &m_numTimesWon, Script::ASSERT ); pFlags->GetInteger( "timesStarted", &m_numTimesStarted, Script::ASSERT ); uint32 team_pro; pFlags->GetChecksum( CRCD(0xced8a3a4,"team_pro"), &team_pro, Script::ASSERT ); if ( team_pro != 0 ) { mp_params->AddChecksum( CRCD(0xced8a3a4,"team_pro"), team_pro ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::GetSaveData( Script::CStruct* pFlags ) { pFlags->AddInteger( "levelNum", GetLevelNum() ); int isLocked = IsLocked(); pFlags->AddInteger( "isLocked", isLocked ); int hasSeen = HasSeenGoal(); pFlags->AddInteger( "hasSeen", hasSeen ); int hasBeaten = HasWonGoal(); pFlags->AddInteger( "hasBeaten", hasBeaten ); /* int isProSpecificChallenge = 0; if ( mp_params->ContainsFlag( "pro_specific_challenge" ) ) isProSpecificChallenge = 1; pFlags->AddInteger( "isProSpecificChallenge", isProSpecificChallenge ); */ int record = 0; uint32 record_type; if ( mp_params->GetChecksum( "record_type", &record_type, Script::NO_ASSERT ) ) { if ( record_type == Script::GenerateCRC( "time" ) ) record = (int)m_elapsedTimeRecord; else if ( record_type == Script::GenerateCRC( "score" ) ) record = m_winScoreRecord; } pFlags->AddInteger( "win_record", record ); // TODO: should this be removed for the release? pFlags->AddInteger( "timesLost", m_numTimesLost ); pFlags->AddInteger( "timesWon", m_numTimesWon ); pFlags->AddInteger( "timesStarted", m_numTimesStarted ); uint32 team_pro = 0; mp_params->GetChecksum( CRCD(0xced8a3a4,"team_pro"), &team_pro, Script::NO_ASSERT ); pFlags->AddChecksum( CRCD(0xced8a3a4,"team_pro"), team_pro ); } /******************************************************************/ /* */ /* */ /******************************************************************/ // utility used by ReplaceTrickText bool fill_trick_and_key_combo_arrays( Script::CArray* p_key_combos, Script::CArray* p_key_combo_strings, Script::CArray* p_trick_names, int premade_cat_index ) { // make sure the arrays are the right size and type Dbg_MsgAssert( p_key_combos->GetSize() == p_key_combo_strings->GetSize(), ( "key combo string array wrong size" ) ); Dbg_MsgAssert( p_key_combos->GetSize() == p_trick_names->GetSize(), ( "trick name array wrong size" ) ); Dbg_MsgAssert( p_key_combo_strings->GetType() == ESYMBOLTYPE_STRING, ( "array is the wrong type" ) ); Dbg_MsgAssert( p_trick_names->GetType() == ESYMBOLTYPE_STRING, ( "array is the wrong type" ) ); Script::CStruct* p_key_combo_map = Script::GetStructure( CRCD(0x8856c817,"goal_tetris_trick_text"), Script::ASSERT ); Mdl::Skate * pSkate = Mdl::Skate::Instance(); Obj::CSkaterProfile* pSkaterProfile = pSkate->GetCurrentProfile(); Script::CStruct* pTricks = pSkaterProfile->GetTrickMapping( CRCD(0xd544aa2d,"trick_mapping") ); // Script::PrintContents( pTricks ); int size = p_key_combos->GetSize(); for ( int i = 0; i < size; i++ ) { uint32 key_combo = p_key_combos->GetChecksum( i ); // printf("checking for key combo %s\n", Script::FindChecksumName( key_combo ) ); uint32 trick_checksum = 0; bool found_a_match = false; int cat_trick_index = 0; bool found_cat = false; if ( pTricks->GetInteger( key_combo, &cat_trick_index, Script::NO_ASSERT ) ) { // load cat info printf("found a cat trick - cat_trick_index = %i\n", cat_trick_index); found_cat = true; found_a_match = true; } else if ( pTricks->GetChecksum( key_combo, &trick_checksum, Script::NO_ASSERT ) ) { found_a_match = true; } else { // look for a special key combo int numSpecials = pSkaterProfile->GetNumSpecialTrickSlots(); // printf("checking special trick slots\n"); for ( int j = 0; j < numSpecials; j++ ) { Obj::SSpecialTrickInfo trick_info = pSkaterProfile->GetSpecialTrickInfo( j ); // printf("trickslot: %s\n", Script::FindChecksumName( trick_info.m_TrickSlot ) ); if ( trick_info.m_TrickSlot == key_combo ) { // printf("found a match\n"); trick_checksum = trick_info.m_TrickName; found_a_match = true; break; } } } if ( !found_a_match ) { // Script::PrintContents( pTricks ); // this key combo isn't assigned! bail out... Dbg_MsgAssert( 0, ( "key combo %s not assigned!\n", Script::FindChecksumName( key_combo ) ) ); return false; } const char* p_key_combo_string; p_key_combo_map->GetString( key_combo, &p_key_combo_string, Script::ASSERT ); const char* p_trick_name; if ( found_cat ) { // printf("getting cat params\n"); Obj::CSkater* pSkater = pSkate->GetLocalSkater(); if ( pSkater ) { // printf("got skater\n"); Game::CCreateATrick* pCreatedTrick = pSkater->m_created_trick[cat_trick_index]; Dbg_Assert( pCreatedTrick ); // Script::PrintContents( pCreatedTrick->mp_other_params ); pCreatedTrick->mp_other_params->GetString( CRCD( 0xa1dc81f9, "name" ), &p_trick_name, Script::ASSERT ); } } else { if ( premade_cat_index > -1 ) { Script::CArray* pPremadeCats = Script::GetArray( CRCD(0xffd7913f,"Premade_CATS"), Script::ASSERT ); Script::CStruct* pPremadeCat = pPremadeCats->GetStructure( premade_cat_index ); pPremadeCat->GetString( CRCD(0xa1dc81f9,"name"), &p_trick_name, Script::ASSERT ); } else { Script::CStruct* p_trick_struct = Script::GetStructure( trick_checksum, Script::ASSERT ); Script::CStruct* p_trick_params; p_trick_struct->GetStructure( CRCD(0x7031f10c,"Params"), &p_trick_params, Script::ASSERT ); p_trick_params->GetLocalString( CRCD(0xa1dc81f9,"Name"), &p_trick_name, Script::ASSERT ); } } // printf("setting strings: %s\n%s\n", p_key_combo_string, p_trick_name ); p_key_combo_strings->SetString( i, Script::CreateString( p_key_combo_string ) ); p_trick_names->SetString( i, Script::CreateString( p_trick_name ) ); } return true; } // utility used by CGoal::ReplaceTrickText...finds and replaces \t and \k with // the trick name and key combo, respectively void find_and_replace_trick_string( const char* p_old, char* p_out, Script::CArray* p_key, Script::CArray* p_trick, uint out_buffer_size ) { #ifdef __NOPT_ASSERT__ const char *p_out_start = p_out; #endif const char *p_in = p_old; while( *p_in ) { int tag_num; if ( *p_in == '\\' && *(p_in+1) == 't' && ( *(p_in+2) <= '9' && *(p_in+2) >= '0' ) ) { // printf("found the trick tag\n"); // get the index tag_num = *(p_in+2) - 48; if ( *(p_in+3) <= '9' && *(p_in+3) >= '0' ) { tag_num *= 10; tag_num += *(p_in+3) - 48; // move ahead an extra char p_in++; } // printf( "found a tag num of %i\n", tag_num ); Dbg_MsgAssert( ( tag_num > 0 ) && tag_num <= (int)p_trick->GetSize(), ( "Tag value too large" ) ); const char* p_trick_string = p_trick->GetString( tag_num - 1 ); Dbg_MsgAssert( p_trick_string, ( "ReplaceTrickText found a \\t tag but no key combo." ) ); sprintf( p_out, p_trick_string ); int length = strlen( p_trick_string ); for ( int i = 0; i < length; i++ ) p_out++; // move past the tag p_in++; p_in++; p_in++; } else if ( *p_in == '\\' && *(p_in+1) == 'k' && ( *(p_in+2) <= '9' && *(p_in+2) >= '0' ) ) { // printf("found the key tag\n"); // get the index tag_num = *(p_in+2) - 48; if ( *(p_in+3) <= '9' && *(p_in+3) >= '0' ) { tag_num *= 10; tag_num += *(p_in+3) - 48; // move ahead an extra char p_in++; } // printf( "found a tag num of %i\n", tag_num ); Dbg_MsgAssert( ( tag_num > 0 ) && tag_num <= (int)p_key->GetSize(), ( "Tag value too large" ) ); const char* p_key_string = p_key->GetString( tag_num - 1 ); Dbg_MsgAssert( p_key_string, ( "ReplaceTrickText found a \\k tag but no key combo." ) ); sprintf( p_out, p_key_string ); int length = strlen( p_key_string ); for ( int i = 0; i < length; i++ ) p_out++; // move past the tag p_in++; p_in++; p_in++; } else { *p_out++ = *p_in++; } } *p_out++ = '\0'; Dbg_MsgAssert(strlen(p_out_start) < out_buffer_size,("String overflow with\n\n%s\n\nMake it shorter than %d chars, or get a bigger buffer",p_out_start, out_buffer_size)); } bool CGoal::ReplaceTrickText() { // printf("ReplaceTrickText %s\n", Script::FindChecksumName( GetGoalId() ) ); // see if there's a key_combo associated with this goal Script::CArray* p_key_combo = NULL; if ( !mp_params->GetArray( "key_combos", &p_key_combo, Script::NO_ASSERT ) ) { // printf("no key combos\n"); return false; } // Make sure we have copies of the original text. We want // to update properly if they change their trick bindings. if ( !mp_params->ContainsComponentNamed( "original_goal_description" ) ) { const char* p_ogd; Script::CArray* p_ogd_array; if ( mp_params->GetString( "goal_description", &p_ogd, Script::NO_ASSERT ) ) mp_params->AddString( "original_goal_description", p_ogd ); else if ( mp_params->GetArray( "goal_description", &p_ogd_array, Script::ASSERT ) ) mp_params->AddArray( "original_goal_description", p_ogd_array ); } if ( !mp_params->ContainsComponentNamed( "original_view_goals_text" ) ) { const char* p_ovgt; if ( mp_params->GetString( "view_goals_text", &p_ovgt, Script::NO_ASSERT ) ) mp_params->AddString( "original_view_goals_text", p_ovgt ); } if ( !mp_params->ContainsComponentNamed( "original_goal_text" ) ) { const char* p_ogt; if ( mp_params->GetString( "goal_text", &p_ogt, Script::NO_ASSERT ) ) mp_params->AddString( "original_goal_text", p_ogt ); } if ( !mp_params->ContainsComponentNamed( "original_key_combo_text" ) ) { const char* p_okct; if ( mp_params->GetString( "key_combo_text", &p_okct, Script::NO_ASSERT ) ) mp_params->AddString( "original_key_combo_text", p_okct ); } // special case for cat goal int premade_cat_index = -1; if ( mp_params->ContainsFlag( CRCD(0x8e6014f6,"create_a_trick") ) ) { mp_params->GetInteger( CRCD(0xb502200,"premade_cat_index"), &premade_cat_index, Script::ASSERT ); } // get the new string arrays Script::CArray* p_key = new Script::CArray(); Script::CArray* p_trick = new Script::CArray(); int size = p_key_combo->GetSize(); p_key->SetSizeAndType( size, ESYMBOLTYPE_STRING ); p_trick->SetSizeAndType( size, ESYMBOLTYPE_STRING ); if ( !fill_trick_and_key_combo_arrays( p_key_combo, p_key, p_trick, premade_cat_index ) ) { Script::CleanUpArray( p_key ); Script::CleanUpArray( p_trick ); delete p_key; delete p_trick; return false; } const char* p_string; Script::CArray* p_string_array = NULL; char new_string[Game::NEW_STRING_LENGTH]; // replace the goal description if ( mp_params->GetString( "original_goal_description", &p_string, Script::NO_ASSERT ) ) { find_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH ); mp_params->AddString( "goal_description", p_string ); } else if ( mp_params->GetArray( "original_goal_description", &p_string_array, Script::ASSERT ) ) { int size = p_string_array->GetSize(); Script::CArray* p_new_string_array = new Script::CArray(); p_new_string_array->SetSizeAndType( size, ESYMBOLTYPE_STRING ); for ( int i = 0; i < size; i++ ) { p_string = p_string_array->GetString( i ); find_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH ); p_new_string_array->SetString( i, Script::CreateString( new_string ) ); } mp_params->AddArray( "goal_description", p_new_string_array ); Script::CleanUpArray( p_new_string_array ); delete p_new_string_array; } // replace the view goals text if ( mp_params->GetString( "original_view_goals_text", &p_string, Script::NO_ASSERT ) ) { find_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH ); mp_params->AddString( "view_goals_text", new_string ); } // replace the goal text if ( mp_params->GetString( "original_goal_text", &p_string, Script::NO_ASSERT ) ) { find_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH ); mp_params->AddString( "goal_text", new_string ); } // replace the key combo text if ( mp_params->GetString( "original_key_combo_text", &p_string, Script::NO_ASSERT ) ) { find_and_replace_trick_string( p_string, new_string, p_key, p_trick, Game::NEW_STRING_LENGTH ); mp_params->AddString( "key_combo_text", new_string ); } // cleanup! Script::CleanUpArray( p_key ); Script::CleanUpArray( p_trick ); delete p_key; delete p_trick; return true; } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetNumberCollected() { int number_collected = 0; // check for special counter goal num if ( mp_params->GetInteger( CRCD(0x129daa10,"number_collected"), &number_collected, Script::NO_ASSERT ) ) return number_collected; // return the number of flags set return m_flagsSet; } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetNumberOfFlags() { int num_flags_to_win = m_numflags; mp_params->GetInteger( CRCD(0x1171a555,"num_flags_to_win"), &num_flags_to_win, Script::NO_ASSERT ); if ( num_flags_to_win != 0 ) return num_flags_to_win; return -1; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::ColorTrickObjects( int seqIndex, bool clear ) { Mdl::Skate * skate_mod = Mdl::Skate::Instance(); Obj::CTrickObjectManager* p_trickObjMan = skate_mod->GetTrickObjectManager(); Script::CArray* p_clusters = NULL; if ( !mp_params->GetArray( "kill_clusters", &p_clusters, Script::NO_ASSERT ) ) return; int numClusters = p_clusters->GetSize(); for ( int i = 0; i < numClusters; i++ ) { Script::CStruct* p_temp = p_clusters->GetStructure( i ); uint32 cluster_id; p_temp->GetChecksum( "id", &cluster_id, Script::ASSERT ); Obj::CTrickCluster* p_trickCluster = p_trickObjMan->GetTrickCluster( cluster_id ); if ( p_trickCluster ) { if ( clear ) { // printf("clearing cluster %s\n", Script::FindChecksumName( cluster_id ) ); Obj::CTrickCluster* p_trickCluster = p_trickObjMan->GetTrickCluster( cluster_id ); if ( p_trickCluster ) p_trickCluster->ClearCluster( seqIndex ); } else p_trickObjMan->GetTrickCluster( cluster_id )->ModulateTrickObjectColor( seqIndex ); } else Dbg_Message( "WARNING: cluster %s not found\n", Script::FindChecksumName( cluster_id ) ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ int CGoal::GetNumberOfTimesGoalStarted() { return m_numTimesStarted; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::GetRewardsStructure( Script::CStruct *p_structure, bool give_cash ) { CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); GameNet::Manager * gamenet_man = GameNet::Manager::Instance(); if ( !mp_params->ContainsFlag( CRCD(0x981d3ad0,"edited_goal") ) ) pGoalManager->AddGoalPoint(); p_structure->AddChecksum( NONAME, CRCD( 0xc7fef529, "awarded_goal_point" ) ); // No rewards in net games, only fanfare if( gamenet_man->InNetGame() == false ) { // special case for special trick goal if ( mp_params->ContainsFlag( "reward_trickslot" ) && !mp_params->ContainsFlag( CRCD( 0x8e6014f6, "create_a_trick" ) ) ) { // printf("found trickslot flag\n"); Mdl::Skate* skate_mod = Mdl::Skate::Instance(); Obj::CSkaterProfile* p_SkaterProfile = skate_mod->GetCurrentProfile(); int num_slots = p_SkaterProfile->GetNumSpecialTrickSlots(); if ( num_slots <= Script::GetInteger( CRCD(0x20297d6f,"max_number_of_special_trickslots") ) ) { // printf("has less than the max number of slots\n"); int should_remove = 0; mp_params->GetInteger( "should_remove_trick", &should_remove, Script::NO_ASSERT ); if ( should_remove == 1 ) { // printf("was going to remove the special trick, but don't!\n"); mp_params->AddInteger( "should_remove_trick", 0 ); // p_reward_params->AddChecksum( NONAME, CRCD( 0x65ca5ffc, "already_added_trickslot" ) ); mp_params->AddChecksum( NONAME, CRCD( 0x65ca5ffc, "already_added_trickslot" ) ); mp_params->AddInteger( CRCD(0xb45fd352,"just_added_trickslot"), 1 ); } } } // ************************ // new global reward stuff // ************************ // grab the list of rewards Script::CStruct* p_all_rewards = Script::GetStructure( "goal_rewards", Script::ASSERT ); Script::CStruct* p_rewards = NULL; p_all_rewards->GetStructure( GetGoalId(), &p_rewards, Script::NO_ASSERT ); if ( p_rewards ) { // map the reward_stat flag to an int if ( p_rewards->ContainsFlag( "reward_stat" ) ) { p_rewards->RemoveComponent( "reward_stat" ); p_rewards->AddInteger( "reward_stat", 1 ); } p_structure->AppendStructure( p_rewards ); if ( give_cash ) { int reward_cash; if ( p_rewards->GetInteger( "reward_cash", &reward_cash, Script::NO_ASSERT ) ) p_structure->AddInteger( "cash", reward_cash ); } } // ************************** // old reward stuff // ************************** else { if ( give_cash ) { int reward_cash; // give 'em cash if ( mp_params->GetInteger( "reward_cash", &reward_cash, Script::NO_ASSERT ) ) p_structure->AddInteger( "cash", reward_cash ); } // stat points int stat_points; if ( mp_params->ContainsFlag( "reward_stat" ) ) p_structure->AddInteger( "reward_stat", 1 ); else if ( mp_params->GetInteger( "reward_stat", &stat_points, Script::NO_ASSERT ) ) p_structure->AddInteger( "reward_stat", stat_points ); } } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::UnlockRewardGoals() { CGoalManager* pGoalManager = GetGoalManager(); // unlock a new goal Script::CArray* p_new_goal_array = NULL; uint32 new_goal_checksum = 0; if ( mp_params->GetChecksum( "reward_goal", &new_goal_checksum, Script::NO_ASSERT ) ) pGoalManager->UnlockGoal( new_goal_checksum ); // check for an array of goals to unlock else if ( mp_params->GetArray( "reward_goal", &p_new_goal_array, Script::NO_ASSERT ) ) { int num_goals_to_unlock = p_new_goal_array->GetSize(); for ( int i = 0; i < num_goals_to_unlock; i++ ) { new_goal_checksum = p_new_goal_array->GetChecksum( i ); if ( new_goal_checksum ) pGoalManager->UnlockGoal( new_goal_checksum ); } } } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetEndRunType( EndRunType newEndRunType ) { m_endRunType = newEndRunType; } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::SetShouldDeactivateOnExpire( bool should_deactivate ) { m_deactivateOnExpire = should_deactivate; } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsHorseGoal() { return mp_params->ContainsFlag( CRCD(0x9d65d0e7,"horse") ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::IsFindGapsGoal() { return ( mp_params->ContainsFlag( CRCD( 0xc5ec08e6, "findGaps" ) ) ); } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::ShouldRequireCombo() { return mp_params->ContainsFlag( CRCD(0xf8e31760,"require_combo") ); } /******************************************************************/ /* */ /* */ /******************************************************************/ void CGoal::AppendDifficultyLevelParams() { Script::CArray* pLevelParams; if ( mp_params->GetArray( CRCD( 0x85104ab3, "difficulty_level_params" ), &pLevelParams, Script::NO_ASSERT ) ) { CGoalManager* pGoalManager = GetGoalManager(); Dbg_Assert( pGoalManager ); Game::GOAL_MANAGER_DIFFICULTY_LEVEL difficulty_level = pGoalManager->GetDifficultyLevel(); Dbg_MsgAssert( difficulty_level < (int)pLevelParams->GetSize(), ( "Difficulty params array has wrong size in goal %s", Script::FindChecksumName( GetGoalId() ) ) ); mp_params->AppendStructure( pLevelParams->GetStructure( difficulty_level ) ); CreateGoalFlags( mp_params ); } } /******************************************************************/ /* */ /* */ /******************************************************************/ bool CGoal::RunCallbackScript( uint32 script_name ) { #if 1 uint32 checksum; if ( mp_params->GetChecksum( script_name, &checksum, Script::NO_ASSERT ) ) { Script::RunScript( checksum, mp_params ); return true; } #else Script::CStruct* pStruct; if ( mp_params->GetStructure( script_name, &pStruct, Script::NO_ASSERT ) ) { // target script name is required uint32 checksum; pStruct->GetChecksum( CRCD(0xb990d003,"target"), &checksum, Script::ASSERT ); // but not the params... Script::CStruct* pSubStruct = NULL; pStruct->GetStructure( CRCD(0x7031f10c,"params"), &pSubStruct, Script::NO_ASSERT ); if ( pParams ) pSubStruct->AppendStructure( pParams ); Script::RunScript( checksum, pSubStruct ); return true; } #endif else { return false; } } } // namespace Game