diff --git a/data/mp/stats/templates.ini b/data/mp/stats/templates.ini index 514cdc1fe..2f88a1433 100644 --- a/data/mp/stats/templates.ini +++ b/data/mp/stats/templates.ini @@ -1030,7 +1030,7 @@ type = DROID weapons = RailGun2Mk1 [BabaPickUp] -compBody = B2RKJeepBody +compBody = BabaJeepBody compConstruct = Spade1Mk1 type = DROID diff --git a/lib/framework/wzconfig.h b/lib/framework/wzconfig.h index f84e2bc43..5a2e48589 100644 --- a/lib/framework/wzconfig.h +++ b/lib/framework/wzconfig.h @@ -103,7 +103,10 @@ public: { return m_settings.status(); } - + QString group() + { + return m_settings.group(); + } }; #endif diff --git a/lib/netplay/nettypes.cpp b/lib/netplay/nettypes.cpp index 81e78d5e6..cff668e27 100644 --- a/lib/netplay/nettypes.cpp +++ b/lib/netplay/nettypes.cpp @@ -26,6 +26,7 @@ #include "lib/framework/wzglobal.h" #include "lib/framework/string_ext.h" #include +#include #ifndef WZ_OS_WIN #include @@ -620,7 +621,6 @@ void NETbool(bool *bp) *bp = !!i; } - /** Sends or receives a string to or from the current network package. * \param str When encoding a packet this is the (NUL-terminated string to * be sent in the current network package. When decoding this @@ -664,6 +664,31 @@ void NETstring(char *str, uint16_t maxlen) } } +void NETqstring(QString &str) +{ + uint16_t len = str.size(); + + queueAuto(len); + + if (NETgetPacketDir() == PACKET_DECODE) + { + str.resize(len); + } + for (unsigned i = 0; i < len; ++i) + { + uint16_t c; + if (NETgetPacketDir() == PACKET_ENCODE) + { + c = str[i].unicode(); + } + queueAuto(c); + if (NETgetPacketDir() == PACKET_DECODE) + { + str[i] = QChar(c); + } + } +} + void NETstring(char const *str, uint16_t maxlen) { ASSERT(NETgetPacketDir() == PACKET_ENCODE, "Writing to const!"); diff --git a/lib/netplay/nettypes.h b/lib/netplay/nettypes.h index 1da2b5973..ec690a3f3 100644 --- a/lib/netplay/nettypes.h +++ b/lib/netplay/nettypes.h @@ -28,6 +28,8 @@ #include "lib/framework/vector.h" #include "lib/netplay/netqueue.h" +class QString; + enum PACKETDIR { PACKET_ENCODE, @@ -86,6 +88,7 @@ void NETint64_t(int64_t *ip); void NETuint64_t(uint64_t *ip); void NETbool(bool *bp); void NETbool(bool *bp); +void NETqstring(QString &str); void NETstring(char *str, uint16_t maxlen); void NETstring(char const *str, uint16_t maxlen); ///< Encode-only version of NETstring. void NETbin(uint8_t *str, uint32_t len); diff --git a/lib/widget/bar.cpp b/lib/widget/bar.cpp index 306be2026..068f173e8 100644 --- a/lib/widget/bar.cpp +++ b/lib/widget/bar.cpp @@ -42,7 +42,6 @@ W_BARINIT::W_BARINIT() , precision(0) //sCol //sMinorCol - , pTip(NULL) { sCol.rgba = 0; sMinorCol.rgba = 0; @@ -61,7 +60,7 @@ W_BARGRAPH::W_BARGRAPH(W_BARINIT const *init) , majorCol(init->sCol) , minorCol(init->sMinorCol) , textCol(WZCOL_BLACK) - , pTip(QString::fromUtf8(init->pTip)) + , pTip(init->pTip) , backgroundColour(WZCOL_FORM_BACKGROUND) { /* Set the minor colour if necessary */ diff --git a/lib/widget/button.cpp b/lib/widget/button.cpp index 2e3089e9d..3fa48f107 100644 --- a/lib/widget/button.cpp +++ b/lib/widget/button.cpp @@ -37,7 +37,6 @@ W_BUTINIT::W_BUTINIT() : pText(NULL) - , pTip(NULL) , FontID(font_regular) {} @@ -45,7 +44,7 @@ W_BUTTON::W_BUTTON(W_BUTINIT const *init) : WIDGET(init, WIDG_BUTTON) , state(WBUT_PLAIN) , pText(QString::fromUtf8(init->pText)) - , pTip(QString::fromUtf8(init->pTip)) + , pTip(init->pTip) , HilightAudioID(WidgGetHilightAudioID()) , ClickedAudioID(WidgGetClickedAudioID()) , AudioCallback(WidgGetAudioCallback()) diff --git a/lib/widget/form.cpp b/lib/widget/form.cpp index 315f9079d..61cffea70 100644 --- a/lib/widget/form.cpp +++ b/lib/widget/form.cpp @@ -38,7 +38,6 @@ W_FORMINIT::W_FORMINIT() : disableChildren(false) - , pTip(NULL) {} W_FORM::W_FORM(W_FORMINIT const *init) @@ -58,7 +57,7 @@ W_FORM::W_FORM(WIDGET *parent) W_CLICKFORM::W_CLICKFORM(W_FORMINIT const *init) : W_FORM(init) , state(WBUT_PLAIN) - , pTip(QString::fromUtf8(init->pTip)) + , pTip(init->pTip) , HilightAudioID(WidgGetHilightAudioID()) , ClickedAudioID(WidgGetClickedAudioID()) , AudioCallback(WidgGetAudioCallback()) diff --git a/lib/widget/label.cpp b/lib/widget/label.cpp index ea28dbd76..2a3798bbb 100644 --- a/lib/widget/label.cpp +++ b/lib/widget/label.cpp @@ -35,7 +35,6 @@ W_LABINIT::W_LABINIT() : pText(NULL) - , pTip(NULL) , FontID(font_regular) {} @@ -43,7 +42,7 @@ W_LABEL::W_LABEL(W_LABINIT const *init) : WIDGET(init, WIDG_LABEL) , aText(QString::fromUtf8(init->pText)) , FontID(init->FontID) - , pTip(QString::fromUtf8(init->pTip)) + , pTip(init->pTip) , fontColour(WZCOL_FORM_TEXT) { ASSERT((init->style & ~(WLAB_PLAIN | WLAB_ALIGNLEFT | WLAB_ALIGNRIGHT | WLAB_ALIGNCENTRE | WLAB_ALIGNTOP | WLAB_ALIGNBOTTOM | WIDG_HIDDEN)) == 0, "Unknown button style"); diff --git a/lib/widget/slider.cpp b/lib/widget/slider.cpp index a45c9f243..f9f2f804b 100644 --- a/lib/widget/slider.cpp +++ b/lib/widget/slider.cpp @@ -42,7 +42,6 @@ W_SLDINIT::W_SLDINIT() , numStops(0) , barSize(0) , pos(0) - , pTip(NULL) {} W_SLIDER::W_SLIDER(W_SLDINIT const *init) @@ -52,7 +51,7 @@ W_SLIDER::W_SLIDER(W_SLDINIT const *init) , barSize(init->barSize) , pos(init->pos) , state(0) - , pTip(QString::fromUtf8(init->pTip)) + , pTip(init->pTip) { ASSERT((init->style & ~(WBAR_PLAIN | WIDG_HIDDEN)) == 0, "Unknown style"); ASSERT(init->orientation >= WSLD_LEFT || init->orientation <= WSLD_BOTTOM, "Unknown orientation"); diff --git a/lib/widget/widget.cpp b/lib/widget/widget.cpp index c1f2aeff0..bac2da5fa 100644 --- a/lib/widget/widget.cpp +++ b/lib/widget/widget.cpp @@ -480,7 +480,7 @@ void WIDGET::setTip(QString) } /* Set tip string for a widget */ -void widgSetTip(W_SCREEN *psScreen, UDWORD id, const char *pTip) +void widgSetTip(W_SCREEN *psScreen, UDWORD id, QString pTip) { WIDGET *psWidget = widgGetFromID(psScreen, id); diff --git a/lib/widget/widget.h b/lib/widget/widget.h index af8b2b45d..1eb0d337e 100644 --- a/lib/widget/widget.h +++ b/lib/widget/widget.h @@ -125,7 +125,7 @@ struct W_FORMINIT : public W_INIT W_FORMINIT(); bool disableChildren; - const char *pTip; ///< Tool tip for the form itself + QString pTip; ///< Tool tip for the form itself }; /** Label initialisation structure */ @@ -134,7 +134,7 @@ struct W_LABINIT : public W_INIT W_LABINIT(); const char *pText; ///< label text - const char *pTip; ///< Tool tip for the label. + QString pTip; ///< Tool tip for the label. enum iV_fonts FontID; ///< ID of the IVIS font to use for this widget. }; @@ -144,7 +144,7 @@ struct W_BUTINIT : public W_INIT W_BUTINIT(); const char *pText; ///< Button text - const char *pTip; ///< Tool tip text + QString pTip; ///< Tool tip text enum iV_fonts FontID; //< ID of the IVIS font to use for this widget. }; @@ -180,7 +180,7 @@ struct W_BARINIT : public W_INIT int precision; ///< Number of places after the decimal point to display, 0 by default. PIELIGHT sCol; ///< Bar colour PIELIGHT sMinorCol; ///< Minor bar colour - const char *pTip; ///< Tool tip text + QString pTip; ///< Tool tip text }; @@ -202,7 +202,7 @@ struct W_SLDINIT : public W_INIT UWORD numStops; ///< Number of stops on the slider UWORD barSize; ///< Size of the bar UWORD pos; ///< Initial position of the slider bar - const char *pTip; ///< Tip string + QString pTip; ///< Tip string }; /***********************************************************************************/ @@ -289,7 +289,7 @@ extern void widgSetUserData2(W_SCREEN *psScreen, UDWORD id, UDWORD UserData); extern WIDGET *widgGetFromID(W_SCREEN *psScreen, UDWORD id); /** Set tip string for a widget */ -extern void widgSetTip(W_SCREEN *psScreen, UDWORD id, const char *pTip); +extern void widgSetTip(W_SCREEN *psScreen, UDWORD id, QString pTip); /** Colour numbers */ enum _w_colour diff --git a/src/ai.cpp b/src/ai.cpp index a5bebd4a6..c1de416e1 100644 --- a/src/ai.cpp +++ b/src/ai.cpp @@ -475,7 +475,7 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker, /* indirect firing units have slow reload times, so give the target a chance to die, * and give a different unit a chance to get in range, too. */ if (weaponROF(attackerWeapon, psAttacker->player) < TARGET_DOOMED_SLOW_RELOAD_T) { - debug(LOG_NEVER,"Not killing unit - doomed. My ROF: %i (%s)", weaponROF(attackerWeapon, psAttacker->player), attackerWeapon->pName); + debug(LOG_NEVER,"Not killing unit - doomed. My ROF: %i (%s)", weaponROF(attackerWeapon, psAttacker->player), getName(attackerWeapon)); return noTarget; } attackWeight /= TARGET_DOOMED_PENALTY_F; diff --git a/src/baseobject.cpp b/src/baseobject.cpp index bf415d54a..fa0e99722 100644 --- a/src/baseobject.cpp +++ b/src/baseobject.cpp @@ -75,9 +75,12 @@ Spacetime interpolateObjectSpacetime(const SIMPLE_OBJECT *obj, uint32_t t) SIMPLE_OBJECT::SIMPLE_OBJECT(OBJECT_TYPE type, uint32_t id, unsigned player) : type(type) , id(id) + , pos(0, 0, 0) + , rot(0, 0, 0) , player(player) , born(gameTime) , died(0) + , time(0) {} SIMPLE_OBJECT::~SIMPLE_OBJECT() @@ -96,9 +99,13 @@ BASE_OBJECT::BASE_OBJECT(OBJECT_TYPE type, uint32_t id, unsigned player) , lastEmission(0) , lastHitWeapon(WSC_NUM_WEAPON_SUBCLASSES) // No such weapon. , timeLastHit(UDWORD_MAX) + , body(0) + , periodicalDamageStart(0) + , periodicalDamage(0) , bTargetted(false) , watchedTiles(NULL) { + memset(visible, 0, sizeof(visible)); sDisplay.imd = NULL; sDisplay.frameNumber = 0; sDisplay.screenX = 0; diff --git a/src/combat.cpp b/src/combat.cpp index 85af53a51..d455293bb 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -105,7 +105,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in if (psTarget->visible[psAttacker->player] != UBYTE_MAX) { // Can't see it - can't hit it - objTrace(psAttacker->id, "combFire(%u[%s]->%u): Object has no indirect sight of target", psAttacker->id, psStats->pName, psTarget->id); + objTrace(psAttacker->id, "combFire(%u[%s]->%u): Object has no indirect sight of target", psAttacker->id, getName(psStats), psTarget->id); return false; } @@ -172,7 +172,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in else { /* Out of range */ - objTrace(psAttacker->id, "combFire(%u[%s]->%u): Out of range", psAttacker->id, psStats->pName, psTarget->id); + objTrace(psAttacker->id, "combFire(%u[%s]->%u): Out of range", psAttacker->id, getName(psStats), psTarget->id); return false; } @@ -267,7 +267,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in if (isHit) { /* Kerrrbaaang !!!!! a hit */ - objTrace(psAttacker->id, "combFire: [%s]->%u: resultHitChance=%d, visibility=%d", psStats->pName, psTarget->id, resultHitChance, (int)psTarget->visible[psAttacker->player]); + objTrace(psAttacker->id, "combFire: [%s]->%u: resultHitChance=%d, visibility=%d", getName(psStats), psTarget->id, resultHitChance, (int)psTarget->visible[psAttacker->player]); syncDebug("hit=(%d,%d,%d)", predict.x, predict.y, predict.z); } else /* Deal with a missed shot */ diff --git a/src/design.cpp b/src/design.cpp index cc4a45774..8407c10e6 100644 --- a/src/design.cpp +++ b/src/design.cpp @@ -401,10 +401,9 @@ static bool _intAddDesign(bool bShowCentreScreen) /* Initialise the current design */ sDefaultDesignTemplate.droidType = DROID_ANY; sCurrDesign = sDefaultDesignTemplate; - sCurrDesign.pName = NULL; sCurrDesign.stored = false; sstrcpy(aCurrName, _("New Vehicle")); - sstrcpy(sCurrDesign.aName, aCurrName); + sCurrDesign.name = aCurrName; /* Add the design templates form */ if (!intAddTemplateForm(NULL)) // Was psCurrTemplate instead of NULL, but psCurrTemplate was always NULL. Deleted psCurrTemplate, but leaving this here, in case intAddTemplateForm(NULL) does something useful. @@ -1065,8 +1064,7 @@ const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate) psTemplate->asParts[COMP_REPAIRUNIT] != 0 || psTemplate->asParts[COMP_BRAIN] != 0) { - const char *pStr = getStatName(psStats); - sstrcpy(aCurrName, pStr); + sstrcpy(aCurrName, getName(psStats)); sstrcat(aCurrName, " "); } @@ -1080,15 +1078,13 @@ const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate) psStats = (COMPONENT_STATS *)(asBodyStats + compIndex); if (psTemplate->asParts[COMP_BODY] != 0) { - const char *pStr = getStatName(psStats); - - if (strlen(aCurrName) + strlen(pStr) > MAX_STR_LENGTH) + if (strlen(aCurrName) + psStats->name.size() > MAX_STR_LENGTH) { - debug(LOG_ERROR, "Name string too long %s+%s > %u", aCurrName, pStr, MAX_STR_LENGTH); + debug(LOG_ERROR, "Name string too long %s+%s > %u", aCurrName, getName(psStats), MAX_STR_LENGTH); debug(LOG_ERROR, "Please report what language you are using in the bug report!"); } - sstrcat(aCurrName, pStr); + sstrcat(aCurrName, getName(psStats)); sstrcat(aCurrName, " "); } @@ -1097,15 +1093,13 @@ const char *GetDefaultTemplateName(DROID_TEMPLATE *psTemplate) psStats = (COMPONENT_STATS *)(asPropulsionStats + compIndex); if (psTemplate->asParts[COMP_PROPULSION] != 0) { - const char *pStr = getStatName(psStats); - - if (strlen(aCurrName) + strlen(pStr) > MAX_STR_LENGTH) + if (strlen(aCurrName) + psStats->name.size() > MAX_STR_LENGTH) { - debug(LOG_ERROR, "Name string too long %s+%s", aCurrName, pStr); + debug(LOG_ERROR, "Name string too long %s+%s", aCurrName, getName(psStats)); debug(LOG_ERROR, "Please report what language you are using in the bug report!"); } - sstrcat(aCurrName, pStr); + sstrcat(aCurrName, getName(psStats)); } return aCurrName; @@ -1118,7 +1112,7 @@ static void intSetEditBoxTextFromTemplate(DROID_TEMPLATE *psTemplate) /* show component names if default template else show stat name */ if (psTemplate->droidType != DROID_DEFAULT) { - sstrcpy(aCurrName, getTemplateName(psTemplate)); + sstrcpy(aCurrName, getName(psTemplate)); } else { @@ -2915,7 +2909,7 @@ bool intValidTemplate(DROID_TEMPLATE *psTempl, const char *newName, bool complai psTempl->enabled = true; /* copy name into template */ - sstrcpy(psTempl->aName, newName); + psTempl->name = newName; return true; } @@ -2924,7 +2918,6 @@ static void desCreateDefaultTemplate(void) { /* set current design to default */ sCurrDesign = sDefaultDesignTemplate; - sCurrDesign.pName = NULL; sCurrDesign.stored = false; /* reset stats */ @@ -2974,7 +2967,7 @@ static void intSetButtonFlash(UDWORD id, bool bFlash) static bool desTemplateNameCustomised(DROID_TEMPLATE *psTemplate) { if ((psTemplate->droidType == DROID_DEFAULT) || - (strcmp(getTemplateName(psTemplate), + (strcmp(getName(psTemplate), GetDefaultTemplateName(psTemplate)) == 0)) { return false; @@ -3011,8 +3004,7 @@ void intProcessDesign(UDWORD id) desCreateDefaultTemplate(); aCurrName[0] = '\0'; - sCurrDesign.aName[0] = '\0'; - sstrcpy(sCurrDesign.aName, aCurrName); + sCurrDesign.name = aCurrName; /* reveal body button */ widgReveal(psWScreen, IDDES_BODYBUTTON); @@ -3042,7 +3034,7 @@ void intProcessDesign(UDWORD id) { /* Set the new template */ sCurrDesign = *psTempl; - sstrcpy(aCurrName, getTemplateName(psTempl)); + sstrcpy(aCurrName, getName(psTempl)); /* reveal body/propulsion/turret component buttons */ widgReveal(psWScreen, IDDES_BODYBUTTON); @@ -3343,7 +3335,7 @@ void intProcessDesign(UDWORD id) /* update name if not customised */ if (bTemplateNameCustomised == false) { - sstrcpy(sCurrDesign.aName, GetDefaultTemplateName(&sCurrDesign)); + sCurrDesign.name = GetDefaultTemplateName(&sCurrDesign); } /* Update the name in the edit box */ @@ -3473,7 +3465,7 @@ void intProcessDesign(UDWORD id) /* update name if not customised */ if (bTemplateNameCustomised == false) { - sstrcpy(sCurrDesign.aName, GetDefaultTemplateName(&sCurrDesign)); + sCurrDesign.name = GetDefaultTemplateName(&sCurrDesign); } /* Update the name in the edit box */ @@ -3519,8 +3511,8 @@ void intProcessDesign(UDWORD id) break; /* The name edit box */ case IDDES_NAMEBOX: - sstrcpy(sCurrDesign.aName, widgGetString(psWScreen, IDDES_NAMEBOX)); - sstrcpy(aCurrName, sCurrDesign.aName); + sCurrDesign.name = widgGetString(psWScreen, IDDES_NAMEBOX); + sstrcpy(aCurrName, getName(&sCurrDesign)); break; case IDDES_BIN: { @@ -3540,7 +3532,6 @@ void intProcessDesign(UDWORD id) //before deleting the template, need to make sure not being used in production deleteTemplateFromProduction(psTempl, selectedPlayer, ModeQueue); // Delete the template. - free(i->pName); localTemplates.erase(i); break; } @@ -3558,7 +3549,7 @@ void intProcessDesign(UDWORD id) /* Set the new template */ sCurrDesign = *psTempl; - sstrcpy(aCurrName, getTemplateName(psTempl)); + sstrcpy(aCurrName, getName(psTempl)); intSetEditBoxTextFromTemplate(psTempl); @@ -4001,7 +3992,6 @@ static bool saveTemplate(void) /* Copy the template */ *psTempl = sCurrDesign; - sstrcpy(psTempl->aName, aCurrName); /* Now update the droid template form */ widgDelete(psWScreen, IDDES_TEMPLBASE); diff --git a/src/display.cpp b/src/display.cpp index bdd4a6136..c5777e6f8 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -1806,7 +1806,7 @@ static void dealWithLMBStructure(STRUCTURE* psStructure, SELECTION_TYPE selectio #ifdef DEBUG if (getDebugMappingStatus()) { - CONPRINTF(ConsoleString, (ConsoleString, "(Enemy!) %s, ref: %d, ID: %d Damage %d%%", psStructure->pStructureType->pName, psStructure->pStructureType->ref, + CONPRINTF(ConsoleString, (ConsoleString, "(Enemy!) %s, ref: %d, ID: %d Damage %d%%", getID(psStructure->pStructureType), psStructure->pStructureType->ref, psStructure->id, 100 - clip(PERCENT(psStructure->body, psStructure->pStructureType->upgrade[psStructure->player].hitpoints), 0, 100))); } #endif @@ -1976,7 +1976,7 @@ static void dealWithLMBFeature(FEATURE* psFeature) #ifdef DEBUG if (getDebugMappingStatus()) { - CONPRINTF(ConsoleString, (ConsoleString, "(Feature) %s, ID: %d, ref: %d, body: (%d):%d", psFeature->psStats->pName, psFeature->id, psFeature->psStats->ref, psFeature->psStats->body, psFeature->body )); + CONPRINTF(ConsoleString, (ConsoleString, "(Feature) %s, ID: %d, ref: %d, body: (%d):%d", getID(psFeature->psStats), psFeature->id, psFeature->psStats->ref, psFeature->psStats->body, psFeature->body )); } #endif driveDisableTactical(); diff --git a/src/droid.cpp b/src/droid.cpp index 6a434417e..bdfcacf64 100644 --- a/src/droid.cpp +++ b/src/droid.cpp @@ -333,6 +333,8 @@ DROID::DROID(uint32_t id, unsigned player) , actionPos(0, 0) , psCurAnim(NULL) { + memset(aName, 0, sizeof(aName)); + memset(asBits, 0, sizeof(asBits)); pos = Vector3i(0, 0, 0); rot = Vector3i(0, 0, 0); order.type = DORDER_NONE; @@ -1668,7 +1670,7 @@ UDWORD calcTemplateBuild(DROID_TEMPLATE *psTemplate) // FIX ME: ASSERT( psTemplate->asWeaps[i]pName ); - "Invalid Template weapon for %s", getTemplateName(psTemplate) ); + "Invalid Template weapon for %s", getName(psTemplate) ); build += (asWeaponStats + psTemplate->asWeaps[i])->buildPoints; } @@ -1766,7 +1768,7 @@ DROID *reallyBuildDroid(DROID_TEMPLATE *pTemplate, Position pos, UDWORD player, ASSERT(!bMultiPlayer || worldOnMap(pos.x, pos.y), "the build locations are not on the map"); psDroid = new DROID(generateSynchronisedObjectId(), player); - droidSetName(psDroid, pTemplate->aName); + droidSetName(psDroid, getName(pTemplate)); // Set the droids type psDroid->droidType = droidTemplateType(pTemplate); // Is set again later to the same thing, in droidSetBits. @@ -3232,7 +3234,7 @@ DROID *giftSingleDroid(DROID *psD, UDWORD to) return NULL; } templateSetParts(psD, &sTemplate); // create a template based on the droid - sstrcpy(sTemplate.aName, psD->aName); // copy the name across + sTemplate.name = psD->aName; // copy the name across // only play the nexus sound if unit being taken over is selectedPlayer's but not going to the selectedPlayer if (psD->player == selectedPlayer && to != selectedPlayer && !bMultiPlayer) { diff --git a/src/droiddef.h b/src/droiddef.h index feaf0790c..7d6682c78 100644 --- a/src/droiddef.h +++ b/src/droiddef.h @@ -60,9 +60,6 @@ struct DROID_TEMPLATE : public BASE_STATS { DROID_TEMPLATE(); - /// this contains the full editable UTF-8 encoded name of the template - char aName[MAX_STR_LENGTH]; - /*! * The droid components. * diff --git a/src/feature.cpp b/src/feature.cpp index 3189d0826..bc2ea32c8 100644 --- a/src/feature.cpp +++ b/src/feature.cpp @@ -80,8 +80,10 @@ bool loadFeatureStats(const char *pFileName) for (int i = 0; i < list.size(); ++i) { ini.beginGroup(list[i]); - asFeatureStats[i] = FEATURE_STATS(REF_FEATURE_START + i, list[i].toUtf8().constData()); + asFeatureStats[i] = FEATURE_STATS(REF_FEATURE_START + i); FEATURE_STATS *p = &asFeatureStats[i]; + p->name = ini.value("name").toString(); + p->id = list[i]; QString subType = ini.value("type").toString(); if (subType == "TANK WRECK") p->subType = FEAT_TANK; else if (subType == "GENERIC ARTEFACT") p->subType = FEAT_GEN_ARTE; @@ -117,10 +119,6 @@ bool loadFeatureStats(const char *pFileName) /* Release the feature stats memory */ void featureStatsShutDown(void) { - for (unsigned i = 0; i < numFeatureStats; ++i) - { - free(asFeatureStats[i].pName); - } delete[] asFeatureStats; asFeatureStats = NULL; numFeatureStats = 0; @@ -239,8 +237,8 @@ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,bool FromSave) MAPTILE *psTile = mapTile(b.map.x + width, b.map.y + breadth); //check not outside of map - for load save game - ASSERT_OR_RETURN(NULL, b.map.x + width < mapWidth, "x coord bigger than map width - %s, id = %d", getName(psFeature->psStats->pName), psFeature->id); - ASSERT_OR_RETURN(NULL, b.map.y + breadth < mapHeight, "y coord bigger than map height - %s, id = %d", getName(psFeature->psStats->pName), psFeature->id); + ASSERT_OR_RETURN(NULL, b.map.x + width < mapWidth, "x coord bigger than map width - %s, id = %d", getName(psFeature->psStats), psFeature->id); + ASSERT_OR_RETURN(NULL, b.map.y + breadth < mapHeight, "y coord bigger than map height - %s, id = %d", getName(psFeature->psStats), psFeature->id); if (width != psStats->baseWidth && breadth != psStats->baseBreadth) { @@ -249,8 +247,8 @@ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,bool FromSave) FEATURE *psBlock = (FEATURE *)psTile->psObject; debug(LOG_ERROR, "%s(%d) already placed at (%d+%d, %d+%d) when trying to place %s(%d) at (%d+%d, %d+%d) - removing it", - getName(psBlock->psStats->pName), psBlock->id, map_coord(psBlock->pos.x), psBlock->psStats->baseWidth, map_coord(psBlock->pos.y), - psBlock->psStats->baseBreadth, getName(psFeature->psStats->pName), psFeature->id, b.map.x, b.size.x, b.map.y, b.size.y); + getName(psBlock->psStats), psBlock->id, map_coord(psBlock->pos.x), psBlock->psStats->baseWidth, map_coord(psBlock->pos.y), + psBlock->psStats->baseBreadth, getName(psFeature->psStats), psFeature->id, b.map.x, b.size.x, b.map.y, b.size.y); removeFeature(psBlock); } @@ -490,15 +488,14 @@ bool destroyFeature(FEATURE *psDel, unsigned impactTime) } -SDWORD getFeatureStatFromName( const char *pName ) +SDWORD getFeatureStatFromName(const char *pName) { - unsigned int inc; FEATURE_STATS *psStat; - for (inc = 0; inc < numFeatureStats; inc++) + for (int inc = 0; inc < numFeatureStats; inc++) { psStat = &asFeatureStats[inc]; - if (!strcmp(psStat->pName, pName)) + if (psStat->id.compare(pName) == 0) { return inc; } diff --git a/src/featuredef.h b/src/featuredef.h index a4df421ee..e6cda1533 100644 --- a/src/featuredef.h +++ b/src/featuredef.h @@ -45,8 +45,7 @@ enum FEATURE_TYPE /* Stats for a feature */ struct FEATURE_STATS : public BASE_STATS { - FEATURE_STATS() {} - FEATURE_STATS(int idx, const char *s) : BASE_STATS(idx, s) {} + FEATURE_STATS(int idx = 0) : BASE_STATS(idx) {} FEATURE_TYPE subType; ///< type of feature diff --git a/src/frontend.cpp b/src/frontend.cpp index 57c1bbc2f..039926a86 100644 --- a/src/frontend.cpp +++ b/src/frontend.cpp @@ -1826,7 +1826,6 @@ void addSmallTextButton(UDWORD id, UDWORD PosX, UDWORD PosY, const char *txt, u { W_BUTINIT sButInit; - memset(&sButInit, 0, sizeof(W_BUTINIT)); sButInit.formID = FRONTEND_BOTFORM; sButInit.id = id; sButInit.x = (short)PosX; diff --git a/src/game.cpp b/src/game.cpp index f0d2affe9..6e946a83a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1608,7 +1608,7 @@ static void setIniStructureStats(WzConfig &ini, QString const &key, STRUCTURE_ST { if (stats != NULL) { - ini.setValue(key, stats->pName); + ini.setValue(key, stats->id); } } @@ -1964,10 +1964,6 @@ bool loadGame(const char *pGameToLoad, bool keepObjects, bool freeMem, bool User } } } - for (std::list::iterator i = localTemplates.begin(); i != localTemplates.end(); ++i) - { - free(i->pName); - } localTemplates.clear(); //load in the templates @@ -4248,21 +4244,20 @@ static bool loadSaveDroid(const char *pFileName, DROID **ppsCurrentDroidLists) else { // Create fake template - psTemplate->pName = NULL; - sstrcpy(templ.aName, ini.value("name", "UNKNOWN").toString().toUtf8().constData()); + templ.name = ini.value("name", "UNKNOWN").toString(); psTemplate->droidType = (DROID_TYPE)ini.value("droidType").toInt(); psTemplate->numWeaps = ini.value("weapons", 0).toInt(); ini.beginGroup("parts"); // the following is copy-pasted from loadSaveTemplate() -- fixme somehow - psTemplate->asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", QString("ZNULLBODY")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", QString("ZNULLBRAIN")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", QString("ZNULLPROP")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", QString("ZNULLREPAIR")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", QString("ZNULLECM")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", QString("ZNULLSENSOR")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", QString("ZNULLCONSTRUCT")).toString().toUtf8().constData()); - psTemplate->asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", QString("ZNULLWEAPON")).toString().toUtf8().constData()); - psTemplate->asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", QString("ZNULLWEAPON")).toString().toUtf8().constData()); - psTemplate->asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", QString("ZNULLWEAPON")).toString().toUtf8().constData()); + psTemplate->asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", "ZNULLBODY").toString()); + psTemplate->asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", "ZNULLBRAIN").toString()); + psTemplate->asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", "ZNULLPROP").toString()); + psTemplate->asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", "ZNULLREPAIR").toString()); + psTemplate->asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", "ZNULLECM").toString()); + psTemplate->asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", "ZNULLSENSOR").toString()); + psTemplate->asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", "ZNULLCONSTRUCT").toString()); + psTemplate->asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", "ZNULLWEAPON").toString()); + psTemplate->asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", "ZNULLWEAPON").toString()); + psTemplate->asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", "ZNULLWEAPON").toString()); ini.endGroup(); } @@ -4483,16 +4478,16 @@ static bool writeDroid(WzConfig &ini, DROID *psCurr, bool onMission, int &counte if (psCurr->periodicalDamage > 0) ini.setValue("periodicalDamage", psCurr->periodicalDamage); ini.setValue("droidType", psCurr->droidType); ini.setValue("weapons", psCurr->numWeaps); - ini.setValue("parts/body", (asBodyStats + psCurr->asBits[COMP_BODY])->pName); - ini.setValue("parts/propulsion", (asPropulsionStats + psCurr->asBits[COMP_PROPULSION])->pName); - ini.setValue("parts/brain", (asBrainStats + psCurr->asBits[COMP_BRAIN])->pName); - ini.setValue("parts/repair", (asRepairStats + psCurr->asBits[COMP_REPAIRUNIT])->pName); - ini.setValue("parts/ecm", (asECMStats + psCurr->asBits[COMP_ECM])->pName); - ini.setValue("parts/sensor", (asSensorStats + psCurr->asBits[COMP_SENSOR])->pName); - ini.setValue("parts/construct", (asConstructStats + psCurr->asBits[COMP_CONSTRUCT])->pName); + ini.setValue("parts/body", (asBodyStats + psCurr->asBits[COMP_BODY])->id); + ini.setValue("parts/propulsion", (asPropulsionStats + psCurr->asBits[COMP_PROPULSION])->id); + ini.setValue("parts/brain", (asBrainStats + psCurr->asBits[COMP_BRAIN])->id); + ini.setValue("parts/repair", (asRepairStats + psCurr->asBits[COMP_REPAIRUNIT])->id); + ini.setValue("parts/ecm", (asECMStats + psCurr->asBits[COMP_ECM])->id); + ini.setValue("parts/sensor", (asSensorStats + psCurr->asBits[COMP_SENSOR])->id); + ini.setValue("parts/construct", (asConstructStats + psCurr->asBits[COMP_CONSTRUCT])->id); for (int j = 0; j < psCurr->numWeaps; j++) { - ini.setValue("parts/weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j].nStat)->pName); + ini.setValue("parts/weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j].nStat)->id); } ini.setValue("moveStatus", psCurr->sMove.Status); ini.setValue("pathIndex", psCurr->sMove.pathIndex); @@ -4642,7 +4637,7 @@ bool loadSaveStructure(char *pFileData, UDWORD filesize) psStats = asStructureStats + statInc; //loop until find the same name - if (!strcmp(psStats->pName, psSaveStructure->name)) + if (psStats->id.compare(psSaveStructure->name) == 0) { found = true; break; @@ -4721,7 +4716,7 @@ static UDWORD getResearchIdFromName(const char *pName) { for (int inc = 0; inc < asResearch.size(); inc++) { - if (!strcmp(asResearch[inc].pName, pName)) + if (asResearch[inc].id.compare(pName) == 0) { return inc; } @@ -4767,7 +4762,7 @@ static bool loadSaveStructure2(const char *pFileName, STRUCTURE **ppList) { psStats = asStructureStats + statInc; //loop until find the same name - if (name.compare(psStats->pName) == 0) + if (name.compare(psStats->id) == 0) { found = true; break; @@ -5046,7 +5041,7 @@ bool writeStructFile(const char *pFileName) ini.beginGroup("structure_" + QString("%1").arg(counter++, 10, 10, QLatin1Char('0'))); // Zero padded so that alphabetical sort works. ini.setValue("id", psCurr->id); setPlayer(ini, psCurr->player); - ini.setValue("name", psCurr->pStructureType->pName); + ini.setValue("name", psCurr->pStructureType->id); ini.setVector3i("position", psCurr->pos); ini.setVector3i("rotation", psCurr->rot); ini.setValue("health", psCurr->body); @@ -5065,7 +5060,7 @@ bool writeStructFile(const char *pFileName) ini.setValue("weapons", psCurr->numWeaps); for (int j = 0; j < psCurr->numWeaps; j++) { - ini.setValue("parts/weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j].nStat)->pName); + ini.setValue("parts/weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j].nStat)->id); if (psCurr->asWeaps[j].nStat > 0) { ini.setValue("ammo/" + QString::number(j), psCurr->asWeaps[j].ammo); @@ -5136,7 +5131,7 @@ bool writeStructFile(const char *pFileName) ini.setValue("Research/timeStartHold", ((RESEARCH_FACILITY *)psCurr->pFunctionality)->timeStartHold); if (((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject) { - ini.setValue("Research/target", ((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject->pName); + ini.setValue("Research/target", ((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject->id); } } else if (psCurr->pStructureType->type == REF_POWER_GEN) @@ -5333,7 +5328,7 @@ bool loadSaveFeature(char *pFileData, UDWORD filesize) { psStats = asFeatureStats + statInc; //loop until find the same name - if (!strcmp(psStats->pName, psSaveFeature->name)) + if (psStats->id.compare(psSaveFeature->name) == 0) { found = true; break; @@ -5399,7 +5394,7 @@ bool loadSaveFeature2(const char *pFileName) { psStats = asFeatureStats + statInc; //loop until find the same name - if (!strcmp(psStats->pName, name.toUtf8().constData())) + if (psStats->id.compare(name) == 0) { found = true; break; @@ -5454,7 +5449,7 @@ bool writeFeatureFile(const char *pFileName) { ini.beginGroup("feature_" + QString("%1").arg(counter++, 10, 10, QLatin1Char('0'))); // Zero padded so that alphabetical sort works. ini.setValue("id", psCurr->id); - ini.setValue("name", psCurr->psStats->pName); + ini.setValue("name", psCurr->psStats->id); ini.setVector3i("position", psCurr->pos); ini.setVector3i("rotation", psCurr->rot); ini.setValue("periodicalDamage", psCurr->periodicalDamage); @@ -5483,21 +5478,20 @@ bool loadSaveTemplate(const char *pFileName) ini.beginGroup(list[i]); int player = getPlayer(ini); DROID_TEMPLATE *psTemplate = new DROID_TEMPLATE; - psTemplate->pName = NULL; - sstrcpy(psTemplate->aName, ini.value("name").toString().toUtf8().constData()); + psTemplate->name = ini.value("name").toString(); psTemplate->ref = ini.value("ref").toInt(); psTemplate->droidType = (DROID_TYPE)ini.value("droidType").toInt(); psTemplate->multiPlayerID = ini.value("multiPlayerID").toInt(); - psTemplate->asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", QString("ZNULLBODY")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", QString("ZNULLBRAIN")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", QString("ZNULLPROP")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", QString("ZNULLREPAIR")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", QString("ZNULLECM")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", QString("ZNULLSENSOR")).toString().toUtf8().constData()); - psTemplate->asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", QString("ZNULLCONSTRUCT")).toString().toUtf8().constData()); - psTemplate->asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", QString("ZNULLWEAPON")).toString().toUtf8().constData()); - psTemplate->asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", QString("ZNULLWEAPON")).toString().toUtf8().constData()); - psTemplate->asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", QString("ZNULLWEAPON")).toString().toUtf8().constData()); + psTemplate->asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", "ZNULLBODY").toString()); + psTemplate->asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", "ZNULLBRAIN").toString()); + psTemplate->asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", "ZNULLPROP").toString()); + psTemplate->asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", "ZNULLREPAIR").toString()); + psTemplate->asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", "ZNULLECM").toString()); + psTemplate->asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", "ZNULLSENSOR").toString()); + psTemplate->asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", "ZNULLCONSTRUCT").toString()); + psTemplate->asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", "ZNULLWEAPON").toString()); + psTemplate->asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", "ZNULLWEAPON").toString()); + psTemplate->asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", "ZNULLWEAPON").toString()); psTemplate->numWeaps = ini.value("weapons").toInt(); psTemplate->enabled = ini.value("enabled").toBool(); psTemplate->prefab = false; // not AI template @@ -5549,23 +5543,23 @@ bool writeTemplateFile(const char *pFileName) for (DROID_TEMPLATE *psCurr = apsDroidTemplates[player]; psCurr != NULL; psCurr = psCurr->psNext) { ini.beginGroup("template_" + QString::number(psCurr->multiPlayerID) + "_player" + QString::number(player)); - ini.setValue("name", psCurr->aName); + ini.setValue("name", psCurr->name); ini.setValue("ref", psCurr->ref); ini.setValue("droidType", psCurr->droidType); ini.setValue("multiPlayerID", psCurr->multiPlayerID); setPlayer(ini, player); - ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->pName); - ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->pName); - ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->pName); - ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->pName); - ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->pName); - ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->pName); - ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->pName); + ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->id); + ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->id); + ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->id); + ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->id); + ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->id); + ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->id); + ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->id); ini.setValue("weapons", psCurr->numWeaps); ini.setValue("enabled", psCurr->enabled); for (int j = 0; j < psCurr->numWeaps; j++) { - ini.setValue("weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j])->pName); + ini.setValue("weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j])->id); } ini.endGroup(); } @@ -5692,20 +5686,12 @@ bool loadSaveCompList(const char *pFileName) { QString name = list[i]; int state = ini.value(name, UNAVAILABLE).toInt(); - int type = -1; - int compInc = -1; - for (int j = 0; j < COMP_NUMCOMPONENTS && compInc == -1; j++) - { - // this is very inefficient, but I am so not giving in to the deranged nature of the components code - // and convoluting the new savegame format for its sake - compInc = getCompFromName(j, name.toUtf8().constData()); - type = j; - } - ASSERT(compInc >= 0, "Bad component %d", compInc); - ASSERT(type >= 0 && type != COMP_NUMCOMPONENTS, "Bad type %d", type); + COMPONENT_STATS *psComp = getCompStatsFromName(name); + ASSERT(psComp, "Bad component %s", name.toUtf8().constData()); + ASSERT(psComp->compType >= 0 && psComp->compType != COMP_NUMCOMPONENTS, "Bad type %d", psComp->compType); ASSERT_OR_RETURN(false, state == UNAVAILABLE || state == AVAILABLE || state == FOUND || state == REDUNDANT, "Bad state %d for %s", state, name.toUtf8().constData()); - apCompLists[player][type][compInc] = state; + apCompLists[player][psComp->compType][psComp->index] = state; } ini.endGroup(); } @@ -5726,49 +5712,49 @@ static bool writeCompListFile(const char *pFileName) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asBodyStats + i); const int state = apCompLists[player][COMP_BODY][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numWeaponStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asWeaponStats + i); const int state = apCompLists[player][COMP_WEAPON][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numConstructStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asConstructStats + i); const int state = apCompLists[player][COMP_CONSTRUCT][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numECMStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asECMStats + i); const int state = apCompLists[player][COMP_ECM][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numPropulsionStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asPropulsionStats + i); const int state = apCompLists[player][COMP_PROPULSION][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numSensorStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asSensorStats + i); const int state = apCompLists[player][COMP_SENSOR][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numRepairStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asRepairStats + i); const int state = apCompLists[player][COMP_REPAIRUNIT][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } for (int i = 0; i < numBrainStats; i++) { COMPONENT_STATS *psStats = (COMPONENT_STATS *)(asBrainStats + i); const int state = apCompLists[player][COMP_BRAIN][i]; - if (state != UNAVAILABLE) ini.setValue(psStats->pName, state); + if (state != UNAVAILABLE) ini.setValue(psStats->id, state); } ini.endGroup(); } @@ -5797,7 +5783,7 @@ static bool loadSaveStructTypeList(const char *pFileName) { STRUCTURE_STATS *psStats = asStructureStats + statInc; - if (name.compare(psStats->pName) == 0) + if (name.compare(psStats->id) == 0) { apStructTypeLists[player][statInc] = state; break; @@ -5823,7 +5809,7 @@ static bool writeStructTypeListFile(const char *pFileName) STRUCTURE_STATS *psStats = asStructureStats; for (int i = 0; i < numStructureStats; i++, psStats++) { - if (apStructTypeLists[player][i] != UNAVAILABLE) ini.setValue(psStats->pName, apStructTypeLists[player][i]); + if (apStructTypeLists[player][i] != UNAVAILABLE) ini.setValue(psStats->id, apStructTypeLists[player][i]); } ini.endGroup(); } @@ -5848,7 +5834,7 @@ bool loadSaveResearch(const char *pFileName) { RESEARCH *psStats = &asResearch[statInc]; //loop until find the same name - if (!strcmp(psStats->pName, name)) + if (psStats->id.compare(name) == 0) { found = true; @@ -5916,7 +5902,7 @@ static bool writeResearchFile(char *pFileName) if (valid) { ini.beginGroup("research_" + QString::number(i)); - ini.setValue("name", psStats->pName); + ini.setValue("name", psStats->id); ini.setValue("possible", possibles); ini.setValue("researched", researched); ini.setValue("currentPoints", points); @@ -6145,7 +6131,7 @@ bool loadSaveStructLimits(const char *pFileName) for (statInc = 0; statInc < numStructureStats; statInc++) { STRUCTURE_STATS *psStats = asStructureStats + statInc; - if (name.compare(psStats->pName) == 0) + if (name.compare(psStats->id) == 0) { asStructLimits[player][statInc].limit = limit != 255? limit : LOTS_OF; break; @@ -6174,7 +6160,7 @@ bool writeStructLimitsFile(const char *pFileName) for (int i = 0; i < numStructureStats; i++, psStats++) { const int limit = MIN(asStructLimits[player][i].limit, 255); - if (limit != 255) ini.setValue(psStats->pName, limit); + if (limit != 255) ini.setValue(psStats->id, limit); } ini.endGroup(); } diff --git a/src/hci.cpp b/src/hci.cpp index e48a90ca1..41a443ef7 100644 --- a/src/hci.cpp +++ b/src/hci.cpp @@ -1476,7 +1476,7 @@ INT_RETVAL intRunWidgets(void) // the fact that we're cheating ourselves a new // structure. sasprintf((char **)&msg, _("Player %u is cheating (debug menu) him/herself a new structure: %s."), - selectedPlayer, psStructure->pStructureType->pName); + selectedPlayer, getName(psStructure->pStructureType)); sendTextMessage(msg, true); Cheated = true; } @@ -1487,7 +1487,7 @@ INT_RETVAL intRunWidgets(void) // Send a text message to all players, notifying them of the fact that we're cheating ourselves a new feature. sasprintf((char **)&msg, _("Player %u is cheating (debug menu) him/herself a new feature: %s."), - selectedPlayer, psPositionStats->pName); + selectedPlayer, getName(psPositionStats)); sendTextMessage(msg, true); Cheated = true; // Notify the other hosts that we've just built ourselves a feature @@ -3092,8 +3092,6 @@ static bool intAddObjectWindow(BASE_OBJECT *psObjects, BASE_OBJECT *psSelected, sBarInit2.x = STAT_POWERBARX; sBarInit2.y = STAT_POWERBARY; sBarInit2.size = 50; - // don't set the tip cos we haven't got a suitable text string at this point - 2/2/99 - sBarInit2.pTip = NULL; W_LABINIT sLabInit; sLabInit.id = IDOBJ_COUNTSTART; @@ -3221,11 +3219,11 @@ static bool intAddObjectWindow(BASE_OBJECT *psObjects, BASE_OBJECT *psSelected, default: ASSERT(false, "intAddObject: invalid structure type"); } - objButton->setTip(getName(((STRUCTURE *)psObj)->pStructureType->pName)); + objButton->setTip(getName(((STRUCTURE *)psObj)->pStructureType)); break; case OBJ_FEATURE: - objButton->setTip(getName(((FEATURE *)psObj)->psStats->pName)); + objButton->setTip(getName(((FEATURE *)psObj)->psStats)); break; default: @@ -3306,17 +3304,7 @@ static bool intAddObjectWindow(BASE_OBJECT *psObjects, BASE_OBJECT *psSelected, if (psStats != NULL) { - // If it's a droid the name might not be a stringID - if (psStats->ref >= REF_TEMPLATE_START && - psStats->ref < REF_TEMPLATE_START + REF_RANGE) - { - statButton->setTip(getTemplateName((DROID_TEMPLATE *)psStats)); - } - else - { - statButton->setTip(getName(psStats->pName)); - } - + statButton->setTip(getName(psStats)); statButton->setObjectAndStats(psObj, psStats); } else if ((psObj->type == OBJ_DROID) && (((DROID *)psObj)->droidType == DROID_COMMAND)) @@ -3606,17 +3594,7 @@ static void intSetStats(UDWORD id, BASE_STATS *psStats) if (psStats) { - // If it's a droid the name might not be a stringID - if (psStats->ref >= REF_TEMPLATE_START && - psStats->ref < REF_TEMPLATE_START + REF_RANGE) - { - statButton->setTip(getTemplateName((DROID_TEMPLATE *)psStats)); - } - else - { - statButton->setTip(getName(psStats->pName)); - } - + statButton->setTip(getName(psStats)); statButton->setObjectAndStats(intGetObject(id), psStats); // Add a text label for the size of the production run. @@ -3823,18 +3801,7 @@ static bool intAddStats(BASE_STATS **ppsStatsList, UDWORD numStats, statList->addWidgetToLayout(button); BASE_STATS *Stat = ppsStatsList[i]; - // If it's a droid the name might not be a stringID - QString tipString; - if (Stat->ref >= REF_TEMPLATE_START && - Stat->ref < REF_TEMPLATE_START + REF_RANGE) - { - tipString = QString::fromUtf8(getTemplateName((DROID_TEMPLATE *)ppsStatsList[i])); - } - else - { - tipString = QString::fromUtf8(getName(ppsStatsList[i]->pName)); - } - + QString tipString = ppsStatsList[i]->name; unsigned powerCost = 0; W_BARGRAPH *bar; if (Stat->ref >= REF_STRUCTURE_START && diff --git a/src/intdisplay.cpp b/src/intdisplay.cpp index 342ff3ce9..2c4ac76b5 100644 --- a/src/intdisplay.cpp +++ b/src/intdisplay.cpp @@ -1606,12 +1606,12 @@ void IntFancyButton::displayIMD(Image image, ImdObject imdObject, int xOffset, i Radius = getComponentRadius((BASE_STATS *)Object); scale = rescaleButtonObject(Radius, COMP_BUT_SCALE, COMPONENT_RADIUS); // NOTE: The Super transport is huge, and is considered a component type, so refit it to inside the button. - const char *const name = ((BASE_STATS *)Object)->pName; - if (!strcmp(name, "SuperTransportBody")) + BASE_STATS *psStats = (BASE_STATS *)Object; + if (psStats->id.compare("SuperTransportBody") == 0) { scale *= .4; } - else if (!strcmp(name, "TransporterBody")) + else if (psStats->id.compare("TransporterBody") == 0) { scale *= .6; } diff --git a/src/intdisplay.h b/src/intdisplay.h index fc94bd516..31c8185ed 100644 --- a/src/intdisplay.h +++ b/src/intdisplay.h @@ -149,7 +149,7 @@ public: void setStats(BASE_STATS *stats) { Stat = stats; } void setStatsAndTip(BASE_STATS *stats) { setStats(stats); setTip(getStatName(Stat)); } - void setStatsAndTip(DROID_TEMPLATE *stats) { setStats(stats); setTip(getTemplateName(stats)); } + void setStatsAndTip(DROID_TEMPLATE *stats) { setStats(stats); setTip(getName(stats)); } protected: BASE_STATS *Stat; diff --git a/src/keybind.cpp b/src/keybind.cpp index 26e6cc572..9aa6d1f21 100644 --- a/src/keybind.cpp +++ b/src/keybind.cpp @@ -387,7 +387,7 @@ void kf_CloneSelected( void ) { for (DROID_TEMPLATE *psTempl = apsDroidTemplates[selectedPlayer]; psTempl; psTempl = psTempl->psNext) { - if (!strcmp(psTempl->aName, psDroid->aName)) + if (psTempl->name.compare(psDroid->aName) == 0) { sTemplate = psTempl; break; @@ -415,7 +415,7 @@ void kf_CloneSelected( void ) } else { - debug(LOG_ERROR, "Cloning has failed for template:%s id:%d", sTemplate->pName, sTemplate->multiPlayerID); + debug(LOG_ERROR, "Cloning has failed for template:%s id:%d", getID(sTemplate), sTemplate->multiPlayerID); } } sasprintf((char**)&msg, _("Player %u is cheating a new droid army of: %s."), selectedPlayer, psDroid->aName); @@ -1541,7 +1541,7 @@ void kf_FinishResearch( void ) { researchResult(rindex, selectedPlayer, true, psCurr, true); } - sasprintf((char**)&cmsg, _("(Player %u) is using cheat :%s %s"), selectedPlayer, _("Researched"), getName(pSubject->pName)); + sasprintf((char**)&cmsg, _("(Player %u) is using cheat :%s %s"), selectedPlayer, _("Researched"), getName(pSubject)); sendTextMessage(cmsg, true); intResearchFinished(psCurr); } diff --git a/src/main.cpp b/src/main.cpp index d35262306..47607be5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -762,13 +762,6 @@ static void startGameLoop(void) debug( LOG_FATAL, "Shutting down after failure" ); exit(EXIT_FAILURE); } - //after data is loaded check the research stats are valid - if (!checkResearchStats()) - { - debug( LOG_FATAL, "Invalid Research Stats" ); - debug( LOG_FATAL, "Shutting down after failure" ); - exit(EXIT_FAILURE); - } screen_StopBackDrop(); diff --git a/src/mapdisplay.cpp b/src/mapdisplay.cpp index a72ecd36a..0cd0b01b6 100644 --- a/src/mapdisplay.cpp +++ b/src/mapdisplay.cpp @@ -110,12 +110,11 @@ void renderResearchToBuffer(RESEARCH *psResearch, UDWORD OriginX, UDWORD OriginY IMDType = IMDTYPE_COMPONENT; psResGraphic = psResearch->psStat; // FIXME: Another kludge to deal with the superTransport to make it "fit" the display. - // Using pName, should be safe to compare, pName doesn't get translated. - if (!strcmp("R-SuperTransport", psResearch->pName)) + if (psResearch->id.compare("R-SuperTransport") == 0) { scale = RESEARCH_COMPONENT_SCALE / 3; } - else if (!strcmp("R-Cyborg-Transport", psResearch->pName)) + else if (psResearch->id.compare("R-Cyborg-Transport") == 0) { scale = RESEARCH_COMPONENT_SCALE / 2; } diff --git a/src/mission.cpp b/src/mission.cpp index 8c447f411..3139212e1 100644 --- a/src/mission.cpp +++ b/src/mission.cpp @@ -2299,7 +2299,6 @@ static bool _intAddMissionResult(bool result, bool bPlaySuccess) sButInit.style = WBUT_TXTCENTRE; sButInit.width = MISSION_TEXT_W; sButInit.height = MISSION_TEXT_H; - sButInit.pTip = NULL; sButInit.pDisplay = displayTextOption; // If won or in debug mode if (result || getDebugMappingStatus() || bMultiPlayer) diff --git a/src/multibot.cpp b/src/multibot.cpp index 687c880ee..339fac22a 100644 --- a/src/multibot.cpp +++ b/src/multibot.cpp @@ -283,14 +283,7 @@ bool SendDroid(DROID_TEMPLATE* pTemplate, uint32_t x, uint32_t y, uint8_t player NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); - if (pTemplate->pName) - { - NETstring(pTemplate->pName, strlen(pTemplate->pName) + 1); - } - else - { - NETstring(pTemplate->aName, strlen(pTemplate->aName) + 1); - } + NETqstring(pTemplate->name); NETint32_t(&droidType); NETuint8_t(&pTemplate->asParts[COMP_BODY]); NETuint8_t(&pTemplate->asParts[COMP_BRAIN]); @@ -337,8 +330,8 @@ bool recvDroid(NETQUEUE queue) NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); - NETstring(pT->aName, sizeof(pT->aName)); - pT->pName = pT->aName; + NETqstring(pT->name); + pT->id = pT->name; NETint32_t(&droidType); NETuint8_t(&pT->asParts[COMP_BODY]); NETuint8_t(&pT->asParts[COMP_BRAIN]); diff --git a/src/multigifts.cpp b/src/multigifts.cpp index 06facfa8c..f613e77c5 100644 --- a/src/multigifts.cpp +++ b/src/multigifts.cpp @@ -726,14 +726,14 @@ bool pickupArtefact(int toPlayer, int fromPlayer) MakeResearchPossible(&asPlayerResList[toPlayer][topic]); if (toPlayer == selectedPlayer) { - CONPRINTF(ConsoleString,(ConsoleString,_("You Discover Blueprints For %s"), getName(asResearch[topic].pName))); + CONPRINTF(ConsoleString,(ConsoleString,_("You Discover Blueprints For %s"), getName(&asResearch[topic]))); } break; } // Invalid topic else { - debug(LOG_WARNING, "%s is a invalid research topic?", getName(asResearch[topic].pName)); + debug(LOG_WARNING, "%s is a invalid research topic?", getName(&asResearch[topic])); } } } diff --git a/src/multiint.cpp b/src/multiint.cpp index 91a610924..9cb794fad 100644 --- a/src/multiint.cpp +++ b/src/multiint.cpp @@ -1718,7 +1718,6 @@ static void addDifficultyChooser(int player) sButInit.y = (MULTIOP_PLAYERHEIGHT + 5) * i + 4; sButInit.width = MULTIOP_PLAYERWIDTH + 1; sButInit.height = MULTIOP_PLAYERHEIGHT; - sButInit.pTip = NULL; switch (i) { case 0: sButInit.pTip = _("Starts disadvantaged"); break; @@ -2431,10 +2430,6 @@ void addPlayerBox(bool players) { sButInit.pTip = _("Teams locked"); } - else - { - sButInit.pTip = NULL; - } sButInit.pDisplay = displayTeamChooser; sButInit.UserData = i; @@ -2461,10 +2456,6 @@ void addPlayerBox(bool players) { sColInit.pTip = _("Click to change player colour"); } - else - { - sColInit.pTip = NULL; - } sColInit.pDisplay = displayColour; sColInit.UserData = i; widgAddButton(psWScreen, &sColInit); @@ -2484,7 +2475,6 @@ void addPlayerBox(bool players) sButInit.y = playerBoxHeight(i); sButInit.width = MULTIOP_PLAYERWIDTH - MULTIOP_TEAMSWIDTH - MULTIOP_READY_WIDTH - MULTIOP_COLOUR_WIDTH; sButInit.height = MULTIOP_PLAYERHEIGHT; - sButInit.pTip = NULL; if ((selectedPlayer == i || NetPlay.isHost) && NetPlay.players[i].allocated && !locked.position) { sButInit.pTip = _("Click to change player position"); diff --git a/src/multilimit.cpp b/src/multilimit.cpp index 10b92be93..6323f2c2d 100644 --- a/src/multilimit.cpp +++ b/src/multilimit.cpp @@ -379,7 +379,7 @@ static void displayStructureBar(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset // draw name iV_SetFont(font_regular); // font iV_SetTextColour(WZCOL_TEXT_BRIGHT); - iV_DrawText(_(getName(stat->pName)), x + 80, y + psWidget->height()/2 + 3); + iV_DrawText(_(getName(stat)), x + 80, y + psWidget->height()/2 + 3); // draw limit ssprintf(str, "%d", ((W_SLIDER *)widgGetFromID(psWScreen, psWidget->id + 1))->pos); diff --git a/src/multiopt.cpp b/src/multiopt.cpp index a558edb8f..9a10d7a36 100644 --- a/src/multiopt.cpp +++ b/src/multiopt.cpp @@ -314,12 +314,6 @@ bool multiShutdown(void) bool addTemplateToList(DROID_TEMPLATE *psNew, DROID_TEMPLATE **ppList) { DROID_TEMPLATE *psTempl = new DROID_TEMPLATE(*psNew); - psTempl->pName = NULL; - - if (psNew->pName) - { - psTempl->pName = strdup(psNew->pName); - } psTempl->psNext = *ppList; *ppList = psTempl; diff --git a/src/multiplay.cpp b/src/multiplay.cpp index 6371938c2..857d01b0c 100644 --- a/src/multiplay.cpp +++ b/src/multiplay.cpp @@ -1014,7 +1014,7 @@ bool recvResearchStatus(NETQUEUE queue) if (!researchAvailable(index, player, ModeImmediate) && bMultiPlayer) { - debug(LOG_ERROR, "Player %d researching impossible topic \"%s\".", player, asResearch[index].pName); + debug(LOG_ERROR, "Player %d researching impossible topic \"%s\".", player, getName(&asResearch[index])); return false; } @@ -1420,7 +1420,7 @@ bool recvTextMessageAI(NETQUEUE queue) static void NETtemplate(DROID_TEMPLATE *pTempl) { - NETstring(pTempl->aName, sizeof(pTempl->aName)); + NETqstring(pTempl->name); for (unsigned i = 0; i < ARRAY_SIZE(pTempl->asParts); ++i) { @@ -1468,7 +1468,6 @@ bool recvTemplate(NETQUEUE queue) t.prefab = false; t.psNext = NULL; - t.pName = NULL; t.ref = REF_TEMPLATE_START; psTempl = IdToTemplate(t.multiPlayerID,player); @@ -1598,7 +1597,7 @@ bool recvDestroyFeature(NETQUEUE queue) return false; } - debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, pF->psStats->pName); + debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, getName(pF->psStats)); // Remove the feature locally turnOffMultiMsg(true); destroyFeature(pF, gameTime - deltaGameTime + 1); // deltaGameTime is actually 0 here, since we're between updates. However, the value of gameTime - deltaGameTime + 1 will not change when we start the next tick. diff --git a/src/objects.cpp b/src/objects.cpp index ee9690976..383b361fd 100644 --- a/src/objects.cpp +++ b/src/objects.cpp @@ -77,20 +77,19 @@ const char *objInfo(const BASE_OBJECT *psObj) case OBJ_DROID: { const DROID *psDroid = (const DROID *)psObj; - return droidGetName(psDroid); } case OBJ_STRUCTURE: { const STRUCTURE *psStruct = (const STRUCTURE *)psObj; - - return getName(psStruct->pStructureType->pName); + sstrcpy(info, getName(psStruct->pStructureType)); + break; } case OBJ_FEATURE: { const FEATURE *psFeat = (const FEATURE *)psObj; - - return getName(psFeat->psStats->pName); + sstrcpy(info, getName(psFeat->psStats)); + break; } case OBJ_PROJECTILE: sstrcpy(info, "Projectile"); // TODO diff --git a/src/order.cpp b/src/order.cpp index 523732c12..cf583ac6a 100644 --- a/src/order.cpp +++ b/src/order.cpp @@ -1496,7 +1496,7 @@ void orderDroidBase(DROID *psDroid, DROID_ORDER_DATA *psOrder) psDroid->order = *psOrder; ASSERT(!psDroid->order.psStats || psDroid->order.psStats->type != REF_DEMOLISH, "Cannot build demolition"); actionDroid(psDroid, DACTION_BUILD, psOrder->pos.x, psOrder->pos.y); - objTrace(psDroid->id, "Starting new construction effort of %s", psOrder->psStats ? psOrder->psStats->pName : "NULL POINTER"); + objTrace(psDroid->id, "Starting new construction effort of %s", psOrder->psStats ? getName(psOrder->psStats) : "NULL"); break; case DORDER_BUILDMODULE: //build a module onto the structure @@ -1508,7 +1508,7 @@ void orderDroidBase(DROID *psDroid, DROID_ORDER_DATA *psOrder) ASSERT(psDroid->order.psStats != NULL, "should have found a module stats"); ASSERT(!psDroid->order.psStats || psDroid->order.psStats->type != REF_DEMOLISH, "Cannot build demolition"); actionDroid(psDroid, DACTION_BUILD, psOrder->psObj->pos.x,psOrder->psObj->pos.y); - objTrace(psDroid->id, "Starting new upgrade of %s", psOrder->psStats ? psOrder->psStats->pName : "NULL POINTER"); + objTrace(psDroid->id, "Starting new upgrade of %s", psOrder->psStats ? getName(psOrder->psStats) : "NULL"); break; case DORDER_HELPBUILD: // help to build a structure that is starting to be built @@ -1519,7 +1519,7 @@ void orderDroidBase(DROID *psDroid, DROID_ORDER_DATA *psOrder) psDroid->order.psStats = ((STRUCTURE *)psOrder->psObj)->pStructureType; ASSERT(!psDroid->order.psStats || psDroid->order.psStats->type != REF_DEMOLISH, "Cannot build demolition"); actionDroid(psDroid, DACTION_BUILD, psDroid->order.pos.x, psDroid->order.pos.y); - objTrace(psDroid->id, "Helping construction of %s", psDroid->order.psStats ? psDroid->order.psStats->pName : "NULL POINTER"); + objTrace(psDroid->id, "Helping construction of %s", psOrder->psStats ? getName(psDroid->order.psStats) : "NULL"); break; case DORDER_DEMOLISH: if (!(psDroid->droidType == DROID_CONSTRUCT || psDroid->droidType == DROID_CYBORG_CONSTRUCT)) diff --git a/src/qtscriptfuncs.cpp b/src/qtscriptfuncs.cpp index b714c7662..cf3f4f1c0 100644 --- a/src/qtscriptfuncs.cpp +++ b/src/qtscriptfuncs.cpp @@ -307,9 +307,9 @@ QScriptValue convResearch(RESEARCH *psResearch, QScriptEngine *engine, int playe } value.setProperty("started", started); // including whether an ally has started it value.setProperty("done", IsResearchCompleted(&asPlayerResList[player][psResearch->index])); - value.setProperty("fullname", getName(psResearch->pName)); // temporary - value.setProperty("name", psResearch->pName); // will be changed to contain fullname - value.setProperty("id", psResearch->pName); + value.setProperty("fullname", psResearch->name); // temporary + value.setProperty("name", psResearch->id); // will be changed to contain fullname + value.setProperty("id", psResearch->id); value.setProperty("type", SCRIPT_RESEARCH); QScriptValue results = engine->newArray(psResearch->resultStrings.size()); for (int i = 0; i < psResearch->resultStrings.size(); i++) @@ -404,7 +404,9 @@ QScriptValue convStructure(STRUCTURE *psStruct, QScriptEngine *engine) { QScriptValue weapon = engine->newObject(); const WEAPON_STATS *psStats = asWeaponStats + psStruct->asWeaps[j].nStat; - weapon.setProperty("name", psStats->pName, QScriptValue::ReadOnly); + weapon.setProperty("fullname", psStats->name, QScriptValue::ReadOnly); + weapon.setProperty("name", psStats->id, QScriptValue::ReadOnly); // will be changed to contain full name + weapon.setProperty("id", psStats->id, QScriptValue::ReadOnly); weapon.setProperty("lastFired", psStruct->asWeaps[j].lastFired, QScriptValue::ReadOnly); weaponlist.setProperty(j, weapon, QScriptValue::ReadOnly); } @@ -556,8 +558,8 @@ QScriptValue convDroid(DROID *psDroid, QScriptEngine *engine) value.setProperty("droidType", (int)type, QScriptValue::ReadOnly); value.setProperty("experience", (double)psDroid->experience / 65536.0, QScriptValue::ReadOnly); value.setProperty("health", 100.0 / (double)psDroid->originalBody * (double)psDroid->body, QScriptValue::ReadOnly); - value.setProperty("body", asBodyStats[psDroid->asBits[COMP_BODY]].pName, QScriptValue::ReadOnly); - value.setProperty("propulsion", asPropulsionStats[psDroid->asBits[COMP_PROPULSION]].pName, QScriptValue::ReadOnly); + value.setProperty("body", asBodyStats[psDroid->asBits[COMP_BODY]].id, QScriptValue::ReadOnly); + value.setProperty("propulsion", asPropulsionStats[psDroid->asBits[COMP_PROPULSION]].id, QScriptValue::ReadOnly); value.setProperty("armed", 0.0, QScriptValue::ReadOnly); // deprecated! QScriptValue weaponlist = engine->newArray(psDroid->numWeaps); for (int j = 0; j < psDroid->numWeaps; j++) @@ -565,7 +567,9 @@ QScriptValue convDroid(DROID *psDroid, QScriptEngine *engine) int armed = droidReloadBar(psDroid, &psDroid->asWeaps[j], j); QScriptValue weapon = engine->newObject(); const WEAPON_STATS *psStats = asWeaponStats + psDroid->asWeaps[j].nStat; - weapon.setProperty("name", psStats->pName, QScriptValue::ReadOnly); + weapon.setProperty("fullname", psStats->name, QScriptValue::ReadOnly); + weapon.setProperty("id", psStats->id, QScriptValue::ReadOnly); // will be changed to full name + weapon.setProperty("name", psStats->id, QScriptValue::ReadOnly); weapon.setProperty("lastFired", psDroid->asWeaps[j].lastFired, QScriptValue::ReadOnly); weapon.setProperty("armed", armed, QScriptValue::ReadOnly); weaponlist.setProperty(j, weapon, QScriptValue::ReadOnly); @@ -626,7 +630,7 @@ QScriptValue convObj(BASE_OBJECT *psObj, QScriptEngine *engine) //;; and subject to change. //;; The following properties are defined: //;; \begin{description} -//;; \item[id] The unique ID of this object. +//;; \item[id] The ID of this object. //;; \item[name] Name of the template. //;; \item[cost] The power cost of the template if put into production. //;; \item[droidType] The type of droid that would be created. @@ -642,23 +646,24 @@ QScriptValue convTemplate(DROID_TEMPLATE *psTempl, QScriptEngine *engine) { QScriptValue value = engine->newObject(); ASSERT_OR_RETURN(value, psTempl, "No object for conversion"); - value.setProperty("id", psTempl->multiPlayerID, QScriptValue::ReadOnly); - value.setProperty("name", psTempl->pName, QScriptValue::ReadOnly); + value.setProperty("fullname", psTempl->name, QScriptValue::ReadOnly); + value.setProperty("name", psTempl->id, QScriptValue::ReadOnly); + value.setProperty("id", psTempl->id, QScriptValue::ReadOnly); value.setProperty("points", calcTemplateBuild(psTempl), QScriptValue::ReadOnly); value.setProperty("power", calcTemplatePower(psTempl), QScriptValue::ReadOnly); // deprecated, use cost below value.setProperty("cost", calcTemplatePower(psTempl), QScriptValue::ReadOnly); value.setProperty("droidType", psTempl->droidType, QScriptValue::ReadOnly); - value.setProperty("body", (asBodyStats + psTempl->asParts[COMP_BODY])->pName, QScriptValue::ReadOnly); - value.setProperty("propulsion", (asPropulsionStats + psTempl->asParts[COMP_PROPULSION])->pName, QScriptValue::ReadOnly); - value.setProperty("brain", (asBrainStats + psTempl->asParts[COMP_BRAIN])->pName, QScriptValue::ReadOnly); - value.setProperty("repair", (asRepairStats + psTempl->asParts[COMP_REPAIRUNIT])->pName, QScriptValue::ReadOnly); - value.setProperty("ecm", (asECMStats + psTempl->asParts[COMP_ECM])->pName, QScriptValue::ReadOnly); - value.setProperty("sensor", (asSensorStats + psTempl->asParts[COMP_SENSOR])->pName, QScriptValue::ReadOnly); - value.setProperty("construct", (asConstructStats + psTempl->asParts[COMP_CONSTRUCT])->pName, QScriptValue::ReadOnly); + value.setProperty("body", (asBodyStats + psTempl->asParts[COMP_BODY])->id, QScriptValue::ReadOnly); + value.setProperty("propulsion", (asPropulsionStats + psTempl->asParts[COMP_PROPULSION])->id, QScriptValue::ReadOnly); + value.setProperty("brain", (asBrainStats + psTempl->asParts[COMP_BRAIN])->id, QScriptValue::ReadOnly); + value.setProperty("repair", (asRepairStats + psTempl->asParts[COMP_REPAIRUNIT])->id, QScriptValue::ReadOnly); + value.setProperty("ecm", (asECMStats + psTempl->asParts[COMP_ECM])->id, QScriptValue::ReadOnly); + value.setProperty("sensor", (asSensorStats + psTempl->asParts[COMP_SENSOR])->id, QScriptValue::ReadOnly); + value.setProperty("construct", (asConstructStats + psTempl->asParts[COMP_CONSTRUCT])->id, QScriptValue::ReadOnly); QScriptValue weaponlist = engine->newArray(psTempl->numWeaps); for (int j = 0; j < psTempl->numWeaps; j++) { - weaponlist.setProperty(j, QScriptValue((asWeaponStats + psTempl->asWeaps[j])->pName), QScriptValue::ReadOnly); + weaponlist.setProperty(j, QScriptValue((asWeaponStats + psTempl->asWeaps[j])->id), QScriptValue::ReadOnly); } value.setProperty("weapons", weaponlist); return value; @@ -857,7 +862,7 @@ bool writeLabels(const char *filename) static QScriptValue js_getWeaponInfo(QScriptContext *context, QScriptEngine *engine) { QString id = context->argument(0).toString(); - int idx = getCompFromName(COMP_WEAPON, id.toUtf8().constData()); + int idx = getCompFromName(COMP_WEAPON, id); SCRIPT_ASSERT(context, idx >= 0, "No such weapon: %s", id.toUtf8().constData()); WEAPON_STATS *psStats = asWeaponStats + idx; QScriptValue info = engine->newObject(); @@ -1213,7 +1218,7 @@ static QScriptValue js_findResearch(QScriptContext *context, QScriptEngine *engi { if (!(asPlayerResList[player][cur->index].ResearchStatus & RESEARCHED)) { - debug(LOG_SCRIPT, "Added research in %d's %s for %s", player, cur->pName, psTarget->pName); + debug(LOG_SCRIPT, "Added research in %d's %s for %s", player, getID(cur), getID(psTarget)); list.append(cur); } RESEARCH *prev = cur; @@ -1314,11 +1319,11 @@ static QScriptValue js_pursueResearch(QScriptContext *context, QScriptEngine *en sendResearchStatus(psStruct, cur->index, player, true); #if defined (DEBUG) char sTemp[128]; - sprintf(sTemp, "player:%d starts topic from script: %s", player, cur->pName); + sprintf(sTemp, "player:%d starts topic from script: %s", player, getID(cur)); NETlogEntry(sTemp, SYNC_FLAG, 0); #endif debug(LOG_SCRIPT, "Started research in %d's %s(%d) of %s", player, - objInfo(psStruct), psStruct->id, cur->pName); + objInfo(psStruct), psStruct->id, getName(cur)); return QScriptValue(true); } } @@ -1337,7 +1342,7 @@ static QScriptValue js_pursueResearch(QScriptContext *context, QScriptEngine *en { cur = reslist.takeFirst(); // retrieve options from the stack } - ASSERT_OR_RETURN(QScriptValue(false), ++iterations < asResearch.size()*100 || !cur, "Possible cyclic dependencies in prerequisites, possibly of research \"%s\".", cur->pName); + ASSERT_OR_RETURN(QScriptValue(false), ++iterations < asResearch.size()*100 || !cur, "Possible cyclic dependencies in prerequisites, possibly of research \"%s\".", getName(cur)); } debug(LOG_SCRIPT, "No research topic found for %s(%d)", objInfo(psStruct), psStruct->id); return QScriptValue(false); // none found @@ -1386,35 +1391,10 @@ static QScriptValue js_enumResearch(QScriptContext *context, QScriptEngine *engi static QScriptValue js_componentAvailable(QScriptContext *context, QScriptEngine *engine) { int player = engine->globalObject().property("me").toInt32(); - if (context->argumentCount() == 1) - { - QString id = context->argument(0).toString(); - int idx = -1; -#define CHECK_COMPONENT(_comp) \ - if ((idx = getCompFromName(_comp, id.toUtf8().constData())) >= 0) \ - { \ - return QScriptValue(apCompLists[player][_comp][idx] == AVAILABLE); \ - } - CHECK_COMPONENT(COMP_BODY); - CHECK_COMPONENT(COMP_BRAIN); - CHECK_COMPONENT(COMP_PROPULSION); - CHECK_COMPONENT(COMP_REPAIRUNIT); - CHECK_COMPONENT(COMP_ECM); - CHECK_COMPONENT(COMP_SENSOR); - CHECK_COMPONENT(COMP_CONSTRUCT); - CHECK_COMPONENT(COMP_WEAPON); -#undef CHECK_COMPONENT - SCRIPT_ASSERT(context, false, "No such component: %s", id.toUtf8().constData()); - return QScriptValue::NullValue; // to satisfy compiler - } - else - { - COMPONENT_TYPE comp = (COMPONENT_TYPE)(context->argument(0).toInt32() + 1); // backwards compat crap - QString compName = context->argument(1).toString(); - int result = getCompFromName(comp, compName.toUtf8().constData()); - SCRIPT_ASSERT(context, result >= 0, "No such component: %s", compName.toUtf8().constData()); - return QScriptValue(apCompLists[player][comp][result] == AVAILABLE); - } + QString id = (context->argumentCount() == 1) ? context->argument(0).toString() : context->argument(1).toString(); + COMPONENT_STATS *psComp = getCompStatsFromName(id); + SCRIPT_ASSERT(context, psComp, "No such component: %s", id.toUtf8().constData()); + return QScriptValue(apCompLists[player][psComp->compType][psComp->index] == AVAILABLE); } //-- \subsection{addFeature(name, x, y)} @@ -1445,7 +1425,7 @@ static int get_first_available_component(int player, int capacity, const QScript for (k = 0; k < length; k++) { QString compName = list.property(k).toString(); - int result = getCompFromName(type, compName.toUtf8().constData()); + int result = getCompFromName(type, compName); if (result >= 0 && (apCompLists[player][type][result] == AVAILABLE || !strict) && (type != COMP_BODY || asBodyStats[result].size <= capacity)) { @@ -1459,7 +1439,7 @@ static int get_first_available_component(int player, int capacity, const QScript } else if (list.isString()) { - int result = getCompFromName(type, list.toString().toUtf8().constData()); + int result = getCompFromName(type, list.toString()); if (result >= 0 && (apCompLists[player][type][result] == AVAILABLE || !strict) && (type != COMP_BODY || asBodyStats[result].size <= capacity)) { @@ -1473,7 +1453,7 @@ static int get_first_available_component(int player, int capacity, const QScript return -1; // no available component found in list } -static DROID_TEMPLATE *makeTemplate(int player, int x, int y, const QString &templName, QScriptContext *context, int paramstart, int capacity, bool strict) +static DROID_TEMPLATE *makeTemplate(int player, const QString &templName, QScriptContext *context, int paramstart, int capacity, bool strict) { const int firstTurret = paramstart + 4; // index position of first turret parameter DROID_TEMPLATE *psTemplate = new DROID_TEMPLATE; @@ -1517,12 +1497,19 @@ static DROID_TEMPLATE *makeTemplate(int player, int x, int y, const QString &tem { compName = context->argument(firstTurret).toString(); } - if ((result = getCompFromName(COMP_WEAPON, compName.toUtf8().constData())) >= 0) + COMPONENT_STATS *psComp = getCompStatsFromName(compName); + if (psComp == NULL) + { + debug(LOG_ERROR, "Wanted to build %s but %s does not exist", templName.toUtf8().constData(), compName.toUtf8().constData()); + delete psTemplate; + return NULL; + } + if (psComp->compType == COMP_WEAPON) { for (int i = 0; i < numTurrets; i++) // may be multi-weapon { result = get_first_available_component(player, SIZE_NUM, context->argument(firstTurret + i), COMP_WEAPON, strict); - if (result < 0) + if (result < -0) { debug(LOG_SCRIPT, "Wanted to build %s but no weapon available", templName.toUtf8().constData()); delete psTemplate; @@ -1534,43 +1521,18 @@ static DROID_TEMPLATE *makeTemplate(int player, int x, int y, const QString &tem } else { - COMPONENT_TYPE compType = COMP_NUMCOMPONENTS; - - if ((result = getCompFromName(COMP_CONSTRUCT, compName.toUtf8().constData())) >= 0) + if (psComp->compType == COMP_BRAIN) { - compType = COMP_CONSTRUCT; - } - else if ((result = getCompFromName(COMP_BRAIN, compName.toUtf8().constData())) >= 0) - { - compType = COMP_BRAIN; psTemplate->numWeaps = 1; // hack, necessary to pass intValidTemplate } - else if ((result = getCompFromName(COMP_REPAIRUNIT, compName.toUtf8().constData())) >= 0) - { - compType = COMP_REPAIRUNIT; - } - else if ((result = getCompFromName(COMP_ECM, compName.toUtf8().constData())) >= 0) - { - compType = COMP_ECM; - } - else if ((result = getCompFromName(COMP_SENSOR, compName.toUtf8().constData())) >= 0) - { - compType = COMP_SENSOR; - } - else - { - debug(LOG_ERROR, "No known component type found for %s", compName.toUtf8().constData()); - delete psTemplate; - return NULL; - } - result = get_first_available_component(player, SIZE_NUM, context->argument(firstTurret), compType, strict); + result = get_first_available_component(player, SIZE_NUM, context->argument(firstTurret), psComp->compType, strict); if (result < 0) { debug(LOG_SCRIPT, "Wanted to build %s but turret unavailable", templName.toUtf8().constData()); delete psTemplate; return NULL; } - psTemplate->asParts[compType] = result; + psTemplate->asParts[psComp->compType] = result; } bool valid = intValidTemplate(psTemplate, templName.toUtf8().constData(), true, player); if (valid) @@ -1597,7 +1559,7 @@ static QScriptValue js_addDroid(QScriptContext *context, QScriptEngine *engine) int x = context->argument(1).toInt32(); int y = context->argument(2).toInt32(); QString templName = context->argument(3).toString(); - DROID_TEMPLATE *psTemplate = makeTemplate(player, x, y, templName, context, 4, SIZE_NUM, false); + DROID_TEMPLATE *psTemplate = makeTemplate(player, templName, context, 4, SIZE_NUM, false); if (psTemplate) { bool oldMulti = bMultiMessages; @@ -1627,7 +1589,7 @@ static QScriptValue js_makeTemplate(QScriptContext *context, QScriptEngine *engi { int player = context->argument(0).toInt32(); QString templName = context->argument(1).toString(); - DROID_TEMPLATE *psTemplate = makeTemplate(player, -1, -1, templName, context, 2, SIZE_NUM, true); + DROID_TEMPLATE *psTemplate = makeTemplate(player, templName, context, 2, SIZE_NUM, true); if (!psTemplate) { return QScriptValue::NullValue; @@ -1655,33 +1617,33 @@ static QScriptValue js_buildDroid(QScriptContext *context, QScriptEngine *engine || psStruct->pStructureType->type == REF_VTOL_FACTORY), "Structure %s is not a factory", objInfo(psStruct)); QString templName = context->argument(1).toString(); const int capacity = psStruct->capacity; // body size limit - DROID_TEMPLATE *psTemplate = makeTemplate(player, psStruct->pos.x, psStruct->pos.y, templName, context, 2, capacity, true); + DROID_TEMPLATE *psTemplate = makeTemplate(player, templName, context, 2, capacity, true); if (psTemplate) { SCRIPT_ASSERT(context, validTemplateForFactory(psTemplate, psStruct, true), "Invalid template %s for factory %s", - psTemplate->aName, psStruct->pStructureType->pName); + getName(psTemplate), getName(psStruct->pStructureType)); // Delete similar template from existing list before adding this one for (int j = 0; j < apsTemplateList.size(); j++) { DROID_TEMPLATE *t = apsTemplateList[j]; - if (strcmp(t->aName, psTemplate->aName) == 0) + if (t->name.compare(psTemplate->name) == 0) { - debug(LOG_SCRIPT, "deleting %s for player %d", t->aName, player); + debug(LOG_SCRIPT, "deleting %s for player %d", getName(t), player); deleteTemplateFromProduction(t, player, ModeQueue); // duplicate? done below? SendDestroyTemplate(t, player); break; } } // Add to list - debug(LOG_SCRIPT, "adding template %s for player %d", psTemplate->aName, player); + debug(LOG_SCRIPT, "adding template %s for player %d", getName(psTemplate), player); psTemplate->multiPlayerID = generateNewObjectId(); psTemplate->psNext = apsDroidTemplates[player]; apsDroidTemplates[player] = psTemplate; sendTemplate(player, psTemplate); if (!structSetManufacture(psStruct, psTemplate, ModeQueue)) { - debug(LOG_ERROR, "Could not produce template %s in %s", psTemplate->aName, objInfo(psStruct)); + debug(LOG_ERROR, "Could not produce template %s in %s", getName(psTemplate), objInfo(psStruct)); return QScriptValue(false); } } @@ -1727,7 +1689,7 @@ static QScriptValue js_enumStruct(QScriptContext *context, QScriptEngine *engine if ((looking == -1 || psStruct->visible[looking]) && !psStruct->died && (type == NUM_DIFF_BUILDINGS || type == psStruct->pStructureType->type) - && (statsName.isEmpty() || statsName.compare(psStruct->pStructureType->pName) == 0)) + && (statsName.isEmpty() || statsName.compare(psStruct->pStructureType->id) == 0)) { matches.push_back(psStruct); } @@ -1780,7 +1742,7 @@ static QScriptValue js_enumStructOffWorld(QScriptContext *context, QScriptEngine if ((looking == -1 || psStruct->visible[looking]) && !psStruct->died && (type == NUM_DIFF_BUILDINGS || type == psStruct->pStructureType->type) - && (statsName.isEmpty() || statsName.compare(psStruct->pStructureType->pName) == 0)) + && (statsName.isEmpty() || statsName.compare(psStruct->pStructureType->id) == 0)) { matches.push_back(psStruct); } @@ -1812,7 +1774,7 @@ static QScriptValue js_enumFeature(QScriptContext *context, QScriptEngine *engin { if ((looking == -1 || psFeat->visible[looking]) && !psFeat->died - && (statsName.isEmpty() || statsName.compare(psFeat->psStats->pName) == 0)) + && (statsName.isEmpty() || statsName.compare(psFeat->psStats->id) == 0)) { matches.push_back(psFeat); } @@ -2060,7 +2022,7 @@ endstructloc: } else { - debug(LOG_SCRIPT, "Did not find valid positioning for %s", psStat->pName); + debug(LOG_SCRIPT, "Did not find valid positioning for %s", getName(psStat)); } return QScriptValue(); } @@ -2255,7 +2217,7 @@ static QScriptValue js_droidCanReach(QScriptContext *context, QScriptEngine *) static QScriptValue js_propulsionCanReach(QScriptContext *context, QScriptEngine *) { QScriptValue propulsionValue = context->argument(0); - int propulsion = getCompFromName(COMP_PROPULSION, propulsionValue.toString().toUtf8().constData()); + int propulsion = getCompFromName(COMP_PROPULSION, propulsionValue.toString()); SCRIPT_ASSERT(context, propulsion > 0, "No such propulsion: %s", propulsionValue.toString().toUtf8().constData()); int x1 = context->argument(1).toInt32(); int y1 = context->argument(2).toInt32(); @@ -2328,7 +2290,7 @@ static QScriptValue js_orderDroidBuild(QScriptContext *context, QScriptEngine *) uint16_t direction = 0; SCRIPT_ASSERT(context, order == DORDER_BUILD, "Invalid order"); - SCRIPT_ASSERT(context, strcmp(psStats->pName, "A0ADemolishStructure") != 0, "Cannot build demolition"); + SCRIPT_ASSERT(context, psStats->id.compare("A0ADemolishStructure") != 0, "Cannot build demolition"); if (context->argumentCount() > 5) { direction = DEG(context->argument(5).toNumber()); @@ -2731,7 +2693,7 @@ static QScriptValue js_enableTemplate(QScriptContext *context, QScriptEngine *en // FIXME: This dual data structure for templates is just plain insane. for (psCurr = apsDroidTemplates[selectedPlayer]; psCurr != NULL; psCurr = psCurr->psNext) { - if (!templateName.compare(psCurr->pName)) + if (templateName.compare(psCurr->id) == 0) { psCurr->enabled = true; found = true; @@ -2745,7 +2707,7 @@ static QScriptValue js_enableTemplate(QScriptContext *context, QScriptEngine *en for (std::list::iterator i = localTemplates.begin(); i != localTemplates.end(); ++i) { psCurr = &*i; - if (!templateName.compare(psCurr->pName)) + if (templateName.compare(psCurr->id) == 0) { psCurr->enabled = true; } @@ -2785,17 +2747,9 @@ static QScriptValue js_applyLimitSet(QScriptContext *context, QScriptEngine *eng static void setComponent(QString name, int player, int value) { - int type = -1; - int compInc = -1; - for (int j = 0; j < COMP_NUMCOMPONENTS && compInc == -1; j++) - { - // this is very inefficient, but I am so not giving in to the deranged nature of the components code - // and convoluting the new script system for its sake - compInc = getCompFromName(j, name.toUtf8().constData()); - type = j; - } - ASSERT_OR_RETURN(, compInc != -1 && type != -1, "Bad component value"); - apCompLists[player][type][compInc] = value; + COMPONENT_STATS *psComp = getCompStatsFromName(name); + ASSERT_OR_RETURN(, psComp, "Bad component %s", name.toUtf8().constData()); + apCompLists[player][psComp->compType][psComp->index] = value; } //-- \subsection{enableComponent(component, player)} @@ -3499,7 +3453,7 @@ static QScriptValue js_getDroidProduction(QScriptContext *context, QScriptEngine psDroid->pos = psStruct->pos; psDroid->rot = psStruct->rot; psDroid->experience = 0; - droidSetName(psDroid, psTemp->aName); + droidSetName(psDroid, getName(psTemp)); droidSetBits(psTemp, psDroid); psDroid->weight = calcDroidWeight(psTemp); psDroid->baseSpeed = calcDroidBaseSpeed(psTemp, psDroid->weight, player); @@ -4118,7 +4072,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { BODY_STATS *psStats = asBodyStats + j; QScriptValue body = engine->newObject(); - body.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + body.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); body.setProperty("Weight", psStats->weight, QScriptValue::ReadOnly | QScriptValue::Undeletable); body.setProperty("BuildPower", psStats->buildPower, QScriptValue::ReadOnly | QScriptValue::Undeletable); body.setProperty("BuildTime", psStats->buildPoints, QScriptValue::ReadOnly | QScriptValue::Undeletable); @@ -4139,7 +4093,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { SENSOR_STATS *psStats = asSensorStats + j; QScriptValue sensor = engine->newObject(); - sensor.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + sensor.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); sensor.setProperty("Weight", psStats->weight, QScriptValue::ReadOnly | QScriptValue::Undeletable); sensor.setProperty("BuildPower", psStats->buildPower, QScriptValue::ReadOnly | QScriptValue::Undeletable); sensor.setProperty("BuildTime", psStats->buildPoints, QScriptValue::ReadOnly | QScriptValue::Undeletable); @@ -4154,7 +4108,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { ECM_STATS *psStats = asECMStats + j; QScriptValue ecm = engine->newObject(); - ecm.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + ecm.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); ecm.setProperty("Weight", psStats->weight, QScriptValue::ReadOnly | QScriptValue::Undeletable); ecm.setProperty("BuildPower", psStats->buildPower, QScriptValue::ReadOnly | QScriptValue::Undeletable); ecm.setProperty("BuildTime", psStats->buildPoints, QScriptValue::ReadOnly | QScriptValue::Undeletable); @@ -4169,7 +4123,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { REPAIR_STATS *psStats = asRepairStats + j; QScriptValue repair = engine->newObject(); - repair.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + repair.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); repair.setProperty("Weight", psStats->weight, QScriptValue::ReadOnly | QScriptValue::Undeletable); repair.setProperty("BuildPower", psStats->buildPower, QScriptValue::ReadOnly | QScriptValue::Undeletable); repair.setProperty("BuildTime", psStats->buildPoints, QScriptValue::ReadOnly | QScriptValue::Undeletable); @@ -4184,7 +4138,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { CONSTRUCT_STATS *psStats = asConstructStats + j; QScriptValue con = engine->newObject(); - con.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + con.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); con.setProperty("Weight", psStats->weight, QScriptValue::ReadOnly | QScriptValue::Undeletable); con.setProperty("BuildPower", psStats->buildPower, QScriptValue::ReadOnly | QScriptValue::Undeletable); con.setProperty("BuildTime", psStats->buildPoints, QScriptValue::ReadOnly | QScriptValue::Undeletable); @@ -4199,7 +4153,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { WEAPON_STATS *psStats = asWeaponStats + j; QScriptValue weap = engine->newObject(); - weap.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + weap.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); weap.setProperty("Weight", psStats->weight, QScriptValue::ReadOnly | QScriptValue::Undeletable); weap.setProperty("BuildPower", psStats->buildPower, QScriptValue::ReadOnly | QScriptValue::Undeletable); weap.setProperty("BuildTime", psStats->buildPoints, QScriptValue::ReadOnly | QScriptValue::Undeletable); @@ -4240,7 +4194,7 @@ bool registerFunctions(QScriptEngine *engine, QString scriptName) { STRUCTURE_STATS *psStats = asStructureStats + j; QScriptValue strct = engine->newObject(); - strct.setProperty("Id", psStats->pName, QScriptValue::ReadOnly | QScriptValue::Undeletable); + strct.setProperty("Id", psStats->id, QScriptValue::ReadOnly | QScriptValue::Undeletable); if (psStats->type == REF_DEFENSE || psStats->type == REF_WALL || psStats->type == REF_WALLCORNER || psStats->type == REF_BLASTDOOR || psStats->type == REF_GATE) { diff --git a/src/research.cpp b/src/research.cpp index ae827e020..dc0054c04 100644 --- a/src/research.cpp +++ b/src/research.cpp @@ -67,16 +67,11 @@ UDWORD aDefaultECM[MAX_PLAYERS]; UDWORD aDefaultRepair[MAX_PLAYERS]; //set the iconID based on the name read in in the stats -static UWORD setIconID(char *pIconName, char *pName); +static UWORD setIconID(char *pIconName, const char *pName); static void replaceComponent(COMPONENT_STATS *pNewComponent, COMPONENT_STATS *pOldComponent, UBYTE player); static bool checkResearchName(RESEARCH *psRes, UDWORD numStats); -static const char *getResearchName(RESEARCH *pResearch) -{ - return(getName(pResearch->pName)); -} - //flag that indicates whether the player can self repair static UBYTE bSelfRepair[MAX_PLAYERS]; static void replaceDroidComponent(DROID *pList, UDWORD oldType, UDWORD oldCompInc, @@ -107,32 +102,6 @@ bool researchInitVars(void) return true; } -//searches for component with given name -//returns NULL if record not found -BASE_STATS* get_any_component_from_ID(QString name) -{ - for (int compType=0; compTypepName, Qt::CaseInsensitive) == 0) - { - return psStats; - } - psStats = (BASE_STATS *)((char *)psStats + statSize); - } - } - - //return NULL if record not found or an invalid component type is passed in - return NULL; -} - /** Load the research stats */ bool loadResearch(QString filename) { @@ -153,21 +122,20 @@ bool loadResearch(QString filename) ini.beginGroup(list[inc]); RESEARCH research; research.index = inc; - research.pName = allocateName(list[inc].toUtf8().constData()); - ASSERT_OR_RETURN(false, research.pName != NULL, "Failed allocating research name"); + research.name = ini.value("name").toString(); + research.id = list[inc]; //check the name hasn't been used already - ASSERT_OR_RETURN(false, checkResearchName(&research, inc), "Research name '%s' used already", research.pName); + ASSERT_OR_RETURN(false, checkResearchName(&research, inc), "Research name '%s' used already", getName(&research)); research.ref = REF_RESEARCH_START + inc; - research.resultStrings = ini.value("results").toStringList(); //set subGroup icon QString subGroup = ini.value("subgroupIconID", "").toString(); if (subGroup.compare("") != 0) { - research.subGroup = setIconID(subGroup.toUtf8().data(), research.pName); + research.subGroup = setIconID(subGroup.toUtf8().data(), getName(&research)); } else { @@ -176,7 +144,7 @@ bool loadResearch(QString filename) //set key topic unsigned int keyTopic = ini.value("keyTopic", 0).toUInt(); - ASSERT(keyTopic <= 1, "Invalid keyTopic for research topic - '%s' ", getResearchName(&research)); + ASSERT(keyTopic <= 1, "Invalid keyTopic for research topic - '%s' ", getName(&research)); if(keyTopic <= 1) research.keyTopic = ini.value("keyTopic", 0).toUInt(); else @@ -184,7 +152,7 @@ bool loadResearch(QString filename) //set tech code UBYTE techCode = ini.value("techCode", 0).toUInt(); - ASSERT(techCode <= 1, "Invalid tech code for research topic - '%s' ", getResearchName(&research)); + ASSERT(techCode <= 1, "Invalid tech code for research topic - '%s' ", getName(&research)); if (techCode == 0) { research.techCode = TC_MAJOR; @@ -198,7 +166,7 @@ bool loadResearch(QString filename) QString iconID = ini.value("iconID", "").toString(); if (iconID.compare("") != 0) { - research.iconID = setIconID(iconID.toUtf8().data(), research.pName); + research.iconID = setIconID(iconID.toUtf8().data(), getName(&research)); } else { @@ -218,20 +186,16 @@ bool loadResearch(QString filename) }else { //try find the component stat with given name - BASE_STATS* tmpComp = get_any_component_from_ID(statID); - if(tmpComp != NULL) - { - research.psStat = tmpComp; - } + research.psStat = getCompStatsFromName(statID); } - ASSERT_OR_RETURN(false, research.psStat != NULL, "Cannot find the statID '%s' for Research '%s'", statID.toUtf8().data(), getResearchName(&research)); + ASSERT_OR_RETURN(false, research.psStat != NULL, "Cannot find the statID '%s' for Research '%s'", statID.toUtf8().data(), getName(&research)); } QString imdName = ini.value("imdName", "").toString(); if (imdName.compare("") != 0) { research.pIMD = (iIMDShape *) resGetData("IMD", imdName.toUtf8().data()); - ASSERT(research.pIMD != NULL, "Cannot find the research PIE '%s' for record '%s'",imdName.toUtf8().data(), getResearchName(&research)); + ASSERT(research.pIMD != NULL, "Cannot find the research PIE '%s' for record '%s'",imdName.toUtf8().data(), getName(&research)); } else { @@ -242,7 +206,7 @@ bool loadResearch(QString filename) if (imdName2.compare("") != 0) { research.pIMD2 = (iIMDShape *) resGetData("IMD", imdName2.toUtf8().data()); - ASSERT(research.pIMD2 != NULL, "Cannot find the 2nd research '%s' PIE for record '%s'",imdName2.toUtf8().data(), getResearchName(&research)); + ASSERT(research.pIMD2 != NULL, "Cannot find the 2nd research '%s' PIE for record '%s'",imdName2.toUtf8().data(), getName(&research)); } else { @@ -253,7 +217,7 @@ bool loadResearch(QString filename) if (msgName.compare("") != 0) { //check its a major tech code - ASSERT(research.techCode == TC_MAJOR, "This research should not have a message associated with it, '%s' the message will be ignored!", getResearchName(&research)); + ASSERT(research.techCode == TC_MAJOR, "This research should not have a message associated with it, '%s' the message will be ignored!", getName(&research)); if (research.techCode == TC_MAJOR) { research.pViewData = getViewData(msgName.toUtf8().data()); @@ -262,12 +226,12 @@ bool loadResearch(QString filename) //set the researchPoints unsigned int resPoints = ini.value("researchPoints", 0).toUInt(); - ASSERT_OR_RETURN(false, resPoints <= UWORD_MAX, "Research Points too high for research topic - '%s' ", getResearchName(&research)); + ASSERT_OR_RETURN(false, resPoints <= UWORD_MAX, "Research Points too high for research topic - '%s' ", getName(&research)); research.researchPoints = resPoints; //set the research power unsigned int resPower = ini.value("researchPower", 0).toUInt(); - ASSERT_OR_RETURN(false, resPower <= UWORD_MAX, "Research Power too high for research topic - '%s' ", getResearchName(&research)); + ASSERT_OR_RETURN(false, resPower <= UWORD_MAX, "Research Power too high for research topic - '%s' ", getName(&research)); research.researchPower = resPower; //rememeber research pre-requisites for futher checking @@ -278,13 +242,13 @@ bool loadResearch(QString filename) for (int j = 0; j < compResults.size(); j++) { QString compID = compResults[j].trimmed(); - BASE_STATS *pComp = get_any_component_from_ID(compID); + COMPONENT_STATS *pComp = getCompStatsFromName(compID); if (pComp != NULL) { - research.componentResults.push_back((COMPONENT_STATS*)pComp); + research.componentResults.push_back(pComp); }else { - ASSERT(false, "Invalid item '%s' in list of result components of research '%s' ", compID.toUtf8().constData(), getResearchName(&research)); + ASSERT(false, "Invalid item '%s' in list of result components of research '%s' ", compID.toUtf8().constData(), getName(&research)); } } @@ -294,23 +258,23 @@ bool loadResearch(QString filename) { //read pair of components oldComponent:newComponent QStringList pair = replacedComp[j].split(':'); - ASSERT(pair.size() == 2, "Invalid item '%s' in list of replaced components of research '%s'. Required format: 'oldItem:newItem, item1:item2'", replacedComp[j].toUtf8().constData(), getResearchName(&research)); + ASSERT(pair.size() == 2, "Invalid item '%s' in list of replaced components of research '%s'. Required format: 'oldItem:newItem, item1:item2'", replacedComp[j].toUtf8().constData(), getName(&research)); if (pair.size() != 2) { continue; //skip invalid entries } QString oldCompID = pair[0].trimmed(); QString newCompID = pair[1].trimmed(); - COMPONENT_STATS *oldComp = (COMPONENT_STATS *)get_any_component_from_ID(oldCompID); + COMPONENT_STATS *oldComp = getCompStatsFromName(oldCompID); if (oldComp == NULL) { - ASSERT(false, "Invalid item '%s' in list of replaced components of research '%s'. Wrong component code.", oldCompID.toUtf8().constData(), getResearchName(&research)); + ASSERT(false, "Invalid item '%s' in list of replaced components of research '%s'. Wrong component code.", oldCompID.toUtf8().constData(), getName(&research)); continue; } - COMPONENT_STATS *newComp = (COMPONENT_STATS *)get_any_component_from_ID(newCompID); + COMPONENT_STATS *newComp = getCompStatsFromName(newCompID); if(newComp == NULL) { - ASSERT(false, "Invalid item '%s' in list of replaced components of research '%s'. Wrong component code.", newCompID.toUtf8().constData(), getResearchName(&research)); + ASSERT(false, "Invalid item '%s' in list of replaced components of research '%s'. Wrong component code.", newCompID.toUtf8().constData(), getName(&research)); continue; } RES_COMP_REPLACEMENT replItem; @@ -324,13 +288,13 @@ bool loadResearch(QString filename) for (int j = 0; j < redComp.size(); j++) { QString compID = redComp[j].trimmed(); - BASE_STATS *pComp = get_any_component_from_ID(compID); + COMPONENT_STATS *pComp = getCompStatsFromName(compID); if (pComp == NULL) { - ASSERT(false, "Invalid item '%s' in list of redundant components of research '%s' ", compID.toUtf8().constData(), getResearchName(&research)); + ASSERT(false, "Invalid item '%s' in list of redundant components of research '%s' ", compID.toUtf8().constData(), getName(&research)); }else { - research.pRedArtefacts.push_back((COMPONENT_STATS*)pComp); + research.pRedArtefacts.push_back(pComp); } } @@ -340,7 +304,7 @@ bool loadResearch(QString filename) { QString strucID = resStruct[j].trimmed(); int structIndex = getStructStatFromName(strucID.toUtf8().data()); - ASSERT(structIndex >= 0, "Invalid item '%s' in list of result structures of research '%s' ", strucID.toUtf8().constData(), getResearchName(&research)); + ASSERT(structIndex >= 0, "Invalid item '%s' in list of result structures of research '%s' ", strucID.toUtf8().constData(), getName(&research)); if (structIndex >= 0) { research.pStructureResults.push_back(structIndex); @@ -353,7 +317,7 @@ bool loadResearch(QString filename) { QString strucID = reqStruct[j].trimmed(); int structIndex = getStructStatFromName(strucID.toUtf8().data()); - ASSERT(structIndex >= 0, "Invalid item '%s' in list of required structures of research '%s' ", strucID.toUtf8().constData(), getResearchName(&research)); + ASSERT(structIndex >= 0, "Invalid item '%s' in list of required structures of research '%s' ", strucID.toUtf8().constData(), getName(&research)); if(structIndex >= 0) { research.pStructList.push_back(structIndex); @@ -366,7 +330,7 @@ bool loadResearch(QString filename) { QString strucID = redStruct[j].trimmed(); int structIndex = getStructStatFromName(strucID.toUtf8().data()); - ASSERT(structIndex >= 0, "Invalid item '%s' in list of redundant structures of research '%s' ", strucID.toUtf8().constData(), getResearchName(&research)); + ASSERT(structIndex >= 0, "Invalid item '%s' in list of redundant structures of research '%s' ", strucID.toUtf8().constData(), getName(&research)); if (structIndex >= 0) { research.pRedStructs.push_back(structIndex); @@ -385,7 +349,7 @@ bool loadResearch(QString filename) { QString resID = preRes[j].trimmed(); RESEARCH *preResItem = getResearch(resID.toUtf8().constData()); - ASSERT(preResItem != NULL, "Invalid item '%s' in list of pre-requisites of research '%s' ", resID.toUtf8().constData(), getResearchName(&asResearch[inc])); + ASSERT(preResItem != NULL, "Invalid item '%s' in list of pre-requisites of research '%s' ", resID.toUtf8().constData(), getName(&asResearch[inc])); if (preResItem != NULL) asResearch[inc].pPRList.push_back(preResItem->index); } @@ -837,7 +801,7 @@ RESEARCH *getResearchForMsg(VIEWDATA *pViewData) } //set the iconID based on the name read in in the stats -static UWORD setIconID(char *pIconName, char *pName) +static UWORD setIconID(char *pIconName, const char *pName) { //compare the names with those created in 'Framer' if (!strcmp(pIconName, "IMAGE_ROCKET")) @@ -1087,11 +1051,9 @@ SDWORD mapIconToRID(UDWORD iconID) //return a pointer to a research topic based on the name RESEARCH *getResearch(const char *pName) { - unsigned int inc = 0; - - for (inc = 0; inc < asResearch.size(); inc++) + for (int inc = 0; inc < asResearch.size(); inc++) { - if (!strcasecmp(asResearch[inc].pName, pName)) + if (asResearch[inc].id.compare(pName) == 0) { return &asResearch[inc]; } @@ -1168,18 +1130,11 @@ static void replaceComponent(COMPONENT_STATS *pNewComponent, COMPONENT_STATS *pO a duplicate*/ static bool checkResearchName(RESEARCH *psResearch, UDWORD numStats) { - UDWORD inc; - char *pName=psResearch->pName; - - for (inc = 0; inc < numStats; inc++) + for (int inc = 0; inc < numStats; inc++) { - if (!strcmp(asResearch[inc].pName, pName)) - { - //oops! found the name - ASSERT( false, "Research name has already been used - %s", pName ); - return false; - } + ASSERT_OR_RETURN(false, asResearch[inc].id.compare(psResearch->id) != 0, + "Research name has already been used - %s", getName(psResearch)); } return true; } @@ -1195,7 +1150,7 @@ bool enableResearch(RESEARCH *psResearch, UDWORD player) inc = psResearch->index; if (inc > asResearch.size()) { - ASSERT( false, "enableResearch: Invalid research topic - %s", getResearchName(psResearch) ); + ASSERT( false, "enableResearch: Invalid research topic - %s", getName(psResearch) ); return false; } @@ -1255,52 +1210,11 @@ void researchReward(UBYTE losingPlayer, UBYTE rewardPlayer) //name the actual reward CONPRINTF(ConsoleString,(ConsoleString,"%s :- %s", _("Research Award"), - getName(asResearch[rewardID].pName))); + getName(&asResearch[rewardID]))); } } } - -/*checks that the research has loaded up as expected - must be done after -all research parts have been loaded*/ -bool checkResearchStats(void) -{ - UDWORD resInc, inc; - for (resInc = 0; resInc < asResearch.size(); resInc++) - { - for (inc = 0; inc < asResearch[resInc].pPRList.size(); inc++) - { - ASSERT(asResearch[resInc].pPRList[inc] <= asResearch.size(), "Invalid PreReq for topic %s", asResearch[resInc].pName); - } - for (inc = 0; inc < asResearch[resInc].pStructList.size(); inc++) - { - ASSERT(asResearch[resInc].pStructList[inc] <= numStructureStats, "Invalid Structure for topic %s", asResearch[resInc].pName); - } - for (inc = 0; inc < asResearch[resInc].pRedStructs.size(); inc++) - { - ASSERT(asResearch[resInc].pRedStructs[inc] <= numStructureStats, - "Invalid Redundant Structure for topic %s", asResearch[resInc].pName); - } - for (inc = 0; inc < asResearch[resInc].pStructureResults.size(); inc++) - { - ASSERT(asResearch[resInc].pStructureResults[inc] <= numStructureStats, - "Invalid Result Structure for topic %s", asResearch[resInc].pName); - } - for (inc = 0; inc < asResearch[resInc].componentResults.size(); inc++) - { - ASSERT(asResearch[resInc].componentResults[inc] != NULL, - "Invalid Comp Result for topic %s", asResearch[resInc].pName); - } - for (inc = 0; inc < asResearch[resInc].pRedArtefacts.size(); inc++) - { - ASSERT(asResearch[resInc].pRedArtefacts[inc] != NULL, - "Invalid Redundant Comp for topic %s", asResearch[resInc].pName); - } - } - - return true; -} - /*flag self repair so droids can start when idle*/ void enableSelfRepair(UBYTE player) { diff --git a/src/research.h b/src/research.h index 1efe77363..fa4116f05 100644 --- a/src/research.h +++ b/src/research.h @@ -125,7 +125,6 @@ extern bool selfRepairEnabled(UBYTE player); extern SDWORD mapRIDToIcon( UDWORD rid ); extern SDWORD mapIconToRID(UDWORD iconID); -extern bool checkResearchStats(void); /*puts research facility on hold*/ extern void holdResearch(STRUCTURE *psBuilding, QUEUE_MODE mode); diff --git a/src/researchdef.h b/src/researchdef.h index a68ee1dc1..26bc5db73 100644 --- a/src/researchdef.h +++ b/src/researchdef.h @@ -66,7 +66,7 @@ struct RESEARCH : public BASE_STATS iIMDShape *pIMD2; /* the 2nd IMD for base plates/turrets*/ int index; ///< Unique index for this research, set incrementally - RESEARCH() : pViewData(NULL), iconID(0), psStat(NULL), pIMD(NULL), pIMD2(NULL) { pName = NULL; } + RESEARCH() : pViewData(NULL), iconID(0), psStat(NULL), pIMD(NULL), pIMD2(NULL) {} }; struct PLAYER_RESEARCH diff --git a/src/scriptai.cpp b/src/scriptai.cpp index 76ab80c82..c4acae4d9 100644 --- a/src/scriptai.cpp +++ b/src/scriptai.cpp @@ -611,7 +611,7 @@ bool scrOrderDroidStatsLoc(void) // HACK: FIXME: Looks like a script error in the player*.slo files // buildOnExactLocation() which references previously destroyed buildings from // _stat = rebuildStructStat[_count] causes this. - if (strcmp(psStats->pName, "A0ADemolishStructure") == 0) + if (psStats->id.compare("A0ADemolishStructure") == 0) { // I don't feel like spamming a ASSERT here, we *know* it is a issue. return true; @@ -1612,7 +1612,7 @@ bool scrSkDoResearch(void) #if defined (DEBUG) { char sTemp[128]; - sprintf(sTemp, "[debug]player:%d starts topic: %s", player, asResearch[i].pName); + sprintf(sTemp, "[debug]player:%d starts topic: %s", player, getName(&asResearch[i])); NETlogEntry(sTemp, SYNC_FLAG, 0); } #endif diff --git a/src/scriptfuncs.cpp b/src/scriptfuncs.cpp index 4b8c840b6..87eec5071 100644 --- a/src/scriptfuncs.cpp +++ b/src/scriptfuncs.cpp @@ -1017,7 +1017,7 @@ bool scrAddDroidToMissionList(void) if (IsPlayerDroidLimitReached(player) && (psTemplate->droidType != DROID_TRANSPORTER && psTemplate->droidType != DROID_SUPERTRANSPORTER)) { debug(LOG_SCRIPT, "Max units reached for player %d adding %s to mission list (type %d)", - player, psTemplate->aName, psTemplate->droidType); + player, getName(psTemplate), psTemplate->droidType); psDroid = NULL; } else @@ -1488,7 +1488,7 @@ bool scrBuildDroid(void) psFactory->pStructureType->type == REF_VTOL_FACTORY), "Structure is not a factory"); ASSERT_OR_RETURN(false, validTemplateForFactory(psTemplate, psFactory, true), "Invalid template - %s for factory - %s", - psTemplate->aName, psFactory->pStructureType->pName); + getName(psTemplate), getID(psFactory->pStructureType)); if (productionRun != 1) { debug(LOG_WARNING, "A wzscript is trying to build a different number (%d) than 1 droid.", productionRun); @@ -1499,7 +1499,7 @@ bool scrBuildDroid(void) } else { - debug(LOG_WARNING, "A wzscript tried to build a template (%s) that has not been researched yet", psTemplate->aName); + debug(LOG_WARNING, "A wzscript tried to build a template (%s) that has not been researched yet", getName(psTemplate)); } return true; } @@ -3922,7 +3922,7 @@ bool scrStructureBuiltInRange(void) psStruct = (STRUCTURE *)psCurr; if ((psStruct->status == SS_BUILT || player == -1) && (player == -1 || psStruct->player == player) - && strcmp(psStruct->pStructureType->pName, psTarget->pName) == 0) + && psStruct->pStructureType->id.compare(psTarget->id) == 0) { break; } @@ -5241,7 +5241,7 @@ endstructloc: } else { - debug(LOG_SCRIPT, "Did not find valid positioning for %s", psStat->pName); + debug(LOG_SCRIPT, "Did not find valid positioning for %s", getID(psStat)); } scrFunctionResult.v.bval = found; if (!stackPushResult(VAL_BOOL, &scrFunctionResult)) // success! @@ -6054,6 +6054,7 @@ bool scrIsVtol(void) // In short, we want to design a ViperLtMGWheels, but it is already available to make, so we must delete it. bool scrTutorialTemplates(void) { +#if 0 DROID_TEMPLATE *psCurr, *psPrev; // find ViperLtMGWheels @@ -6061,7 +6062,7 @@ bool scrTutorialTemplates(void) for (psCurr = apsDroidTemplates[selectedPlayer], psPrev = NULL; psCurr != NULL; psCurr = psCurr->psNext) { - if (strcmp(pName, psCurr->aName) == 0) + if (psCurr->name.compare(pName) == 0) { if (psPrev) { @@ -6097,15 +6098,11 @@ bool scrTutorialTemplates(void) abort(); return false; } +#endif return true; } - - - - - //----------------------------------------- //New functions //----------------------------------------- @@ -7828,7 +7825,7 @@ bool scrNumStructsByStatInRange(void) ydiff = (SDWORD)psCurr->pos.y - y; if (xdiff *xdiff + ydiff *ydiff <= rangeSquared) { - if (strcmp(psCurr->pStructureType->pName, psTarget->pName) == 0) + if (psCurr->pStructureType->id.compare(psTarget->id) == 0) { if (psCurr->visible[lookingPlayer]) //can we see it? { @@ -9553,7 +9550,7 @@ bool scrPursueResearch(void) #if defined (DEBUG) { char sTemp[128]; - sprintf(sTemp, "player:%d starts topic: %s", player, asResearch[foundIndex].pName); + sprintf(sTemp, "player:%d starts topic: %s", player, getName(&asResearch[foundIndex])); NETlogEntry(sTemp, SYNC_FLAG, 0); } #endif diff --git a/src/scriptobj.cpp b/src/scriptobj.cpp index 7386b9f49..2793eb752 100644 --- a/src/scriptobj.cpp +++ b/src/scriptobj.cpp @@ -593,70 +593,70 @@ bool scrGroupObjGet(UDWORD index) // get the name from a stat pointer -static char *scrGetStatName(INTERP_TYPE type, UDWORD data) +static const QString scrGetStatName(INTERP_TYPE type, UDWORD data) { - char *pName = NULL; + QString pName; switch ((unsigned)type) // Unsigned cast to suppress compiler warnings due to enum abuse. { case ST_STRUCTURESTAT: if (data < numStructureStats) { - pName = asStructureStats[data].pName; + pName = asStructureStats[data].id; } break; case ST_FEATURESTAT: if (data < numFeatureStats) { - pName = asFeatureStats[data].pName; + pName = asFeatureStats[data].id; } break; case ST_BODY: if (data < numBodyStats) { - pName = asBodyStats[data].pName; + pName = asBodyStats[data].id; } break; case ST_PROPULSION: if (data < numPropulsionStats) { - pName = asPropulsionStats[data].pName; + pName = asPropulsionStats[data].id; } break; case ST_ECM: if (data < numECMStats) { - pName = asECMStats[data].pName; + pName = asECMStats[data].id; } break; case ST_SENSOR: if (data < numSensorStats) { - pName = asSensorStats[data].pName; + pName = asSensorStats[data].id; } break; case ST_CONSTRUCT: if (data < numConstructStats) { - pName = asConstructStats[data].pName; + pName = asConstructStats[data].id; } break; case ST_WEAPON: if (data < numWeaponStats) { - pName = asWeaponStats[data].pName; + pName = asWeaponStats[data].id; } break; case ST_REPAIR: if (data < numRepairStats) { - pName = asRepairStats[data].pName; + pName = asRepairStats[data].id; } break; case ST_BRAIN: if (data < numBrainStats) { - pName = asBrainStats[data].pName; + pName = asBrainStats[data].id; } break; case ST_BASESTATS: @@ -667,11 +667,7 @@ static char *scrGetStatName(INTERP_TYPE type, UDWORD data) break; } - if (pName == NULL) - { - debug( LOG_FATAL, "scrGetStatName: cannot get name for a base stat" ); - abort(); - } + ASSERT(!pName.isEmpty(), "cannot get name for a base stat"); return pName; } @@ -681,7 +677,7 @@ static char *scrGetStatName(INTERP_TYPE type, UDWORD data) bool scrValDefSave(INTERP_VAL *psVal, WzConfig &ini) { VIEWDATA *psIntMessage; - const char *pName; + QString pName; RESEARCH *psResearch; DROID *psCDroid; @@ -718,7 +714,7 @@ bool scrValDefSave(INTERP_VAL *psVal, WzConfig &ini) case ST_REPAIR: case ST_BRAIN: pName = scrGetStatName(psVal->type, psVal->v.ival); - if (pName) + if (!pName.isEmpty()) { ini.setValue("data", QString(pName)); } @@ -746,10 +742,10 @@ bool scrValDefSave(INTERP_VAL *psVal, WzConfig &ini) break; case ST_RESEARCH: psResearch = (RESEARCH *)psVal->v.oval; - if (psResearch && psResearch->pName && psResearch->pName[0] != '\0') + if (psResearch && !psResearch->id.isEmpty()) { - ini.setValue("data", QString(psResearch->pName)); - ASSERT(psResearch == getResearch(psResearch->pName), "Research %s not found!", psResearch->pName); + ini.setValue("data", psResearch->id); + ASSERT(psResearch == getResearch(getID(psResearch)), "Research %s not found!", getID(psResearch)); } break; case ST_GROUP: @@ -782,17 +778,13 @@ bool scrValDefSave(INTERP_VAL *psVal, WzConfig &ini) // can also return NULL pName = sound_GetTrackName((UDWORD)psVal->v.ival); } - else - { - pName = NULL; - } - if (!pName) + if (pName.isEmpty()) { debug(LOG_WARNING, "Could not get sound track name"); } - if (pName) + else { - ini.setValue("data", QString(pName)); + ini.setValue("data", pName); } break; case ST_STRUCTUREID: diff --git a/src/stats.cpp b/src/stats.cpp index 5c042489a..d0f05893e 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -25,6 +25,7 @@ */ #include #include +#include #include "lib/framework/frame.h" #include "lib/framework/strres.h" @@ -87,6 +88,8 @@ UBYTE *apCompLists[MAX_PLAYERS][COMP_NUMCOMPONENTS]; //store for each players Structure states UBYTE *apStructTypeLists[MAX_PLAYERS]; +QHash lookupStatPtr; + static bool getMovementModel(const char *movementModel, MOVEMENT_MODEL *model); static void storeSpeedFactor(UDWORD terrainType, UDWORD propulsionType, UDWORD speedFactor); @@ -112,11 +115,6 @@ static void updateMaxECMStats(UWORD maxValue); static void updateMaxBodyStats(UWORD maxBody, UWORD maxPower, UWORD maxArmour); static void updateMaxConstStats(UWORD maxValue); -BASE_STATS::BASE_STATS(unsigned ref, std::string const &str) - : ref(ref) - , pName(allocateName(str.c_str())) -{} - static inline bool stringToEnumFindFunction(std::pair const &a, char const *b) { return strcmp(a.first, b) < 0; @@ -145,16 +143,15 @@ static void deallocTerrainTable(void) /* Macro to allocate memory for a set of stats */ #define ALLOC_STATS(numEntries, list, listSize, type) \ - ASSERT( (numEntries) < REF_RANGE, \ - "allocStats: number of stats entries too large for " #type );\ - if ((list)) free((list)); \ - (list) = (type *)malloc(sizeof(type) * (numEntries)); \ + ASSERT((numEntries) < REF_RANGE, "Number of stats entries too large for " #type);\ + if ((list)) delete [] (list); \ + (list) = new type[numEntries]; \ (listSize) = (numEntries); \ return true /*Macro to Deallocate stats*/ #define STATS_DEALLOC(list, listSize) \ - free((COMPONENT_STATS*)(list)); \ + delete [] (list); \ listSize = 0; \ (list) = NULL @@ -177,23 +174,17 @@ void statsInitVars(void) maxPropulsionSpeed = 0; } -static void allocateStatName(BASE_STATS *pStat, const char *Name) -{ - pStat->pName = allocateName(Name); -} - /* body stats need the extra list removing */ static void deallocBodyStats(void) { BODY_STATS *psStat; - UDWORD inc; - for (inc = 0; inc < numBodyStats; inc++) + for (int inc = 0; inc < numBodyStats; inc++) { psStat = &asBodyStats[inc]; free(psStat->ppIMDList); } - free(asBodyStats); + delete [] asBodyStats; asBodyStats = NULL; numBodyStats = 0; } @@ -201,72 +192,21 @@ static void deallocBodyStats(void) /*Deallocate all the stats assigned from input data*/ bool statsShutDown(void) { + lookupStatPtr.clear(); + STATS_DEALLOC(asWeaponStats, numWeaponStats); deallocBodyStats(); STATS_DEALLOC(asBrainStats, numBrainStats); STATS_DEALLOC(asPropulsionStats, numPropulsionStats); STATS_DEALLOC(asRepairStats, numRepairStats); STATS_DEALLOC(asConstructStats, numConstructStats); + STATS_DEALLOC(asECMStats, numECMStats); deallocPropulsionTypes(); deallocTerrainTable(); return true; } -/* Macro to set the stats for a particular ref - * The macro uses the ref number in the stats structure to - * index the correct array entry - */ -#define SET_STATS(stats, list, index, type, refStart) \ - ASSERT( ((stats)->ref >= (refStart)) && ((stats)->ref < (refStart) + REF_RANGE), \ - "setStats: Invalid " #type " ref number" ); \ - memcpy((list) + (index), (stats), sizeof(type)) - -/******************************************************************************* -* Set stats functions -*******************************************************************************/ -/* Set the stats for a particular weapon type */ -static void statsSetWeapon(WEAPON_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asWeaponStats, index, WEAPON_STATS, REF_WEAPON_START); -} -/* Set the stats for a particular body type */ -static void statsSetBody(BODY_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asBodyStats, index, BODY_STATS, REF_BODY_START); -} -/* Set the stats for a particular brain type */ -static void statsSetBrain(BRAIN_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asBrainStats, index, BRAIN_STATS, REF_BRAIN_START); -} -/* Set the stats for a particular power type */ -static void statsSetPropulsion(PROPULSION_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asPropulsionStats, index, PROPULSION_STATS, - REF_PROPULSION_START); -} -/* Set the stats for a particular sensor type */ -static void statsSetSensor(SENSOR_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asSensorStats, index, SENSOR_STATS, REF_SENSOR_START); -} -/* Set the stats for a particular ecm type */ -static void statsSetECM(ECM_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asECMStats, index, ECM_STATS, REF_ECM_START); -} -/* Set the stats for a particular repair type */ -static void statsSetRepair(REPAIR_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asRepairStats, index, REPAIR_STATS, REF_REPAIR_START); -} -/* Set the stats for a particular construct type */ -static void statsSetConstruct(CONSTRUCT_STATS *psStats, UDWORD index) -{ - SET_STATS(psStats, asConstructStats, index, CONSTRUCT_STATS, REF_CONSTRUCT_START); -} - /* Return the number of newlines in a file buffer */ UDWORD numCR(const char *pFileBuffer, UDWORD fileSize) { @@ -330,16 +270,6 @@ bool statsAllocConstruct(UDWORD numStats) ALLOC_STATS(numStats, asConstructStats, numConstructStats, CONSTRUCT_STATS); } -const char *getStatName(const void *Stat) -{ - const BASE_STATS *const psStats = (const BASE_STATS *)Stat; - ASSERT(psStats->pName, "No pName for stats!"); - return getName(psStats->pName); -} - - - - /******************************************************************************* * Load stats functions *******************************************************************************/ @@ -357,33 +287,37 @@ static iIMDShape *statsGetIMD(WzConfig &ini, BASE_STATS *psStats, QString key) return retval; } +void loadCompStats(WzConfig &ini, COMPONENT_STATS *psStats, int index) +{ + psStats->name = ini.value("name").toString(); + psStats->id = ini.group(); + psStats->buildPower = ini.value("buildPower", 0).toUInt(); + psStats->buildPoints = ini.value("buildPoints", 0).toUInt(); + psStats->index = index; + ASSERT(!lookupStatPtr.contains(psStats->id), "Duplicate ID found! (%s)", getID(psStats)); + lookupStatPtr.insert(psStats->id, psStats); +} + /*Load the weapon stats from the file exported from Access*/ bool loadWeaponStats(const char *pFileName) { - WEAPON_STATS sStats, * const psStats = &sStats; UDWORD i, surfaceToAir; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); - if (!statsAllocWeapons(list.size())) - { - return false; - } + statsAllocWeapons(list.size()); // Hack to make sure ZNULLWEAPON is always first in list int nullweapon = list.indexOf("ZNULLWEAPON"); ASSERT_OR_RETURN(false, nullweapon >= 0, "ZNULLWEAPON is mandatory"); - if (nullweapon > 0) - { - list.swap(nullweapon, 0); - } - + list.swap(nullweapon, 0); for (i = 0; i < list.size(); ++i) { - ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(WEAPON_STATS)); + WEAPON_STATS *psStats = &asWeaponStats[i]; + + ini.beginGroup(list[i]); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_WEAPON; - psStats->buildPower = ini.value("buildPower", 0).toUInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toUInt(); psStats->weight = ini.value("weight", 0).toUInt(); psStats->body = ini.value("body", 0).toUInt(); psStats->radiusLife = ini.value("radiusLife", 0).toUInt(); @@ -429,7 +363,6 @@ bool loadWeaponStats(const char *pFileName) ASSERT(psStats->flightSpeed > 0, "Invalid flight speed for %s", list[i].toUtf8().constData()); - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); psStats->ref = REF_WEAPON_START + i; //get the IMD for the component @@ -558,9 +491,6 @@ bool loadWeaponStats(const char *pFileName) psStats->iAudioFireID = NO_SOUND; psStats->iAudioImpactID = NO_SOUND; - //save the stats - statsSetWeapon(psStats, i); - // Set the max stat values for the design screen if (psStats->designable) { @@ -579,24 +509,22 @@ bool loadWeaponStats(const char *pFileName) /*Load the Body stats from the file exported from Access*/ bool loadBodyStats(const char *pFileName) { - BODY_STATS sStats, * const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); statsAllocBody(list.size()); // Hack to make sure ZNULLBODY is always first in list int nullbody = list.indexOf("ZNULLBODY"); ASSERT_OR_RETURN(false, nullbody >= 0, "ZNULLBODY is mandatory"); - if (nullbody > 0) - { - list.swap(nullbody, 0); - } + list.swap(nullbody, 0); for (int i = 0; i < list.size(); ++i) { + BODY_STATS *psStats = &asBodyStats[i]; + ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(*psStats)); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_BODY; + psStats->weight = ini.value("weight", 0).toInt(); - psStats->buildPower = ini.value("buildPower", 0).toInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toInt(); psStats->body = ini.value("hitpoints").toInt(); psStats->weaponSlots = ini.value("weaponSlots").toInt(); psStats->designable = ini.value("designable", false).toBool(); @@ -647,9 +575,6 @@ bool loadBodyStats(const char *pFileName) ini.endGroup(); - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); - statsSetBody(psStats, i); // save the stats - //set the max stat values for the design screen if (psStats->designable) { @@ -666,42 +591,36 @@ bool loadBodyStats(const char *pFileName) /*Load the Brain stats from the file exported from Access*/ bool loadBrainStats(const char *pFileName) { - BRAIN_STATS sStats, * const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); statsAllocBrain(list.size()); // Hack to make sure ZNULLBRAIN is always first in list int nullbrain = list.indexOf("ZNULLBRAIN"); ASSERT_OR_RETURN(false, nullbrain >= 0, "ZNULLBRAIN is mandatory"); - if (nullbrain > 0) - { - list.swap(nullbrain, 0); - } + list.swap(nullbrain, 0); for (int i = 0; i < list.size(); ++i) { - ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(BRAIN_STATS)); + BRAIN_STATS *psStats = &asBrainStats[i]; + + ini.beginGroup(list[i]); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_BRAIN; - psStats->buildPower = ini.value("buildPower", 0).toInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toInt(); psStats->weight = ini.value("weight", 0).toInt(); psStats->maxDroids = ini.value("maxDroids").toInt(); psStats->maxDroidsMult = ini.value("maxDroidsMult").toInt(); psStats->ref = REF_BRAIN_START + i; - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); // check weapon attached psStats->psWeaponStat = NULL; if (ini.contains("turret")) { - int weapon = getCompFromName(COMP_WEAPON, ini.value("turret").toString().toUtf8().constData()); - ASSERT_OR_RETURN(false, weapon >= 0, "Unable to find weapon for brain %s", psStats->pName); + int weapon = getCompFromName(COMP_WEAPON, ini.value("turret").toString()); + ASSERT_OR_RETURN(false, weapon >= 0, "Unable to find weapon for brain %s", getStatName(psStats)); psStats->psWeaponStat = asWeaponStats + weapon; } psStats->designable = ini.value("designable", false).toBool(); ini.endGroup(); - // save the stats - statsSetBrain(psStats, i); } return true; } @@ -758,23 +677,21 @@ bool getPropulsionType(const char *typeName, PROPULSION_TYPE *type) /*Load the Propulsion stats from the file exported from Access*/ bool loadPropulsionStats(const char *pFileName) { - PROPULSION_STATS sStats, *const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); statsAllocPropulsion(list.size()); // Hack to make sure ZNULLPROP is always first in list int nullprop = list.indexOf("ZNULLPROP"); ASSERT_OR_RETURN(false, nullprop >= 0, "ZNULLPROP is mandatory"); - if (nullprop > 0) - { - list.swap(nullprop, 0); - } + list.swap(nullprop, 0); for (int i = 0; i < list.size(); ++i) { + PROPULSION_STATS *psStats = &asPropulsionStats[i]; + ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(*psStats)); - psStats->buildPower = ini.value("buildPower").toInt(); - psStats->buildPoints = ini.value("buildPoints").toInt(); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_PROPULSION; + psStats->weight = ini.value("weight").toInt(); psStats->body = ini.value("hitpoints").toInt(); psStats->maxSpeed = ini.value("speed").toInt(); @@ -795,10 +712,6 @@ bool loadPropulsionStats(const char *pFileName) } ini.endGroup(); - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); - // save the stats - statsSetPropulsion(psStats, i); - // set the max stat values for the design screen if (psStats->designable) { @@ -834,27 +747,21 @@ bool loadPropulsionStats(const char *pFileName) /*Load the Sensor stats from the file exported from Access*/ bool loadSensorStats(const char *pFileName) { - SENSOR_STATS sStats, * const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); - if (!statsAllocSensor(list.size())) - { - return false; - } + statsAllocSensor(list.size()); // Hack to make sure ZNULLSENSOR is always first in list int nullsensor = list.indexOf("ZNULLSENSOR"); ASSERT_OR_RETURN(false, nullsensor >= 0, "ZNULLSENSOR is mandatory"); - if (nullsensor > 0) - { - list.swap(nullsensor, 0); - } - + list.swap(nullsensor, 0); for (int i = 0; i < list.size(); ++i) { + SENSOR_STATS *psStats = &asSensorStats[i]; + ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(SENSOR_STATS)); - psStats->buildPower = ini.value("buildPower", 0).toInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toInt(); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_SENSOR; + psStats->weight = ini.value("weight", 0).toInt(); psStats->body = ini.value("bodyPoints", 0).toInt(); psStats->base.range = ini.value("range").toInt(); @@ -865,7 +772,6 @@ bool loadSensorStats(const char *pFileName) psStats->time = ini.value("time").toInt(); psStats->designable = ini.value("designable", false).toBool(); - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); psStats->ref = REF_SENSOR_START + i; QString location = ini.value("location").toString(); @@ -918,8 +824,6 @@ bool loadSensorStats(const char *pFileName) psStats->pMountGraphic = statsGetIMD(ini, psStats, "mountModel"); ini.endGroup(); - //save the stats - statsSetSensor(psStats, i); // set the max stat values for the design screen if (psStats->designable) @@ -935,27 +839,21 @@ bool loadSensorStats(const char *pFileName) /*Load the ECM stats from the file exported from Access*/ bool loadECMStats(const char *pFileName) { - ECM_STATS sStats, * const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); - if (!statsAllocECM(list.size())) - { - return false; - } + statsAllocECM(list.size()); // Hack to make sure ZNULLECM is always first in list int nullecm = list.indexOf("ZNULLECM"); ASSERT_OR_RETURN(false, nullecm >= 0, "ZNULLECM is mandatory"); - if (nullecm > 0) - { - list.swap(nullecm, 0); - } + list.swap(nullecm, 0); for (int i = 0; i < list.size(); ++i) { - ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(ECM_STATS)); + ECM_STATS *psStats = &asECMStats[i]; + + ini.beginGroup(list[i]); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_ECM; - psStats->buildPower = ini.value("buildPower", 0).toInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toInt(); psStats->weight = ini.value("weight", 0).toInt(); psStats->body = ini.value("body", 0).toInt(); psStats->base.range = ini.value("range").toInt(); @@ -965,7 +863,6 @@ bool loadECMStats(const char *pFileName) } psStats->designable = ini.value("designable", false).toBool(); - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); psStats->ref = REF_ECM_START + i; QString location = ini.value("location").toString(); @@ -987,8 +884,6 @@ bool loadECMStats(const char *pFileName) psStats->pMountGraphic = statsGetIMD(ini, psStats, "mountModel"); ini.endGroup(); - //save the stats - statsSetECM(psStats, i); // Set the max stat values for the design screen if (psStats->designable) @@ -1003,28 +898,21 @@ bool loadECMStats(const char *pFileName) /*Load the Repair stats from the file exported from Access*/ bool loadRepairStats(const char *pFileName) { - REPAIR_STATS sStats, * const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); - if (!statsAllocRepair(list.size())) - { - return false; - } + statsAllocRepair(list.size()); // Hack to make sure ZNULLREPAIR is always first in list int nullrepair = list.indexOf("ZNULLREPAIR"); ASSERT_OR_RETURN(false, nullrepair >= 0, "ZNULLREPAIR is mandatory"); - if (nullrepair > 0) - { - list.swap(nullrepair, 0); - } - + list.swap(nullrepair, 0); for (int i = 0; i < list.size(); ++i) { - ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(REPAIR_STATS)); + REPAIR_STATS *psStats = &asRepairStats[i]; + + ini.beginGroup(list[i]); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_REPAIRUNIT; - psStats->buildPower = ini.value("buildPower", 0).toInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toInt(); psStats->weight = ini.value("weight", 0).toInt(); psStats->base.repairPoints = ini.value("repairPoints").toInt(); for (int j = 0; j < MAX_PLAYERS; j++) @@ -1034,7 +922,6 @@ bool loadRepairStats(const char *pFileName) psStats->time = ini.value("time", 0).toInt() * WEAPON_TIME; psStats->designable = ini.value("designable", false).toBool(); - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); psStats->ref = REF_REPAIR_START + i; QString location = ini.value("location").toString(); @@ -1059,8 +946,6 @@ bool loadRepairStats(const char *pFileName) psStats->pMountGraphic = statsGetIMD(ini, psStats, "mountModel"); ini.endGroup(); - //save the stats - statsSetRepair(psStats, i); //set the max stat values for the design screen if (psStats->designable) @@ -1068,7 +953,6 @@ bool loadRepairStats(const char *pFileName) setMaxRepairPoints(psStats->base.repairPoints); setMaxComponentWeight(psStats->weight); } - } return true; } @@ -1076,27 +960,21 @@ bool loadRepairStats(const char *pFileName) /*Load the Construct stats from the file exported from Access*/ bool loadConstructStats(const char *pFileName) { - CONSTRUCT_STATS sStats, * const psStats = &sStats; WzConfig ini(pFileName, WzConfig::ReadOnlyAndRequired); QStringList list = ini.childGroups(); - if (!statsAllocConstruct(list.size())) - { - return false; - } + statsAllocConstruct(list.size()); // Hack to make sure ZNULLCONSTRUCT is always first in list int nullconstruct = list.indexOf("ZNULLCONSTRUCT"); ASSERT_OR_RETURN(false, nullconstruct >= 0, "ZNULLCONSTRUCT is mandatory"); - if (nullconstruct > 0) - { - list.swap(nullconstruct, 0); - } + list.swap(nullconstruct, 0); for (int i = 0; i < list.size(); ++i) { - ini.beginGroup(list[i]); - memset(psStats, 0, sizeof(CONSTRUCT_STATS)); + CONSTRUCT_STATS *psStats = &asConstructStats[i]; + + ini.beginGroup(list[i]); + loadCompStats(ini, psStats, i); + psStats->compType = COMP_CONSTRUCT; - psStats->buildPower = ini.value("buildPower", 0).toInt(); - psStats->buildPoints = ini.value("buildPoints", 0).toInt(); psStats->weight = ini.value("weight", 0).toInt(); psStats->body = ini.value("bodyPoints", 0).toInt(); psStats->base.constructPoints = ini.value("constructPoints").toInt(); @@ -1105,8 +983,6 @@ bool loadConstructStats(const char *pFileName) psStats->upgrade[j].constructPoints = psStats->base.constructPoints; } psStats->designable = ini.value("designable", false).toBool(); - - allocateStatName((BASE_STATS *)psStats, list[i].toUtf8().constData()); psStats->ref = REF_CONSTRUCT_START + i; //get the IMD for the component @@ -1114,8 +990,6 @@ bool loadConstructStats(const char *pFileName) psStats->pMountGraphic = statsGetIMD(ini, psStats, "mountModel"); ini.endGroup(); - //save the stats - statsSetConstruct(psStats, i); // Set the max stat values for the design screen if (psStats->designable) @@ -1278,7 +1152,7 @@ bool loadBodyPropulsionIMDs(const char *pFileName) for (numStats = 0; numStats < numBodyStats; ++numStats) { psBodyStat = &asBodyStats[numStats]; - if (list[i].compare(psBodyStat->pName) == 0) + if (list[i].compare(psBodyStat->id) == 0) { break; } @@ -1294,7 +1168,7 @@ bool loadBodyPropulsionIMDs(const char *pFileName) for (numStats = 0; numStats < numPropulsionStats; numStats++) { PROPULSION_STATS *psPropulsionStat = &asPropulsionStats[numStats]; - if (keys[j].compare(psPropulsionStat->pName) == 0) + if (keys[j].compare(psPropulsionStat->id) == 0) { break; } @@ -1393,7 +1267,7 @@ bool loadWeaponSounds(const char *pFileName) } for (inc = 0; inc < (SDWORD)numWeaponStats; ++inc) { - if (list[i].compare(asWeaponStats[inc].pName) == 0) + if (list[i].compare(asWeaponStats[inc].id) == 0) { asWeaponStats[inc].iAudioFireID = weaponSoundID; asWeaponStats[inc].iAudioImpactID = explosionSoundID; @@ -1692,97 +1566,23 @@ unsigned int componentType(const char *pType) //used in Scripts SDWORD getCompFromResName(UDWORD compType, const char *pName) { - return getCompFromName(compType, pName); + return getCompFromName((COMPONENT_TYPE)compType, pName); } -void getStatsDetails(UDWORD compType, BASE_STATS **ppsStats, UDWORD *pnumStats, UDWORD *pstatSize) +/// Get the component index for a stat based on the name, and verify correct type +int getCompFromName(COMPONENT_TYPE compType, const QString &name) { - - switch (compType) - { - case COMP_BODY: - *ppsStats = (BASE_STATS *)asBodyStats; - *pnumStats = numBodyStats; - *pstatSize = sizeof(BODY_STATS); - break; - case COMP_BRAIN: - *ppsStats = (BASE_STATS *)asBrainStats; - *pnumStats = numBrainStats; - *pstatSize = sizeof(BRAIN_STATS); - break; - case COMP_PROPULSION: - *ppsStats = (BASE_STATS *)asPropulsionStats; - *pnumStats = numPropulsionStats; - *pstatSize = sizeof(PROPULSION_STATS); - break; - case COMP_REPAIRUNIT: - *ppsStats = (BASE_STATS *)asRepairStats; - *pnumStats = numRepairStats; - *pstatSize = sizeof(REPAIR_STATS); - break; - case COMP_ECM: - *ppsStats = (BASE_STATS *)asECMStats; - *pnumStats = numECMStats; - *pstatSize = sizeof(ECM_STATS); - break; - case COMP_SENSOR: - *ppsStats = (BASE_STATS *)asSensorStats; - *pnumStats = numSensorStats; - *pstatSize = sizeof(SENSOR_STATS); - break; - case COMP_CONSTRUCT: - *ppsStats = (BASE_STATS *)asConstructStats; - *pnumStats = numConstructStats; - *pstatSize = sizeof(CONSTRUCT_STATS); - break; - case COMP_WEAPON: - *ppsStats = (BASE_STATS *)asWeaponStats; - *pnumStats = numWeaponStats; - *pstatSize = sizeof(WEAPON_STATS); - break; - default: - debug(LOG_FATAL, "Invalid component type"); - } + COMPONENT_STATS *psComp = lookupStatPtr.value(name, NULL); + ASSERT_OR_RETURN(-1, psComp, "No such component [%s] found", name.toUtf8().constData()); + ASSERT_OR_RETURN(-1, compType == psComp->compType, "Wrong component type for %s", name.toUtf8().constData()); + return psComp->index; } - -//get the component Inc for a stat based on the name and type -//returns -1 if record not found -SDWORD getCompFromName(UDWORD compType, const char *pName) +/// Get the component for a stat based on the name alone. +/// Returns NULL if record not found +COMPONENT_STATS *getCompStatsFromName(const QString &name) { - BASE_STATS *psStats = NULL; - UDWORD numStats = 0, count, statSize = 0; - - getStatsDetails(compType, &psStats, &numStats, &statSize); - - //find the stat with the same name - for (count = 0; count < numStats; count++) - { - if (!strcmp(pName, psStats->pName)) - { - return count; - } - psStats = (BASE_STATS *)((char *)psStats + statSize); - } - - //return -1 if record not found or an invalid component type is passed in - return -1; -} - -/*return the name to display for the interface - valid for OBJECTS and STATS*/ -const char *getName(const char *pNameID) -{ - /* See if the name has a string resource associated with it by trying - * to get the string resource. - */ - const char *const name = strresGetString(psStringRes, pNameID); - if (!name) - { - debug(LOG_ERROR, "Unable to find string resource for %s", pNameID); - return "Name Unknown"; - } - - return name; + return lookupStatPtr.value(name, NULL); } /*sets the store to the body size based on the name passed in - returns false @@ -2016,25 +1816,6 @@ bool getWeaponClass(QString weaponClassStr, WEAPON_CLASS *weaponClass) return true; } - -/* -looks up the name to get the resource associated with it - or allocates space -and stores the name. Eventually ALL names will be 'resourced' for translation -*/ -char *allocateName(const char *name) -{ - /* Check whether the given string has a string resource associated with - * it. - */ - if (!strresGetString(psStringRes, name)) - { - ASSERT(false, "Unable to find string resource for %s", name); - return NULL; - } - return strdup(name); -} - - /*Access functions for the upgradeable stats of a weapon*/ int weaponFirePause(const WEAPON_STATS *psStats, int player) { diff --git a/src/stats.h b/src/stats.h index 17beb79af..805d17155 100644 --- a/src/stats.h +++ b/src/stats.h @@ -182,7 +182,8 @@ extern UDWORD statRefStart(UDWORD stat); /*Returns the component type based on the string - used for reading in data */ extern UDWORD componentType(const char* pType); //get the component Inc for a stat based on the name -extern SDWORD getCompFromName(UDWORD compType, const char *pName); +int getCompFromName(COMPONENT_TYPE compType, const QString &name); +COMPONENT_STATS *getCompStatsFromName(const QString &name); //get details for given component type extern void getStatsDetails(UDWORD compType, BASE_STATS **ppsStats, UDWORD *pnumStats, UDWORD *pstatSize); //get the component Inc for a stat based on the Resource name held in Names.txt @@ -190,17 +191,10 @@ extern SDWORD getCompFromResName(UDWORD compType, const char *pName); /*returns the weapon sub class based on the string name passed in */ extern bool getWeaponSubClass(const char* subClass, WEAPON_SUBCLASS* wclass); const char *getWeaponSubClass(WEAPON_SUBCLASS wclass); -/*either gets the name associated with the resource (if one) or allocates space and copies pName*/ -extern char* allocateName(const char* name); -/*return the name to display for the interface - valid for OBJECTS and STATS*/ -extern const char* getName(const char *pNameID); /*sets the store to the body size based on the name passed in - returns false if doesn't compare with any*/ extern bool getBodySize(const char *pSize, BODY_SIZE *pStore); -// Pass in a stat and get its name -extern const char* getStatName(const void * pStat); - /** * Determines the propulsion type indicated by the @c typeName string passed * in. diff --git a/src/statsdef.h b/src/statsdef.h index a9c7370e8..620196d41 100644 --- a/src/statsdef.h +++ b/src/statsdef.h @@ -52,32 +52,6 @@ enum DROID_TYPE }; static inline bool stringToEnumSortFunction(std::pair const &a, std::pair const &b) { return strcmp(a.first, b.first) < 0; } -template -static inline STATS *findStatsByName(std::string const &name, STATS *asStats, unsigned numStats) -{ - for (unsigned inc = 0; inc < numStats; ++inc) // Could be more efficient, if the stats were sorted by name... - { - //compare the names - if (name == asStats[inc].pName) - { - return &asStats[inc]; - } - } - return NULL; // Not found. -} -template -static inline STATS *findStatsByName(std::string const &name, STATS **asStats, unsigned numStats) -{ - for (unsigned inc = 0; inc < numStats; ++inc) // Could be more efficient, if the stats were sorted by name... - { - //compare the names - if (name == asStats[inc]->pName) - { - return asStats[inc]; - } - } - return NULL; // Not found. -} template struct StringToEnum @@ -264,29 +238,38 @@ enum TRAVEL_MEDIUM /* Stats common to all stats structs */ struct BASE_STATS { - BASE_STATS(unsigned ref = 0) : ref(ref), pName(NULL) {} ///< Only initialised here when using new/delete! TODO Use new/delete only, not malloc()/free(). - BASE_STATS(unsigned ref, std::string const &str); ///< Only initialised here when using new/delete! TODO Use new/delete only, not malloc()/free(). TODO Then pName could be a QString... - //Gah, too soon to add destructors to BASE_STATS, thanks to local temporaries that are copied with memcpy()... --- virtual ~BASE_STATS() { free(pName); } ///< pName is only freed here when using new/delete! TODO Use new/delete only, not malloc()/free(). - //So this one isn't needed for now, maybe not ever. --- BASE_STATS(BASE_STATS const &stats) : ref(stats.ref), pName(strdup(stats.pName)) {} // TODO Not needed when pName is a QString... - //So this one isn't needed for now, maybe not ever. --- BASE_STATS const &operator =(BASE_STATS const &stats) { ref = stats.ref; free(pName); pName = strdup(stats.pName); return *this; } // TODO Not needed when pName is a QString... + BASE_STATS(unsigned ref = 0) : ref(ref) {} - UDWORD ref; /**< Unique ID of the item */ - char *pName; /**< pointer to the text id name (i.e. short language-independant name) */ + UDWORD ref; /**< Unique ID of the item */ + QString id; /**< Text id (i.e. short language-independant name) */ + QString name; /**< Full / real name of the item */ }; +#define getName(_psStats) (_psStats)->name.toUtf8().constData() +#define getStatName(_psStats) (_psStats)->name.toUtf8().constData() +#define getID(_psStats) (_psStats)->id.toUtf8().constData() + /* Stats common to all droid components */ struct COMPONENT_STATS : public BASE_STATS { + COMPONENT_STATS() : buildPower(0), buildPoints(0), weight(0), body(0), designable(false), pIMD(NULL), + compType(COMP_NUMCOMPONENTS), index(0) {} + UDWORD buildPower; /**< Power required to build the component */ UDWORD buildPoints; /**< Time required to build the component */ UDWORD weight; /**< Component's weight */ UDWORD body; /**< Component's body points */ bool designable; /**< flag to indicate whether this component can be used in the design screen */ iIMDShape *pIMD; /**< The IMD to draw for this component */ + COMPONENT_TYPE compType; + int index; ///< Index into containing array }; struct PROPULSION_STATS : public COMPONENT_STATS { + PROPULSION_STATS() : maxSpeed(0), propulsionType(PROPULSION_TYPE_NUM), turnSpeed(0), spinSpeed(0), + spinAngle(0), skidDeceleration(0), deceleration(0), acceleration(0) {} + UDWORD maxSpeed; ///< Max speed for the droid PROPULSION_TYPE propulsionType; ///< Type of propulsion used - index into PropulsionTable UDWORD turnSpeed; @@ -299,6 +282,12 @@ struct PROPULSION_STATS : public COMPONENT_STATS struct SENSOR_STATS : public COMPONENT_STATS { + SENSOR_STATS() : location(0), type(STANDARD_SENSOR), time(0), pMountGraphic(NULL) + { + memset(&upgrade, 0, sizeof(upgrade)); + memset(&base, 0, sizeof(base)); + } + UDWORD location; ///< specifies whether the Sensor is default or for the Turret SENSOR_TYPE type; ///< used for combat UDWORD time; ///< time delay before associated weapon droids 'know' where the attack is from @@ -312,6 +301,12 @@ struct SENSOR_STATS : public COMPONENT_STATS struct ECM_STATS : public COMPONENT_STATS { + ECM_STATS() : location(0), pMountGraphic(NULL) + { + memset(&upgrade, 0, sizeof(upgrade)); + memset(&base, 0, sizeof(base)); + } + UDWORD location; ///< specifies whether the ECM is default or for the Turret iIMDShape *pMountGraphic; ///< The turret mount to use @@ -323,6 +318,12 @@ struct ECM_STATS : public COMPONENT_STATS struct REPAIR_STATS : public COMPONENT_STATS { + REPAIR_STATS() : location(0), time(0), pMountGraphic(NULL) + { + memset(&upgrade, 0, sizeof(upgrade)); + memset(&base, 0, sizeof(base)); + } + UDWORD location; ///< specifies whether the Repair is default or for the Turret UDWORD time; ///< time delay for repair cycle iIMDShape *pMountGraphic; ///< The turret mount to use @@ -335,6 +336,14 @@ struct REPAIR_STATS : public COMPONENT_STATS struct WEAPON_STATS : public COMPONENT_STATS { + WEAPON_STATS() : pMountGraphic(NULL), pMuzzleGraphic(NULL), pInFlightGraphic(NULL), pTargetHitGraphic(NULL), + pTargetMissGraphic(NULL), pWaterHitGraphic(NULL), pTrailGraphic(NULL), iAudioFireID(0), + iAudioImpactID(0) + { + memset(&upgrade, 0, sizeof(upgrade)); + memset(&base, 0, sizeof(base)); + } + struct { short maxRange; @@ -395,6 +404,12 @@ struct WEAPON_STATS : public COMPONENT_STATS struct CONSTRUCT_STATS : public COMPONENT_STATS { + CONSTRUCT_STATS() : pMountGraphic(NULL) + { + memset(&upgrade, 0, sizeof(upgrade)); + memset(&base, 0, sizeof(base)); + } + iIMDShape *pMountGraphic; ///< The turret mount to use struct @@ -405,21 +420,28 @@ struct CONSTRUCT_STATS : public COMPONENT_STATS struct BRAIN_STATS : public COMPONENT_STATS { + BRAIN_STATS() : psWeaponStat(NULL), maxDroids(0), maxDroidsMult(0) {} + WEAPON_STATS *psWeaponStat; ///< weapon stats associated with this brain - for Command Droids UDWORD maxDroids; ///< base maximum number of droids that the commander can control UDWORD maxDroidsMult; ///< maximum number of controlled droids multiplied by level }; - /* * Stats structures type definitions */ #define SHOOT_ON_GROUND 0x01 #define SHOOT_IN_AIR 0x02 - struct BODY_STATS : public COMPONENT_STATS { + BODY_STATS() : size(SIZE_NUM), weaponSlots(0), droidTypeOverride(DROID_ANY), ppIMDList(NULL), pFlameIMD(NULL) + { + memset(bodyClass, 0, sizeof(bodyClass)); + memset(&upgrade, 0, sizeof(upgrade)); + memset(&base, 0, sizeof(base)); + } + BODY_SIZE size; ///< How big the body is - affects how hit UDWORD weaponSlots; ///< The number of weapon slots on the body DROID_TYPE droidTypeOverride; // if not DROID_ANY, sets droid type diff --git a/src/structure.cpp b/src/structure.cpp index 576beed74..665db902d 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -163,16 +163,6 @@ static int constructorLimit[MAX_PLAYERS]; #define MAX_UNIT_MESSAGE_PAUSE 20000 -/* -Check to see if the stats is some kind of expansion module - -... this replaces the thousands of occurance that is spread through out the code - -... There were a couple of places where it skipping around a routine if the stat was a expansion module - (loadSaveStructureV7 & 9) this code seemed suspect, and to clarify it we replaced it with the routine below -... the module stuff seemed to work though ... TJC (& AB) 8-DEC-98 -*/ - static void auxStructureNonblocking(STRUCTURE *psStructure) { StructureBounds b = getStructureBounds(psStructure); @@ -455,18 +445,18 @@ bool loadStructureStats(QString filename) { ini.beginGroup(list[inc]); STRUCTURE_STATS *psStats = &asStructureStats[inc]; - psStats->pName = allocateName(list[inc].toUtf8().constData()); - ASSERT_OR_RETURN(false, psStats->pName != NULL, "Failed allocating structure ID"); + psStats->name = ini.value("name").toString(); + psStats->id = list[inc]; // check that the name has not been used already - ASSERT_OR_RETURN(false, !checkIDdict.contains(psStats->pName), "Structure ID '%s' used already", psStats->pName); - checkIDdict.insert(psStats->pName,0); + ASSERT_OR_RETURN(false, !checkIDdict.contains(getID(psStats)), "Structure ID '%s' used already", getID(psStats)); + checkIDdict.insert(psStats->id, inc); psStats->ref = REF_STRUCTURE_START + inc; // set structure type QString type = ini.value("type", "").toString(); - ASSERT_OR_RETURN(false, structType.contains(type), "Invalid type '%s' of structure '%s'", type.toUtf8().constData(), psStats->pName); + ASSERT_OR_RETURN(false, structType.contains(type), "Invalid type '%s' of structure '%s'", type.toUtf8().constData(), getID(psStats)); psStats->type = structType[type]; // save indexes of special structures for futher use @@ -496,16 +486,16 @@ bool loadStructureStats(QString filename) // set structure strength QString strength = ini.value("strength", "").toString(); - ASSERT_OR_RETURN(false, structStrength.contains(strength), "Invalid strength '%s' of structure '%s'", strength.toUtf8().constData(), psStats->pName); + ASSERT_OR_RETURN(false, structStrength.contains(strength), "Invalid strength '%s' of structure '%s'", strength.toUtf8().constData(), getID(psStats)); psStats->strength = structStrength[strength]; // set baseWidth psStats->baseWidth = ini.value("baseWidth", 0).toUInt(); - ASSERT_OR_RETURN(false, psStats->baseWidth <= 100, "Invalid baseWidth '%d' for structure '%s'", psStats->baseWidth, psStats->pName); + ASSERT_OR_RETURN(false, psStats->baseWidth <= 100, "Invalid baseWidth '%d' for structure '%s'", psStats->baseWidth, getID(psStats)); // set baseBreadth psStats->baseBreadth = ini.value("baseBreadth", 0).toUInt(); - ASSERT_OR_RETURN(false, psStats->baseBreadth < 100, "Invalid baseBreadth '%d' for structure '%s'", psStats->baseBreadth, psStats->pName); + ASSERT_OR_RETURN(false, psStats->baseBreadth < 100, "Invalid baseBreadth '%d' for structure '%s'", psStats->baseBreadth, getID(psStats)); psStats->height = ini.value("height").toUInt(); psStats->powerToBuild = ini.value("buildPower").toUInt(); @@ -516,7 +506,7 @@ bool loadStructureStats(QString filename) for (int j = 0; j < models.size(); j++) { iIMDShape *imd = (iIMDShape *)resGetData("IMD", models[j].trimmed().toUtf8().constData()); - ASSERT(imd != NULL, "Cannot find the PIE structureModel '%s' for structure '%s'", models[j].toUtf8().constData(), psStats->pName); + ASSERT(imd != NULL, "Cannot find the PIE structureModel '%s' for structure '%s'", models[j].toUtf8().constData(), getID(psStats)); psStats->pIMD.push_back(imd); } @@ -525,26 +515,29 @@ bool loadStructureStats(QString filename) if (baseModel.compare("") != 0) { iIMDShape *imd = (iIMDShape *)resGetData("IMD", baseModel.toUtf8().constData()); - ASSERT(imd != NULL, "Cannot find the PIE baseModel '%s' for structure '%s'", baseModel.toUtf8().constData(), psStats->pName); + ASSERT(imd != NULL, "Cannot find the PIE baseModel '%s' for structure '%s'", baseModel.toUtf8().constData(), getID(psStats)); psStats->pBaseIMD = imd; } - psStats->pECM = findStatsByName(ini.value("ecmID", "ZNULLECM").toString().toUtf8().constData(), asECMStats, numECMStats); - ASSERT(psStats->pECM != NULL, "Invalid ECM found for '%s'", psStats->pName); + int ecm = getCompFromName(COMP_ECM, ini.value("ecmID", "ZNULLECM").toString()); + ASSERT(ecm >= 0, "Invalid ECM found for '%s'", getID(psStats)); + psStats->pECM = asECMStats + ecm; - psStats->pSensor = findStatsByName(ini.value("sensorID", "ZNULLSENSOR").toString().toUtf8().constData(), asSensorStats, numSensorStats); - ASSERT(psStats->pSensor != NULL, "Invalid sensor found for structure '%s'", psStats->pName); + int sensor = getCompFromName(COMP_SENSOR, ini.value("sensorID", "ZNULLSENSOR").toString()); + ASSERT(sensor >= 0, "Invalid sensor found for structure '%s'", getID(psStats)); + psStats->pSensor = asSensorStats + sensor; // set list of weapons std::fill_n(psStats->psWeapStat, STRUCT_MAXWEAPS, (WEAPON_STATS *)NULL); QStringList weapons = ini.value("weapons").toStringList(); - ASSERT_OR_RETURN(false, weapons.size() <= STRUCT_MAXWEAPS, "Too many weapons are attached to structure '%s'. Maximum is %d", psStats->pName, STRUCT_MAXWEAPS); + ASSERT_OR_RETURN(false, weapons.size() <= STRUCT_MAXWEAPS, "Too many weapons are attached to structure '%s'. Maximum is %d", getID(psStats), STRUCT_MAXWEAPS); psStats->numWeaps = weapons.size(); for (int j = 0; j < psStats->numWeaps; j++) { QString weaponsID = weapons[j].trimmed(); - WEAPON_STATS *pWeap = findStatsByName(weaponsID.toUtf8().constData(), asWeaponStats, numWeaponStats); - ASSERT_OR_RETURN(false, pWeap, "Invalid item '%s' in list of weapons of structure '%s' ", weaponsID.toUtf8().constData(), psStats->pName); + int weapon = getCompFromName(COMP_WEAPON, weaponsID); + ASSERT_OR_RETURN(false, weapon >= 0, "Invalid item '%s' in list of weapons of structure '%s' ", weaponsID.toUtf8().constData(), getID(psStats)); + WEAPON_STATS *pWeap = asWeaponStats + weapon; psStats->psWeapStat[j] = pWeap; } @@ -553,7 +546,7 @@ bool loadStructureStats(QString filename) types += psStats->numWeaps != 0; types += psStats->pECM != NULL && psStats->pECM->location == LOC_TURRET; types += psStats->pSensor != NULL && psStats->pSensor->location == LOC_TURRET; - ASSERT(types <= 1, "Too many turret types for structure '%s'", psStats->pName); + ASSERT(types <= 1, "Too many turret types for structure '%s'", getID(psStats)); ini.endGroup(); } @@ -630,7 +623,7 @@ void setCurrentStructQuantity(bool displayError) { //check quantity never exceeds the limit ASSERT(psStructLimits[inc].currentQuantity <= psStructLimits[inc].limit, - "There appears to be too many %s on this map!", asStructureStats[inc].pName); + "There appears to be too many %s on this map!", getName(&asStructureStats[inc])); } } } @@ -1299,7 +1292,7 @@ STRUCTURE* buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y ASSERT_OR_RETURN(NULL, max <= numStructureStats, "Invalid structure type"); - if (!strcmp(pStructureType->pName, "A0CyborgFactory") && player == 0 && !bMultiPlayer) + if (pStructureType->id.compare("A0CyborgFactory") == 0 && player == 0 && !bMultiPlayer) { // HACK: correcting SP bug, needs fixing in script(!!) (only applies for player 0) // should be OK for Skirmish/MP games, since that is set correctly. @@ -1311,7 +1304,7 @@ STRUCTURE* buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y if (asStructLimits[player][max].currentQuantity + 1 > asStructLimits[player][max].limit) { debug(LOG_ERROR, "Player %u: Building %s could not be built due to building limits (has %d, max %d)!", - player, pStructureType->pName, asStructLimits[player][max].currentQuantity, + player, getName(pStructureType), asStructLimits[player][max].currentQuantity, asStructLimits[player][max].limit); return NULL; } @@ -1417,8 +1410,8 @@ STRUCTURE* buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y else if (TileHasStructure(psTile)) { debug(LOG_ERROR, "Player %u (%s): is building %s at (%d, %d) but found %s already at (%d, %d)", - player, isHumanPlayer(player) ? "Human" : "AI", pStructureType->pName, map.x, map.y, - getTileStructure(map.x + width, map.y + breadth)->pStructureType->pName, + player, isHumanPlayer(player) ? "Human" : "AI", getName(pStructureType), map.x, map.y, + getName(getTileStructure(map.x + width, map.y + breadth)->pStructureType), map.x + width, map.y + breadth); delete psBuilding; return NULL; @@ -3857,7 +3850,7 @@ UDWORD fillStructureList(STRUCTURE_STATS **ppList, UDWORD selectedPlayer, UDWORD } } - debug(LOG_NEVER, "adding %s (%x)", psBuilding->pName, apStructTypeLists[selectedPlayer][inc]); + debug(LOG_NEVER, "adding %s (%x)", getName(psBuilding), apStructTypeLists[selectedPlayer][inc]); ppList[count++] = psBuilding; if (count == limit) { @@ -4699,13 +4692,10 @@ bool destroyStruct(STRUCTURE *psDel, unsigned impactTime) return the first one it finds!! */ int32_t getStructStatFromName(char const *pName) { - UDWORD inc; - STRUCTURE_STATS *psStat; - - for (inc = 0; inc < numStructureStats; inc++) + for (int inc = 0; inc < numStructureStats; inc++) { - psStat = &asStructureStats[inc]; - if (!strcmp(psStat->pName, pName)) + STRUCTURE_STATS *psStat = &asStructureStats[inc]; + if (psStat->id.compare(pName) == 0) { return inc; } @@ -5934,7 +5924,7 @@ void factoryReward(UBYTE losingPlayer, UBYTE rewardPlayer) { CONPRINTF(ConsoleString,(ConsoleString,"%s :- %s", _("Factory Reward - Propulsion"), - getName(asPropulsionStats[comp].pName))); + getName(&asPropulsionStats[comp]))); } return; } @@ -5958,7 +5948,7 @@ void factoryReward(UBYTE losingPlayer, UBYTE rewardPlayer) { CONPRINTF(ConsoleString,(ConsoleString,"%s :- %s", _("Factory Reward - Body"), - getName(asBodyStats[comp].pName))); + getName(&asBodyStats[comp]))); } return; } @@ -5982,7 +5972,7 @@ void factoryReward(UBYTE losingPlayer, UBYTE rewardPlayer) { CONPRINTF(ConsoleString,(ConsoleString,"%s :- %s", _("Factory Reward - Weapon"), - getName(asWeaponStats[comp].pName))); + getName(&asWeaponStats[comp]))); } return; } @@ -6019,7 +6009,7 @@ void repairFacilityReward(UBYTE losingPlayer, UBYTE rewardPlayer) { CONPRINTF(ConsoleString,(ConsoleString,"%s :- %s", _("Repair Facility Award - Repair"), - getName(asRepairStats[comp].pName))); + getName(&asRepairStats[comp]))); } return; } diff --git a/src/template.cpp b/src/template.cpp index a8e90eeeb..07aef5a36 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -94,7 +94,7 @@ bool researchedTemplate(DROID_TEMPLATE *psCurr, int player, bool allowRedundant, bool researchedEverything = resBody && resBrain && resProp && resSensor && resEcm && resRepair && resConstruct; if (verbose && !researchedEverything) { - debug(LOG_ERROR, "%s : not researched : body=%d brai=%d prop=%d sensor=%d ecm=%d rep=%d con=%d", psCurr->aName, + debug(LOG_ERROR, "%s : not researched : body=%d brai=%d prop=%d sensor=%d ecm=%d rep=%d con=%d", getName(psCurr), (int)resBody, (int)resBrain, (int)resProp, (int)resSensor, (int)resEcm, (int)resRepair, (int)resConstruct); } unsigned ignoreFirstWeapon = psCurr->asParts[COMP_BRAIN] != 0? 1 : 0; @@ -103,7 +103,7 @@ bool researchedTemplate(DROID_TEMPLATE *psCurr, int player, bool allowRedundant, researchedEverything = researchedWeap(psCurr, player, weapIndex, allowRedundant); if (!researchedEverything && verbose) { - debug(LOG_ERROR, "%s : not researched weapon %u", psCurr->aName, weapIndex); + debug(LOG_ERROR, "%s : not researched weapon %u", getName(psCurr), weapIndex); } } return researchedEverything; @@ -122,19 +122,18 @@ bool initTemplates() { ini.beginGroup(list[i]); DROID_TEMPLATE design; - design.pName = NULL; design.droidType = (DROID_TYPE)ini.value("droidType").toInt(); design.multiPlayerID = generateNewObjectId(); - design.asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", QString("ZNULLBODY")).toString().toUtf8().constData()); - design.asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", QString("ZNULLBRAIN")).toString().toUtf8().constData()); - design.asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", QString("ZNULLPROP")).toString().toUtf8().constData()); - design.asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", QString("ZNULLREPAIR")).toString().toUtf8().constData()); - design.asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", QString("ZNULLECM")).toString().toUtf8().constData()); - design.asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", QString("ZNULLSENSOR")).toString().toUtf8().constData()); - design.asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", QString("ZNULLCONSTRUCT")).toString().toUtf8().constData()); - design.asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", QString("ZNULLWEAPON")).toString().toUtf8().constData()); - design.asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", QString("ZNULLWEAPON")).toString().toUtf8().constData()); - design.asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", QString("ZNULLWEAPON")).toString().toUtf8().constData()); + design.asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("body", QString("ZNULLBODY")).toString()); + design.asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("brain", QString("ZNULLBRAIN")).toString()); + design.asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("propulsion", QString("ZNULLPROP")).toString()); + design.asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("repair", QString("ZNULLREPAIR")).toString()); + design.asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("ecm", QString("ZNULLECM")).toString()); + design.asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("sensor", QString("ZNULLSENSOR")).toString()); + design.asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("construct", QString("ZNULLCONSTRUCT")).toString()); + design.asWeaps[0] = getCompFromName(COMP_WEAPON, ini.value("weapon/1", QString("ZNULLWEAPON")).toString()); + design.asWeaps[1] = getCompFromName(COMP_WEAPON, ini.value("weapon/2", QString("ZNULLWEAPON")).toString()); + design.asWeaps[2] = getCompFromName(COMP_WEAPON, ini.value("weapon/3", QString("ZNULLWEAPON")).toString()); design.numWeaps = ini.value("weapons").toInt(); design.prefab = false; // not AI template design.stored = true; @@ -163,7 +162,7 @@ bool initTemplates() { // Check if template is identical to a loaded template if (psDestTemplate->droidType == design.droidType - && strcmp(psDestTemplate->aName, design.aName) == 0 + && psDestTemplate->name.compare(design.name) == 0 && psDestTemplate->numWeaps == design.numWeaps && psDestTemplate->asWeaps[0] == design.asWeaps[0] && psDestTemplate->asWeaps[1] == design.asWeaps[1] @@ -208,34 +207,34 @@ bool storeTemplates() { if (!psCurr->stored) continue; // not stored ini.beginGroup("template_" + QString::number(psCurr->multiPlayerID)); - ini.setValue("name", psCurr->aName); + ini.setValue("name", psCurr->name); ini.setValue("droidType", psCurr->droidType); - ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->pName); - ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->pName); + ini.setValue("body", (asBodyStats + psCurr->asParts[COMP_BODY])->id); + ini.setValue("propulsion", (asPropulsionStats + psCurr->asParts[COMP_PROPULSION])->id); if (psCurr->asParts[COMP_BRAIN] != 0) { - ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->pName); + ini.setValue("brain", (asBrainStats + psCurr->asParts[COMP_BRAIN])->id); } if ((asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->location == LOC_TURRET) // avoid auto-repair... { - ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->pName); + ini.setValue("repair", (asRepairStats + psCurr->asParts[COMP_REPAIRUNIT])->id); } if ((asECMStats + psCurr->asParts[COMP_ECM])->location == LOC_TURRET) { - ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->pName); + ini.setValue("ecm", (asECMStats + psCurr->asParts[COMP_ECM])->id); } if ((asSensorStats + psCurr->asParts[COMP_SENSOR])->location == LOC_TURRET) { - ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->pName); + ini.setValue("sensor", (asSensorStats + psCurr->asParts[COMP_SENSOR])->id); } if (psCurr->asParts[COMP_CONSTRUCT] != 0) { - ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->pName); + ini.setValue("construct", (asConstructStats + psCurr->asParts[COMP_CONSTRUCT])->id); } ini.setValue("weapons", psCurr->numWeaps); for (int j = 0; j < psCurr->numWeaps; j++) { - ini.setValue("weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j])->pName); + ini.setValue("weapon/" + QString::number(j + 1), (asWeaponStats + psCurr->asWeaps[j])->id); } ini.endGroup(); } @@ -249,7 +248,6 @@ bool shutdownTemplates() DROID_TEMPLATE::DROID_TEMPLATE() // This constructor replaces a memset in scrAssembleWeaponTemplate(), not needed elsewhere. : BASE_STATS(REF_TEMPLATE_START) - //, aName //, asParts , numWeaps(0) //, asWeaps @@ -260,7 +258,6 @@ DROID_TEMPLATE::DROID_TEMPLATE() // This constructor replaces a memset in scrAs , stored(false) , enabled(false) { - aName[0] = '\0'; std::fill_n(asParts, DROID_MAXCOMP, 0); std::fill_n(asWeaps, DROID_MAXWEAPS, 0); } @@ -275,7 +272,8 @@ bool loadDroidTemplates(const char *filename) ini.beginGroup(list[i]); DROID_TEMPLATE design; QString droidType = ini.value("type").toString(); - design.pName = strdup(list[i].toUtf8().constData()); + design.id = list[i]; + design.name = ini.value("name").toString(); if (droidType == "PERSON") design.droidType = DROID_PERSON; else if (droidType == "CYBORG") design.droidType = DROID_CYBORG; else if (droidType == "CYBORG_SUPER") design.droidType = DROID_CYBORG_SUPER; @@ -284,19 +282,19 @@ bool loadDroidTemplates(const char *filename) else if (droidType == "TRANSPORTER") design.droidType = DROID_TRANSPORTER; else if (droidType == "SUPERTRANSPORTER") design.droidType = DROID_SUPERTRANSPORTER; else if (droidType == "DROID") design.droidType = DROID_DEFAULT; - else ASSERT(false, "No such droid type \"%s\" for %s", droidType.toUtf8().constData(), design.pName); + else ASSERT(false, "No such droid type \"%s\" for %s", droidType.toUtf8().constData(), getID(&design)); design.multiPlayerID = generateNewObjectId(); - design.asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("compBody", "ZNULLBODY").toString().toUtf8().constData()); - design.asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("compBrain", "ZNULLBRAIN").toString().toUtf8().constData()); - design.asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("compRepair", "ZNULLREPAIR").toString().toUtf8().constData()); - design.asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("compConstruct", "ZNULLCONSTRUCT").toString().toUtf8().constData()); - design.asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("compECM", "ZNULLECM").toString().toUtf8().constData()); - design.asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("compSensor", "ZNULLSENSOR").toString().toUtf8().constData()); - design.asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("compPropulsion", "ZNULLPROP").toString().toUtf8().constData()); + design.asParts[COMP_BODY] = getCompFromName(COMP_BODY, ini.value("compBody", "ZNULLBODY").toString()); + design.asParts[COMP_BRAIN] = getCompFromName(COMP_BRAIN, ini.value("compBrain", "ZNULLBRAIN").toString()); + design.asParts[COMP_REPAIRUNIT] = getCompFromName(COMP_REPAIRUNIT, ini.value("compRepair", "ZNULLREPAIR").toString()); + design.asParts[COMP_CONSTRUCT] = getCompFromName(COMP_CONSTRUCT, ini.value("compConstruct", "ZNULLCONSTRUCT").toString()); + design.asParts[COMP_ECM] = getCompFromName(COMP_ECM, ini.value("compECM", "ZNULLECM").toString()); + design.asParts[COMP_SENSOR] = getCompFromName(COMP_SENSOR, ini.value("compSensor", "ZNULLSENSOR").toString()); + design.asParts[COMP_PROPULSION] = getCompFromName(COMP_PROPULSION, ini.value("compPropulsion", "ZNULLPROP").toString()); QStringList weapons = ini.value("weapons").toStringList(); for (int j = 0; j < weapons.size(); j++) { - design.asWeaps[j] = getCompFromName(COMP_WEAPON, weapons[j].toUtf8().constData()); + design.asWeaps[j] = getCompFromName(COMP_WEAPON, weapons[j]); } design.numWeaps = weapons.size(); design.prefab = true; @@ -304,7 +302,7 @@ bool loadDroidTemplates(const char *filename) design.enabled = true; bool available = ini.value("available", false).toBool(); char const *droidResourceName = getDroidResourceName(list[i].toUtf8().constData()); - sstrcpy(design.aName, droidResourceName != NULL? droidResourceName : GetDefaultTemplateName(&design)); + design.name = droidResourceName != NULL? droidResourceName : GetDefaultTemplateName(&design); ini.endGroup(); for (int i = 0; i < MAX_PLAYERS; ++i) @@ -324,26 +322,25 @@ bool loadDroidTemplates(const char *filename) DROID_TEMPLATE *psCurr = &*it; if (psCurr->multiPlayerID == design.multiPlayerID) { - debug(LOG_ERROR, "Design id:%d (%s) *NOT* added to UI list (duplicate), player= %d", design.multiPlayerID, design.aName, i); + debug(LOG_ERROR, "Design id:%d (%s) *NOT* added to UI list (duplicate), player= %d", design.multiPlayerID, getName(&design), i); break; } } if (it == localTemplates.end()) { - debug(LOG_NEVER, "Design id:%d (%s) added to UI list, player =%d", design.multiPlayerID, design.aName, i); + debug(LOG_NEVER, "Design id:%d (%s) added to UI list, player =%d", design.multiPlayerID, getName(&design), i); localTemplates.push_front(design); - localTemplates.front().pName = strdup(localTemplates.front().pName); } } else if (!NetPlay.players[i].allocated) // AI template { - debug(LOG_NEVER, "AI (%d): %s id:%d enabled:%d", i, design.aName, design.multiPlayerID, design.enabled); + debug(LOG_NEVER, "AI (%d): %s id:%d enabled:%d", i, getName(&design), design.multiPlayerID, design.enabled); design.prefab = true; // prefabricated templates referenced from VLOs addTemplateToList(&design, &apsDroidTemplates[i]); } } - debug(LOG_NEVER, "Droid template found, aName: %s, MP ID: %d, ref: %u, pname: %s, prefab: %s, type:%d (loading)", - design.aName, design.multiPlayerID, design.ref, design.pName, design.prefab ? "yes":"no", design.droidType); + debug(LOG_NEVER, "Droid template found, Name: %s, MP ID: %d, ref: %u, ID: %s, prefab: %s, type:%d (loading)", + getName(&design), design.multiPlayerID, design.ref, getID(&design), design.prefab ? "yes":"no", design.droidType); } return true; @@ -360,16 +357,11 @@ bool droidTemplateShutDown(void) for (pTemplate = apsDroidTemplates[player]; pTemplate != NULL; pTemplate = pNext) { pNext = pTemplate->psNext; - free(pTemplate->pName); delete pTemplate; } apsDroidTemplates[player] = NULL; } - for (std::list::iterator i = localTemplates.begin(); i != localTemplates.end(); ++i) - { - free(i->pName); - } localTemplates.clear(); return true; @@ -387,8 +379,7 @@ DROID_TEMPLATE *getTemplateFromTranslatedNameNoPlayer(char const *pName) { for (DROID_TEMPLATE *psCurr = apsDroidTemplates[i]; psCurr != NULL; psCurr = psCurr->psNext) { - const char *rName = psCurr->pName ? psCurr->pName : psCurr->aName; - if (strcmp(rName, pName) == 0) + if (psCurr->id.compare(pName) == 0) { return psCurr; } @@ -416,11 +407,6 @@ DROID_TEMPLATE* getTemplateFromMultiPlayerID(UDWORD multiPlayerID) return NULL; } -const char* getTemplateName(const DROID_TEMPLATE *psTemplate) -{ - return psTemplate->aName; -} - /*called when a Template is deleted in the Design screen*/ void deleteTemplateFromProduction(DROID_TEMPLATE *psTemplate, unsigned player, QUEUE_MODE mode) { diff --git a/src/template.h b/src/template.h index 5e5497a03..411283283 100644 --- a/src/template.h +++ b/src/template.h @@ -22,13 +22,10 @@ void fillTemplateList(std::vector &pList, STRUCTURE *psFactory /* gets a template from its name - relies on the name being unique */ DROID_TEMPLATE *getTemplateFromTranslatedNameNoPlayer(char const *pName); + /*getTemplateFromMultiPlayerID gets template for unique ID searching all lists */ DROID_TEMPLATE *getTemplateFromMultiPlayerID(UDWORD multiPlayerID); -/*return the name to display for the interface - we don't know if this is -a string ID or something the user types in*/ -const char* getTemplateName(const DROID_TEMPLATE *psTemplate); - /// Have we researched the components of this template? bool researchedTemplate(DROID_TEMPLATE *psCurr, int player, bool allowRedundant = false, bool verbose = false);