// // ACS_funcSetThingState // static void ACS_funcSetThingState(ACS_FUNCARG) { int32_t tid = args[0]; const char *statename = ACSVM::GetString(args[1]); statenum_t statenum = E_StateNumForName(statename); state_t *state; int32_t count = 0; Mobj *mo = NULL; while((mo = P_FindMobjFromTID(tid, mo, thread->trigger))) { // Look for the named state for that type. if((state = E_GetJumpInfo(mo->info, statename))) { P_SetMobjState(mo, state->index); ++count; } // Otherwise, fall back to the global name. else if(statenum >= 0) { P_SetMobjState(mo, statenum); ++count; } } *retn++ = count; }
// // E_SafeStateName // // As above, but returns index of S_NULL if result of a name lookup // is not found. // int E_SafeStateName(const char *name) { int statenum = E_StateNumForName(name); if(statenum < 0) statenum = NullStateNum; return statenum; }
// // E_GetStateNumForName // // As above, but causes a fatal error if the state doesn't exist. // int E_GetStateNumForName(const char *name) { int statenum = E_StateNumForName(name); if(statenum < 0) I_Error("E_GetStateNumForName: bad frame %s\n", name); return statenum; }
// // E_CountUniqueStates // // haleyjd 03/31/10: counts the number of states in a cfg which do not overwrite // any pre-existing states by virtue of having the same name. // static unsigned int E_CountUniqueStates(cfg_t *cfg, unsigned int numstates) { unsigned int i; unsigned int count = 0; // if the state name hash is empty, short-circuit for efficiency if(!state_namehash.getNumItems()) return numstates; for(i = 0; i < numstates; ++i) { cfg_t *statecfg = cfg_getnsec(cfg, EDF_SEC_FRAME, i); const char *name = cfg_title(statecfg); // if not in the name table, count it if(E_StateNumForName(name) < 0) ++count; } return count; }
// // E_SafeStateNameOrLabel // // haleyjd 07/19/14: Allows lookup of what may either be an EDF global state // name, DECORATE state label relative to a particular mobjinfo, or a state // DeHackEd number. // int E_SafeStateNameOrLabel(mobjinfo_t *mi, const char *name) { char *pos = nullptr; long num = strtol(name, &pos, 0); // Not a number? It is a state name. if(estrnonempty(pos)) { int statenum = NullStateNum; state_t *state = nullptr; // Try global resolution first. if((statenum = E_StateNumForName(name)) < 0) { // Try DECORATE state label resolution. if((state = E_GetJumpInfo(mi, name))) statenum = state->index; } return statenum; } else return E_SafeState((int)num); // DeHackEd number }
// // 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)); } }
// // 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); }