TRIGRET_TYPE CClient::Menu_OnSelect( RESOURCE_ID_BASE rid, int iSelect, CObjBase * pObj ) // Menus for general purpose { ADDTOCALLSTACK("CClient::Menu_OnSelect"); // A select was made. so run the script. // iSelect = 0 = cancel. CResourceLock s; if ( ! g_Cfg.ResourceLock( s, rid )) { // Can't find the resource ? return( TRIGRET_ENDIF ); } if ( pObj == NULL ) pObj = m_pChar; // execute the menu script. if ( iSelect == 0 ) // Cancel button { while ( s.ReadKeyParse() ) { if ( !s.IsKey( "ON" ) || ( *s.GetArgStr() != '@' ) ) continue; if ( strcmpi( s.GetArgStr(), "@cancel" ) ) continue; return pObj->OnTriggerRunVal( s, TRIGRUN_SECTION_TRUE, m_pChar, NULL ); } } else { int i=0; // 1 based selection. while ( s.ReadKeyParse()) { if ( !s.IsKey( "ON" ) || ( *s.GetArgStr() == '@' ) ) continue; i++; if ( i < iSelect ) continue; if ( i > iSelect ) break; return pObj->OnTriggerRunVal( s, TRIGRUN_SECTION_TRUE, m_pChar, NULL ); } } // No selection ? return( TRIGRET_ENDIF ); }
void CClient::Menu_Setup( RESOURCE_ID_BASE rid, CObjBase * pObj ) { ADDTOCALLSTACK("CClient::Menu_Setup"); // Menus for general purpose // Expect PacketMenuChoice::onReceive() back. CResourceLock s; if ( ! g_Cfg.ResourceLock( s, rid )) { return; } if ( pObj == NULL ) { pObj = m_pChar; } s.ReadKey(); // get title for the menu. pObj->ParseText( s.GetKeyBuffer(), m_pChar ); CMenuItem item[MAX_MENU_ITEMS]; item[0].m_sText = s.GetKey(); // item[0].m_id = rid.m_internalrid; // general context id size_t i = 0; while (s.ReadKeyParse()) { if ( ! s.IsKey( "ON" )) continue; i++; if ( ! item[i].ParseLine( s.GetArgRaw(), pObj, m_pChar )) i--; if ( i >= (COUNTOF( item ) - 1)) break; } m_tmMenu.m_ResourceID = rid; ASSERT(i < COUNTOF(item)); addItemMenu( CLIMODE_MENU, item, i, pObj ); }
size_t CClient::Cmd_Skill_Menu_Build( RESOURCE_ID_BASE rid, int iSelect, CMenuItem *item, size_t iMaxSize, bool &fShowMenu, bool &fLimitReached ) { ADDTOCALLSTACK("CClient::Cmd_Skill_Menu_Build"); // Build the skill menu for the curent active skill. // Only list the things we have skill and ingrediants to make. // // ARGS: // m_Targ_UID = the object used to get us here. // rid = which menu ? // iSelect = -2 = Just a test of the whole menu., // iSelect = -1 = 1st setup. // iSelect = 0 = cancel // iSelect = x = execute the selection. // fShowMenu = whether or not menus can be shown // item = pointer to entries list // iMaxSize = maximum number of entries // // RETURN: number of entries in menu // m_tmMenu.m_Item = the menu entries. ASSERT(m_pChar); if ( rid.GetResType() != RES_SKILLMENU ) return 0; // Find section. CResourceLock s; if ( !g_Cfg.ResourceLock(s, rid) ) return 0; // Get title line if ( !s.ReadKey() ) return 0; if ( iSelect == 0 ) // cancelled { while ( s.ReadKeyParse() ) { if ( !s.IsKey("ON") || (*s.GetArgStr() != '@') ) continue; if ( strcmpi(s.GetArgStr(), "@Cancel") ) continue; if ( m_pChar->OnTriggerRunVal(s, TRIGRUN_SECTION_TRUE, m_pChar, NULL) == TRIGRET_RET_TRUE ) return 0; break; } return 1; } if ( iSelect < 0 ) { item[0].m_sText = s.GetKey(); if ( iSelect == -1 ) m_tmMenu.m_ResourceID = rid; } bool fSkip = false; // skip this if we lack resources or skill. int iOnCount = 0; size_t iShowCount = 0; CScriptTriggerArgs Args; while ( s.ReadKeyParse()) { if ( s.IsKeyHead("ON", 2) ) { if ( *s.GetArgStr() == '@' ) { fSkip = true; continue; } // a new option to look at. fSkip = false; iOnCount++; if ( iSelect < 0 ) // building up the list. { if ( iSelect < -1 && iShowCount >= 1 ) // just a test. so we are done. return 1; iShowCount++; if ( !item[iSelect == -2 ? 0 : iShowCount].ParseLine(s.GetArgRaw(), NULL, m_pChar) ) { // remove if the item is invalid. iShowCount--; fSkip = true; continue; } if ( iSelect == -1 ) m_tmMenu.m_Item[iShowCount] = iOnCount; if ( iShowCount >= (iMaxSize - 1) ) break; } else { if ( iOnCount > iSelect ) // we are done. break; } continue; } if ( fSkip ) // we have decided we cant do this option. continue; if ( iSelect > 0 && iOnCount != iSelect ) // only interested in the selected option continue; // Check for a skill / non-consumables required. if ( s.IsKey("TEST") ) { m_pChar->ParseText(s.GetArgRaw(), m_pChar); CResourceQtyArray skills(s.GetArgStr()); if ( !skills.IsResourceMatchAll(m_pChar) ) { iShowCount--; fSkip = true; } continue; } if ( s.IsKey("TESTIF") ) { m_pChar->ParseText(s.GetArgRaw(), m_pChar); if ( !s.GetArgVal() ) { iShowCount--; fSkip = true; } continue; } // select to execute any entries here ? if ( iOnCount == iSelect ) { // Execute command from script TRIGRET_TYPE tRet = m_pChar->OnTriggerRunVal(s, TRIGRUN_SINGLE_EXEC, m_pChar, &Args); if ( tRet != TRIGRET_RET_DEFAULT ) return tRet == TRIGRET_RET_TRUE ? 0 : 1; iShowCount++; // we are good. but continue til the end } else { ASSERT(iSelect < 0); if ( s.IsKey("SKILLMENU") ) { static int sm_iReentrant = 0; if ( sm_iReentrant > 1024 ) { if ( g_Cfg.m_wDebugFlags & DEBUGF_SCRIPTS ) g_Log.EventDebug("SCRIPT: Too many skill menus (circular menus?) to continue searching in menu '%s'\n", g_Cfg.ResourceGetDef(rid)->GetResourceName()); fLimitReached = true; } else { // Test if there is anything in this skillmenu we can do. ++sm_iReentrant; if ( !Cmd_Skill_Menu_Build(g_Cfg.ResourceGetIDType(RES_SKILLMENU, s.GetArgStr()), -2, *&item, iMaxSize, fShowMenu, fLimitReached) ) { iShowCount--; fSkip = true; } else fShowMenu = true; --sm_iReentrant; } continue; } if ( s.IsKey("MAKEITEM") ) { // test if i can make this item using m_Targ_UID. // There should ALWAYS be a valid id here. if ( !m_pChar->Skill_MakeItem(static_cast<ITEMID_TYPE>(g_Cfg.ResourceGetIndexType(RES_ITEMDEF, s.GetArgStr())), m_Targ_UID, SKTRIG_SELECT) ) { iShowCount--; fSkip = true; } continue; } } } return iShowCount; }