예제 #1
0
//
// E_ProcessInventoryDeltas
//
// Does processing for inventorydelta sections, which allow cascading editing
// of existing inventory items. The inventorydelta shares most of its fields
// and processing code with the thingtype section.
//
void E_ProcessInventoryDeltas(cfg_t *cfg)
{
   int i, numdeltas;

   E_EDFLogPuts("\t* Processing inventory deltas\n");

   numdeltas = cfg_size(cfg, EDF_SEC_INVDELTA);

   E_EDFLogPrintf("\t\t%d inventorydelta(s) defined\n", numdeltas);

   for(i = 0; i < numdeltas; i++)
   {
      cfg_t       *deltasec = cfg_getnsec(cfg, EDF_SEC_INVDELTA, i);
      inventory_t *inv;

      // get thingtype to edit
      if(!cfg_size(deltasec, ITEM_DELTA_NAME))
         E_EDFLoggedErr(2, "E_ProcessInventoryDeltas: inventorydelta requires name field\n");

      inv = E_GetInventoryForName(cfg_getstr(deltasec, ITEM_DELTA_NAME));

      E_ProcessInventory(inv, deltasec, cfg, false);

      E_EDFLogPrintf("\t\tApplied inventorydelta #%d to %s(#%d)\n",
                     i, inv->name, inv->numkey);
   }
}
예제 #2
0
//
// Process an individual switch
//
static void E_processSwitch(cfg_t *cfg)
{
   const char *title    = cfg_title(cfg);
   ESwitchDef *def      = e_switch_namehash.objectForKey(title);
   const bool  modified = !!def;
   if(!def)
   {
      def = new ESwitchDef;
      def->offpic = title;
      e_switch_namehash.addObject(def);
      eswitches.add(def);
      E_EDFLogPrintf("\t\tDefined switch %s\n", title);
   }
   else
      E_EDFLogPrintf("\t\tModified switch %s\n", title);

   auto isset = [modified, cfg](const char *field) {
      return !modified || cfg_size(cfg, field) > 0;
   };

   if(isset(ITEM_SWITCH_ONPIC))
      def->onpic    = cfg_getstr(cfg, ITEM_SWITCH_ONPIC);
   if(isset(ITEM_SWITCH_ONSOUND))
      def->onsound  = cfg_getstr(cfg, ITEM_SWITCH_ONSOUND);
   if(isset(ITEM_SWITCH_OFFSOUND))
      def->offsound = cfg_getstr(cfg, ITEM_SWITCH_OFFSOUND);
   if(isset(ITEM_SWITCH_GAMEINDEX))
      def->episode  = cfg_getint(cfg, ITEM_SWITCH_GAMEINDEX);
}
예제 #3
0
//
// E_CheckInclude
//
// Pass a pointer to some cached data and the size of that data. The SHA-1
// hash will be calculated and compared against the SHA-1 hashes of all other
// data sources that have been sent into this function. Returns true if the
// data should be included, and false otherwise (ie. there was a match).
//
bool E_CheckInclude(const char *data, size_t size)
{
   size_t numincludes;
   char *digest;
   
   // calculate the SHA-1 hash of the data   
   HashData newHash(HashData::SHA1, (const uint8_t *)data, (uint32_t)size);

   // output digest string
   digest = newHash.digestToString();

   E_EDFLogPrintf("\t\t  SHA-1 = %s\n", digest);

   efree(digest);

   numincludes = eincludes.getLength();

   // compare against existing includes
   for(size_t i = 0; i < numincludes; i++)
   {
      // found a match?
      if(newHash == eincludes[i])
      {
         E_EDFLogPuts("\t\t\tDeclined, SHA-1 match detected.\n");
         return false;
      }
   }

   // this source has not been processed before, so add its hash to the list
   eincludes.add(newHash);

   return true;
}
예제 #4
0
//
// E_OpenAndCheckInclude
//
// Performs the following actions:
// 1. Caches the indicated file or lump (lump only if lumpnum >= 0).
//    If the file cannot be opened, the libConfuse error code 1 is
//    returned.
// 2. Calls E_CheckInclude on the cached data.
// 3. If there is a hash collision, the data is freed. The libConfuse 
//    "ok" code 0 will be returned.
// 4. If there is not a hash collision, the data is included through a
//    call to cfg_lexer_include. The return value of that function will
//    be propagated.
//
static int E_OpenAndCheckInclude(cfg_t *cfg, const char *fn, int lumpnum)
{
   size_t len;
   char *data;
   int code = 1;

   E_EDFLogPrintf("\t\t* Including %s\n", fn);

   // must open the data source
   if((data = cfg_lexer_mustopen(cfg, fn, lumpnum, &len)))
   {
      // see if we already parsed this data source
      if(E_CheckInclude(data, len))
         code = cfg_lexer_include(cfg, data, fn, lumpnum);
      else
      {
         // we already parsed it, but this is not an error;
         // we ignore the include and return 0 to indicate success.
         efree(data);
         code = 0;
      }
   }

   return code;
}
예제 #5
0
//
// E_ProcessInventoryDefs
//
// Resolves and loads all information for the inventory structures.
//
void E_ProcessInventoryDefs(cfg_t *cfg)
{
   unsigned int i, numInventory;

   E_EDFLogPuts("\t* Processing inventory data\n");

   if(!(numInventory = cfg_size(cfg, EDF_SEC_INVENTORY)))
      return;

   // allocate inheritance stack and hitlist
   inv_pstack = ecalloc(inventory_t **, numInventoryDefs, sizeof(inventory_t *));

   // TODO: any first-time-only processing?

   for(i = 0; i < numInventory; i++)
   {
      cfg_t       *invsec = cfg_getnsec(cfg, EDF_SEC_INVENTORY, i);
      const char  *name   = cfg_title(invsec);
      inventory_t *inv    = E_InventoryForName(name);

      // reset the inheritance stack
      E_ResetInventoryPStack();

      // add this def to the stack
      E_AddInventoryToPStack(inv);

      E_ProcessInventory(inv, invsec, cfg, true);

      E_EDFLogPrintf("\t\tFinished inventory %s(#%d)\n", inv->name, inv->numkey);
   }

   // free tables
   efree(inv_pstack);
}
예제 #6
0
파일: e_edf.cpp 프로젝트: fragglet/autodoom
//
// E_ParseEDF
//
// Shared parsing phase code for E_ProcessEDF and E_ProcessNewEDF
//
static void E_ParseEDF(cfg_t *cfg, const char *filename)
{
   E_EDFLogPuts("\n===================== Parsing Phase =====================\n");

   // Parse the "root" EDF, which is either a chain of wad lumps named EDFROOT;
   // or a single file, which is determined by the -edf parameter, a GFS script,
   // the /base/game directory, or the default master EDF, which is root.edf in
   // /base.

   if(W_CheckNumForName("EDFROOT") != -1)
   {
      puts("E_ProcessEDF: Loading root lump.\n");
      E_EDFLogPuts("\t* Parsing lump EDFROOT\n");

      E_ParseEDFLump(cfg, "EDFROOT");
   }
   else if(filename)
   {
      printf("E_ProcessEDF: Loading root file %s\n", filename);
      E_EDFLogPrintf("\t* Parsing EDF file %s\n", filename);

      E_ParseEDFFile(cfg, filename);
   }

   // Parse independent EDF lumps, which are not supposed to have been included
   // through any of the above (though if they have been, this is now accounted
   // for via the SHA-1 hashing mechanism which avoids reparses).
   E_ParseIndividualLumps(cfg);
}
예제 #7
0
파일: e_edf.cpp 프로젝트: fragglet/autodoom
//
// E_ProcessSpriteVars
//
// Sets the sprite numbers to be used for the player and blank
// sprites by looking up a provided name in the sprite hash
// table.
//
static void E_ProcessSpriteVars(cfg_t *cfg)
{
   static bool firsttime = true;
   int sprnum;
   const char *str;

   E_EDFLogPuts("\t* Processing sprite variables\n");

   // haleyjd 11/11/09: removed processing of obsolete playersprite variable

   // haleyjd 11/21/11: on subsequent runs, only replace if changed
   if(!firsttime && cfg_size(cfg, ITEM_BLANKSPRITE) == 0)
      return;

   firsttime = false;

   // load blank sprite number

   str = cfg_getstr(cfg, ITEM_BLANKSPRITE);
   sprnum = E_SpriteNumForName(str);
   if(sprnum == -1)
   {
      E_EDFLoggedErr(2, 
         "E_ProcessSpriteVars: invalid blank sprite name: '%s'\n", str);
   }
   E_EDFLogPrintf("\t\tSet sprite %s(#%d) as blank sprite\n", str, sprnum);
   blankSpriteNum = sprnum;
}
예제 #8
0
//
// Processes "switch" blocks
//
void E_ProcessSwitches(cfg_t *cfg)
{
   unsigned numswitches = cfg_size(cfg, EDF_SEC_SWITCH);

   E_EDFLogPrintf("\t* Processing switches\n"
                  "\t\t%u switch(es) defined\n", numswitches);

   for(unsigned i = 0; i < numswitches; ++i)
      E_processSwitch(cfg_getnsec(cfg, EDF_SEC_SWITCH, i));
}
예제 #9
0
//
// E_ProcessStrings
//
// 03/27/05: EDF can now define custom string objects.
// These are now processed first. This is extremely simple.
//
void E_ProcessStrings(cfg_t *cfg)
{
   unsigned int i, numstrings = cfg_size(cfg, EDF_SEC_STRING);

   E_EDFLogPrintf("\t* Processing strings\n"
                  "\t\t%d string(s) defined\n", numstrings);

   for(i = 0; i < numstrings; ++i)
   {
      cfg_t *sec = cfg_getnsec(cfg, EDF_SEC_STRING, i);
      const char *mnemonic, *value, *bex, *bexsource;
      int number;
      dehstr_t *dehstr;

      mnemonic = cfg_title(sec);
      value    = cfg_getstr(sec, ITEM_STRING_VAL);
      number   = cfg_getint(sec, ITEM_STRING_NUM);

      // haleyjd 09/16/07: support also assigning the value of a BEX string,
      // and filling this string object with the value of a BEX string
      bex       = cfg_getstr(sec, ITEM_STRING_BEXDST);
      bexsource = cfg_getstr(sec, ITEM_STRING_BEXSRC);

      // if bexsource is a valid BEX mnemonic, the value to use becomes the 
      // value of that BEX string rather than any specified in this string object.
      if((dehstr = D_GetBEXStr(bexsource)))
         value = *(dehstr->ppstr);

      E_CreateString(value, mnemonic, number);

      E_EDFLogPrintf("\t\tDefined string '%s' (#%d)\n"
                     "\t\t\tvalue = '%s'\n",
                     mnemonic, number, value);

      if((dehstr = D_GetBEXStr(bex)))
      {
         *(dehstr->ppstr) = estrdup(value);

         E_EDFLogPrintf("\t\t\tCopied to BEX string '%s'\n", bex);
      }
   }
}
예제 #10
0
//
// E_CollectInventory
//
// Pre-creates and hashes by name the inventory definitions, for purpose 
// of mutual and forward references.
//
void E_CollectInventory(cfg_t *cfg)
{
   static int currentID = 1;
   unsigned int i;
   unsigned int numInventory;    // number of inventory defs defined by the cfg
   inventory_t *newInvDefs  = NULL;

   // get number of inventory definitions defined by the cfg
   numInventory = cfg_size(cfg, EDF_SEC_INVENTORY);

   // echo counts
   E_EDFLogPrintf("\t\t%u inventory items defined\n", numInventory);

   if(numInventory)
   {
      // allocate inventory structures for the new thingtypes
      newInvDefs = estructalloc(inventory_t, numInventory);

      numInventoryDefs += numInventory;

      // create metatables
      for(i = 0; i < numInventory; i++)
         newInvDefs[i].meta = new MetaTable("inventory");
   }

   // build hash tables
   E_EDFLogPuts("\t\tBuilding inventory hash tables\n");
   
   // cycle through the thingtypes defined in the cfg
   for(i = 0; i < numInventory; i++)
   {
      cfg_t *invcfg = cfg_getnsec(cfg, EDF_SEC_INVENTORY, i);
      const char *name = cfg_title(invcfg);

      // This is a new inventory, whether or not one already exists by this name
      // in the hash table. For subsequent addition of EDF inventory defs at 
      // runtime, the hash table semantics of "find newest first" take care of 
      // overriding, while not breaking objects that depend on the original 
      // definition of the inventory type for inheritance purposes.
      inventory_t *inv = &newInvDefs[i];

      // initialize name
      inv->name = estrdup(name);

      // add to name hash
      inv_namehash.addObject(inv);

      // create ID number and add to hash table
      inv->numkey = currentID++;
      inv_numhash.addObject(inv);
   }
}
예제 #11
0
파일: e_edf.cpp 프로젝트: fragglet/autodoom
static void E_EchoEnables()
{
   E_Enable_t *enable = edf_enables;

   E_EDFLogPuts("\t* Final enable values:\n");

   while(enable->name)
   {
      E_EDFLogPrintf("\t\t%s is %s\n", 
                     enable->name, 
                     enable->enabled ? "enabled" : "disabled");
      ++enable;
   }
}
예제 #12
0
파일: e_edf.cpp 프로젝트: fragglet/autodoom
//
// E_ParseIndividualLumps
//
// haleyjd 03/21/10: consolidated function to handle the parsing of all
// independent EDF lumps.
//
static void E_ParseIndividualLumps(cfg_t *cfg)
{
   const char *lumpname;
   int i = 0;

   while((lumpname = edf_lumpnames[i++]))
   {
      E_EDFLogPrintf("\t* Parsing %s lump", lumpname);

      if(!E_ParseEDFLumpOptional(cfg, lumpname))
         E_EDFLogPuts(" - not found, skipping.\n");
      else
         E_EDFLogPuts("\n");
   }
}
예제 #13
0
//
// Adds a switch defined externally
//
void E_AddSwitchDef(const ESwitchDef &extdef)
{
   if(extdef.offpic.empty())
      return;
   const char *title = extdef.offpic.constPtr();
   ESwitchDef *def   = e_switch_namehash.objectForKey(title);

   // NOTE: by external means, switches can't be modified. EDF takes priority.
   if(def)
      return;

   def = new ESwitchDef(extdef);
   e_switch_namehash.addObject(def);
   eswitches.add(def);
   E_EDFLogPrintf("\t\tDefined switch %s from ANIMDEFS\n", title);
}
예제 #14
0
파일: e_edf.cpp 프로젝트: fragglet/autodoom
//
// E_ProcessBossTypes
//
// Gets the thing type entries in the boss_spawner_types list,
// for use by the SpawnFly codepointer.
//
// modified by schepe to remove 11-type limit
//
static void E_ProcessBossTypes(cfg_t *cfg)
{
   int i, a = 0;
   int numTypes = cfg_size(cfg, SEC_BOSSTYPES);
   int numProbs = cfg_size(cfg, SEC_BOSSPROBS);
   bool useProbs = true;

   E_EDFLogPuts("\t* Processing boss spawn types\n");

   if(!numTypes)
   {
      // haleyjd 05/31/06: allow zero boss types
      E_EDFLogPuts("\t\tNo boss types defined\n");
      return;
   }

   // haleyjd 11/19/03: allow defaults for boss spawn probs
   if(!numProbs)
      useProbs = false;

   if(useProbs ? numTypes != numProbs : numTypes != 11)
   {
      E_EDFLoggedErr(2, 
         "E_ProcessBossTypes: %d boss types, %d boss probs\n",
         numTypes, useProbs ? numProbs : 11);
   }

   // haleyjd 11/21/11: allow multiple runs
   if(BossSpawnTypes)
   {
      efree(BossSpawnTypes);
      BossSpawnTypes = NULL;
   }
   if(BossSpawnProbs)
   {
      efree(BossSpawnProbs);
      BossSpawnProbs = NULL;
   }

   NumBossTypes = numTypes;
   BossSpawnTypes = ecalloc(int *, numTypes, sizeof(int));
   BossSpawnProbs = ecalloc(int *, numTypes, sizeof(int));

   // load boss spawn probabilities
   for(i = 0; i < numTypes; ++i)
   {
      if(useProbs)
      {
         a += cfg_getnint(cfg, SEC_BOSSPROBS, i);
         BossSpawnProbs[i] = a;
      }
      else
         BossSpawnProbs[i] = BossDefaults[i];
   }

   // check that the probabilities total 256
   if(useProbs && a != 256)
   {
      E_EDFLoggedErr(2, 
         "E_ProcessBossTypes: boss spawn probs do not total 256\n");
   }

   for(i = 0; i < numTypes; ++i)
   {
      const char *typeName = cfg_getnstr(cfg, SEC_BOSSTYPES, i);
      int typeNum = E_ThingNumForName(typeName);

      if(typeNum == -1)
      {
         E_EDFLoggedWarning(2, "Warning: invalid boss type '%s'\n", typeName);

         typeNum = UnknownThingType;
      }

      BossSpawnTypes[i] = typeNum;

      E_EDFLogPrintf("\t\tAssigned type %s(#%d) to boss type %d\n",
                     mobjinfo[typeNum]->name, typeNum, i);
   }
}
예제 #15
0
파일: e_edf.cpp 프로젝트: fragglet/autodoom
//
// E_ProcessCast
//
// Creates the DOOM II cast call information
//
static void E_ProcessCast(cfg_t *cfg)
{
   static bool firsttime = true;
   int i, numcastorder = 0, numcastsections = 0;
   cfg_t **ci_order;

   E_EDFLogPuts("\t* Processing cast call\n");
   
   // get number of cast sections
   numcastsections = cfg_size(cfg, SEC_CAST);

   if(firsttime && !numcastsections) // on main parse, at least one is required.
      E_EDFLoggedErr(2, "E_ProcessCast: no cast members defined.\n");

   firsttime = false;

   E_EDFLogPrintf("\t\t%d cast member(s) defined\n", numcastsections);

   // haleyjd 11/21/11: allow multiple runs
   if(castorder)
   {
      int i;

      // free names
      for(i = 0; i < max_castorder; i++)
      {
         if(castorder[i].name)
            efree(castorder[i].name);
      }
      // free castorder
      efree(castorder);
      castorder = NULL;
      max_castorder = 0;
   }

   // check if the "castorder" array is defined for imposing an
   // order on the castinfo sections
   numcastorder = cfg_size(cfg, SEC_CASTORDER);

   E_EDFLogPrintf("\t\t%d cast member(s) in castorder\n", numcastorder);

   // determine size of castorder
   max_castorder = (numcastorder > 0) ? numcastorder : numcastsections;

   // allocate with size+1 for an end marker
   castorder = estructalloc(castinfo_t, max_castorder + 1);
   ci_order  = ecalloc(cfg_t **, sizeof(cfg_t *), max_castorder);

   if(numcastorder > 0)
   {
      for(i = 0; i < numcastorder; ++i)
      {
         const char *title = cfg_getnstr(cfg, SEC_CASTORDER, i);         
         cfg_t *section    = cfg_gettsec(cfg, SEC_CAST, title);

         if(!section)
         {
            E_EDFLoggedErr(2, 
               "E_ProcessCast: unknown cast member '%s' in castorder\n", 
               title);
         }

         ci_order[i] = section;
      }
   }
   else
   {
      // no castorder array is defined, so use the cast members
      // in the order they are encountered (for backward compatibility)
      for(i = 0; i < numcastsections; ++i)
         ci_order[i] = cfg_getnsec(cfg, SEC_CAST, i);
   }


   for(i = 0; i < max_castorder; ++i)
   {
      int j;
      const char *tempstr;
      int tempint = 0;
      cfg_t *castsec = ci_order[i];

      // resolve thing type
      tempstr = cfg_getstr(castsec, ITEM_CAST_TYPE);
      if(!tempstr || 
         (tempint = E_ThingNumForName(tempstr)) == -1)
      {
         E_EDFLoggedWarning(2, "Warning: cast %d: unknown thing type %s\n",
                            i, tempstr);

         tempint = UnknownThingType;
      }
      castorder[i].type = tempint;

      // get cast name, if any -- the first seventeen entries can
      // default to using the internal string editable via BEX strings
      tempstr = cfg_getstr(castsec, ITEM_CAST_NAME);
      if(cfg_size(castsec, ITEM_CAST_NAME) == 0 && i < 17)
         castorder[i].name = NULL; // set from DeHackEd
      else
         castorder[i].name = estrdup(tempstr); // store provided value

      // get stopattack flag (used by player)
      castorder[i].stopattack = cfg_getbool(castsec, ITEM_CAST_SA);

      // process sound blocks (up to four will be processed)
      tempint = cfg_size(castsec, ITEM_CAST_SOUND);
      for(j = 0; j < 4; ++j)
      {
         castorder[i].sounds[j].frame = 0;
         castorder[i].sounds[j].sound = 0;
      }
      for(j = 0; j < tempint && j < 4; ++j)
      {
         int num;
         sfxinfo_t *sfx;
         const char *name;
         cfg_t *soundsec = cfg_getnsec(castsec, ITEM_CAST_SOUND, j);

         // if these are invalid, just fill them with zero rather
         // than causing an error, as they're very unimportant

         // name of sound to play
         name = cfg_getstr(soundsec, ITEM_CAST_SOUNDNAME);
         
         // haleyjd 03/22/06: modified to support dehnum auto-allocation
         if((sfx = E_EDFSoundForName(name)) == NULL)
         {
            E_EDFLoggedWarning(2, "Warning: cast member references invalid sound %s\n",
                               name);
            castorder[i].sounds[j].sound = 0;
         }
         else
         {
            if(sfx->dehackednum != -1 || E_AutoAllocSoundDEHNum(sfx))
               castorder[i].sounds[j].sound = sfx->dehackednum;
            else
            {
               E_EDFLoggedWarning(2, "Warning: could not auto-allocate a DeHackEd number "
                                     "for sound %s\n", name);
               castorder[i].sounds[j].sound = 0;
            }
         }

         // name of frame that triggers sound event
         name = cfg_getstr(soundsec, ITEM_CAST_SOUNDFRAME);
         if((num = E_StateNumForName(name)) < 0)
            num = 0;
         castorder[i].sounds[j].frame = num;
      }
   }

   // initialize the end marker to all zeroes
   memset(&castorder[max_castorder], 0, sizeof(castinfo_t));

   // free the ci_order table
   efree(ci_order);
}