// // Reads the raw vertices and obtains final ones // void UDMFParser::loadVertices() const { numvertexes = (int)mVertices.getLength(); vertexes = estructalloctag(vertex_t, numvertexes, PU_LEVEL); for(int i = 0; i < numvertexes; i++) { vertexes[i].x = mVertices[i].x; vertexes[i].y = mVertices[i].y; // SoM: Cardboard stores float versions of vertices. vertexes[i].fx = M_FixedToFloat(vertexes[i].x); vertexes[i].fy = M_FixedToFloat(vertexes[i].y); } }
// // R_BuildDynaBSP // // Call to build a dynamic BSP sub-tree for sorting of dynasegs. // rpolybsp_t *R_BuildDynaBSP(subsector_t *subsec) { rpolybsp_t *bsp = NULL; dseglist_t segs = NULL; if(R_collapseFragmentsToDSList(subsec, &segs)) { bsp = estructalloctag(rpolybsp_t, 1, PU_LEVEL); bsp->dirty = false; bsp->root = R_createNode(&segs); } return bsp; }
// // R_CreatePortal // // Function to internally create a new portal. // static portal_t *R_CreatePortal() { portal_t *ret = estructalloctag(portal_t, 1, PU_LEVEL); if(!portals) portals = last = ret; else { last->next = ret; last = ret; } ret->poverlay = R_NewPlaneHash(32); ret->globaltex = 1; return ret; }
static pwindow_t *newPortalWindow() { pwindow_t *ret; if(unusedhead) { ret = unusedhead; unusedhead = unusedhead->next; } else { ret = estructalloctag(pwindow_t, 1, PU_LEVEL); float *buf = emalloctag(float *, 2*video.width*sizeof(float), PU_LEVEL, NULL); ret->top = buf; ret->bottom = buf + video.width; } R_ClearPortalWindow(ret); return ret; }
// // ACS_LoadScriptACS0 // void ACS_LoadScriptACS0(ACSVM *vm, WadDirectory *dir, int lump, byte *data) { uint32_t lumpAvail; // Used in bounds checking. uint32_t lumpLength = dir->lumpLength(lump); int32_t *rover; uint32_t tableIndex; // Header + table index + script count + string count = 16 bytes. if (lumpLength < 16) return; lumpAvail = lumpLength - 16; rover = (int32_t *)data + 1; // Find script table. tableIndex = SwapLong(*rover); // Aha, but there might really be an ACSE header here! if(tableIndex >= 8 && tableIndex <= lumpLength) { uint32_t fakeHeader = SwapULong(*(uint32_t *)(data + tableIndex - 4)); if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'E')) { ACS_LoadScriptACSE(vm, dir, lump, data, tableIndex - 8); return; } else if(fakeHeader == ACS_CHUNKID('A', 'C', 'S', 'e')) { ACS_LoadScriptACSe(vm, dir, lump, data, tableIndex - 8); return; } } // At the index there must be at least the script count and string count. // Subtracting from lumpLength instead of adding to tableIndex in case the // latter would cause an overflow. if (tableIndex > lumpLength - 8) return; rover = (int32_t *)(data + tableIndex); // Read script count. vm->numScripts = SwapLong(*rover++); // Verify that there is enough space for the given number of scripts. if (vm->numScripts * 12 > lumpAvail) return; lumpAvail -= vm->numScripts * 12; // Also verify that the string count will be inside the lump. if (tableIndex + 8 > lumpLength - (vm->numScripts * 12)) return; tableIndex += 8 + (vm->numScripts * 12); // Read scripts. vm->scripts = estructalloctag(ACSScript, vm->numScripts, PU_LEVEL); for(ACSScript *itr = vm->scripts, *end = itr + vm->numScripts; itr != end; ++itr) { itr->number = SwapLong(*rover++); itr->codeIndex = SwapLong(*rover++); itr->numArgs = SwapLong(*rover++); itr->numVars = ACS_NUM_LOCALVARS; itr->vm = vm; if(itr->number >= 1000) { itr->type = ACS_STYPE_OPEN; itr->number -= 1000; } else itr->type = ACS_STYPE_CLOSED; } // Read string count. vm->numStrings = SwapLong(*rover++); // Again, verify that there is enough space for the table first. if (vm->numStrings * 4 > lumpAvail) return; lumpAvail -= vm->numStrings * 4; // This time, just verify the end of the table is in bounds. if (tableIndex > lumpLength - (vm->numStrings * 4)) return; // Read strings. vm->strings = (uint32_t *)Z_Malloc(vm->numStrings * sizeof(uint32_t), PU_LEVEL, NULL); for(uint32_t *itr = vm->strings, *end = itr + vm->numStrings; itr != end; ++itr) { tableIndex = SwapLong(*rover++); if (tableIndex < lumpLength) *itr = ACS_LoadStringACS0(data + tableIndex, data + lumpLength); else *itr = ACS_LoadStringACS0(data + lumpLength, data + lumpLength); } // The first part of the global string table must match VM-0 for compatibility. if(vm->id == 0 && ACSVM::GlobalNumStrings < vm->numStrings) vm->addStrings(); // Read code. ACS_LoadScriptCodeACS0(vm, data, lumpLength, false); vm->loaded = true; }
// // Loads sectors // void UDMFParser::loadSectors(UDMFSetupSettings &setupSettings) const { numsectors = (int)mSectors.getLength(); sectors = estructalloctag(sector_t, numsectors, PU_LEVEL); for(int i = 0; i < numsectors; ++i) { sector_t *ss = sectors + i; const USector &us = mSectors[i]; if(mNamespace == namespace_Eternity) { // These two pass the fixed_t value now ss->floorheight = us.heightfloor; ss->ceilingheight = us.heightceiling; // New to Eternity ss->floor_xoffs = us.xpanningfloor; ss->floor_yoffs = us.ypanningfloor; ss->ceiling_xoffs = us.xpanningceiling; ss->ceiling_yoffs = us.ypanningceiling; ss->floorbaseangle = static_cast<float> (E_NormalizeFlatAngle(us.rotationfloor) * PI / 180.0f); ss->ceilingbaseangle = static_cast<float> (E_NormalizeFlatAngle(us.rotationceiling) * PI / 180.0f); // Flags ss->flags |= us.secret ? SECF_SECRET : 0; // Friction: set the parameter directly from UDMF if(us.friction >= 0) // default: -1 { int friction, movefactor; P_CalcFriction(us.friction, friction, movefactor); ss->flags |= SECF_FRICTION; // add the flag too ss->friction = friction; ss->movefactor = movefactor; } // Damage ss->damage = us.damageamount; ss->damagemask = us.damageinterval; ss->damagemod = E_DamageTypeNumForName(us.damagetype.constPtr()); // If the following flags are true for the current sector, then set the // appropriate damageflags to true, otherwise don't set them. ss->damageflags |= us.damage_endgodmode ? SDMG_ENDGODMODE : 0; ss->damageflags |= us.damage_exitlevel ? SDMG_EXITLEVEL : 0; ss->damageflags |= us.damageterraineffect ? SDMG_TERRAINHIT : 0; ss->leakiness = eclamp(us.leakiness, 0, 256); // Terrain types if(us.floorterrain.strCaseCmp(DEFAULT_flat)) ss->floorterrain = E_TerrainForName(us.floorterrain.constPtr()); if (us.ceilingterrain.strCaseCmp(DEFAULT_flat)) ss->ceilingterrain = E_TerrainForName(us.ceilingterrain.constPtr()); // Lights ss->floorlightdelta = static_cast<int16_t>(us.lightfloor); ss->ceilinglightdelta = static_cast<int16_t>(us.lightceiling); ss->flags |= (us.lightfloorabsolute ? SECF_FLOORLIGHTABSOLUTE : 0) | (us.lightceilingabsolute ? SECF_CEILLIGHTABSOLUTE : 0); // sector colormaps ss->topmap = ss->midmap = ss->bottommap = -1; // mark as not specified } else { ss->floorheight = us.heightfloor << FRACBITS; ss->ceilingheight = us.heightceiling << FRACBITS; } ss->floorpic = R_FindFlat(us.texturefloor.constPtr()); P_SetSectorCeilingPic(ss, R_FindFlat(us.textureceiling.constPtr())); ss->lightlevel = us.lightlevel; ss->special = us.special; ss->tag = us.identifier; P_InitSector(ss); // // HERE GO THE PROPERTIES THAT MUST TAKE EFFECT AFTER P_InitSector // if(mNamespace == namespace_Eternity) { if(us.colormaptop.strCaseCmp(DEFAULT_default)) { ss->topmap = R_ColormapNumForName(us.colormaptop.constPtr()); setupSettings.setSectorFlag(i, UDMF_SECTOR_INIT_COLORMAPPED); } if(us.colormapmid.strCaseCmp(DEFAULT_default)) { ss->midmap = R_ColormapNumForName(us.colormapmid.constPtr()); setupSettings.setSectorFlag(i, UDMF_SECTOR_INIT_COLORMAPPED); } if(us.colormapbottom.strCaseCmp(DEFAULT_default)) { ss->bottommap = R_ColormapNumForName(us.colormapbottom.constPtr()); setupSettings.setSectorFlag(i, UDMF_SECTOR_INIT_COLORMAPPED); } // Portal fields // Floors ss->f_pflags |= us.portal_floor_alpha << PO_OPACITYSHIFT; ss->f_pflags |= us.portal_floor_blocksound ? PF_BLOCKSOUND : 0; ss->f_pflags |= us.portal_floor_disabled ? PF_DISABLED : 0; ss->f_pflags |= us.portal_floor_nopass ? PF_NOPASS : 0; ss->f_pflags |= us.portal_floor_norender ? PF_NORENDER : 0; if(!us.portal_floor_overlaytype.strCaseCmp(RENDERSTYLE_translucent)) ss->f_pflags |= PS_OVERLAY; else if(!us.portal_floor_overlaytype.strCaseCmp(RENDERSTYLE_add)) ss->f_pflags |= PS_OBLENDFLAGS; // PS_OBLENDFLAGS is PS_OVERLAY | PS_ADDITIVE ss->f_pflags |= us.portal_floor_useglobaltex ? PS_USEGLOBALTEX : 0; // Ceilings ss->c_pflags |= us.portal_ceil_alpha << PO_OPACITYSHIFT; ss->c_pflags |= us.portal_ceil_blocksound ? PF_BLOCKSOUND : 0; ss->c_pflags |= us.portal_ceil_disabled ? PF_DISABLED : 0; ss->c_pflags |= us.portal_ceil_nopass ? PF_NOPASS : 0; ss->c_pflags |= us.portal_ceil_norender ? PF_NORENDER : 0; if(!us.portal_ceil_overlaytype.strCaseCmp(RENDERSTYLE_translucent)) ss->c_pflags |= PS_OVERLAY; else if(!us.portal_ceil_overlaytype.strCaseCmp(RENDERSTYLE_add)) ss->c_pflags |= PS_OBLENDFLAGS; // PS_OBLENDFLAGS is PS_OVERLAY | PS_ADDITIVE ss->c_pflags |= us.portal_ceil_useglobaltex ? PS_USEGLOBALTEX : 0; } } }
// // Loads linedefs. Returns false on error. // bool UDMFParser::loadLinedefs() { numlines = (int)mLinedefs.getLength(); lines = estructalloctag(line_t, numlines, PU_LEVEL); for(int i = 0; i < numlines; ++i) { line_t *ld = lines + i; const ULinedef &uld = mLinedefs[i]; if(uld.blocking) ld->flags |= ML_BLOCKING; if(uld.blockmonsters) ld->flags |= ML_BLOCKMONSTERS; if(uld.twosided) ld->flags |= ML_TWOSIDED; if(uld.dontpegtop) ld->flags |= ML_DONTPEGTOP; if(uld.dontpegbottom) ld->flags |= ML_DONTPEGBOTTOM; if(uld.secret) ld->flags |= ML_SECRET; if(uld.blocksound) ld->flags |= ML_SOUNDBLOCK; if(uld.dontdraw) ld->flags |= ML_DONTDRAW; if(uld.mapped) ld->flags |= ML_MAPPED; if(mNamespace == namespace_Doom || mNamespace == namespace_Eternity) { if(uld.passuse) ld->flags |= ML_PASSUSE; } // Eternity if(mNamespace == namespace_Eternity) { if(uld.midtex3d) ld->flags |= ML_3DMIDTEX; if(uld.firstsideonly) ld->extflags |= EX_ML_1SONLY; if(uld.blockeverything) ld->extflags |= EX_ML_BLOCKALL; if(uld.zoneboundary) ld->extflags |= EX_ML_ZONEBOUNDARY; if(uld.clipmidtex) ld->extflags |= EX_ML_CLIPMIDTEX; if(uld.midtex3dimpassible) ld->extflags |= EX_ML_3DMTPASSPROJ; } // TODO: Strife if(mNamespace == namespace_Hexen || mNamespace == namespace_Eternity) { if(uld.playercross) ld->extflags |= EX_ML_PLAYER | EX_ML_CROSS; if(uld.playeruse) ld->extflags |= EX_ML_PLAYER | EX_ML_USE; if(uld.monstercross) ld->extflags |= EX_ML_MONSTER | EX_ML_CROSS; if(uld.monsteruse) ld->extflags |= EX_ML_MONSTER | EX_ML_USE; if(uld.impact) ld->extflags |= EX_ML_MISSILE | EX_ML_IMPACT; if(uld.playerpush) ld->extflags |= EX_ML_PLAYER | EX_ML_PUSH; if(uld.monsterpush) ld->extflags |= EX_ML_MONSTER | EX_ML_PUSH; if(uld.missilecross) ld->extflags |= EX_ML_MISSILE | EX_ML_CROSS; if(uld.repeatspecial) ld->extflags |= EX_ML_REPEAT; } ld->special = uld.special; ld->tag = uld.identifier; ld->args[0] = uld.arg[0]; ld->args[1] = uld.arg[1]; ld->args[2] = uld.arg[2]; ld->args[3] = uld.arg[3]; ld->args[4] = uld.arg[4]; if(uld.v1 < 0 || uld.v1 >= numvertexes || uld.v2 < 0 || uld.v2 >= numvertexes || uld.sidefront < 0 || uld.sidefront >= numsides || uld.sideback < -1 || uld.sideback >= numsides) { mLine = uld.errorline; mColumn = 1; mError = "Vertex or sidedef overflow"; return false; } ld->v1 = &vertexes[uld.v1]; ld->v2 = &vertexes[uld.v2]; ld->sidenum[0] = uld.sidefront; ld->sidenum[1] = uld.sideback; P_InitLineDef(ld); P_PostProcessLineFlags(ld); // more Eternity if(mNamespace == namespace_Eternity) { ld->alpha = uld.alpha; if(!uld.renderstyle.strCaseCmp(RENDERSTYLE_add)) ld->extflags |= EX_ML_ADDITIVE; if(!uld.tranmap.empty()) { if(uld.tranmap != "TRANMAP") { int special = W_CheckNumForName(uld.tranmap.constPtr()); if(special < 0 || W_LumpLength(special) != 65536) ld->tranlump = 0; else ld->tranlump = special + 1; } else ld->tranlump = 0; } } } return true; }
// // Loads sidedefs // void UDMFParser::loadSidedefs() const { numsides = (int)mSidedefs.getLength(); sides = estructalloctag(side_t, numsides, PU_LEVEL); }