#include "global.h" /* ----------------------------------------------------------------------------- Class: Inventory Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "Inventory.h" #include "ThemeManager.h" #include "RageUtil.h" #include "GameState.h" #include "RageTimer.h" #include "PrefsManager.h" #include "song.h" #include "ScreenManager.h" #include "ScreenGameplay.h" #define NUM_ITEM_TYPES THEME->GetMetricF("Inventory","NumItemTypes") #define ITEM_DURATION_SECONDS THEME->GetMetricF("Inventory","ItemDurationSeconds") #define ITEM_COMBO( i ) THEME->GetMetricI("Inventory",ssprintf("Item%dCombo",i+1)) #define ITEM_EFFECT( i ) THEME->GetMetric ("Inventory",ssprintf("Item%dEffect",i+1)) #define ITEM_LEVEL( i ) THEME->GetMetricI("Inventory",ssprintf("Item%dLevel",i+1)) CachedThemeMetricF ITEM_USE_RATE_SECONDS("Inventory","ItemUseRateSeconds"); const PlayerNumber OPPOSITE_PLAYER[NUM_PLAYERS] = { PLAYER_2, PLAYER_1 }; #define ITEM_USE_PROBABILITY (1.f/ITEM_USE_RATE_SECONDS) struct Item { AttackLevel level; int iCombo; CString sModifier; }; vector g_Items; void ReloadItems() { g_Items.clear(); for( int i=0; im_PlayMode ) { case PLAY_MODE_BATTLE: break; default: ASSERT(0); } } Inventory::~Inventory() { for( unsigned i=0; im_PlayMode ) { case PLAY_MODE_BATTLE: m_soundAcquireItem.Load( THEME->GetPathToS("Inventory aquire item") ); for( unsigned i=0; iGetPathToS( ssprintf("Inventory use item %u",i+1) ); pSound->Load( sPath ); m_vpSoundUseItem.push_back( pSound ); } m_soundItemEnding.Load( THEME->GetPathToS("Inventory item ending") ); break; } } void Inventory::Update( float fDelta ) { if( GAMESTATE->m_bActiveAttackEndedThisUpdate[m_PlayerNumber] ) m_soundItemEnding.Play(); PlayerNumber pn = m_PlayerNumber; // check to see if they deserve a new item if( GAMESTATE->m_CurStageStats.iCurCombo[pn] != m_iLastSeenCombo ) { int iOldCombo = m_iLastSeenCombo; m_iLastSeenCombo = GAMESTATE->m_CurStageStats.iCurCombo[pn]; int iNewCombo = m_iLastSeenCombo; #define CROSSED(i) (iOldCombo=i) #define BROKE_ABOVE(i) (iNewCombo=i) for( unsigned i=0; im_bBreakComboToGetItem ) bEarnedThisItem = BROKE_ABOVE(g_Items[i].iCombo); else bEarnedThisItem = CROSSED(g_Items[i].iCombo); if( bEarnedThisItem ) { AwardItem( i ); break; } } } // use items if this player is CPU-controlled if( GAMESTATE->m_PlayerController[m_PlayerNumber] != PC_HUMAN && GAMESTATE->m_fSongBeat < GAMESTATE->m_pCurSong->m_fLastBeat ) { // every 1 seconds, try to use an item int iLastSecond = (int)(RageTimer::GetTimeSinceStart() - fDelta); int iThisSecond = (int)RageTimer::GetTimeSinceStart(); if( iLastSecond != iThisSecond ) { for( int s=0; sm_Inventory[m_PlayerNumber][s].IsBlank() ) if( randomf(0,1) < ITEM_USE_PROBABILITY ) UseItem( s ); } } } void Inventory::AwardItem( int iItemIndex ) { // CPU player is vanity only. It should have no effect on gameplay // and should not aquire/launch attacks. if( GAMESTATE->IsCpuPlayer(m_PlayerNumber) ) return; // search for the first open slot int iOpenSlot = -1; Attack* asInventory = GAMESTATE->m_Inventory[m_PlayerNumber]; //[NUM_INVENTORY_SLOTS] if( asInventory[NUM_INVENTORY_SLOTS/2].IsBlank() ) iOpenSlot = NUM_INVENTORY_SLOTS/2; else { for( int s=0; sm_Inventory[m_PlayerNumber]; //[NUM_INVENTORY_SLOTS] if( asInventory[iSlot].IsBlank() ) return; PlayerNumber pnToAttack = OPPOSITE_PLAYER[m_PlayerNumber]; Attack a = asInventory[iSlot]; // remove the item asInventory[iSlot].MakeBlank(); m_vpSoundUseItem[a.level]->Play(); GAMESTATE->LaunchAttack( pnToAttack, a ); float fPercentHealthToDrain = (a.level+1) / 10.f; ASSERT( fPercentHealthToDrain > 0 ); GAMESTATE->m_fOpponentHealthPercent -= fPercentHealthToDrain; CLAMP( GAMESTATE->m_fOpponentHealthPercent, 0.f, 1.f ); // play announcer sound SCREENMAN->SendMessageToTopScreen( (ScreenMessage)(SM_BattleDamageLevel1+a.level) ); }