int CArmorClass::FireGetMaxHP (CItemCtx &ItemCtx, int iMaxHP) const // FireGetMaxHP // // Fire GetMaxHP event { SEventHandlerDesc Event; if (FindEventHandlerArmorClass(evtGetMaxHP, &Event)) { // Setup arguments CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(ItemCtx.GetSource()); Ctx.SaveAndDefineItemVar(ItemCtx); Ctx.DefineInteger(CONSTLIT("aMaxHP"), iMaxHP); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(GET_MAX_HP_EVENT, pResult); else if (!pResult->IsNil()) iMaxHP = Max(0, pResult->GetIntegerValue()); Ctx.Discard(pResult); } return iMaxHP; }
COverlayType *CDeviceClass::FireGetOverlayType (CItemCtx &ItemCtx) const // FireGetOverlayType // // Fire GetOverlayType event { SEventHandlerDesc Event; if (FindEventHandlerDeviceClass(evtGetOverlayType, &Event)) { // Setup arguments CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(ItemCtx.GetSource()); Ctx.SaveAndDefineItemVar(ItemCtx); ICCItem *pResult = Ctx.Run(Event); DWORD dwUNID = 0; if (pResult->IsError()) ItemCtx.GetSource()->ReportEventError(GET_OVERLAY_TYPE_EVENT, pResult); else if (!pResult->IsNil()) dwUNID = pResult->GetIntegerValue(); Ctx.Discard(pResult); // Done return COverlayType::AsType(g_pUniverse->FindDesignType(dwUNID)); } else return GetOverlayType(); }
int CShieldClass::FireGetMaxHP (CInstalledDevice *pDevice, CSpaceObject *pSource, int iMaxHP) const // FireGetMaxHP // // Fire GetMaxHP event { SEventHandlerDesc Event; if (FindEventHandlerShieldClass(evtGetMaxHP, &Event)) { ASSERT(pSource); ASSERT(pDevice); CCodeChainCtx Ctx; Ctx.SaveAndDefineSourceVar(pSource); Ctx.SaveAndDefineItemVar(pSource->GetItemForDevice(pDevice)); Ctx.DefineInteger(CONSTLIT("aMaxHP"), iMaxHP); ICCItem *pResult = Ctx.Run(Event); if (pResult->IsError()) pSource->ReportEventError(GET_MAX_HP_EVENT, pResult); else if (!pResult->IsNil()) iMaxHP = Max(0, pResult->GetIntegerValue()); Ctx.Discard(pResult); } return iMaxHP; }
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); } }
ICCItem *CCAtomTable::UnstreamItem (CCodeChain *pCC, IReadStream *pStream) // UnstreamItem // // Unstream the sub-class specific data { ALERROR error; int i, iCount; // Read the count error = pStream->Read((char *)&iCount, sizeof(iCount), NULL); if (error) return pCC->CreateSystemError(error); // Read all the items for (i = 0; i < iCount; i++) { ICCItem *pItem; int iKey, iValue; BOOL bAdded; // Load the key pItem = pCC->UnstreamItem(pStream); if (pItem->IsError()) return pItem; iKey = pItem->GetIntegerValue(); pItem->Discard(pCC); // Now load the value pItem = pCC->UnstreamItem(pStream); // Note that we don't abort in case of an error // because the list might contain errors // Append the item to the symbol table if (m_Table.ReplaceEntry(iKey, (int)pItem, TRUE, &bAdded, &iValue) != NOERROR) return pCC->CreateMemoryError(); // No need to discard pItem because we're adding it to the // symbol table. // If we have a previous entry, decrement its refcount since we're // throwing it away ASSERT(bAdded); } return pCC->CreateTrue(); }
void CDockScreenStack::IncData (const CString &sAttrib, ICCItem *pValue, ICCItem **retpResult) // IncData // // Increments data { CCodeChain &CC = g_pUniverse->GetCC(); if (IsEmpty()) { if (retpResult) *retpResult = CC.CreateNil(); return; } // If pValue is NULL, we default to 1. We add ref no matter what so that // we can discard unconditionally. if (pValue == NULL) pValue = CC.CreateInteger(1); else pValue->Reference(); // If the entry is currently blank, then we just take the increment. ICCItem *pOriginal = GetData(sAttrib); ICCItem *pResult = NULL; if (pOriginal->IsNil()) pResult = pValue->Reference(); // Otherwise, we need to get the data value else { if (pOriginal->IsDouble() || pValue->IsDouble()) pResult = CC.CreateDouble(pOriginal->GetDoubleValue() + pValue->GetDoubleValue()); else pResult = CC.CreateInteger(pOriginal->GetIntegerValue() + pValue->GetIntegerValue()); } pOriginal->Discard(&CC); // Store SetData(sAttrib, pResult); // Done if (retpResult) *retpResult = pResult; else pResult->Discard(&CC); pValue->Discard(&CC); }
bool CWeaponFireDesc::FireOnDamageOverlay (SDamageCtx &Ctx, CEnergyField *pOverlay) // FireOnDamageOverlay // // Fire OnDamageOverlay event. Returns TRUE if we should skip further overlay damage { SEventHandlerDesc Event; if (FindEventHandler(evtOnDamageOverlay, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(Ctx.pObj); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineInteger(CONSTLIT("aOverlayID"), pOverlay->GetID()); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); ICCItem *pResult = CCCtx.Run(Event); if (pResult->IsError()) Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // Otherwise, the result is the damage left else { Ctx.iDamage = pResult->GetIntegerValue(); bResult = true; } CCCtx.Discard(pResult); return bResult; } else return false; }
void CArmorClass::FireOnArmorDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx) // FireOnArmorDamage // // Fires OnArmorDamage event { SEventHandlerDesc Event; if (FindEventHandlerArmorClass(evtOnArmorDamage, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CCCtx.SaveAndDefineSourceVar(ItemCtx.GetSource()); CCCtx.SaveAndDefineItemVar(ItemCtx); CCCtx.DefineInteger(CONSTLIT("aArmorHP"), Ctx.iHPLeft); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineDamageEffects(CONSTLIT("aDamageEffects"), Ctx); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); ICCItem *pResult = CCCtx.Run(Event); // If we return Nil, then nothing if (pResult->IsNil()) NULL; // If we return an integer, then this is the damage that armor should take else if (pResult->IsInteger()) Ctx.iDamage = pResult->GetIntegerValue(); // If we return a list, then we it to be a DamageEffects list (modifications to // aDamageEffects) else if (pResult->IsList()) LoadDamageEffectsFromItem(pResult, Ctx); CCCtx.Discard(pResult); } }
ICCItem *CCodeChain::LookupFunction (CEvalContext *pCtx, ICCItem *pName) // LookupFunction // // Returns the binding for a function { ICCItem *pBinding; // See if the identifier is already bound pBinding = pName->GetFunctionBinding(); if (pBinding) return pBinding; // If not bound, check global scope pBinding = m_pGlobalSymbols->Lookup(this, pName); if (!pBinding->IsError() || pBinding->GetIntegerValue() != CCRESULT_NOTFOUND) { pName->SetFunctionBinding(this, pBinding); return pBinding; } // If not found, check local scope if (pCtx) { pBinding->Discard(this); pBinding = Lookup(pCtx, pName); if (!pBinding->IsError()) // We don't set a function binding because local variables often change // (as when we pass a function as a parameter) return pBinding; } // If we get this far then we could not find it pBinding->Discard(this); pBinding = CreateError(LITERAL("Unknown function"), pName); return pBinding; }
bool CWeaponFireDesc::FireOnDamageShields (SDamageCtx &Ctx, int iDevice) // FireOnDamageShields // // Fire OnDamageShields event. Returns TRUE if we should skip further shields damage { SEventHandlerDesc Event; if (FindEventHandler(evtOnDamageShields, &Event)) { // Setup arguments CCodeChainCtx CCCtx; CItemListManipulator ItemList(Ctx.pObj->GetItemList()); CShip *pShip = Ctx.pObj->AsShip(); if (pShip) pShip->SetCursorAtDevice(ItemList, iDevice); CCCtx.SaveAndDefineSourceVar(Ctx.pObj); CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit); CCCtx.DefineInteger(CONSTLIT("aDevice"), iDevice); CCCtx.DefineItem(CONSTLIT("aDeviceItem"), ItemList.GetItemAtCursor()); CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause); CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj()); CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL)); CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos); CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection); CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage); CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType())); CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType()); CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft); CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); if (Ctx.bReflect) { CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb); } else { CCCtx.DefineNil(CONSTLIT("aShieldReflect")); CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage); CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb); } ICCItem *pResult = CCCtx.Run(Event); // If we return Nil, then we continue processing bool bResult; if (pResult->IsNil()) bResult = false; // If this is an integer, we pass damage to armor else if (pResult->IsInteger()) { Ctx.iDamage = pResult->GetIntegerValue(); bResult = true; } // If we return a list, then modify variables else if (pResult->IsList()) { // A single value means we modified the damage to armor if (pResult->GetCount() == 1) { if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; } else { Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); if (Ctx.bReflect) { Ctx.bReflect = false; Ctx.iAbsorb = Ctx.iOriginalAbsorb; } } } // Two values mean we modified both damage to armor and shield damage else if (pResult->GetCount() == 2) { Ctx.bReflect = false; Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue())); } // Otherwise, we deal with reflection else { Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT); Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft)); Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue())); } // Proceed with processing bResult = false; } // If this is the string "reflect" then we reflect else if (strEquals(pResult->GetStringValue(), STR_SHIELD_REFLECT)) { Ctx.bReflect = true; Ctx.iAbsorb = Ctx.iDamage; Ctx.iShieldDamage = 0; bResult = false; } // Otherwise, error else { Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult); bResult = true; } CCCtx.Discard(pResult); return bResult; } else return false; }
bool IDockScreenDisplay::ParseBackgrounDesc (ICCItem *pDesc, SBackgroundDesc *retDesc) // ParseBackroundDesc // // Parses a descriptor. Returns TRUE if successful. { CCodeChain &CC = g_pUniverse->GetCC(); // Nil means no default value if (pDesc->IsNil()) retDesc->iType = backgroundDefault; // If we have a struct, we expect a certain format else if (pDesc->IsSymbolTable()) { CString sType = pDesc->GetStringAt(FIELD_TYPE); if (sType.IsBlank() || strEquals(sType, TYPE_NONE)) retDesc->iType = backgroundNone; else if (strEquals(sType, TYPE_HERO)) { retDesc->iType = backgroundObjHeroImage; retDesc->pObj = CreateObjFromItem(CC, pDesc->GetElement(FIELD_OBJ)); if (retDesc->pObj == NULL) return false; } else if (strEquals(sType, TYPE_IMAGE)) { retDesc->iType = backgroundImage; ICCItem *pImage = pDesc->GetElement(FIELD_IMAGE); if (pImage == NULL) return false; else if (pImage->IsInteger()) retDesc->dwImageID = pImage->GetIntegerValue(); else return false; } else if (strEquals(sType, TYPE_OBJECT)) { retDesc->pObj = CreateObjFromItem(CC, pDesc->GetElement(FIELD_OBJ)); if (retDesc->pObj == NULL) return false; if (retDesc->pObj->IsPlayer()) retDesc->iType = backgroundObjSchematicImage; else retDesc->iType = backgroundObjHeroImage; } else if (strEquals(sType, TYPE_SCHEMATIC)) { retDesc->iType = backgroundObjSchematicImage; retDesc->pObj = CreateObjFromItem(CC, pDesc->GetElement(FIELD_OBJ)); if (retDesc->pObj == NULL) return false; } else return false; } // Otherwise, we can't parse. // // LATER: We should eventually handle a list-based image descriptor, but we // would need to enhance SBackgroundDesc for that. else return false; // Success return true; }
void GenerateShipTable (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; // Some options bool bAllClasses = (pCmdLine->GetAttributeBool(CONSTLIT("allClasses")) || pCmdLine->GetAttributeBool(CONSTLIT("all"))); // Get the criteria from the command line. Always append 's' because we // want ship classes. CString sCriteria = strPatternSubst(CONSTLIT("%s s"), pCmdLine->GetAttribute(CONSTLIT("criteria"))); CDesignTypeCriteria Criteria; if (CDesignTypeCriteria::ParseCriteria(sCriteria, &Criteria) != NOERROR) { printf("ERROR: Unable to parse criteria.\n"); return; } // Generate a list of columns to display TArray<CString> Cols; Cols.Insert(FIELD_LEVEL); Cols.Insert(FIELD_NAME); for (i = 0; i < pCmdLine->GetAttributeCount(); i++) { CString sAttrib = pCmdLine->GetAttributeName(i); if (strEquals(sAttrib, FIELD_BALANCE)) { Cols.Insert(CONSTLIT("balanceType")); Cols.Insert(CONSTLIT("combatStrength")); Cols.Insert(CONSTLIT("damage")); Cols.Insert(CONSTLIT("defenseStrength")); } else if (!IsMainCommandParam(sAttrib) && !strEquals(sAttrib, CONSTLIT("shiptable"))) { CString sValue = pCmdLine->GetAttribute(i); if (!strEquals(sValue, CONSTLIT("true"))) Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue)); else Cols.Insert(sAttrib); } } // Output the header for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); printf(Cols[j].GetASCIIZPointer()); } printf("\n"); // Generate a table CSymbolTable Table(FALSE, TRUE); // Loop over all items that match and add them to // a sorted table. for (i = 0; i < Universe.GetShipClassCount(); i++) { CShipClass *pClass = Universe.GetShipClass(i); // Only include generic classes unless otherwise specified if (!bAllClasses && !pClass->HasLiteralAttribute(CONSTLIT("genericClass"))) continue; if (!pClass->MatchesCriteria(Criteria)) continue; // Figure out the sort order char szBuffer[1024]; wsprintf(szBuffer, "%04d%s%d", pClass->GetLevel(), pClass->GetNounPhrase(0).GetASCIIZPointer(), pClass->GetUNID()); Table.AddEntry(CString(szBuffer), (CObject *)pClass); } // Output table CCodeChainCtx CCCtx; for (i = 0; i < Table.GetCount(); i++) { CShipClass *pClass = (CShipClass *)Table.GetValue(i); // Output each row for (j = 0; j < Cols.GetCount(); j++) { if (j != 0) printf("\t"); const CString &sField = Cols[j]; ICCItem *pResult = pClass->GetProperty(CCCtx, sField); if (strEquals(sField, FIELD_MANEUVER) || strEquals(sField, FIELD_THRUST_TO_WEIGHT)) printf("%.1f", pResult->GetIntegerValue() / 1000.0); else if (strEquals(sField, FIELD_SCORE_CALC)) printf("%d", pClass->CalcScore()); else { CString sValue = pResult->Print(&g_pUniverse->GetCC(), PRFLAG_NO_QUOTES | PRFLAG_ENCODE_FOR_DISPLAY); printf(sValue.GetASCIIZPointer()); } } printf("\n"); } printf("\n"); }
void CRandomEnhancementGenerator::EnhanceItem (CItem &Item) // EnhanceItem // // Enhances the given item { // See if this item is enhanced if (mathRandom(1, 100) > m_iChance) return; // If we have code, execute the code to figure out the mod if (m_pCode) { CCodeChainCtx Ctx; // Save the previous value of gItem Ctx.SaveItemVar(); Ctx.DefineItem(Item); // Execute the code ICCItem *pResult = Ctx.Run(m_pCode); // LATER:Event // If we have an error, report it DWORD dwMods; if (pResult->IsError()) { CString sError = strPatternSubst(CONSTLIT("Generate Enhancement: %s"), pResult->GetStringValue()); kernelDebugLogMessage(sError); dwMods = 0; } // Otherwise, the result code is the mods else dwMods = (DWORD)pResult->GetIntegerValue(); // Done with code Ctx.Discard(pResult); // Enhance the item Item.AddEnhancement(dwMods); } // Otherwise, if we have a constant mod, apply that else if (m_dwMods) { Item.AddEnhancement(m_dwMods); } // Otherwise, we need to generate a random mod appropriate to the // particular item else { DWORD dwMods; CItemType *pType = Item.GetType(); int iRoll = mathRandom(1, 100); switch (pType->GetCategory()) { case itemcatArmor: case itemcatShields: if (iRoll < 40) // HP + 10% dwMods = 0x0101; else if (iRoll < 65) // HP + 20% dwMods = 0x0102; else if (iRoll < 80) // HP + 30% dwMods = 0x0103; else if (iRoll < 90) // Damage Adj at 50% (and 75%) dwMods = 0x0A05 + (mathRandom(0, 3) << 4); else if (iRoll < 95) // Immunity to special ion attacks dwMods = 0x0C00; else // Regeneration dwMods = 0x0200; break; case itemcatWeapon: if (iRoll < 50) // Damage + 10% dwMods = 0x0101; else if (iRoll < 80) // Damage + 20% dwMods = 0x0102; else if (iRoll < 95) // Damage + 30% dwMods = 0x0103; else // Delay time at 70% of original dwMods = 0x1003; break; default: dwMods = 0; } Item.AddEnhancement(dwMods); } }