ALERROR CEffectCreator::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Load from XML. This is only called if we go through the EffectType path // (as opposed to plain Effect). { ALERROR error; // Basic info m_sUNID = strFromInt(GetUNID(), FALSE); m_dwSoundUNID = pDesc->GetAttributeInteger(SOUND_ATTRIB); m_iSound = -1; // Allow our subclass to initialize based on the effect // (We know we have one because we couldn't have gotten this far // without one. See CreateTypeFromXML.) CXMLElement *pEffect = pDesc->GetContentElementByTag(EFFECT_TAG); ASSERT(pEffect); if (pEffect->GetContentElementCount() == 1) error = OnEffectCreateFromXML(Ctx, pEffect->GetContentElement(0), m_sUNID); else error = OnEffectCreateFromXML(Ctx, pEffect, m_sUNID); if (error) return error; // Load damage descriptors CXMLElement *pDamageDesc = pDesc->GetContentElementByTag(DAMAGE_TAG); if (pDamageDesc) { m_pDamage = new CWeaponFireDesc; CString sUNID = strPatternSubst(CONSTLIT("%d/d"), GetUNID()); if (error = m_pDamage->InitFromXML(Ctx, pDamageDesc, sUNID, true)) return error; } return NOERROR; }
void CEffectCreator::InitPainterParameters (CCreatePainterCtx &Ctx, IEffectPainter *pPainter) // InitPainterParameters // // Initialize painter parameters { SEventHandlerDesc Event; if (FindEventHandlerEffectType(evtGetParameters, &Event)) { CCodeChainCtx CCCtx; CCCtx.SaveAndDefineDataVar(Ctx.GetData()); ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) ::kernelDebugLogMessage(CONSTLIT("EffectType %x GetParameters: %s"), GetUNID(), (LPSTR)pResult->GetStringValue()); else if (pResult->IsSymbolTable()) { int i; CCSymbolTable *pTable = (CCSymbolTable *)pResult; for (i = 0; i < pTable->GetCount(); i++) { CString sParam = pTable->GetKey(i); ICCItem *pValue = pTable->GetElement(i); CEffectParamDesc Value; if (pValue->IsNil()) Value.InitNull(); else if (pValue->IsInteger()) Value.InitInteger(pValue->GetIntegerValue()); else if (pValue->IsIdentifier()) { CString sValue = pValue->GetStringValue(); char *pPos = sValue.GetASCIIZPointer(); // If this is a color, parse it if (*pPos == '#') Value.InitColor(::LoadRGBColor(sValue)); // Otherwise, a string else Value.InitString(sValue); } pPainter->SetParam(Ctx, sParam, Value); } } else ::kernelDebugLogMessage(CONSTLIT("EffectType %x GetParameters: Expected struct result."), GetUNID()); CCCtx.Discard(pResult); } }
ALERROR CItemTable::OnBindDesign (SDesignLoadCtx &Ctx) // OnBindDesign // // Load design references { ALERROR error; if (m_pGenerator) { if (error = m_pGenerator->OnDesignLoadComplete(Ctx)) { Ctx.sError = strPatternSubst(CONSTLIT("ItemTable (%x): %s"), GetUNID(), Ctx.sError); return error; } } return NOERROR; }
ALERROR CItemTable::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Create from XML descriptor { ALERROR error; CXMLElement *pElement = pDesc->GetContentElement(0); if (pElement) { if (error = IItemGenerator::CreateFromXML(Ctx, pElement, &m_pGenerator)) { Ctx.sError = strPatternSubst(CONSTLIT("ItemTable (%x): %s"), GetUNID(), Ctx.sError); return error; } } return NOERROR; }
ALERROR CEnergyFieldType::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Create from XML { ALERROR error; // Effect CXMLElement *pEffect = pDesc->GetContentElementByTag(EFFECT_TAG); if (pEffect) { if (error = CEffectCreator::CreateFromXML(Ctx, pEffect, strPatternSubst(CONSTLIT("%d:e"), GetUNID()), &m_pEffect)) { Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load effect"), GetUNID()); return error; } } pEffect = pDesc->GetContentElementByTag(HIT_EFFECT_TAG); if (pEffect == NULL) pEffect = pDesc->GetContentElementByTag(EFFECT_WHEN_HIT_TAG); if (pEffect) { if (error = CEffectCreator::CreateFromXML(Ctx, pEffect, strPatternSubst(CONSTLIT("%d:h"), GetUNID()), &m_pHitEffect)) { Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load hit effect"), GetUNID()); return error; } // For compatibility with previous versions, if we're using the old // <ShipEnergyFieldType> then altEffect defaults to TRUE. Otherwise, for new // <OverlayType> altEffect defaults to false. bool bAltEffect; if (pEffect->FindAttributeBool(ALT_EFFECT_ATTRIB, &bAltEffect)) m_bAltHitEffect = bAltEffect; else m_bAltHitEffect = strEquals(pDesc->GetTag(), SHIP_ENERGY_FIELD_TYPE_TAG); } else m_bAltHitEffect = false; // Rotation m_bRotateWithShip = !pDesc->GetAttributeBool(IGNORE_SHIP_ROTATION_ATTRIB); // Damage adjustment LoadDamageAdj(pDesc, ABSORB_ADJ_ATTRIB, m_iAbsorbAdj); // Bonus adjustment LoadDamageAdj(pDesc, BONUS_ADJ_ATTRIB, m_iBonusAdj); // Load the weapon suppress if (error = m_WeaponSuppress.InitFromXML(pDesc->GetAttribute(WEAPON_SUPPRESS_ATTRIB))) { Ctx.sError = CONSTLIT("Unable to load weapon suppress attribute"); return error; } // Keep track of the events that we have m_bHasOnUpdateEvent = FindEventHandler(ON_UPDATE_EVENT); // Done return NOERROR; }
ALERROR CEffectCreator::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Load from XML. This is only called if we go through the EffectType path // (as opposed to plain Effect types). { ALERROR error; // Basic info m_sUNID = strFromInt(GetUNID(), false); if (error = InitBasicsFromXML(Ctx, pDesc)) return error; // Allow our subclass to initialize based on the effect // (We know we have one because we couldn't have gotten this far // without one. See CreateTypeFromXML.) CXMLElement *pEffect = pDesc->GetContentElementByTag(EFFECT_TAG); ASSERT(pEffect); // Continue if (pEffect->GetContentElementCount() == 1) { CXMLElement *pEffectDesc = pEffect->GetContentElement(0); // Load events for this effect, in case they're here. CXMLElement *pEventsDesc = pEffectDesc->GetContentElementByTag(EVENTS_TAG); if (pEventsDesc) { if (error = m_Events.InitFromXML(Ctx, pEventsDesc)) return error; } // Load the single effect error = OnEffectCreateFromXML(Ctx, pEffectDesc, m_sUNID); } else error = OnEffectCreateFromXML(Ctx, pEffect, m_sUNID); if (error) return error; // Load damage descriptors CXMLElement *pDamageDesc = pDesc->GetContentElementByTag(DAMAGE_TAG); if (pDamageDesc) { m_pDamage = new CWeaponFireDesc; CString sUNID = strPatternSubst(CONSTLIT("%d/d"), GetUNID()); if (error = m_pDamage->InitFromXML(Ctx, pDamageDesc, sUNID, true)) return error; } return NOERROR; }
ALERROR CSystemMap::AddFixedTopology (CTopology &Topology, CString *retsError) // AddFixedTopology // // Adds all the nodes in its fixed topology { ALERROR error; int i; // If we already added this map, then we're done if (m_bAdded) return NOERROR; // Mark this map as added so we don't recurse back here when we // process all the Uses statments. m_bAdded = true; // Load all the maps that this map requires for (i = 0; i < m_Uses.GetCount(); i++) { if (error = m_Uses[i]->AddFixedTopology(Topology, retsError)) return error; } // Iterate over all creators and execute them CTopologyNodeList NodesAdded; STopologyCreateCtx Ctx; Ctx.pMap = GetDisplayMap(); Ctx.pNodesAdded = &NodesAdded; // We need to include any maps that we use. Ctx.Tables.Insert(&m_FixedTopology); for (i = 0; i < m_Uses.GetCount(); i++) Ctx.Tables.Insert(&m_Uses[i]->m_FixedTopology); for (i = 0; i < m_Creators.GetCount(); i++) { if (error = ExecuteCreator(Ctx, Topology, m_Creators[i])) { *retsError = strPatternSubst(CONSTLIT("SystemMap (%x): %s"), GetUNID(), Ctx.sError); return error; } } // Add any additional nodes marked as "root" (this is here only for backwards compatibility) // NOTE: This call only worries about the first table (Ctx.Tables[0]) if (error = Topology.AddTopology(Ctx)) { *retsError = strPatternSubst(CONSTLIT("SystemMap (%x): %s"), GetUNID(), Ctx.sError); return error; } // Apply any topology processors (in order) on all the newly added nodes for (i = 0; i < m_Processors.GetCount(); i++) { // Make a copy of the node list because each call will destroy it CTopologyNodeList NodeList = NodesAdded; // Process if (error = m_Processors[i]->Process(this, Topology, NodeList, retsError)) { *retsError = strPatternSubst(CONSTLIT("SystemMap (%x): %s"), GetUNID(), *retsError); return error; } } // Make sure every node added has a system UNID for (i = 0; i < NodesAdded.GetCount(); i++) if (NodesAdded[i]->GetSystemDescUNID() == 0) { *retsError = strPatternSubst(CONSTLIT("SystemMap (%x): NodeID %s: No system specified"), GetUNID(), NodesAdded[i]->GetID()); return ERR_FAIL; } return NOERROR; }
ALERROR CSystemMap::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML { ALERROR error; int i; // Load some basic info m_sName = pDesc->GetAttribute(NAME_ATTRIB); m_dwBackgroundImage = pDesc->GetAttributeInteger(BACKGROUND_IMAGE_ATTRIB); if (error = m_pPrimaryMap.LoadUNID(Ctx, pDesc->GetAttribute(PRIMARY_MAP_ATTRIB))) return error; m_bStartingMap = pDesc->GetAttributeBool(STARTING_MAP_ATTRIB); // If we have a primary map, then add it to the Uses list. if (m_pPrimaryMap.GetUNID() != 0) m_Uses.Insert(m_pPrimaryMap); // Scale information m_iInitialScale = pDesc->GetAttributeIntegerBounded(INITIAL_SCALE_ATTRIB, 10, 1000, 100); m_iMaxScale = pDesc->GetAttributeIntegerBounded(MAX_SCALE_ATTRIB, 100, 1000, 200); m_iMinScale = pDesc->GetAttributeIntegerBounded(MIN_SCALE_ATTRIB, 10, 100, 50); // Generate an UNID CString sUNID = strPatternSubst(CONSTLIT("%d"), GetUNID()); // Keep track of root nodes TArray<CString> RootNodes; // Iterate over all child elements and process them for (i = 0; i < pDesc->GetContentElementCount(); i++) { CXMLElement *pItem = pDesc->GetContentElement(i); if (strEquals(pItem->GetTag(), TOPOLOGY_CREATOR_TAG) || strEquals(pItem->GetTag(), ROOT_NODE_TAG)) { m_Creators.Insert(pItem->OrphanCopy()); if (strEquals(pItem->GetTag(), ROOT_NODE_TAG)) RootNodes.Insert(pItem->GetAttribute(ID_ATTRIB)); } else if (strEquals(pItem->GetTag(), TOPOLOGY_PROCESSOR_TAG)) { ITopologyProcessor *pNewProc; CString sProcessorUNID = strPatternSubst(CONSTLIT("%d:p%d"), GetUNID(), m_Processors.GetCount()); if (error = ITopologyProcessor::CreateFromXMLAsGroup(Ctx, pItem, sProcessorUNID, &pNewProc)) return error; m_Processors.Insert(pNewProc); } else if (strEquals(pItem->GetTag(), SYSTEM_TOPOLOGY_TAG)) { if (error = m_FixedTopology.LoadFromXML(Ctx, pItem, this, sUNID, true)) return error; } else if (strEquals(pItem->GetTag(), USES_TAG)) { CSystemMapRef *pRef = m_Uses.Insert(); if (error = pRef->LoadUNID(Ctx, pItem->GetAttribute(UNID_ATTRIB))) return error; } else { // If it's none of the above, see if it is a node descriptor if (error = m_FixedTopology.LoadNodeFromXML(Ctx, pItem, this, sUNID)) return error; } } // Mark all the root nodes. // // We need to do this for backwards compatibility because the old technique // of having a root node with [Prev] for a stargate requires this. This was // used by Huaramarca. for (i = 0; i < RootNodes.GetCount(); i++) if (error = m_FixedTopology.AddRootNode(Ctx, RootNodes[i])) return error; // Init m_bAdded = false; // Debug info m_bDebugShowAttributes = pDesc->GetAttributeBool(DEBUG_SHOW_ATTRIBUTES_ATTRIB); return NOERROR; }
ALERROR COverlayType::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Create from XML { ALERROR error; // Effect CXMLElement *pEffect = pDesc->GetContentElementByTag(EFFECT_TAG); if (pEffect) { if (error = CEffectCreator::CreateFromXML(Ctx, pEffect, strPatternSubst(CONSTLIT("%d:e"), GetUNID()), &m_pEffect)) { Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load effect"), GetUNID()); return error; } } pEffect = pDesc->GetContentElementByTag(HIT_EFFECT_TAG); if (pEffect == NULL) pEffect = pDesc->GetContentElementByTag(EFFECT_WHEN_HIT_TAG); if (pEffect) { if (error = CEffectCreator::CreateFromXML(Ctx, pEffect, strPatternSubst(CONSTLIT("%d:h"), GetUNID()), &m_pHitEffect)) { Ctx.sError = strPatternSubst(CONSTLIT("energy field %x: Unable to load hit effect"), GetUNID()); return error; } // For compatibility with previous versions, if we're using the old // <ShipEnergyFieldType> then altEffect defaults to TRUE. Otherwise, for new // <OverlayType> altEffect defaults to false. bool bAltEffect; if (pEffect->FindAttributeBool(ALT_EFFECT_ATTRIB, &bAltEffect)) m_fAltHitEffect = bAltEffect; else m_fAltHitEffect = strEquals(pDesc->GetTag(), SHIP_ENERGY_FIELD_TYPE_TAG); } else m_fAltHitEffect = false; // Rotation m_fRotateWithShip = !pDesc->GetAttributeBool(IGNORE_SHIP_ROTATION_ATTRIB); // Damage adjustment int iAbsorbCount; LoadDamageAdj(pDesc, ABSORB_ADJ_ATTRIB, m_iAbsorbAdj, &iAbsorbCount); // Bonus adjustment LoadDamageAdj(pDesc, BONUS_ADJ_ATTRIB, m_iBonusAdj); // Load the weapon suppress if (error = m_WeaponSuppress.InitFromXML(pDesc->GetAttribute(WEAPON_SUPPRESS_ATTRIB))) { Ctx.sError = CONSTLIT("Unable to load weapon suppress attribute"); return error; } // Keep track of the events that we have m_fHasOnUpdateEvent = FindEventHandler(ON_UPDATE_EVENT); // Are we a field/shield overlay (or part of hull)? // By default, we are a shield overlay if we absorb damage. bool bValue; if (pDesc->FindAttributeBool(SHIELD_OVERLAY_ATTRIB, &bValue)) m_fShieldOverlay = bValue; else m_fShieldOverlay = (iAbsorbCount > 0); // Counter CXMLElement *pCounter = pDesc->GetContentElementByTag(COUNTER_TAG); if (pCounter) { CString sStyle = pCounter->GetAttribute(STYLE_ATTRIB); if (strEquals(sStyle, COUNTER_PROGRESS)) m_iCounterType = counterProgress; else if (strEquals(sStyle, COUNTER_RADIUS)) m_iCounterType = counterRadius; else { Ctx.sError = strPatternSubst(CONSTLIT("Unknown counter style: %s"), sStyle); return ERR_FAIL; } m_sCounterLabel = pCounter->GetAttribute(LABEL_ATTRIB); m_iCounterMax = pCounter->GetAttributeIntegerBounded(MAX_ATTRIB, 0, -1, 100); m_wCounterColor = ::LoadRGBColor(pCounter->GetAttribute(COLOR_ATTRIB)); } else { m_iCounterType = counterNone; m_iCounterMax = 0; m_wCounterColor = 0; } // Options m_fDisarmShip = pDesc->GetAttributeBool(DISARM_ATTRIB); m_fParalyzeShip = pDesc->GetAttributeBool(PARALYZE_ATTRIB); m_fDisableShipScreen = pDesc->GetAttributeBool(DISABLE_SHIP_SCREEN_ATTRIB); m_fSpinShip = pDesc->GetAttributeBool(SPIN_ATTRIB); int iDrag; if (pDesc->FindAttributeInteger(DRAG_ATTRIB, &iDrag)) m_rDrag = Min(Max(0, iDrag), 100) / 100.0; else m_rDrag = 1.0; // Done return NOERROR; }