ALERROR CEconomyType::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Load from XML { m_sSID = pDesc->GetAttribute(ID_ATTRIB); if (m_sSID.IsBlank()) return ComposeLoadError(Ctx, CONSTLIT("Invalid ID")); // Parse the currency name m_sCurrencyName = pDesc->GetAttribute(CURRENCY_ATTRIB); if (m_sCurrencyName.IsBlank()) return ComposeLoadError(Ctx, CONSTLIT("Invalid currency name")); m_sCurrencySingular = ParseNounForm(m_sCurrencyName, 0, false, true); if (m_sCurrencySingular.IsBlank()) return ComposeLoadError(Ctx, CONSTLIT("Invalid singular form of currency name")); m_sCurrencyPlural = ParseNounForm(m_sCurrencyName, 0, true, true); if (m_sCurrencyPlural.IsBlank()) return ComposeLoadError(Ctx, CONSTLIT("Invalid plural form of currency name")); // Get the conversion rate m_iCreditConversion = pDesc->GetAttributeIntegerBounded(CONVERSION_ATTRIB, 1, -1, 100); return NOERROR; }
ALERROR CAdventureDesc::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Load from XML { ALERROR error; // If we are part of the default resource, then get the adventure UNID if (Ctx.pExtension == NULL) { m_dwExtensionUNID = pDesc->GetAttributeInteger(ADVENTURE_UNID_ATTRIB); m_fInDefaultResource = true; } // Otherwise, we remember the extension that we were loaded from else { m_dwExtensionUNID = Ctx.pExtension->dwUNID; m_fInDefaultResource = false; } // Load the name, etc m_sName = pDesc->GetAttribute(NAME_ATTRIB); m_dwBackgroundUNID = ::LoadUNID(Ctx, pDesc->GetAttribute(BACKGROUND_ID_ATTRIB)); // Starting ship criteria CString sCriteria; if (!pDesc->FindAttribute(STARTING_SHIP_CRITERIA_ATTRIB, &sCriteria)) sCriteria = CONSTLIT("*"); if (error = CDesignTypeCriteria::ParseCriteria(sCriteria, &m_StartingShips)) return ComposeLoadError(Ctx, ERR_STARTING_SHIP_CRITERIA); // Starting position m_sStartingNodeID = pDesc->GetAttribute(STARTING_SYSTEM_ATTRIB); m_sStartingPos = pDesc->GetAttribute(STARTING_POS_ATTRIB); // Welcome message if (!pDesc->FindAttribute(WELCOME_MESSAGE_ATTRIB, &m_sWelcomeMessage)) m_sWelcomeMessage = CONSTLIT("Welcome to Transcendence!"); // Init some flags m_fIsCurrentAdventure = false; // If the extension doesn't have a name, then we can set it if (Ctx.pExtension && strFind(Ctx.pExtension->sName, CONSTLIT("Extension")) == 0) Ctx.pExtension->sName = m_sName; return NOERROR; }
ALERROR CAdventureDesc::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Load from XML { ALERROR error; int i; // If we are part of the default resource, then get the adventure UNID if (Ctx.pExtension == NULL) { m_dwExtensionUNID = pDesc->GetAttributeInteger(ADVENTURE_UNID_ATTRIB); m_fInDefaultResource = true; } // Otherwise, we remember the extension that we were loaded from else { m_dwExtensionUNID = Ctx.pExtension->GetUNID(); m_fInDefaultResource = false; } // Load the name, etc m_sName = pDesc->GetAttribute(NAME_ATTRIB); if (error = ::LoadUNID(Ctx, pDesc->GetAttribute(BACKGROUND_ID_ATTRIB), &m_dwBackgroundUNID)) return error; // Starting ship criteria CString sCriteria; if (!pDesc->FindAttribute(STARTING_SHIP_CRITERIA_ATTRIB, &sCriteria)) sCriteria = CONSTLIT("*"); if (error = CDesignTypeCriteria::ParseCriteria(sCriteria, &m_StartingShips)) return ComposeLoadError(Ctx, ERR_STARTING_SHIP_CRITERIA); m_fIncludeOldShipClasses = pDesc->GetAttributeBool(INCLUDE_10_STARTING_CLASSES_ATTRIB); // Starting position m_sStartingNodeID = pDesc->GetAttribute(STARTING_SYSTEM_ATTRIB); m_sStartingPos = pDesc->GetAttribute(STARTING_POS_ATTRIB); // Welcome message if (!pDesc->FindAttribute(WELCOME_MESSAGE_ATTRIB, &m_sWelcomeMessage)) m_sWelcomeMessage = CONSTLIT("Welcome to Transcendence!"); // Init some flags m_fIsCurrentAdventure = false; // If we don't have a name, then get it from the extension if (m_sName.IsBlank()) { if (Ctx.pExtension) m_sName = Ctx.pExtension->GetName(); } // Otherwise, if the extension doesn't have a name, then we can set it else if (Ctx.pExtension && strFind(Ctx.pExtension->GetName(), CONSTLIT("Extension")) == 0) Ctx.pExtension->SetName(m_sName); // Initialize armor and shield damage adjustment tables InitDefaultDamageAdj(); for (i = 1; i <= MAX_ITEM_LEVEL; i++) { m_ArmorDamageAdj[i - 1] = g_ArmorDamageAdj[i - 1]; m_ShieldDamageAdj[i - 1] = g_ShieldDamageAdj[i - 1]; } // Load constants CXMLElement *pConstants = pDesc->GetContentElementByTag(CONSTANTS_TAG); if (pConstants) { for (i = 0; i < pConstants->GetContentElementCount(); i++) { CXMLElement *pItem = pConstants->GetContentElement(i); if (strEquals(pItem->GetTag(), ARMOR_DAMAGE_ADJ_TAG)) { int iLevel = pItem->GetAttributeInteger(LEVEL_ATTRIB); if (iLevel < 1 || iLevel > MAX_ITEM_LEVEL) { Ctx.sError = strPatternSubst(CONSTLIT("Invalid level: %d."), iLevel); return ERR_FAIL; } if (error = m_ArmorDamageAdj[iLevel - 1].InitFromXML(Ctx, pItem, true)) return error; } else if (strEquals(pItem->GetTag(), SHIELD_DAMAGE_ADJ_TAG)) { int iLevel = pItem->GetAttributeInteger(LEVEL_ATTRIB); if (iLevel < 1 || iLevel > MAX_ITEM_LEVEL) { Ctx.sError = strPatternSubst(CONSTLIT("Invalid level: %d."), iLevel); return ERR_FAIL; } if (error = m_ShieldDamageAdj[iLevel - 1].InitFromXML(Ctx, pItem, true)) return error; } else { Ctx.sError = strPatternSubst(CONSTLIT("Invalid constant definition element: %s."), pItem->GetTag()); return ERR_FAIL; } } } return NOERROR; }
ALERROR CPlayerSettings::InitFromXML (SDesignLoadCtx &Ctx, CShipClass *pClass, CXMLElement *pDesc) // InitFromXML // // Initialize from an XML element { ALERROR error; int i; m_sDesc = pDesc->GetAttribute(DESC_ATTRIB); m_dwLargeImage = LoadUNID(Ctx, pDesc->GetAttribute(LARGE_IMAGE_ATTRIB)); m_fDebug = pDesc->GetAttributeBool(DEBUG_ONLY_ATTRIB); m_fInitialClass = pDesc->GetAttributeBool(INITIAL_CLASS_ATTRIB); m_fHasArmorDesc = false; m_fHasReactorDesc = false; m_fHasShieldDesc = false; // Some ship capabilities bool bValue; if (pDesc->FindAttributeBool(AUTOPILOT_ATTRIB, &bValue)) m_fAutopilot = bValue; else m_fAutopilot = true; // Load some miscellaneous data CString sAttrib; if (!pDesc->FindAttribute(STARTING_CREDITS_ATTRIB, &sAttrib)) sAttrib = CONSTLIT("5d20+200"); if (error = m_StartingCredits.InitFromXML(Ctx, sAttrib)) return error; m_sStartNode = pDesc->GetAttribute(STARTING_SYSTEM_ATTRIB); m_sStartPos = pDesc->GetAttribute(STARTING_POS_ATTRIB); if (m_sStartPos.IsBlank()) m_sStartPos = CONSTLIT("Start"); // Load the ship screen CString sShipScreenUNID = pDesc->GetAttribute(SHIP_SCREEN_ATTRIB); if (sShipScreenUNID.IsBlank()) sShipScreenUNID = strFromInt(DEFAULT_SHIP_SCREEN_UNID, FALSE); m_pShipScreen.LoadUNID(Ctx, sShipScreenUNID); // Load the armor display data CXMLElement *pArmorDisplay = pDesc->GetContentElementByTag(ARMOR_DISPLAY_TAG); if (pArmorDisplay && pArmorDisplay->GetContentElementCount() > 0) { m_iArmorDescCount = pArmorDisplay->GetContentElementCount(); m_pArmorDesc = new SArmorImageDesc [m_iArmorDescCount]; for (i = 0; i < m_iArmorDescCount; i++) { SArmorImageDesc &ArmorDesc = m_pArmorDesc[i]; CXMLElement *pSegment = pArmorDisplay->GetContentElement(i); if (error = ArmorDesc.Image.InitFromXML(Ctx, pSegment)) return ComposeLoadError(Ctx, ERR_ARMOR_DISPLAY_NEEDED); ArmorDesc.sName = pSegment->GetAttribute(NAME_ATTRIB); ArmorDesc.xDest = pSegment->GetAttributeInteger(DEST_X_ATTRIB); ArmorDesc.yDest = pSegment->GetAttributeInteger(DEST_Y_ATTRIB); ArmorDesc.xHP = pSegment->GetAttributeInteger(HP_X_ATTRIB); ArmorDesc.yHP = pSegment->GetAttributeInteger(HP_Y_ATTRIB); ArmorDesc.yName = pSegment->GetAttributeInteger(NAME_Y_ATTRIB); ArmorDesc.cxNameBreak = pSegment->GetAttributeInteger(NAME_BREAK_WIDTH); ArmorDesc.xNameDestOffset = pSegment->GetAttributeInteger(NAME_DEST_X_ATTRIB); ArmorDesc.yNameDestOffset = pSegment->GetAttributeInteger(NAME_DEST_Y_ATTRIB); } m_fHasArmorDesc = true; } else { m_fHasArmorDesc = false; m_iArmorDescCount = 0; m_pArmorDesc = NULL; } // Load shield display data CXMLElement *pShieldDisplay = pDesc->GetContentElementByTag(SHIELD_DISPLAY_TAG); if (pShieldDisplay) { if (error = m_ShieldDesc.Image.InitFromXML(Ctx, pShieldDisplay->GetContentElementByTag(IMAGE_TAG))) return ComposeLoadError(Ctx, ERR_SHIELD_DISPLAY_NEEDED); m_fHasShieldDesc = true; } // Load reactor display data CXMLElement *pReactorDisplay = pDesc->GetContentElementByTag(REACTOR_DISPLAY_TAG); if (pReactorDisplay) { if (error = m_ReactorDesc.ReactorImage.InitFromXML(Ctx, pReactorDisplay->GetContentElementByTag(IMAGE_TAG))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); CXMLElement *pImage = pReactorDisplay->GetContentElementByTag(POWER_LEVEL_IMAGE_TAG); if (pImage == NULL || (error = m_ReactorDesc.PowerLevelImage.InitFromXML(Ctx, pImage))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); m_ReactorDesc.xPowerLevelImage = pImage->GetAttributeInteger(DEST_X_ATTRIB); m_ReactorDesc.yPowerLevelImage = pImage->GetAttributeInteger(DEST_Y_ATTRIB); pImage = pReactorDisplay->GetContentElementByTag(FUEL_LEVEL_IMAGE_TAG); if (pImage == NULL || (error = m_ReactorDesc.FuelLevelImage.InitFromXML(Ctx, pImage))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); m_ReactorDesc.xFuelLevelImage = pImage->GetAttributeInteger(DEST_X_ATTRIB); m_ReactorDesc.yFuelLevelImage = pImage->GetAttributeInteger(DEST_Y_ATTRIB); pImage = pReactorDisplay->GetContentElementByTag(FUEL_LOW_LEVEL_IMAGE_TAG); if (pImage == NULL || (error = m_ReactorDesc.FuelLowLevelImage.InitFromXML(Ctx, pImage))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(REACTOR_TEXT_TAG), &m_ReactorDesc.rcReactorText)) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(POWER_LEVEL_TEXT_TAG), &m_ReactorDesc.rcPowerLevelText)) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(FUEL_LEVEL_TEXT_TAG), &m_ReactorDesc.rcFuelLevelText)) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); m_fHasReactorDesc = true; } // Done return NOERROR; }
ALERROR CPlayerSettings::Bind (SDesignLoadCtx &Ctx, CShipClass *pClass) // Bind // // Bind design { ALERROR error; int i; // Bind basic stuff if (error = m_pShipScreen.Bind(Ctx, pClass->GetLocalScreens())) return error; if (error = m_StartingCredits.Bind(Ctx)) return error; // Armor display if (m_fHasArmorDesc) { for (i = 0; i < m_iArmorDescCount; i++) { SArmorImageDesc &ArmorDesc = m_pArmorDesc[i]; if (error = ArmorDesc.Image.OnDesignLoadComplete(Ctx)) return error; } } else if (m_pArmorDescInherited = pClass->GetArmorDescInherited()) ; else return ComposeLoadError(Ctx, ERR_ARMOR_DISPLAY_NEEDED); // Shields if (m_fHasShieldDesc) { if (error = m_ShieldDesc.Image.OnDesignLoadComplete(Ctx)) return error; } else if (m_pShieldDescInherited = pClass->GetShieldDescInherited()) ; else return ComposeLoadError(Ctx, ERR_SHIELD_DISPLAY_NEEDED); // Reactor if (m_fHasReactorDesc) { if (error = m_ReactorDesc.ReactorImage.OnDesignLoadComplete(Ctx)) return error; if (error = m_ReactorDesc.PowerLevelImage.OnDesignLoadComplete(Ctx)) return error; if (error = m_ReactorDesc.FuelLevelImage.OnDesignLoadComplete(Ctx)) return error; if (error = m_ReactorDesc.FuelLowLevelImage.OnDesignLoadComplete(Ctx)) return error; } else if (m_pReactorDescInherited = pClass->GetReactorDescInherited()) ; else return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); // Done return NOERROR; }
ALERROR CPlayerSettings::InitFromXML (SDesignLoadCtx &Ctx, CShipClass *pClass, CXMLElement *pDesc) // InitFromXML // // Initialize from an XML element { ALERROR error; int i; m_sDesc = pDesc->GetAttribute(DESC_ATTRIB); if (error = LoadUNID(Ctx, pDesc->GetAttribute(LARGE_IMAGE_ATTRIB), &m_dwLargeImage)) return error; m_fDebug = pDesc->GetAttributeBool(DEBUG_ONLY_ATTRIB); CString sInitialClass = pDesc->GetAttribute(INITIAL_CLASS_ATTRIB); if (strEquals(sInitialClass, CONSTLIT("always"))) { m_fInitialClass = true; m_fIncludeInAllAdventures = true; } else { m_fInitialClass = CXMLElement::IsBoolTrueValue(sInitialClass); m_fIncludeInAllAdventures = false; } m_fHasArmorDesc = false; m_fHasReactorDesc = false; m_fHasShieldDesc = false; // Some ship capabilities bool bValue; if (pDesc->FindAttributeBool(AUTOPILOT_ATTRIB, &bValue)) m_fAutopilot = bValue; else m_fAutopilot = true; // Load some miscellaneous data CString sAttrib; if (!pDesc->FindAttribute(STARTING_CREDITS_ATTRIB, &sAttrib)) sAttrib = CONSTLIT("5d20+200"); if (error = m_StartingCredits.InitFromXML(Ctx, sAttrib)) return error; m_sStartNode = pDesc->GetAttribute(STARTING_SYSTEM_ATTRIB); m_sStartPos = pDesc->GetAttribute(STARTING_POS_ATTRIB); if (m_sStartPos.IsBlank()) m_sStartPos = CONSTLIT("Start"); // Load the ship screen CString sShipScreenUNID = pDesc->GetAttribute(SHIP_SCREEN_ATTRIB); if (sShipScreenUNID.IsBlank()) sShipScreenUNID = strFromInt(DEFAULT_SHIP_SCREEN_UNID, false); m_pShipScreen.LoadUNID(Ctx, sShipScreenUNID); // Load the armor display data CXMLElement *pArmorDisplay = pDesc->GetContentElementByTag(ARMOR_DISPLAY_TAG); if (pArmorDisplay && pArmorDisplay->GetContentElementCount() > 0) { // Loop over all sub elements for (i = 0; i < pArmorDisplay->GetContentElementCount(); i++) { CXMLElement *pSub = pArmorDisplay->GetContentElement(i); if (strEquals(pSub->GetTag(), ARMOR_SECTION_TAG)) { SArmorSegmentImageDesc &ArmorDesc = *m_ArmorDesc.Segments.Insert(); if (error = ArmorDesc.Image.InitFromXML(Ctx, pSub)) return ComposeLoadError(Ctx, ERR_ARMOR_DISPLAY_NEEDED); ArmorDesc.sName = pSub->GetAttribute(NAME_ATTRIB); ArmorDesc.xDest = pSub->GetAttributeInteger(DEST_X_ATTRIB); ArmorDesc.yDest = pSub->GetAttributeInteger(DEST_Y_ATTRIB); ArmorDesc.xHP = pSub->GetAttributeInteger(HP_X_ATTRIB); ArmorDesc.yHP = pSub->GetAttributeInteger(HP_Y_ATTRIB); ArmorDesc.yName = pSub->GetAttributeInteger(NAME_Y_ATTRIB); ArmorDesc.cxNameBreak = pSub->GetAttributeInteger(NAME_BREAK_WIDTH); ArmorDesc.xNameDestOffset = pSub->GetAttributeInteger(NAME_DEST_X_ATTRIB); ArmorDesc.yNameDestOffset = pSub->GetAttributeInteger(NAME_DEST_Y_ATTRIB); } else if (strEquals(pSub->GetTag(), SHIP_IMAGE_TAG)) { if (error = m_ArmorDesc.ShipImage.InitFromXML(Ctx, pSub)) return ComposeLoadError(Ctx, ERR_SHIP_IMAGE_NEEDED); } else return ComposeLoadError(Ctx, strPatternSubst(CONSTLIT("Unknown ArmorDisplay element: "), pSub->GetTag())); } m_fHasArmorDesc = true; } else m_fHasArmorDesc = false; // Load shield display data CXMLElement *pShieldDisplay = pDesc->GetContentElementByTag(SHIELD_DISPLAY_TAG); if (pShieldDisplay) { // Load the new shield effect if (error = m_ShieldDesc.pShieldEffect.LoadEffect(Ctx, strPatternSubst(CONSTLIT("%d:p:s"), pClass->GetUNID()), pShieldDisplay->GetContentElementByTag(SHIELD_EFFECT_TAG), pShieldDisplay->GetAttribute(SHIELD_EFFECT_ATTRIB))) return error; // If we don't have the new effect, load the backwards compatibility // image. if (m_ShieldDesc.pShieldEffect.IsEmpty()) { if (error = m_ShieldDesc.Image.InitFromXML(Ctx, pShieldDisplay->GetContentElementByTag(IMAGE_TAG))) return ComposeLoadError(Ctx, ERR_SHIELD_DISPLAY_NEEDED); } m_fHasShieldDesc = true; } // If we have a shield effect then we must have an armor image if (!m_ShieldDesc.pShieldEffect.IsEmpty() && m_ArmorDesc.ShipImage.GetBitmapUNID() == 0) return ComposeLoadError(Ctx, ERR_MUST_HAVE_SHIP_IMAGE); // Load reactor display data CXMLElement *pReactorDisplay = pDesc->GetContentElementByTag(REACTOR_DISPLAY_TAG); if (pReactorDisplay) { if (error = m_ReactorDesc.ReactorImage.InitFromXML(Ctx, pReactorDisplay->GetContentElementByTag(IMAGE_TAG))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); CXMLElement *pImage = pReactorDisplay->GetContentElementByTag(POWER_LEVEL_IMAGE_TAG); if (pImage == NULL || (error = m_ReactorDesc.PowerLevelImage.InitFromXML(Ctx, pImage))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); m_ReactorDesc.xPowerLevelImage = pImage->GetAttributeInteger(DEST_X_ATTRIB); m_ReactorDesc.yPowerLevelImage = pImage->GetAttributeInteger(DEST_Y_ATTRIB); pImage = pReactorDisplay->GetContentElementByTag(FUEL_LEVEL_IMAGE_TAG); if (pImage == NULL || (error = m_ReactorDesc.FuelLevelImage.InitFromXML(Ctx, pImage))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); m_ReactorDesc.xFuelLevelImage = pImage->GetAttributeInteger(DEST_X_ATTRIB); m_ReactorDesc.yFuelLevelImage = pImage->GetAttributeInteger(DEST_Y_ATTRIB); pImage = pReactorDisplay->GetContentElementByTag(FUEL_LOW_LEVEL_IMAGE_TAG); if (pImage == NULL || (error = m_ReactorDesc.FuelLowLevelImage.InitFromXML(Ctx, pImage))) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(REACTOR_TEXT_TAG), &m_ReactorDesc.rcReactorText)) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(POWER_LEVEL_TEXT_TAG), &m_ReactorDesc.rcPowerLevelText)) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); if (error = InitRectFromElement(pReactorDisplay->GetContentElementByTag(FUEL_LEVEL_TEXT_TAG), &m_ReactorDesc.rcFuelLevelText)) return ComposeLoadError(Ctx, ERR_REACTOR_DISPLAY_NEEDED); m_fHasReactorDesc = true; } // Done return NOERROR; }
ALERROR CExtension::Load (ELoadStates iDesiredState, IXMLParserController *pResolver, bool bNoResources, bool bKeepXML, CString *retsError) // Load // // Makes sure that the extension is fully loaded. { ALERROR error; int i; switch (m_iLoadState) { case loadNone: { *retsError = CONSTLIT("Unable to load."); return ERR_FAIL; } case loadEntities: case loadAdventureDesc: { if (iDesiredState == loadNone || iDesiredState == loadEntities) return NOERROR; else if (iDesiredState == loadAdventureDesc && m_iLoadState == loadAdventureDesc) return NOERROR; // Open the file CResourceDb ExtDb(m_sFilespec, true); if (error = ExtDb.Open(DFOPEN_FLAG_READ_ONLY, retsError)) return ERR_FAIL; // Setup SDesignLoadCtx Ctx; Ctx.sResDb = m_sFilespec; Ctx.pResDb = &ExtDb; Ctx.bNoVersionCheck = true; // Obsolete now Ctx.bNoResources = bNoResources; Ctx.bKeepXML = bKeepXML; Ctx.bLoadAdventureDesc = (iDesiredState == loadAdventureDesc && m_iType == extAdventure); Ctx.sErrorFilespec = m_sFilespec; // If this is a registered extension then compute a digest for the // file (so that we can compare against the cloud's digest). // // We need to do this even if we fail later because we don't want to // have to recalc it later. if (m_Digest.IsEmpty() && GetFolderType() == folderCollection && IsRegistered()) { if (error = fileCreateDigest(m_sFilespec, &m_Digest)) { *retsError = strPatternSubst(CONSTLIT("Unable to compute digest for: %s."), m_sFilespec); return error; } } // If we've already loaded a root element, then we need to clean up if (m_pRootXML) CleanUpXML(); // Parse the XML file into a structure if (error = ExtDb.LoadGameFile(&m_pRootXML, pResolver, retsError)) { // If we're in debug mode then this is a real error. if (g_pUniverse->InDebugMode() && !ExtDb.IsTDB()) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Error parsing %s: %s"), m_sFilespec, *retsError); return ERR_FAIL; } // Otherwise, we try to continue as if nothing bad had happened, but we // disable the extension. else { SetDisabled((retsError ? *retsError : CONSTLIT("Unable to load"))); return NOERROR; } } // Set up context Ctx.pExtension = this; // Load all the design elements for (i = 0; i < m_pRootXML->GetContentElementCount(); i++) { CXMLElement *pItem = m_pRootXML->GetContentElement(i); if (error = LoadDesignElement(Ctx, pItem)) { if (!bKeepXML) { delete m_pRootXML; m_pRootXML = NULL; } if (g_pUniverse->InDebugMode() && !ExtDb.IsTDB()) return ComposeLoadError(Ctx, retsError); SetDisabled(Ctx.sError); return NOERROR; } } // Restore Ctx.pExtension = NULL; // Done m_iLoadState = (m_iType == extAdventure ? iDesiredState : loadComplete); if (!bKeepXML) { delete m_pRootXML; m_pRootXML = NULL; } // If we get this far and we have no libraries, then include the // compatibility library. if (m_iLoadState == loadComplete) AddDefaultLibraryReferences(Ctx); // Debug output switch (m_iType) { case extAdventure: if (m_iLoadState == loadAdventureDesc) kernelDebugLogMessage("Loaded adventure desc: %s", m_sFilespec); else kernelDebugLogMessage("Loaded adventure: %s", m_sFilespec); break; case extExtension: kernelDebugLogMessage("Loaded extension: %s", m_sFilespec); break; case extLibrary: kernelDebugLogMessage("Loaded library: %s", m_sFilespec); break; } return NOERROR; } case loadComplete: return NOERROR; default: ASSERT(false); return ERR_FAIL; } }