CItemType *CWeaponFireDesc::GetWeaponType (CItemType **retpLauncher) const // GetWeaponType // // Returns the item type that best represents this descriptor. For missiles, // we return the missile item UNID; for single-shot weapons (including ammo weapons) // we return the weapon item UNID { char *pPos = m_sUNID.GetPointer(); // Get the weapon UNID and the ordinal DWORD dwUNID = (DWORD)strParseInt(pPos, 0, &pPos); ASSERT(*pPos == '/'); pPos++; int iOrdinal = strParseInt(pPos, 0, &pPos); // Get the weapon descriptor CWeaponClass *pClass = (CWeaponClass *)g_pUniverse->FindDeviceClass(dwUNID); if (pClass == NULL) return NULL; // Return the device/launcher if (retpLauncher) *retpLauncher = pClass->GetItemType(); // For launchers, figure out which missile this is if (pClass->GetCategory() == itemcatLauncher) { CWeaponFireDesc *pMissileDesc = pClass->GetVariant(iOrdinal); if (pMissileDesc == NULL) return NULL; // If we have ammo, then return the ammo type CItemType *pAmmoType = pMissileDesc->GetAmmoType(); if (pAmmoType) return pAmmoType; // Otherwise return the launcher (e.g., DM600) return pClass->GetItemType(); } // Otherwise, return the weapon else return pClass->GetItemType(); }
ALERROR LoadTotalCount (const CString &sFilename, CSymbolTable &TotalCount) { ALERROR error; CFileReadBlock Input(sFilename); if (error = Input.Open()) { printf("ERROR: Unable to open total count file. Use /generateSimTables."); return error; } char *pPos = Input.GetPointer(0, -1); char *pEndPos = pPos + Input.GetLength(); while (pPos < pEndPos) { // Read an UNID DWORD dwUNID = (DWORD)strParseInt(pPos, 0, &pPos); if (dwUNID == 0) break; // Read an count if (pPos >= pEndPos) { printf("ERROR: Unexpected end of file."); return ERR_FAIL; } int iCount = strParseInt(pPos, 0, &pPos); // Add the entry CString sKey = strFromInt(dwUNID, false); EntryInfo *pEntry = new EntryInfo; pEntry->dwUNID = dwUNID; pEntry->rTotalCount = (double)iCount / 1000.0; if (error = TotalCount.AddEntry(sKey, pEntry)) { printf("ERROR: Invalid UNID."); return error; } } return NOERROR; }
TreeNode* createTree(vector<string> nums) { unsigned int i = 0, j; vector<TreeNode*> treeNodes; TreeNode* treeNode; for (; i < nums.size(); i++) { if (!nums[i].compare("null")) { treeNode = NULL; treeNodes.push_back(treeNode); continue; } treeNode = (TreeNode*)(malloc(sizeof(TreeNode))); treeNode->val = strParseInt(nums[i]); treeNode->left = NULL; treeNode->right = NULL; treeNodes.push_back(treeNode); } for (i = 0; i < nums.size() / 2; i++) { j = 2 * i + 1; if (j < nums.size()) treeNodes[i]->left = treeNodes[j]; j++; if (j < nums.size()) treeNodes[i]->right = treeNodes[j]; } return treeNodes[0]; }
void ReadLine (char *pPos, char *pEndPos, TArray<int> *retValues, char **retpPos) { while (true) { // Skip to the next number. while (pPos < pEndPos && !strIsDigit(pPos) && *pPos != '-' && *pPos != '+' && *pPos != '\n' && *pPos != '\r') pPos++; if (pPos >= pEndPos || *pPos == '\n' || *pPos == '\r') { while (pPos < pEndPos && (*pPos == '\n' || *pPos == '\r')) pPos++; break; } // Parse the number int iValue = strParseInt(pPos, 0, &pPos); retValues->Insert(iValue); } if (retpPos) *retpPos = pPos; }
ICCItem *fnSubst (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData) // fnSubst // // Substitutes string parameters // // (subst string arg1 arg2 ... argn) { CCodeChain *pCC = pCtx->pCC; ICCItem *pArgs; // Evaluate the arguments and validate them pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("s*")); if (pArgs->IsError()) return pArgs; CString sPattern = pArgs->GetElement(0)->GetStringValue(); // Do the substitution char szResult[4096]; char *pPos = sPattern.GetASCIIZPointer(); char *pDest = szResult; char *pEndDest = szResult + sizeof(szResult) - 1; while (*pPos != '\0' && pDest < pEndDest) { if (*pPos == '%') { pPos++; int iArg = strParseInt(pPos, 0, &pPos, NULL); if (iArg > 0) { CString sParam = pArgs->GetElement(iArg)->GetStringValue(); char *pParam = sParam.GetASCIIZPointer(); while (*pParam != '\0' && pDest < pEndDest) *pDest++ = *pParam++; pPos++; } else { if (*pPos == '%') *pDest++ = *pPos++; } } else *pDest++ = *pPos++; } // Done *pDest = '\0'; pArgs->Discard(pCC); return pCC->CreateString(CString(szResult)); }
bool CComplexDateTime::CreateFromString (const CString &sString, CDateTime *retDateTime) // CreateFromString // // Reverse of AsString { char *pPos = sString.GetParsePointer(); int iYear = strParseInt(pPos, 0, &pPos); if (iYear < 1 || iYear > 30827) return false; if (*pPos++ != '-') return false; int iMonth = strParseInt(pPos, 0, &pPos); if (iMonth < 1 || iMonth > 12) return false; if (*pPos++ != '-') return false; int iDay = strParseInt(pPos, 0, &pPos); if (iDay < 1 || iDay > CDateTime::GetDaysInMonth(iMonth, iYear)) return false; if (*pPos++ != 'T') return false; int iHour = strParseInt(pPos, -1, &pPos); if (iHour < 0 || iHour > 23) return false; if (*pPos++ != ':') return false; int iMinute = strParseInt(pPos, -1, &pPos); if (iMinute < 0 || iMinute > 59) return false; if (*pPos++ != ':') return false; int iSecond = strParseInt(pPos, -1, &pPos); if (iSecond < 0 || iSecond > 59) return false; if (*pPos++ != '.') return false; int iMillisecond = strParseInt(pPos, -1, &pPos); if (iMillisecond < 0 || iMillisecond > 999) return false; // Done *retDateTime = CDateTime(iDay, iMonth, iYear, iHour, iMinute, iSecond, iMillisecond); return true; }
CEffectCreator *CEffectCreator::FindEffectCreator (const CString &sUNID) // FindEffectCreator // // Finds the effect creator from a complex UNID (or NULL if not found) { // A complex UNID looks like this: // // For effects: // // {unid} // // "12345" = Effect UNID 12345 // "12345/0" = Effect UNID 12345; variant 0 // "12345/d:h" = Effect UNID 12345; damage; hit effect // // For overlays: // // {unid}:e // {unid}:h // // For shields: // // {unid}:h // "12345:h" = Shield UNID 12345; Hit effect // // For system maps: // // {unid}/{nodeID} // {unid}/{nodeID}[/{nodeID}] // // For weapons: // // {unid}/{var}[/f{frag}]:(e | h | f) // // "12345/0:e" = Weapon UNID 12345; variant 0; Bullet effect // "12345/0/f0:h" = Weapon UNID 12345; variant 0; fragment 0; Hit Effect // // First we parse the UNID char *pPos = sUNID.GetASCIIZPointer(); DWORD dwUNID = strParseInt(pPos, 0, &pPos); // Look for the design type CDesignType *pDesign = g_pUniverse->FindDesignType(dwUNID); if (pDesign == NULL) return NULL; // Allow the design type to parse the remainder of the UNID return pDesign->FindEffectCreatorInType(CString(pPos)); }
CEffectCreator *CEffectCreator::OnFindEffectCreator (const CString &sUNID) // OnFindEffectCreator // // Finds the effect creator by UNID { char *pPos = sUNID.GetASCIIZPointer(); // If we're done, then we mean ourselves if (*pPos == '\0') return this; if (*pPos++ != '/') return NULL; // Damage selector? if (*pPos == 'd') { pPos++; if (m_pDamage == NULL) return NULL; return m_pDamage->FindEffectCreator(CString(pPos)); } // Sub effect int iSubEffect = strParseInt(pPos, -1, 0, &pPos); if (iSubEffect == -1) return NULL; CEffectCreator *pSubEffect = GetSubEffect(iSubEffect); if (pSubEffect == NULL) return NULL; return pSubEffect->FindEffectCreatorInType(CString(pPos)); }
ICCItem *CreateResultFromDataField (CCodeChain &CC, const CString &sValue) // CreateResultFromDataField // // Converts a data field result into either an integer or a string { // Blank values are Nil if (sValue.IsBlank()) return CC.CreateNil(); // If prefixed with = sign, then this is a CodeChain expression else if (*sValue.GetASCIIZPointer() == '=') return CC.Link(sValue, 1, NULL); // Handle some special constants else if (strEquals(sValue, CONSTLIT("true"))) return CC.CreateTrue(); else if (strEquals(sValue, CONSTLIT("nil")) || strEquals(sValue, CONSTLIT("false")) || strEquals(sValue, CONSTLIT("none"))) return CC.CreateNil(); // Otherwise, see if it is a string or an integer else { char *pPos = sValue.GetASCIIZPointer(); char *pEnd; bool bNull; int iResult = strParseInt(pPos, 0, &pEnd, &bNull); if (!bNull && *pEnd == '\0') return CC.CreateInteger(iResult); else return CC.CreateString(sValue); } }
ALERROR CMissionType::OnCreateFromXML (SDesignLoadCtx &Ctx, CXMLElement *pDesc) // OnCreateFromXML // // Create from XML { ALERROR error; m_sName = pDesc->GetAttribute(NAME_ATTRIB); m_iPriority = pDesc->GetAttributeIntegerBounded(PRIORITY_ATTRIB, 0, -1, 1); m_iExpireTime = pDesc->GetAttributeIntegerBounded(EXPIRE_TIME_ATTRIB, 1, -1, -1); m_iFailIfOutOfSystem = pDesc->GetAttributeIntegerBounded(FAILURE_AFTER_OUT_OF_SYSTEM_ATTRIB, 0, -1, -1); m_fNoFailureOnOwnerDestroyed = pDesc->GetAttributeBool(NO_FAILURE_ON_OWNER_DESTROYED_ATTRIB); m_fNoDebrief = pDesc->GetAttributeBool(NO_DEBRIEF_ATTRIB); m_fNoStats = pDesc->GetAttributeBool(NO_STATS_ATTRIB); m_fCloseIfOutOfSystem = pDesc->GetAttributeBool(DEBRIEF_AFTER_OUT_OF_SYSTEM_ATTRIB); m_fForceUndockAfterDebrief = pDesc->GetAttributeBool(FORCE_UNDOCK_AFTER_DEBRIEF_ATTRIB); m_fAllowDelete = pDesc->GetAttributeBool(ALLOW_PLAYER_DELETE_ATTRIB); CString sAttrib; if (pDesc->FindAttribute(MAX_APPEARING_ATTRIB, &sAttrib)) { if (error = m_MaxAppearing.LoadFromXML(sAttrib)) { Ctx.sError = CONSTLIT("Invalid maxAppearing parameter."); return ERR_FAIL; } } m_iMaxAppearing = (m_MaxAppearing.IsEmpty() ? -1 : m_MaxAppearing.Roll()); m_iAccepted = 0; // Level if (pDesc->FindAttribute(LEVEL_ATTRIB, &sAttrib)) { // Parse this value char *pPos = sAttrib.GetASCIIZPointer(); m_iMinLevel = Max(1, Min(strParseInt(pPos, 1, &pPos), MAX_SYSTEM_LEVEL)); while (*pPos == ' ') pPos++; if (*pPos == '-') { pPos++; m_iMaxLevel = Max(m_iMinLevel, Min(strParseInt(pPos, MAX_SYSTEM_LEVEL), MAX_SYSTEM_LEVEL)); } else m_iMaxLevel = m_iMinLevel; } else { m_iMinLevel = 1; m_iMaxLevel = MAX_SYSTEM_LEVEL; } return NOERROR; }
bool CTimeSpan::ParsePartial (char *pPos, DWORD *retdwDays, DWORD *retdwMilliseconds, char **retpPos) // ParsePartial // // Parses a string of the form: // // xx {time-unit} { // Skip whitespace while (*pPos == ' ') pPos++; // Parse a number bool bFailed; DWORD dwValue1 = strParseInt(pPos, 0, &pPos, &bFailed); if (bFailed) return false; // See if we have a decimal DWORD dwValue2; if (*pPos == '.') { pPos++; dwValue2 = strParseInt(pPos, 0, &pPos, &bFailed); if (bFailed) return false; // Decimal extend to three digits. E.g., if .7, we convert to 700. if (dwValue2 < 10) dwValue2 *= 100; else if (dwValue2 < 100) dwValue2 *= 10; } else dwValue2 = 0; // Skip whitespace while (*pPos == ' ') pPos++; // Get the time unit char *pStart = pPos; while (*pPos != ' ' && *pPos != '\0') pPos++; // We can guess the time unit based on the first character if (*pStart == 'y') { *retdwDays = dwValue1 * 365; *retdwMilliseconds = 0; } else if (*pStart == 'd') { *retdwDays = dwValue1; *retdwMilliseconds = 0; } else if (*pStart == 'h') { *retdwDays = 0; *retdwMilliseconds = dwValue1 * 60 * 60 * 1000; } else if (*pStart == 'm') { *retdwDays = 0; *retdwMilliseconds = dwValue1 * 60 * 1000; } else if (*pStart == 's') { *retdwDays = 0; *retdwMilliseconds = dwValue1 * 1000 + dwValue2; } else return false; // Done *retpPos = pPos; return true; }
bool NextEntity (char **ioPos, char *pEnd, CString *retsName, DWORD *retdwValue) { char *pPos = *ioPos; while (true) { // Look for '<' while (pPos < pEnd && *pPos != '<' && *pPos != ']') pPos++; if (pPos == pEnd || *pPos == ']') return false; // Look for '!' pPos++; if (*pPos != '!') continue; // Look for 'E' pPos++; if (*pPos != 'E') continue; // Skip to whitespace while (pPos < pEnd && *pPos != ' ' && *pPos != '\t') pPos++; if (pPos == pEnd) return false; // Skip to non-space while (pPos < pEnd && (*pPos == ' ' || *pPos == '\t')) pPos++; if (pPos == pEnd) return false; // Skip to whitespace char *pStart = pPos; while (pPos < pEnd && *pPos != ' ' && *pPos != '\t') pPos++; if (pPos == pEnd) return false; *retsName = CString(pStart, pPos - pStart); // Skip to quote while (pPos < pEnd && *pPos != '\"') pPos++; if (pPos == pEnd) return false; pPos++; *retdwValue = strParseInt(pPos, 0, &pPos); if (*retdwValue != 0) { *ioPos = pPos; return true; } } }
bool CG16bitFont::ParseFontDesc (const CString &sDesc, CString *retsTypeface, int *retiSize, bool *retbBold, bool *retbItalic) // ParseFontDesc // // Parses a string of the form: // // {typeface} {font-size} [bold] [italic] // // Returns TRUE if valid { char *pPos = sDesc.GetASCIIZPointer(); CString sTypeface = CONSTLIT("Arial"); int iSize = 16; bool bBold = false; bool bItalic = false; // Skip whitespace while (*pPos == ' ' || *pPos == '\t') pPos++; // Skip delimiters bool bSpaceDelimiter; if (*pPos == '\'' || *pPos == '\"') { bSpaceDelimiter = false; pPos++; } else bSpaceDelimiter = true; // Look for typeface char *pStart = pPos; while (*pPos != '\'' && *pPos != '\"' && (!bSpaceDelimiter || *pPos != ' ') && *pPos != '\0') pPos++; sTypeface = CString(pStart, pPos - pStart); // Look for size while ((*pPos < '0' || *pPos > '9') && *pPos != '\0') pPos++; if (*pPos == '\0') { //printf("DirectXFont: Expected font size."); return false; } iSize = strParseInt(pPos, -1, &pPos); if (iSize == -1) { //printf("DirectXFont: Invalid font size."); return false; } // Skip whitespace while (*pPos == ' ' || *pPos == '\t') pPos++; // Parse bold/italic pStart = pPos; bool bDone = (*pPos == '\0'); while (!bDone) { if (*pPos == ' ' || *pPos == '\0') { CString sStyle = CString(pStart, pPos - pStart); if (strEquals(sStyle, CONSTLIT("bold"))) bBold = true; else if (strEquals(sStyle, CONSTLIT("italic"))) bItalic = true; // Skip whitespace while (*pPos == ' ') pPos++; pStart = pPos; bDone = (*pPos == '\0'); } else pPos++; } // Done *retsTypeface = sTypeface; *retiSize = iSize; *retbBold = bBold; *retbItalic = bItalic; return true; }
bool CTimeDate::Parse (const CString &sFormat, const CString &sValue, CString *retsError) // Parse // // Parse a date of the given format. { // Internet format: // // Sun, 06 Nov 1994 08:49:37 GMT if (strEquals(sFormat, FORMAT_INTERNET)) { char *pPos = sValue.GetASCIIZPointer(); char *pPosEnd = pPos + sValue.GetLength(); // Skip leading whitespace while (strIsWhitespace(pPos)) pPos++; // Skip day of week while (pPos < pPosEnd && (*pPos < '0' || *pPos > '9')) pPos++; if (pPos >= pPosEnd) goto InvalidValue; // Day bool bFail; m_Time.wDay = strParseInt(pPos, 0, &pPos, &bFail); if (bFail || m_Time.wDay < 1 || m_Time.wDay > 31) goto InvalidValue; pPos++; if (pPos >= pPosEnd) goto InvalidValue; // Month if (*pPos == 'A') { pPos++; if (*pPos == 'p') { m_Time.wMonth = 4; pPos += 3; } else if (*pPos == 'u') { m_Time.wMonth = 8; pPos += 3; } else goto InvalidValue; } else if (*pPos == 'D') { m_Time.wMonth = 12; pPos += 4; } else if (*pPos == 'F') { m_Time.wMonth = 2; pPos += 4; } else if (*pPos == 'J') { pPos++; if (*pPos == 'a') { m_Time.wMonth = 1; pPos += 3; } else if (*pPos == 'u') { pPos++; if (*pPos == 'l') { m_Time.wMonth = 7; pPos += 2; } else if (*pPos == 'n') { m_Time.wMonth = 6; pPos += 2; } else goto InvalidValue; } else goto InvalidValue; } else if (*pPos == 'M') { pPos++; if (*pPos == 'a') { pPos++; if (*pPos == 'r') { m_Time.wMonth = 3; pPos += 2; } else if (*pPos == 'y') { m_Time.wMonth = 5; pPos += 2; } else goto InvalidValue; } else goto InvalidValue; } else if (*pPos == 'N') { m_Time.wMonth = 11; pPos += 4; } else if (*pPos == 'O') { m_Time.wMonth = 10; pPos += 4; } else if (*pPos == 'S') { m_Time.wMonth = 9; pPos += 4; } else goto InvalidValue; if (pPos >= pPosEnd) goto InvalidValue; // Year m_Time.wYear = strParseInt(pPos, 0, &pPos, &bFail); if (bFail || m_Time.wYear < 1) goto InvalidValue; pPos++; if (pPos >= pPosEnd) goto InvalidValue; // Hour m_Time.wHour = strParseInt(pPos, 0, &pPos, &bFail); if (bFail || m_Time.wHour > 23) goto InvalidValue; pPos++; if (pPos >= pPosEnd) goto InvalidValue; // Minute m_Time.wMinute = strParseInt(pPos, 0, &pPos, &bFail); if (bFail || m_Time.wMinute > 59) goto InvalidValue; pPos++; if (pPos >= pPosEnd) goto InvalidValue; // Second m_Time.wSecond = strParseInt(pPos, 0, &pPos, &bFail); if (bFail || m_Time.wSecond > 59) goto InvalidValue; // Millisecond is not stored m_Time.wMilliseconds = 0; // We don't store day of week m_Time.wDayOfWeek = 0xffff; // Done return true; InvalidValue: if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid date value: %s"), sValue); return false; } else { if (retsError) *retsError = strPatternSubst(CONSTLIT("Unsupported date format: %s."), sFormat); return false; } }
void GenerateShieldStats (CUniverse &Universe, CXMLElement *pCmdLine) { int i; CString sUNID = pCmdLine->GetAttribute(CONSTLIT("unid")); DWORD dwUNID = strToInt(sUNID, 0, NULL); CItemType *pItem = Universe.FindItemType(dwUNID); if (pItem == NULL) { CItemCriteria Crit; CItem::InitCriteriaAll(&Crit); CItem Item = CItem::CreateItemByName(sUNID, Crit); pItem = Item.GetType(); if (pItem == NULL) { printf("ERROR: Unknown item '%s'\n", sUNID.GetASCIIZPointer()); return; } } if (pItem->GetCategory() != itemcatShields) { printf("ERROR: Item '%s' is not a shield generator\n", pItem->GetNounPhrase().GetASCIIZPointer()); return; } bool bVerbose = pCmdLine->GetAttributeBool(CONSTLIT("verbose")); bool bEval = pCmdLine->GetAttributeBool(CONSTLIT("eval")); // Get the stats for the shield Metric rHP = (Metric)pItem->GetDataFieldInteger(FIELD_HP); Metric rHPRegenPerTick = pItem->GetDataFieldInteger(FIELD_REGEN) / 1000.0; int iDamageAdj[damageCount]; CString sDamageAdj = pItem->GetDataField(CONSTLIT("damageAdj")); char *pPos = sDamageAdj.GetASCIIZPointer(); int iCount = 0; while (iCount < damageCount) { iDamageAdj[iCount] = strParseInt(pPos, 0, &pPos, NULL); if (*pPos != '\0') pPos++; iCount++; } // Print header printf("%s\n\n", pItem->GetNounPhrase().GetASCIIZPointer()); // Loop over all weapons and sort them by level and then name CSymbolTable List(FALSE, TRUE); for (i = 0; i < Universe.GetItemTypeCount(); i++) { CItemType *pWeapon = Universe.GetItemType(i); if (pWeapon->GetCategory() != itemcatWeapon) continue; CString sLevel = (pWeapon->GetLevel() < 10 ? strPatternSubst(CONSTLIT("0%d"), pWeapon->GetLevel()) : strFromInt(pWeapon->GetLevel(), FALSE)); CString sSortName = strPatternSubst(CONSTLIT("%s%s"), sLevel, pWeapon->GetNounPhrase()); List.AddEntry(sSortName, (CObject *)pWeapon); } // Loop over sorted list and output data for (i = 0; i < List.GetCount(); i++) { CItemType *pWeapon = (CItemType *)List.GetValue(i); // Get the data for the weapon int iFireDelay = pWeapon->GetDataFieldInteger(CONSTLIT("fireDelay")); Metric rAverageDamage = pWeapon->GetDataFieldInteger(CONSTLIT("averageDamage")) / 1000.0; int iDamageType = pWeapon->GetDataFieldInteger(CONSTLIT("damageType")); if (iDamageType < 0 || iDamageType >= damageCount) iDamageType = 0; // Adjust damage for type rAverageDamage = rAverageDamage * (iDamageAdj[iDamageType] / 100.0); if (rAverageDamage < 1.0) rAverageDamage = 0.0; // Calculate how many shots it would take to pierce through the shields char szBuffer[256]; Metric rShotsToDeplete; Metric rRegenPerShot = rHPRegenPerTick * (Metric)iFireDelay; if (rRegenPerShot >= rAverageDamage) { rShotsToDeplete = 1000000.0; lstrcpy(szBuffer, "ineffective"); } else { Metric rDrainPerShot = rAverageDamage - rRegenPerShot; rShotsToDeplete = rHP / rDrainPerShot; sprintf(szBuffer, "%.2f", rShotsToDeplete); } // See if this weapon is overpowered or underpowered char szEval[256]; if (bEval) { lstrcpy(szEval, "\t"); if (pWeapon->GetLevel() < pItem->GetLevel()) { if (rShotsToDeplete <= 10.0) lstrcpy(szEval, "\tOVERpowered"); } else { if (rShotsToDeplete > 20.0) lstrcpy(szEval, "\tUNDERpowered"); } } else lstrcpy(szEval, ""); // Print table if (bVerbose) { printf("%s\t%s\t%s\t(%d ticks; %.2f damage; %.2f regen/shot)%s\n", RomanNumeral(pWeapon->GetLevel()), pWeapon->GetNounPhrase().GetASCIIZPointer(), szBuffer, iFireDelay, rAverageDamage, rRegenPerShot, szEval); } else { printf("%s\t%s\t%s%s\n", RomanNumeral(pWeapon->GetLevel()), pWeapon->GetNounPhrase().GetASCIIZPointer(), szBuffer, szEval); } } }
CWeaponFireDesc *CWeaponFireDesc::FindWeaponFireDescFromFullUNID (const CString &sUNID) // FindWeaponFireDesc // // Finds the descriptor by name { char *pPos = sUNID.GetPointer(); // Get the UNID of the type DWORD dwUNID = (DWORD)strParseInt(pPos, 0, &pPos); if (dwUNID == 0) return NULL; // Get the type CDesignType *pType = g_pUniverse->FindDesignType(dwUNID); if (pType == NULL) return NULL; // If this is an item, then it must be a weapon if (pType->GetType() == designItemType) { CItemType *pItemType = CItemType::AsType(pType); ASSERT(pItemType); CDeviceClass *pDevice = pItemType->GetDeviceClass(); if (pDevice == NULL) return NULL; CWeaponClass *pClass = pDevice->AsWeaponClass(); if (pClass == NULL) return NULL; // Get the ordinal ASSERT(*pPos == '/'); pPos++; int iOrdinal = strParseInt(pPos, 0, &pPos); // Get the weapon fire desc of the ordinal CWeaponFireDesc *pDesc = pClass->GetVariant(iOrdinal); if (pDesc == NULL) return NULL; // Continue parsing return pDesc->FindWeaponFireDesc(CString(pPos)); } // If this is an effect, then get it from that else if (pType->GetType() == designEffectType) { CEffectCreator *pEffectType = CEffectCreator::AsType(pType); ASSERT(pEffectType); // Expect /d ASSERT(*pPos == '/'); pPos++; ASSERT(*pPos == 'd'); pPos++; CWeaponFireDesc *pDesc = pEffectType->GetDamageDesc(); if (pDesc == NULL) return NULL; // Continue parsing return pDesc->FindWeaponFireDesc(CString(pPos)); } // Otherwise, we don't know else return NULL; }
CWeaponFireDesc *CWeaponFireDesc::FindWeaponFireDesc (const CString &sUNID, char **retpPos) // FindWeaponFireDesc // // Finds the weapon fire desc from a partial UNID { char *pPos = sUNID.GetASCIIZPointer(); // If we're done, then we want this descriptor if (*pPos == '\0') return this; // If a slash, then we have another weapon fire desc else if (*pPos == '/') { pPos++; // The enhanced section if (*pPos == 'e') { pPos++; if (m_pEnhanced) return m_pEnhanced->FindWeaponFireDesc(CString(pPos, -1, TRUE), retpPos); else return NULL; } // A fragment else if (*pPos == 'f') { pPos++; int iIndex = strParseInt(pPos, 0, &pPos); SFragmentDesc *pNext = m_pFirstFragment; while (iIndex-- > 0 && pNext) pNext = pNext->pNext; if (pNext) return pNext->pDesc->FindWeaponFireDesc(CString(pPos, -1, TRUE), retpPos); else return NULL; } else return NULL; } // Otherwise, we have an effect else if (*pPos == ':') { if (retpPos) *retpPos = pPos; return this; } else return NULL; }
CString ResolveEntity (ParserCtx *pCtx, const CString &sName, bool *retbFound) // ResolveEntity // // Resolves the entity from the parser table { *retbFound = true; CString sResult; // Check to see if the name is one of the standard entities CString sNameLC = strToLower(sName); if (strEquals(sNameLC, ENTITY_AMP)) return ENTITY_AMP_SUB; else if (strEquals(sNameLC, ENTITY_LT)) return ENTITY_LT_SUB; else if (strEquals(sNameLC, ENTITY_GT)) return ENTITY_GT_SUB; else if (strEquals(sNameLC, ENTITY_QUOT)) return ENTITY_QUOT_SUB; else if (strEquals(sNameLC, ENTITY_APOS)) return ENTITY_APOS_SUB; // If the entity is a hex number, then this is a character char *pPos = sName.GetParsePointer(); if (*pPos == '#') { pPos++; if (*pPos == 'x' || *pPos == 'X') { *pPos++; char chChar = (char)strParseIntOfBase(pPos, 16, 0x20, NULL, NULL); return CString(&chChar, 1); } else { char chChar = (char)strParseInt(pPos, 0x20); return CString(&chChar, 1); } } // Otherwise, it is a general attribute bool bFound; CString sValue = pCtx->LookupEntity(sName, &bFound); if (bFound) { // Parse the value to resolve embedded entities ParserCtx SubCtx(pCtx, sValue); ParseToken(&SubCtx, ParseEntityState); if (SubCtx.iToken == tkText) sResult = SubCtx.sToken; else { bFound = false; sResult = sName; } } if (retbFound) *retbFound = bFound; return sResult; }
ALERROR CItemEnhancement::InitFromDesc (const CString &sDesc, CString *retsError) // InitFromDesc // // Initializes from a string of the following forms: // // {number} Interpret as a mod code // +armor:{n} Add armor special damage, where n is an item level // +hpBonus:{n} Add hp bonus. // +immunity:{s} Immunity to special damage s. // +reflect:{s} Reflects damage type s. // +regen Regenerate // +resist:{s}:{n} DamageAdj for type s set to n // +resistDamageClass:{s}:{n} DamageAdj for type s (and its next-tier mate) set to n // +resistDamageTier:{s}:{n} DamageAdj for type s (and its tier mate) set to n // +resistEnergy:{n} DamageAdj for energy damage set to n // +resistMatter:{n} DamageAdj for matter damage set to n // +shield:{n} Add shield disrupt special damage, where n is an item level // +speed:{n} Faster. n is new delay value as a percent of normal { // If the string is a number then we interpret it as a mod code. bool bFailed; DWORD dwCode = strToInt(sDesc, 0, &bFailed); if (!bFailed) { m_dwMods = dwCode; return NOERROR; } // Parse the string char *pPos = sDesc.GetASCIIZPointer(); // Expect either "+" or "-" (for disadvantage) bool bDisadvantage; if (*pPos == '+') bDisadvantage = false; else if (*pPos == '-') bDisadvantage = true; else { if (retsError) *retsError = CONSTLIT("Invalid enhancement description: expected '+' or '-'."); return ERR_FAIL; } pPos++; // Parse the enhancement name char *pStart = pPos; while (*pPos != ':' && *pPos != '\0') pPos++; CString sID(pStart, (int)(pPos - pStart)); // See if we have a value int iValue = 0; CString sValue; if (*pPos == ':') { pPos++; if (*pPos == '-' || *pPos == '+' || (*pPos >= '0' && *pPos <= '9')) iValue = strParseInt(pPos, 0, &pPos); else { char *pStart = pPos; while (*pPos != '\0' && *pPos != ':') pPos++; sValue = CString(pStart, (int)(pPos - pStart)); } } // See if we have a second value int iValue2 = 0; if (*pPos == ':') { pPos++; iValue2 = strParseInt(pPos, 0, &pPos); } // See if this is an hpBonus if (strEquals(sID, CONSTLIT("hpBonus"))) { if (bDisadvantage && iValue > 0) iValue = -iValue; if (iValue < -100) { if (retsError) *retsError = CONSTLIT("hpBonus penalty cannot exceed 100%."); return ERR_FAIL; } else if (iValue < 0) SetModCode(EncodeAX(etHPBonus | etDisadvantage, 0, -iValue)); else if (iValue == 0) SetModCode(Encode12(etStrengthen)); else if (iValue <= 1000) SetModCode(EncodeAX(etHPBonus, 0, iValue)); else { if (retsError) *retsError = CONSTLIT("hpBonus cannot exceed 1000%."); return ERR_FAIL; } } // Immunity else if (strEquals(sID, CONSTLIT("immunity"))) { if (strEquals(sValue, CONSTLIT("ionEffects"))) m_dwMods = Encode12(etImmunityIonEffects); else { SpecialDamageTypes iSpecial = DamageDesc::ConvertToSpecialDamageTypes(sValue); switch (iSpecial) { case specialRadiation: case specialBlinding: case specialEMP: case specialDeviceDamage: case specialDisintegration: case specialMomentum: case specialShieldDisrupt: case specialDeviceDisrupt: case specialShatter: { if (bDisadvantage) { if (retsError) *retsError = CONSTLIT("Disadvantage not supported."); return ERR_FAIL; } SetModImmunity(iSpecial); break; } default: { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid immunity: %s"), sID); return ERR_FAIL; } } } } // Reflect bonus else if (strEquals(sID, CONSTLIT("reflect"))) { DamageTypes iDamageType = LoadDamageTypeFromXML(sValue); if (iDamageType == damageError) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid damage type: %s"), sValue); return ERR_FAIL; } SetModReflect(iDamageType); } // Regen else if (strEquals(sID, CONSTLIT("regen"))) { m_dwMods = Encode12(etRegenerate | (bDisadvantage ? etDisadvantage : 0)); } // Resist damage else if (strEquals(sID, CONSTLIT("resist"))) { DamageTypes iDamageType = LoadDamageTypeFromXML(sValue); if (iDamageType == damageError) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid damage type: %s"), sValue); return ERR_FAIL; } SetModResistDamage(iDamageType, iValue2); } // Resist damage else if (strEquals(sID, CONSTLIT("resistDamageClass"))) { DamageTypes iDamageType = LoadDamageTypeFromXML(sValue); if (iDamageType == damageError) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid damage type: %s"), sValue); return ERR_FAIL; } SetModResistDamageClass(iDamageType, iValue2); } // Resist damage tier else if (strEquals(sID, CONSTLIT("resistDamageTier"))) { DamageTypes iDamageType = LoadDamageTypeFromXML(sValue); if (iDamageType == damageError) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid damage type: %s"), sValue); return ERR_FAIL; } SetModResistDamageTier(iDamageType, iValue2); } // Resist energy/matter else if (strEquals(sID, CONSTLIT("resistEnergy"))) SetModResistEnergy(iValue); else if (strEquals(sID, CONSTLIT("resistMatter"))) SetModResistMatter(iValue); // Speed bonus else if (strEquals(sID, CONSTLIT("speed"))) { if (iValue <= 0) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid speed value: %s."), iValue); return ERR_FAIL; } else // LATER: Support min and max delay limits SetModSpeed(iValue); } // Otherwise, see if this is a special damage else { SpecialDamageTypes iSpecial = DamageDesc::ConvertToSpecialDamageTypes(sID); switch (iSpecial) { case specialArmor: case specialShieldDisrupt: { if (bDisadvantage) { if (retsError) *retsError = CONSTLIT("Disadvantage not supported."); return ERR_FAIL; } if (iValue < 1 || iValue > MAX_ITEM_LEVEL) { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid %s damage level: %d"), sID, iValue); return ERR_FAIL; } SetModSpecialDamage(iSpecial, iValue); break; } default: { if (retsError) *retsError = strPatternSubst(CONSTLIT("Invalid enhancement name: %s"), sID); return ERR_FAIL; } } } // Done return NOERROR; }
bool CTimeSpan::Parse (const CString &sValue, CTimeSpan *retValue) // Parse // // Parses a string of the form: // // D:0xddd M:0xmmm // (where ddd = days; mmm = milliseconds) { char *pPos = sValue.GetASCIIZPointer(); // If the first character is a 'D' then we assume an encoded TimeSpan if (*pPos == 'D') { pPos++; if (*pPos++ != ':') return false; bool bFailed; DWORD dwDays = strParseInt(pPos, 0, &pPos, &bFailed); if (bFailed) return false; if (*pPos++ != ' ') return false; if (*pPos++ != 'M') return false; if (*pPos++ != ':') return false; DWORD dwMilliseconds = strParseInt(pPos, 0, &pPos, &bFailed); if (bFailed) return false; *retValue = CTimeSpan(dwDays, dwMilliseconds); return true; } // Otherwise we try to parse a plain English time span else { DWORD dwTotalDays = 0; DWORD dwTotalMilliseconds = 0; // Parse components DWORD dwDays; DWORD dwMilliseconds; if (!ParsePartial(pPos, &dwDays, &dwMilliseconds, &pPos)) return false; dwTotalDays += dwDays; dwTotalMilliseconds += dwMilliseconds; // Look for 'and' while (*pPos == ' ') pPos++; if (*pPos++ == 'a') { if (*pPos++ != 'n') return false; if (*pPos++ != 'd') return false; if (!ParsePartial(pPos, &dwDays, &dwMilliseconds, &pPos)) return false; dwTotalDays += dwDays; dwTotalMilliseconds += dwMilliseconds; } // Done *retValue = CTimeSpan(dwTotalDays, dwTotalMilliseconds); return true; } }