www.pudn.com > GameEngine_src.rar > CItemFactory.cpp
#include "CItemFactory.h" #include "CMap.h" #include "CEasyDraw.h" #include "CEPKFile.h" #include "normal.h" #include "CHero.h" #include#include extern CMap theMap; extern PEASYDRAW g_pEasyDraw; extern CItemBox theItemBag; extern CItemBox theItemTrough; extern CItemBox theItemStorage; extern CItemBox theEquipmentBox; //装备栏 extern CItemBox theItemShop; extern CHero theHero; //itm文件的文件头 struct ITEM_FILE_HEADER { int itmFileType; char itmName[32]; //名字字符串 char itmGroundECP[32]; //在地上的ECP图像 char itmBoxECP[32]; //在框里的ECP图像 int itmInfoSize; //物品信息字符串长度 ITEM_TYPE itmType; //物品种类 ITEM_HOLD_TYPE itmHoldType; //占位方式 int itmCmdNum; //脚本命令数量 int itmLevel; //物品的级别(英雄要达到该级别才能使用) int itmPrice; //物品的价格 HERO_CLASS itmHeroClass; //职业限制 int itmUseTime; //使用次数 }; const int ITM_FILE = 'IT'; //英雄属性 const char *SZ_BASE_INFO[21] = { "等级加%d", "生命加%d", "精力加%d", "力量加%d", "敏捷加%d", "智力加%d", "毒抗加%d", "诅抗加%d", "火抗加%d", "冰抗加%d", "雷抗加%d", "保留加%d", "生命加%d", "魔法加%d", "伤害加%d", "防御加%d", "回避加%d", "命中加%d", "速度加%d", "回复加%d", "再生加%d", }; const char *SZ_ALL_INFO[2] = { "所有能力加%d", "所有抗力加%d" }; const char *SZ_HERO_CLASS[4] = { "所有职业可用", "剑士专用", "秘术师专用", "咒术师专用", }; ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CItemFactory::CItemFactory() { } CItemFactory::~CItemFactory() { } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CItemFactory::Init() { if ( m_ItemPool.Init( 256 ) == false ) return false; int cw = g_pEasyDraw->GetCharWidth() * 16; int ch = g_pEasyDraw->GetCharHeight() * 8; m_NameSurface = g_pEasyDraw->CreateSurfaceEx( NULL, cw, ch/8, true, 0, 0 ); m_InfoSurface = g_pEasyDraw->CreateSurfaceEx( NULL, cw, ch, true, true, 0 ); m_InfoBackSurface= g_pEasyDraw->CreateSurfaceEx( NULL, cw, ch, true, 0, 0 ); m_SurfWidth = cw; m_SurfHeight = ch; //初始化各种箱子: CEPKFile epk; if ( false == epk.Open( "..\\data\\box.epk", EPK_IN ) ) assert(false); //初始化背包 BYTE *buf = epk.Read( "item_bag.ecp" ); debug_assert( buf != NULL ); PSURFACE surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); int half_w = g_pEasyDraw->GetDeviceWidth() / 2; int half_h = g_pEasyDraw->GetDeviceHeight()/ 2; int x = half_w + ( half_w - surf->GetWidth() ) / 2; int y = half_h - surf->GetHeight() / 2; theItemBag.Init( x, y, 10, 6, surf, ITEM_BAG ); theItemBag.SetCloseButtonRect( 254, 190, 285, 244 ); //初始化快捷使用栏 buf = epk.Read( "item_trough.ecp" ); debug_assert( buf != NULL ); surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); y = g_pEasyDraw->GetDeviceHeight() - surf->GetHeight() - 4; theItemTrough.Init( 0, y, 12, 1, surf, ITEM_TROUGH ); //初始化保管箱 buf = epk.Read( "item_shop.ecp" ); debug_assert( buf != NULL ); surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); x = ( half_w - surf->GetWidth() ) / 2; y = half_h - surf->GetHeight() / 2; theItemStorage.Init( x, y, 10, 12, surf, ITEM_STORAGE ); theItemStorage.SetCloseButtonRect( 253, 367, 288, 403 ); theItemShop.Init( x, y, 10, 12, surf, ITEM_SHOP ); theItemShop.SetCloseButtonRect( 253, 367, 288, 403 ); //初始化装备栏 buf = epk.Read( "equipment_box.ecp" ); debug_assert( buf != NULL ); surf = g_pEasyDraw->CreateSurfaceFromMemory( buf ); x = ( half_w - surf->GetWidth() ) / 2; y = half_h - surf->GetHeight() / 2; theEquipmentBox.Init( x, y, 2, 2, surf, ITEM_EQUIPMENT ); theEquipmentBox.SetCloseButtonRect( 206,315,240,348 ); theItemTrough.OpenBox(); return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CItemFactory::Free() { theItemBag.Free(); theItemTrough.Free(); theItemStorage.Free(); theEquipmentBox.Free(); theItemShop.Free(); m_ItemPool.Free(); m_ItemInfoArray.Free(); m_ItemNameArray.Free(); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CItemFactory::OnFreeLvl() { CItemBox * boxArray[4] = { &theItemBag, &theItemTrough, &theEquipmentBox, &theItemStorage }; for ( int i = 0; i < 4; ++i ) { CPool &pool = boxArray[i]->GetItemPool(); for ( pool.Begin(); pool.IsNotNull(); pool.MoveNext() ) { CItem *item = *(pool.GetCur()); ITEM_INFO *it = item->GetItemInfo(); item->SetItemInfo( NULL ); for ( int n = 0; n < m_ItemInfoArray.GetLength(); ++n ) { if ( it == &m_ItemInfoArray[n] ) { m_ItemNameArray2.Add( m_ItemNameArray[n] ); break; } } } } for ( m_ItemPool.Begin(); m_ItemPool.IsNotNull(); m_ItemPool.MoveNext() ) { CItem *item = m_ItemPool.GetCur(); if ( item->GetItemInfo() != NULL ) m_ItemPool.FreeCur(); } m_ItemInfoArray.Clear(); m_NumItem1 = 0; m_NumItem2 = 0; m_NumItem3 = 0; } ////////////////////////////////////////////////////////////////////// //载入MAP文件中的物品信息 //首先读取普通,高级和稀有物品的数量,再分别读取其文件名 ////////////////////////////////////////////////////////////////////// void CItemFactory::OnLoadMap( FILE *fp ) { fread( &m_NumItem1, 4, 1, fp ); //普通物品的数量就是高级物品在数组中开始的索引位置 fread( &m_NumItem2, 4, 1, fp ); fread( &m_NumItem3, 4, 1, fp ); int sum = m_NumItem1 + m_NumItem2 + m_NumItem3; m_ItemNameArray.Clear(); m_ItemNameArray.SetSize( sum ); char sz[32]; for ( int i = 0; i < sum; ++i ) { fread( sz, 32, 1, fp ); m_ItemNameArray[i] = sz; } for ( i = 0; i < m_ItemNameArray2.GetLength(); ++i ) { m_ItemNameArray.Add( m_ItemNameArray2[i] ); } m_ItemNameArray2.Free(); } ////////////////////////////////////////////////////////////////////// //根据载入列表载入所有ITM文件,文件全是已经排好顺序的 //itm文件结构:文件头+物品信息字符串+脚本 ////////////////////////////////////////////////////////////////////// void CItemFactory::OnLoadLvl() { CEPKFile epk; if ( false == epk.Open( "..\\data\\item.epk", EPK_IN ) ) assert( false ); for ( int i = 0; i < m_ItemNameArray.GetLength(); ++i ) { BYTE *buf = epk.Read( m_ItemNameArray[i].c_str() ); assert( buf != NULL ); ITEM_FILE_HEADER ifh = READ_MEMORY( buf, ITEM_FILE_HEADER ); //读取文件头 buf += sizeof(ITEM_FILE_HEADER); debug_assert( ifh.itmFileType == ITM_FILE ); ITEM_INFO *pInfo = m_ItemInfoArray.CreateOneElement(); memcpy( pInfo->m_Name, ifh.itmName, 32 ); pInfo->m_ItemType = ifh.itmType; pInfo->m_HoldType = ifh.itmHoldType; pInfo->m_HeroClass= ifh.itmHeroClass; pInfo->m_ItemLvl = ifh.itmLevel; pInfo->m_ItemPrice= ifh.itmPrice; pInfo->m_ItemUseTime=ifh.itmUseTime; if ( ifh.itmInfoSize > 1 ) { pInfo->m_szInfoBuf = new char[ifh.itmInfoSize]; debug_assert( pInfo->m_szInfoBuf != NULL ); memcpy( pInfo->m_szInfoBuf, buf, ifh.itmInfoSize ); //读取物品附加信息字符串 } buf += ifh.itmInfoSize; //别少了这句 CES_CmdPool::LoadCmdBufFromMemory( buf, 0, pInfo->m_CmdBuf, pInfo->m_CmdNum );//读取脚本 buf = epk.Read( ifh.itmGroundECP ); //读取物品在地面上的图片 debug_assert( buf != NULL ); pInfo->m_GroundSurface = g_pEasyDraw->CreateSurfaceFromMemory( buf ); buf = epk.Read( ifh.itmBoxECP ); //读取物品在箱子里的图片 debug_assert( buf != NULL ); pInfo->m_BoxSurface = g_pEasyDraw->CreateSurfaceFromMemory( buf ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CItemFactory::OnInitLvl() { CItemBox * boxArray[4] = { &theItemBag, &theItemTrough, &theEquipmentBox, &theItemStorage }; int sum = m_NumItem1 + m_NumItem2 + m_NumItem3; int n = 0; for ( int i = 0; i < 4; ++i ) { CPool &pool = boxArray[i]->GetItemPool(); for ( pool.Begin(); pool.IsNotNull(); pool.MoveNext() ) { (*(pool.GetCur()))->SetItemInfo( &m_ItemInfoArray[sum + n] ); n++; } } } const int RAND_INFO[32] = { SI_MLF, SI_MMN, SI_MLF, SI_MMN, SI_MLF, SI_MMN, SI_MLF, SI_MMN, SI_STR, SI_AGI, SI_INT, SI_MLF, SI_MMN, SI_MLF, SI_MMN, SI_ARMOR, SI_RESISTANCE, SI_ACCURACY, SI_ARMOR, SI_RESISTANCE, SI_ACCURACY, SI_STR, SI_AGI, SI_INT, SI_ARMOR, SI_RESISTANCE, SI_ACCURACY, SI_POISON, SI_CURSE, SI_FIRE, SI_COLD, SI_THUNDER, }; const int RAND_INFO2[4] = { SI_DAMAGE, SI_DAMAGE, SI_SPEED, SI_ADDMANA }; ////////////////////////////////////////////////////////////////////// //怪物死后掉用此函数产生物品 ////////////////////////////////////////////////////////////////////// void CItemFactory::CreateItemOnGround( const POINT &base, int lvl, int randSeed ) { CELL cell; theMap.PointToCell( base, cell ); BYTE mask = BUILDING_MASK | ITEM_MASK; bool isBoss = false; if ( lvl % 8 == 0 ) isBoss = true; //如果等级能被8整除,将产生多于一件物品 srand( randSeed ); int begin, num, randNum; for ( int i = cell.row-1; i <= cell.row+1; ++i ) { for ( int j = cell.col-1; j <= cell.col+1; ++j ) { if ( theMap.IsCellHold( i, j, mask ) == false ) { randNum = rand() % 512; //随机的决定产生普通,高级还是稀有物品 if ( randNum < 16 ) { begin = m_NumItem1 + m_NumItem2; num = m_NumItem3; } else if ( randNum < 128 ) { begin = m_NumItem1; num = m_NumItem2; } else { begin = 0; num = m_NumItem1; } CItem *pItem = m_ItemPool.Alloc(); if ( pItem != NULL ) { randNum = (rand() % num) + begin; ITEM_INFO *pInfo = &m_ItemInfoArray[randNum]; pItem->Init( pInfo ); //随机产生物品附加属性 if ( pItem->GetItemType() >= IT_ARMOR && pItem->GetItemType() <= IT_SHIELD ) { pItem->SetMoney( pItem->GetMoney() / 4 ); randNum = rand() % 1024; if ( randNum < 512 ) { ES_CMD cmd; if ( randNum < 16 ) { cmd.cmd_id = ADD_HERO_ALL_INFO; cmd.param_1 = ( isBoss ? 1 : 0 ); //增加所有抗性的物品,只有BOSS才会掉出 cmd.param_2 = 1; } else { cmd.cmd_id = ADD_HERO_INFO; if ( randNum == 17 ) cmd.param_1 = RAND_INFO2[randNum%4]; else cmd.param_1 = RAND_INFO[randNum%32]; cmd.param_2 = ( randNum % 4 ) + 1; } pItem->AddAttribute( cmd ); } } POINT p = { j * CELL_WIDTH, i * CELL_HEIGHT }; pItem->OnDropDown( p ); if ( theMap.AddItem( pItem ) == false ) { m_ItemPool.Free( pItem ); debug_assert(false); } } if ( pItem->GetItemType() == IT_GOLD ) pItem->SetMoney( lvl + randNum ); if ( isBoss == false ) return; //如果不是BOSS,则只产生一件物品 } } } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CItemFactory::DeleteItem( CItem *pItem ) { m_ItemPool.Free( pItem ); } DWORD NAME_COLOR[4] = { 0xffffff, 0xff00, 0xff8888, 0xff }; //物品名字的颜色:白,绿,蓝,红 ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CItemFactory::DrawName( ITEM_INFO *pInfo, int colorIndex, int x, int y ) { m_NameSurface->ClearSurface( 0x0, 0 ); m_NameSurface->WriteTextCenter( pInfo->m_Name, NAME_COLOR[colorIndex] ); m_NameSurface->DrawSurface( x, y - 24, 0 ); } ////////////////////////////////////////////////////////////////////// //绘制物品信息 ////////////////////////////////////////////////////////////////////// void CItemFactory::DrawInfo( CItem *pItem, const ES_CMD *CmdBuf, int CmdNum, int x, int y ) { ITEM_INFO *pInfo = pItem->GetItemInfo(); int colorIndex = pItem->GetNumAttribute(); char sz[32]; m_InfoSurface->ClearSurface( 0, 0 ); m_InfoSurface->BeginDrawText( 0, 0 ); m_InfoSurface->DrawText( pInfo->m_Name, NAME_COLOR[colorIndex], 0 ); //写上物品名字 for ( int i = 0; i < CmdNum; ++i ) //绘制属性 { const ES_CMD &cmd = CmdBuf[i]; switch ( cmd.cmd_id ) { case ADD_HERO_LIFE: wsprintf( sz, "生命回复加%d", cmd.param_1 ); m_InfoSurface->DrawText( sz, 0xffff00, 0 ); break; case ADD_HERO_MANA: wsprintf( sz, "魔法回复加%d", cmd.param_1 ); m_InfoSurface->DrawText( sz, 0xffff00, 0 ); break; case ADD_HERO_INFO: { DWORD color = 0xffff00; if ( i > 1 ) color = 0xff; wsprintf( sz, SZ_BASE_INFO[ -(cmd.param_1) + SI_BEGIN ], cmd.param_2 ); m_InfoSurface->DrawText( sz, color, 0 ); } break; case ADD_HERO_ALL_INFO: wsprintf( sz, SZ_ALL_INFO[ cmd.param_1 ], cmd.param_2 ); m_InfoSurface->DrawText( sz, 0xff, 0 ); break; } } if ( pInfo->m_szInfoBuf ) //显示物品信息 m_InfoSurface->DrawText( pInfo->m_szInfoBuf, 0xff00, 0 ); if ( pItem->GetItemType() == IT_DRUG || pItem->GetItemType() == IT_STONE ) { wsprintf( sz, "可用次数%d", pItem->GetUseTime() ); m_InfoSurface->DrawText( sz, 0xffffff, 0 ); } else { m_InfoSurface->DrawText( SZ_HERO_CLASS[(int)pItem->GetHeroClass()], 0xffff, 0 ); wsprintf( sz, "等级%d", pItem->GetItemLevel() ); m_InfoSurface->DrawText( sz, 0xffff, 0 ); } if ( theItemShop.IsOpen() ) { wsprintf( sz, "价格%d", pItem->GetMoney() ); m_InfoSurface->DrawText( sz, 0xffffff, 0 ); } m_InfoSurface->EndDrawText(); if ( x - m_SurfWidth > 0 ) x -= m_SurfWidth; if ( y + m_SurfHeight > g_pEasyDraw->GetDeviceHeight() ) y -= m_SurfHeight; #ifdef ALPHA_SHADOW m_InfoBackSurface->DrawAlphaMMX( x, y ); #else m_InfoBackSurface->DrawSurface( x, y, 0 ); #endif m_InfoSurface->DrawSurface( x, y, 0 ); } ////////////////////////////////////////////////////////////////////// //打开商店 //参数为物品的珍贵度: ////////////////////////////////////////////////////////////////////// void CItemFactory::OpenItemShop( int itemIndex ) { if ( theItemShop.IsOpen() ) return; int begin = 0; int num = m_NumItem1; if ( itemIndex == 2 ) { begin = m_NumItem1; num = m_NumItem2; } else if ( itemIndex == 3 ) { begin = m_NumItem1 + m_NumItem2; num = m_NumItem3; } for ( int i = 0; i < num; ++i ) { CItem *pItem = m_ItemPool.Alloc(); if ( pItem != NULL ) { pItem->Init( &m_ItemInfoArray[begin+i] ); theItemShop.AddItem( pItem ); } } theItemShop.OpenBox(); } ////////////////////////////////////////////////////////////////////// //保存英雄的物品,包括背包,快捷使用栏,装备栏和保管箱 ////////////////////////////////////////////////////////////////////// void CItemFactory::SaveHeroItem( FILE *fp ) { //1.写入背包,使用栏,装备栏,保管箱物品数量 CItemBox * boxArray[4] = { &theItemBag, &theItemTrough, &theEquipmentBox, &theItemStorage }; for ( int i = 0; i < 4; ++i ) { int num = boxArray[i]->GetItemPool().GetLength(); fwrite( &num, 4, 1, fp ); } //2.获取物品文件名并写入 for ( i = 0; i < 4; ++i ) { CPool &pool = boxArray[i]->GetItemPool(); for ( pool.Begin(); pool.IsNotNull(); pool.MoveNext() ) { ITEM_INFO *it = (*pool.GetCur())->GetItemInfo(); for ( int n = 0; n < m_ItemInfoArray.GetLength(); ++n ) { if ( it == &m_ItemInfoArray[n] ) { char sz[32]; memset( sz, 0, 32 ); strcpy( sz, m_ItemNameArray[n].c_str() ); fwrite( sz, 32, 1, fp ); break; } } } } //3.写入物品附加信息 for ( i = 0; i < 4; ++i ) { CPool &pool = boxArray[i]->GetItemPool(); for ( pool.Begin(); pool.IsNotNull(); pool.MoveNext() ) { CItem *item = (*pool.GetCur()); HERO_ITEM heroItem; heroItem.numCmd = item->GetCmdPool().GetCmdNum(); heroItem.useTime= item->GetUseTime(); heroItem.money = item->GetMoney(); heroItem.rect = item->GetRect(); heroItem.holdType = item->GetHoldType(); fwrite( &heroItem, sizeof(HERO_ITEM), 1, fp ); //写入HERO_ITEM结构 fwrite( item->GetCmdPool().GetCmdBuf(), heroItem.numCmd * sizeof(ES_CMD), 1, fp ); //写入脚本 } } } ////////////////////////////////////////////////////////////////////// //载入英雄物品文件名列表 ////////////////////////////////////////////////////////////////////// void CItemFactory::LoadHeroItem( FILE *fp ) { int numArray[4]; fread( numArray, 16, 1, fp ); //读取各个箱子物品数量 int sum = numArray[0] + numArray[1] + numArray[2] + numArray[3]; CDynamicArray nameArray; for ( int i = 0; i < sum; ++i ) { char sz[32]; fread( sz, 32, 1, fp ); nameArray.Add( sz ); //读取物品文件名 } int n = 0; int m = 0; m_ItemNameArray2.Free(); for ( i = 0; i < 4; ++i ) { m += numArray[i]; for ( int j = m - 1; j >= n; --j ) m_ItemNameArray2.Add( nameArray[j] ); n += numArray[i]; } CItemBox * boxArray[4] = { &theItemBag, &theItemTrough, &theEquipmentBox, &theItemStorage }; for ( i = 0; i < 4; ++i ) { for ( int j = 0; j < numArray[i]; ++j ) { CItem *pItem = m_ItemPool.Alloc(); assert( pItem != NULL ); HERO_ITEM heroItem; fread( &heroItem, sizeof(heroItem), 1, fp ); pItem->Init( heroItem ); pItem->GetCmdPool().LoadCmdFromFile( fp, heroItem.numCmd ); boxArray[i]->AddItem( pItem, heroItem.rect.left, heroItem.rect.top, heroItem.holdType ); } } }