Beispiel #1
0
//
// edf_ifngametype
//
// haleyjd 09/06/05: As above, but negated.
//
static int edf_ifngametype(cfg_t *cfg, cfg_opt_t *opt, int argc,
                           const char **argv)
{
   int i, type;
   bool type_nomatch = true;

   if(argc < 1)
   {
      cfg_error(cfg, "wrong number of args to ifngametype()\n");
      return 1;
   }

   for(i = 0; i < argc; ++i)
   {
      type = E_StrToNumLinear(e_typenames, NumGameModeTypes, argv[i]);

      // if gametype equals NONE of the parameters, we will process
      // the block (can short circuit after first failure)
      if(!(type_nomatch = (type_nomatch && type != GameModeInfo->type)))
         break;
   }

   // did it match some type?
   if(!type_nomatch)
   {
      // force libConfuse to look for an endif function
      cfg->flags |= CFGF_LOOKFORFUNC;
      cfg->lookfor = "endif";
   }

   return 0;
}
Beispiel #2
0
//
// edf_ifgametype
//
// haleyjd 09/06/05: Just like ifenabled, but considers the game type
// from the game mode info instead of enable values.
//
static int edf_ifgametype(cfg_t *cfg, cfg_opt_t *opt, int argc,
                          const char **argv)
{
   int i, type;
   bool type_match = false;

   if(argc < 1)
   {
      cfg_error(cfg, "wrong number of args to ifgametype()\n");
      return 1;
   }

   for(i = 0; i < argc; ++i)
   {
      type = E_StrToNumLinear(e_typenames, NumGameModeTypes, argv[i]);

      // if the gametype matches ANY specified, we will process the
      // block in question (can short circuit after first match)
      if((type_match = (type_match || type == GameModeInfo->type)))
         break;
   }

   // no type was matched?
   if(!type_match)
   {
      // force libConfuse to look for an endif function
      cfg->flags |= CFGF_LOOKFORFUNC;
      cfg->lookfor = "endif";
   }

   return 0;
}
Beispiel #3
0
// Expecting a MapInfo keyword
bool XLEMapInfoParser::doStateExpectKeyword(XLTokenizer &tokenizer)
{
   int tokenType = tokenizer.getTokenType();
   
   switch(tokenType)
   {
   case XLTokenizer::TOKEN_BRACKETSTR:
      // if we find a bracketed string instead, it's actually the start of a new
      // section; process it through the header state handler immediately
      return doStateExpectHeader(tokenizer);

   case XLTokenizer::TOKEN_KEYWORD:
   case XLTokenizer::TOKEN_STRING:
      // record as the current key and expect potential = to follow
      key   = tokenizer.getToken();
      value = "";
      state = STATE_EXPECTEQUAL;
      if(E_StrToNumLinear(multiValKeywords, MVKW_NUMKEYWORDS, key.constPtr()) != MVKW_NUMKEYWORDS)
         allowMultiValue = true;
      else
         allowMultiValue = false;
      break;

   default:
      // if we see anything else, keep scanning
      break;
   }

   return true;
}
Beispiel #4
0
// Expecting a map-level command
bool XLMapInfoParser::doStateExpectMapCmd(XLTokenizer &token)
{
   auto &tokenVal = token.getToken();
   int   mapKwd   = E_StrToNumLinear(mapKeywords, XL_NUMMAPINFO_FIELDS, 
                                     tokenVal.constPtr());

   if(mapKwd == XL_NUMMAPINFO_FIELDS) // unknown keyword, error
   {
      // see if it is a new global keyword
      return doStateExpectCmd(token);
   }

   // get the parsing information for this map keyword
   kwd = &mapKeywordParseTable[mapKwd];

   switch(kwd->kwtype)
   {
   case KW_TYPE_SKY:
      state = STATE_EXPECTSKYNAME; // sky name should be next token
      break;
   case KW_TYPE_FLAG:              // flags have no value; presence means set it now
      curInfo->setInt(kwd->key, 1);
      state = STATE_EXPECTMAPCMD;
      break;      
   case KW_TYPE_VALUE:             // next token should be value
      state = STATE_EXPECTVALUE;
      break;
   }

   return true;
}
Beispiel #5
0
//
// E_SetDialect
//
// Changes the parser dialect. This setting applies upward on the include
// stack, so including a file that does not explicitly set its own dialect will
// cause it to be treated as the same dialect as the including file.
//
int E_SetDialect(cfg_t *cfg, cfg_opt_t *opt, int argc, const char **argv)
{
   int dialect;

   if(argc != 1)
   {
      cfg_error(cfg, "wrong number of args to setdialect()\n");
      return 1;
   }

   dialect = E_StrToNumLinear(dialectNames, CFG_NUMDIALECTS, argv[0]);
   if(dialect == CFG_NUMDIALECTS)
   {
      cfg_error(cfg, "invalid libConfuse dialect %s\n", argv[0]);
      return 1;
   }

   cfg_lexer_set_dialect((cfg_dialect_t)dialect);
   return 0;
}
Beispiel #6
0
// Expecting a command at the global level
bool XLMapInfoParser::doStateExpectCmd(XLTokenizer &token)
{
   auto &tokenVal = token.getToken();
   int   kwNum    = E_StrToNumLinear(globalKeywords, KW_NUMGLOBAL, tokenVal.constPtr());

   if(kwNum == KW_NUMGLOBAL)
      return false; // error, stop parsing.

   switch(kwNum)
   {
   case KW_GLOBAL_MAP:
      state = STATE_EXPECTMAPNAME; // map name or number should be next.
      break;
   default:
      globalKW = kwNum;
      state = STATE_EXPECTGLOBALVAL; // should have a value for global variable
      break;
   }

   return true;
}
Beispiel #7
0
//
// Returns a pointer to an weaponinfo's native state field if the given name
// is a match for that field's corresponding DECORATE label. Returns null
// if the name is not a match for a native state field.
//
static int *E_getNativeWepStateLoc(weaponinfo_t *wi, const char *label)
{
   int nativenum = E_StrToNumLinear(nativeWepStateLabels, NUMNATIVEWSTATES, label);
   int *ret = nullptr;

   switch(nativenum)
   {
   case WSTATE_SELECT:    ret = &wi->upstate;    break;
   case WSTATE_DESELECT:  ret = &wi->downstate;  break;
   case WSTATE_READY:     ret = &wi->readystate; break;
   case WSTATE_FIRE:      ret = &wi->atkstate;   break;
   case WSTATE_FLASH:     ret = &wi->flashstate; break;
   case WSTATE_HOLD:      ret = &wi->holdstate;  break;
   case WSTATE_FIRE_ALT:  ret = &wi->atkstate_alt;   break;
   case WSTATE_FLASH_ALT: ret = &wi->flashstate_alt; break;
   case WSTATE_HOLD_ALT:  ret = &wi->holdstate_alt;  break;
   default:
      break;
   }

   return ret;
}
Beispiel #8
0
//
// INStatsMgrPimpl::parseCSVScores
//
// Parse the CSV input file used to save top scores.
//
void INStatsMgrPimpl::parseCSVScores(char *input)
{
   Collection<qstring> fields;

   // Go past the first line of input, which consists of column headers
   while(*input && *input != '\n')
      ++input;

   // Parse each remaining line
   while(*input)
   {
      parseCSVLine(input, fields);

      if(fields.getLength() >= FIELD_NUMFIELDS)
      {
         int recordType = E_StrToNumLinear(recordTypeNames, INSTAT_NUMTYPES, 
                                           fields[FIELD_RECORDTYPE].constPtr());

         if(recordType < INSTAT_NUMTYPES)
         {
            in_stat_t *newStats = estructalloc(in_stat_t, 1);

            newStats->levelkey   = fields[FIELD_LEVELKEY  ].duplicate(PU_STATIC);
            newStats->playername = fields[FIELD_PLAYERNAME].duplicate(PU_STATIC);
            newStats->skill      = fields[FIELD_SKILL     ].toInt();
            newStats->value      = fields[FIELD_VALUE     ].toInt();
            newStats->maxValue   = fields[FIELD_MAXVALUE  ].toInt();

            newStats->recordType = recordType;

            // add to hash tables
            statsByLevelKey.addObject(newStats);
         }
      }
   }
}
Beispiel #9
0
//
// E_ProcessInventory
//
// Generalized code to process the data for a single inventory definition
// structure. Doubles as code for inventory and inventorydelta.
//
static void E_ProcessInventory(inventory_t *inv, cfg_t *invsec, cfg_t *pcfg, bool def)
{
   //int tempint;
   const char *tempstr;
   bool inherits = false;

   // possible when inheriting from an inventory def of a previous EDF generation
   if(!invsec) 
      return;

   // Process inheritance (not in deltas)
   if(def)
   {
      // if this inventory is already processed via recursion due to
      // inheritance, don't process it again
      if(inv->processed)
         return;
      
      if(cfg_size(invsec, ITEM_INVENTORY_INHERITS) > 0)
      {
         cfg_t *parent_invsec;
         
         // resolve parent inventory def
         inventory_t *parent = E_GetInventoryForName(cfg_getstr(invsec, ITEM_INVENTORY_INHERITS));

         // check against cyclic inheritance
         if(!E_CheckInventoryInherit(parent))
         {
            E_EDFLoggedErr(2, 
               "E_ProcessInventory: cyclic inheritance detected in inventory '%s'\n",
               inv->name);
         }
         
         // add to inheritance stack
         E_AddInventoryToPStack(parent);

         // process parent recursively
         parent_invsec = cfg_gettsec(pcfg, EDF_SEC_INVENTORY, parent->name);
         E_ProcessInventory(parent, parent_invsec, pcfg, true);
         
         // copy parent to this thing
         E_CopyInventory(inv, parent);

         // keep track of parent explicitly
         inv->parent = parent;
         
         // we inherit, so treat defaults as no value
         inherits = true;
      }
      else
         inv->parent = NULL; // no parent.

      // mark this inventory def as processed
      inv->processed = true;
   }

   // field processing
   
   if(IS_SET(ITEM_INVENTORY_CLASS))
   {
      const char *classname = cfg_getstr(invsec, ITEM_INVENTORY_CLASS);
      int classtype = E_StrToNumLinear(inventoryClassNames, INV_CLASS_NUMCLASSES, classname);

      if(classtype == INV_CLASS_NUMCLASSES)
      {
         E_EDFLoggedWarning(2, "Warning: unknown inventory class %s\n", classname);
         classtype = INV_CLASS_NONE;
      }

      inv->classtype = classtype;
   }

#ifdef RANGECHECK
   if(inv->classtype < 0 || inv->classtype >= INV_CLASS_NUMCLASSES)
      E_EDFLoggedErr(2, "E_ProcessInventory: internal error - bad classtype %d\n", inv->classtype);
#endif

   // process subclass fields
   inventorySubClasses[inv->classtype](inv, invsec, def, inherits);

   if(IS_SET(ITEM_INVENTORY_AMOUNT))
      inv->amount = cfg_getint(invsec, ITEM_INVENTORY_AMOUNT);

   if(IS_SET(ITEM_INVENTORY_MAXAMOUNT))
      inv->maxAmount = cfg_getint(invsec, ITEM_INVENTORY_MAXAMOUNT);

   if(IS_SET(ITEM_INVENTORY_INTERHUBAMOUNT))
      inv->interHubAmount = cfg_getint(invsec, ITEM_INVENTORY_INTERHUBAMOUNT);

   if(IS_SET(ITEM_INVENTORY_ICON))
      E_ReplaceString(inv->icon, cfg_getstrdup(invsec, ITEM_INVENTORY_ICON));

   if(IS_SET(ITEM_INVENTORY_PICKUPMESSAGE))
      E_ReplaceString(inv->pickUpMessage, cfg_getstrdup(invsec, ITEM_INVENTORY_PICKUPMESSAGE));

   if(IS_SET(ITEM_INVENTORY_PICKUPSOUND))
      E_ReplaceString(inv->pickUpSound, cfg_getstrdup(invsec, ITEM_INVENTORY_PICKUPSOUND));

   if(IS_SET(ITEM_INVENTORY_PICKUPFLASH))
      E_ReplaceString(inv->pickUpFlash, cfg_getstrdup(invsec, ITEM_INVENTORY_PICKUPFLASH));

   if(IS_SET(ITEM_INVENTORY_USESOUND))
      E_ReplaceString(inv->useSound, cfg_getstrdup(invsec, ITEM_INVENTORY_USESOUND));

   if(IS_SET(ITEM_INVENTORY_RESPAWNTICS))
      inv->respawnTics = cfg_getint(invsec, ITEM_INVENTORY_RESPAWNTICS);

   if(IS_SET(ITEM_INVENTORY_GIVEQUEST))
      inv->giveQuest = cfg_getint(invsec, ITEM_INVENTORY_GIVEQUEST);

   if(IS_SET(ITEM_INVENTORY_FLAGS))
   {
      tempstr = cfg_getstr(invsec, ITEM_INVENTORY_FLAGS);
      if(*tempstr == '\0')
         inv->flags = 0;
      else
         inv->flags = E_ParseFlags(tempstr, &inventory_flagset);
   }
   
   // TODO: addflags/remflags   
}
//
// E_processGamePropsBlock
//
// Process a single gameproperties block.
//
static void E_processGamePropsBlock(cfg_t *props)
{
   // Flags

   if(IS_SET(ITEM_GPROP_FLAGSADD))
   {
      const char *flagstr = cfg_getstr(props, ITEM_GPROP_FLAGSADD);

      GameModeInfo->flags |= E_ParseFlags(flagstr, &gmi_flagset);
   }

   if(IS_SET(ITEM_GPROP_FLAGSREM))
   {
      const char *flagstr = cfg_getstr(props, ITEM_GPROP_FLAGSREM);
      unsigned int curFlags = GameModeInfo->flags;

      GameModeInfo->flags &= ~E_ParseFlags(flagstr, &gmi_flagset);

      GameModeInfo->flags |= (curFlags & GIF_SHAREWARE); // nice try, bitch.
   }

   if(IS_SET(ITEM_GPROP_MFLAGSADD))
   {
      const char *flagstr = cfg_getstr(props, ITEM_GPROP_MFLAGSADD);

      GameModeInfo->missionInfo->flags |= E_ParseFlags(flagstr, &mission_flagset);
   }

   if(IS_SET(ITEM_GPROP_MFLAGSREM))
   {
      const char *flagstr = cfg_getstr(props, ITEM_GPROP_MFLAGSREM);

      GameModeInfo->missionInfo->flags &= ~E_ParseFlags(flagstr, &mission_flagset);
   }

   // Demo Loop Properties

   if(IS_SET(ITEM_GPROP_TITLETICS))
      GameModeInfo->titleTics = cfg_getint(props, ITEM_GPROP_TITLETICS);
   
   if(IS_SET(ITEM_GPROP_ADVISORTICS))
      GameModeInfo->advisorTics = cfg_getint(props, ITEM_GPROP_ADVISORTICS);
   
   if(IS_SET(ITEM_GPROP_PAGETICS))
      GameModeInfo->pageTics = cfg_getint(props, ITEM_GPROP_PAGETICS);

   // Menu Properties
   if(IS_SET(ITEM_GPROP_MENUBKGND))
   {
      E_setDynamicString(GameModeInfo->menuBackground, GI_STR_MENUBKGND, 
                         cfg_getstr(props, ITEM_GPROP_MENUBKGND));
   }

   if(IS_SET(ITEM_GPROP_TRANSFRAME))
   {
      int stateNum = E_StateNumForName(cfg_getstr(props, ITEM_GPROP_TRANSFRAME));

      if(stateNum >= 0 &&
         (states[stateNum]->dehnum >= 0 || E_AutoAllocStateDEHNum(stateNum)))
      {
         GameModeInfo->transFrame = states[stateNum]->dehnum;
      }
   }

   if(IS_SET(ITEM_GPROP_MENUSKVASND))
   {
      sfxinfo_t *snd = E_SoundForName(cfg_getstr(props, ITEM_GPROP_MENUSKVASND));

      if(snd && (snd->dehackednum >= 0 || E_AutoAllocSoundDEHNum(snd)))
         GameModeInfo->skvAtkSound = snd->dehackednum;
   }

   if(IS_SET(ITEM_GPROP_MENUOFFSET))
      GameModeInfo->menuOffset = cfg_getint(props, ITEM_GPROP_MENUOFFSET);

   if(IS_SET(ITEM_GPROP_MENUPTR1) && GameModeInfo->menuCursor->numpatches >= 1)
   {
      E_setDynamicString(GameModeInfo->menuCursor->patches[0], GI_STR_MENUPTR1,
                         cfg_getstr(props, ITEM_GPROP_MENUPTR1));
   }

   if(IS_SET(ITEM_GPROP_MENUPTR2) && GameModeInfo->menuCursor->numpatches >= 2)
   {
      E_setDynamicString(GameModeInfo->menuCursor->patches[1], GI_STR_MENUPTR2,
                         cfg_getstr(props, ITEM_GPROP_MENUPTR2));
   }

   // Border Properties

   if(IS_SET(ITEM_GPROP_BORDERFLAT))
   {
      E_setDynamicString(GameModeInfo->borderFlat, GI_STR_BORDERFLAT,
                         cfg_getstr(props, ITEM_GPROP_BORDERFLAT));
   }

   if(IS_SET(ITEM_GPROP_BORDERTL))
   {
      E_setDynamicString(GameModeInfo->border->c_tl, GI_STR_BORDERTL, 
                         cfg_getstr(props, ITEM_GPROP_BORDERTL));
   }

   if(IS_SET(ITEM_GPROP_BORDERTOP))
   {
      E_setDynamicString(GameModeInfo->border->top, GI_STR_BORDERTOP, 
                         cfg_getstr(props, ITEM_GPROP_BORDERTOP));
   }

   if(IS_SET(ITEM_GPROP_BORDERTR))
   {
      E_setDynamicString(GameModeInfo->border->c_tr, GI_STR_BORDERTR, 
                         cfg_getstr(props, ITEM_GPROP_BORDERTR));
   }

   if(IS_SET(ITEM_GPROP_BORDERLEFT))
   {
      E_setDynamicString(GameModeInfo->border->left, GI_STR_BORDERLEFT, 
                         cfg_getstr(props, ITEM_GPROP_BORDERLEFT));
   }

   if(IS_SET(ITEM_GPROP_BORDERRIGHT))
   {
      E_setDynamicString(GameModeInfo->border->right, GI_STR_BORDERRIGHT, 
                         cfg_getstr(props, ITEM_GPROP_BORDERRIGHT));
   }

   if(IS_SET(ITEM_GPROP_BORDERBL))
   {
      E_setDynamicString(GameModeInfo->border->c_bl, GI_STR_BORDERBL, 
                         cfg_getstr(props, ITEM_GPROP_BORDERBL));
   }

   if(IS_SET(ITEM_GPROP_BORDERBOTT))
   {
      E_setDynamicString(GameModeInfo->border->bottom, GI_STR_BORDERBOTT, 
                         cfg_getstr(props, ITEM_GPROP_BORDERBOTT));
   }

   if(IS_SET(ITEM_GPROP_BORDERBR))
   {
      E_setDynamicString(GameModeInfo->border->c_br, GI_STR_BORDERBR, 
                         cfg_getstr(props, ITEM_GPROP_BORDERBR));
   }

   // Console Properties

   if(IS_SET(ITEM_GPROP_CCHARSPERLN))
      GameModeInfo->c_numCharsPerLine = cfg_getint(props, ITEM_GPROP_CCHARSPERLN);

   if(IS_SET(ITEM_GPROP_CBELLSOUND))
   {
      sfxinfo_t *snd = E_SoundForName(cfg_getstr(props, ITEM_GPROP_CBELLSOUND));

      if(snd && (snd->dehackednum >= 0 || E_AutoAllocSoundDEHNum(snd)))
         GameModeInfo->c_BellSound = snd->dehackednum;
   }

   if(IS_SET(ITEM_GPROP_CCHATSOUND))
   {
      sfxinfo_t *snd = E_SoundForName(cfg_getstr(props, ITEM_GPROP_CCHATSOUND));

      if(snd && (snd->dehackednum >= 0 || E_AutoAllocSoundDEHNum(snd)))
         GameModeInfo->c_ChatSound = snd->dehackednum;
   }

   if(IS_SET(ITEM_GPROP_CBACKDROP))
   {
      E_setDynamicString(GameModeInfo->consoleBack, GI_STR_CBACKDROP,
                         cfg_getstr(props, ITEM_GPROP_CBACKDROP));
   }

   // HUD Properties

   if(IS_SET(ITEM_GPROP_PAUSEPATCH))
   {
      E_setDynamicString(GameModeInfo->pausePatch, GI_STR_PAUSEPATCH,
                         cfg_getstr(props, ITEM_GPROP_PAUSEPATCH));
   }

   // Gamesim Properties

   if(IS_SET(ITEM_GPROP_PUFFTYPE))
   {
      const char *name = cfg_getstr(props, ITEM_GPROP_PUFFTYPE);

      if(E_ThingNumForName(name) >= 0)
         E_setDynamicString(GameModeInfo->puffType, GI_STR_PUFFTYPE, name);
   }

   if(IS_SET(ITEM_GPROP_TELEFOGTYPE))
   {
      const char *name = cfg_getstr(props, ITEM_GPROP_TELEFOGTYPE);

      if(E_ThingNumForName(name) >= 0)
         E_setDynamicString(GameModeInfo->teleFogType, GI_STR_TELEFOGTYPE, name);
   }

   if(IS_SET(ITEM_GPROP_TELEFOGHT))
   {
      int num = cfg_getint(props, ITEM_GPROP_TELEFOGHT);

      GameModeInfo->teleFogHeight = num * FRACUNIT;
   }

   if(IS_SET(ITEM_GPROP_TELESOUND))
   {
      sfxinfo_t *snd = E_SoundForName(cfg_getstr(props, ITEM_GPROP_TELESOUND));

      if(snd && (snd->dehackednum >= 0 || E_AutoAllocSoundDEHNum(snd)))
         GameModeInfo->teleSound = snd->dehackednum;
   }

   if(IS_SET(ITEM_GPROP_THRUSTFACTR))
      GameModeInfo->thrustFactor = (int16_t)cfg_getint(props, ITEM_GPROP_THRUSTFACTR);

   if(IS_SET(ITEM_GPROP_DEFPCLASS))
   {
      E_setDynamicString(GameModeInfo->defPClassName, GI_STR_DEFPCLASS,
                         cfg_getstr(props, ITEM_GPROP_DEFPCLASS));
   }

   // Determines behavior of the Teleport_EndGame line special when LevelInfo
   // has not provided a specific finale type for the level.
   if(IS_SET(ITEM_GPROP_FINTYPE))
   {
      int finaleType = E_StrToNumLinear(finaleTypeStrs, FINALE_NUMFINALES, 
                                        cfg_getstr(props, ITEM_GPROP_FINTYPE));

      if(finaleType >= 0 && finaleType < FINALE_NUMFINALES)
         GameModeInfo->teleEndGameFinaleType = finaleType;
   }

   // Finale Properties

   if(IS_SET(ITEM_GPROP_FINALEX))
      GameModeInfo->fTextPos->x = cfg_getint(props, ITEM_GPROP_FINALEX);

   if(IS_SET(ITEM_GPROP_FINALEY))
      GameModeInfo->fTextPos->y = cfg_getint(props, ITEM_GPROP_FINALEY);

   if(IS_SET(ITEM_GPROP_CASTTITLEY))
      GameModeInfo->castTitleY = cfg_getint(props, ITEM_GPROP_CASTTITLEY);

   if(IS_SET(ITEM_GPROP_CASTNAMEY))
      GameModeInfo->castNameY = cfg_getint(props, ITEM_GPROP_CASTNAMEY);

   // Intermission Properties

   if(IS_SET(ITEM_GPROP_INTERPIC))
   {
      E_setDynamicString(GameModeInfo->interPic, GI_STR_INTERPIC,
                         cfg_getstr(props, ITEM_GPROP_INTERPIC));
   }

   // Sound Properties

   if(IS_SET(ITEM_GPROP_DEFMUSNAME))
   {
      E_setDynamicString(GameModeInfo->defMusName, GI_STR_DEFMUSNAME,
                         cfg_getstr(props, ITEM_GPROP_DEFMUSNAME));
   }

   if(IS_SET(ITEM_GPROP_DEFSNDNAME))
   {
      E_setDynamicString(GameModeInfo->defSoundName, GI_STR_DEFSNDNAME,
                         cfg_getstr(props, ITEM_GPROP_DEFSNDNAME));
   }
   
   // Credit Screen Properties

   if(IS_SET(ITEM_GPROP_CREDITBKGND))
   {
      E_setDynamicString(GameModeInfo->creditBackground, GI_STR_CREDITBKGND,
                         cfg_getstr(props, ITEM_GPROP_CREDITBKGND));
   }

   if(IS_SET(ITEM_GPROP_CREDITY))
      GameModeInfo->creditY = cfg_getint(props, ITEM_GPROP_CREDITY);

   if(IS_SET(ITEM_GPROP_CREDITTSTEP))
      GameModeInfo->creditTitleStep = cfg_getint(props, ITEM_GPROP_CREDITTSTEP);
   
   // Exit Properties
   
   if(IS_SET(ITEM_GPROP_ENDTEXTNAME))
   {
      E_setDynamicString(GameModeInfo->endTextName, GI_STR_ENDTEXTNAME,
                         cfg_getstr(props, ITEM_GPROP_ENDTEXTNAME));
   }
}