/** * Called when a moving plat needs to be removed. * * @param plat Ptr to the plat to remove. */ static void stopPlat(plat_t *plat) { DENG2_ASSERT(plat); P_ToXSector(plat->sector)->specialData = nullptr; P_NotifySectorFinished(P_ToXSector(plat->sector)->tag); Thinker_Remove(&plat->thinker); }
void writeSoundTargets() { #if !__JHEXEN__ if (!IS_SERVER) return; // Not for us. // Write the total number. int count = 0; for (int i = 0; i < numsectors; ++i) { xsector_t *xsec = P_ToXSector((Sector *)P_ToPtr(DMU_SECTOR, i)); if (xsec->soundTarget) { count += 1; } } // beginSegment(); Writer_WriteInt32(writer, count); // Write the mobj references using the mobj archive. for (int i = 0; i < numsectors; ++i) { xsector_t *xsec = P_ToXSector((Sector *)P_ToPtr(DMU_SECTOR, i)); if (xsec->soundTarget) { Writer_WriteInt32(writer, i); Writer_WriteInt16(writer, thingArchive->serialIdFor(xsec->soundTarget)); } } // endSegment(); #endif }
/** * Called when a moving plat needs to be removed. * * @param plat Ptr to the plat to remove. */ static void stopPlat(plat_t* plat) { P_ToXSector(plat->sector)->specialData = NULL; #if __JHEXEN__ P_TagFinished(P_ToXSector(plat->sector)->tag); #endif Thinker_Remove(&plat->thinker); }
void P_CopySector(Sector *dest, Sector *src) { xsector_t *xsrc = P_ToXSector(src); xsector_t *xdest = P_ToXSector(dest); if(src == dest) return; // no point copying self. // Copy the built-in properties. float ftemp[4]; coord_t dtemp[2]; P_SetFloatp (dest, DMU_LIGHT_LEVEL, P_GetFloatp(src, DMU_LIGHT_LEVEL)); P_GetFloatpv (src, DMU_COLOR, ftemp); P_SetFloatpv (dest, DMU_COLOR, ftemp); P_SetDoublep (dest, DMU_FLOOR_HEIGHT, P_GetDoublep(src, DMU_FLOOR_HEIGHT)); P_SetPtrp (dest, DMU_FLOOR_MATERIAL, P_GetPtrp(src, DMU_FLOOR_MATERIAL)); P_GetFloatpv (src, DMU_FLOOR_COLOR, ftemp); P_SetFloatpv (dest, DMU_FLOOR_COLOR, ftemp); P_GetDoublepv(src, DMU_FLOOR_MATERIAL_OFFSET_XY, dtemp); P_SetDoublepv(dest, DMU_FLOOR_MATERIAL_OFFSET_XY, dtemp); P_SetIntp (dest, DMU_FLOOR_SPEED, P_GetIntp(src, DMU_FLOOR_SPEED)); P_SetDoublep (dest, DMU_FLOOR_TARGET_HEIGHT, P_GetFloatp(src, DMU_FLOOR_TARGET_HEIGHT)); P_SetDoublep (dest, DMU_CEILING_HEIGHT, P_GetDoublep(src, DMU_CEILING_HEIGHT)); P_SetPtrp (dest, DMU_CEILING_MATERIAL, P_GetPtrp(src, DMU_CEILING_MATERIAL)); P_GetFloatpv (src, DMU_CEILING_COLOR, ftemp); P_SetFloatpv (dest, DMU_CEILING_COLOR, ftemp); P_GetDoublepv(src, DMU_CEILING_MATERIAL_OFFSET_XY, dtemp); P_SetDoublepv(dest, DMU_CEILING_MATERIAL_OFFSET_XY, dtemp); P_SetIntp (dest, DMU_CEILING_SPEED, P_GetIntp(src, DMU_CEILING_SPEED)); P_SetDoublep (dest, DMU_CEILING_TARGET_HEIGHT, P_GetFloatp(src, DMU_CEILING_TARGET_HEIGHT)); // Copy the extended properties too #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ xdest->special = xsrc->special; xdest->soundTraversed = xsrc->soundTraversed; xdest->soundTarget = xsrc->soundTarget; #if __JHERETIC__ xdest->seqType = xsrc->seqType; #endif xdest->SP_floororigheight = xsrc->SP_floororigheight; xdest->SP_ceilorigheight = xsrc->SP_ceilorigheight; xdest->origLight = xsrc->origLight; std::memcpy(xdest->origRGB, xsrc->origRGB, sizeof(float) * 3); if(xsrc->xg && xdest->xg) std::memcpy(xdest->xg, xsrc->xg, sizeof(*xdest->xg)); else xdest->xg = 0; #else xdest->special = xsrc->special; xdest->soundTraversed = xsrc->soundTraversed; xdest->soundTarget = xsrc->soundTarget; xdest->seqType = xsrc->seqType; #endif }
/** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnStrobeFlash(sector_t *sector, int fastOrSlow, int inSync) { strobe_t *flash; float lightlevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); flash = Z_Malloc(sizeof(*flash), PU_MAPSPEC, 0); P_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->darkTime = fastOrSlow; flash->brightTime = STROBEBRIGHT; flash->thinker.function = T_StrobeFlash; flash->maxLight = lightlevel; flash->minLight = P_FindMinSurroundingLight(sector, lightlevel); if(flash->minLight == flash->maxLight) flash->minLight = 0; // nothing special about it during gameplay P_ToXSector(sector)->special = 0; if(!inSync) flash->count = (P_Random() & 7) + 1; else flash->count = 1; }
coord_t Mobj_Friction(mobj_t const *mo) { if(Mobj_IsAirborne(mo)) { // Airborne "friction". return FRICTION_FLY; } #if __JHERETIC__ if(P_ToXSector(Mobj_Sector(mo))->special == 15) // Low friction. { return FRICTION_LOW; } #endif #if __JHEXEN__ terraintype_t const *tt = P_MobjFloorTerrain(mo); if(tt->flags & TTF_FRICTION_LOW) { return FRICTION_LOW; } #endif #if LIBCOMMON_HAVE_XG // Use the current sector's friction. return XS_Friction(Mobj_Sector(mo)); #else return FRICTION_NORMAL; #endif }
/** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnStrobeFlash(Sector *sector, int fastOrSlow, int inSync) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; strobe_t *flash = (strobe_t *)Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = (thinkfunc_t) T_StrobeFlash; Thinker_Add(&flash->thinker); flash->sector = sector; flash->darkTime = fastOrSlow; flash->brightTime = STROBEBRIGHT; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; if(flash->minLight == flash->maxLight) flash->minLight = 0; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; if(!inSync) { flash->count = (P_Random() & 7) + 1; } else { flash->count = 1; } }
/** * After the map has been loaded, scan each sector * for specials that spawn thinkers */ void P_SpawnLightFlash(Sector *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; lightflash_t *flash = (lightflash_t *)Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = (thinkfunc_t) T_LightFlash; Thinker_Add(&flash->thinker); flash->sector = sector; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; flash->maxTime = 64; flash->minTime = 7; flash->count = (P_Random() & flash->maxTime) + 1; }
coord_t Mobj_ThrustMul(mobj_t const *mo) { coord_t mul = 1.0; #if __JHEXEN__ if(P_MobjFloorTerrain(mo)->flags & TTF_FRICTION_LOW) { mul /= 2; } #else // !__JHEXEN__ Sector *sec = Mobj_Sector(mo); #if __JHERETIC__ if(P_ToXSector(sec)->special == 15) // Friction_Low { mul /= 4; return mul; // XG friction ignored. } #endif // Use a thrust multiplier based on the sector's friction. mul = Mobj_ThrustMulForFriction(XS_Friction(sec)); #endif return mul; }
void T_BuildPillar(pillar_t *pillar) { DENG2_ASSERT(pillar); // First, raise the floor result_e res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floorDest, pillar->crush, 0, pillar->direction); // floorOrCeiling, direction // Then, lower the ceiling result_e res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed, pillar->ceilingDest, pillar->crush, 1, -pillar->direction); if(res1 == pastdest && res2 == pastdest) { P_ToXSector(pillar->sector)->specialData = 0; SN_StopSequenceInSec(pillar->sector); P_NotifySectorFinished(P_ToXSector(pillar->sector)->tag); Thinker_Remove(&pillar->thinker); } }
/** * Called every tic frame that the player origin is in a special sector */ void P_PlayerInSpecialSector(player_t *player) { Sector *sector = Mobj_Sector(player->plr->mo); if(IS_CLIENT) return; // Falling, not all the way down yet? if(!FEQUAL(player->plr->mo->origin[VZ], P_GetDoublep(sector, DMU_FLOOR_HEIGHT))) return; // Has hitten ground. switch(P_ToXSector(sector)->special) { default: break; case 5: ///< HELLSLIME DAMAGE if(!player->powers[PT_IRONFEET]) if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 10, false); break; case 7: ///< NUKAGE DAMAGE if(!player->powers[PT_IRONFEET]) if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 5, false); break; case 16: ///< SUPER HELLSLIME DAMAGE case 4: ///< STROBE HURT if(!player->powers[PT_IRONFEET] || (P_Random() < 5)) { if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 20, false); } break; case 9: ///< SECRET SECTOR player->secretCount++; P_ToXSector(sector)->special = 0; if(cfg.secretMsg) { P_SetMessage(player, "You've found a secret area!"); // S_ConsoleSound(SFX_SECRET, 0, player - players); // jd64 } break; } }
void T_FloorWaggle(waggle_t *waggle) { DENG_ASSERT(waggle != 0); switch(waggle->state) { default: case WS_STABLE: if(waggle->ticker != -1) { if(!--waggle->ticker) { waggle->state = WS_REDUCE; } } break; case WS_EXPAND: if((waggle->scale += waggle->scaleDelta) >= waggle->targetScale) { waggle->scale = waggle->targetScale; waggle->state = WS_STABLE; } break; case WS_REDUCE: if((waggle->scale -= waggle->scaleDelta) <= 0) { // Remove. P_SetDoublep(waggle->sector, DMU_FLOOR_HEIGHT, waggle->originalHeight); P_ChangeSector(waggle->sector, 1 /*crush damage*/); P_ToXSector(waggle->sector)->specialData = nullptr; P_NotifySectorFinished(P_ToXSector(waggle->sector)->tag); Thinker_Remove(&waggle->thinker); return; } break; } waggle->accumulator += waggle->accDelta; coord_t fh = waggle->originalHeight + FLOATBOBOFFSET(((int) waggle->accumulator) & 63) * waggle->scale; P_SetDoublep(waggle->sector, DMU_FLOOR_HEIGHT, fh); P_SetDoublep(waggle->sector, DMU_FLOOR_TARGET_HEIGHT, fh); P_SetFloatp(waggle->sector, DMU_FLOOR_SPEED, 0); P_ChangeSector(waggle->sector, 1 /*crush damage*/); }
dd_bool EV_StartFloorWaggle(int tag, int height, int speed, int offset, int timer) { iterlist_t *list = P_GetSectorIterListForTag(tag, false); if(!list) return false; dd_bool retCode = false; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { if(P_ToXSector(sec)->specialData) continue; // Already moving, so keep going... retCode = true; waggle_t *waggle = (waggle_t *)Z_Calloc(sizeof(*waggle), PU_MAP, 0); waggle->thinker.function = (thinkfunc_t) T_FloorWaggle; Thinker_Add(&waggle->thinker); P_ToXSector(sec)->specialData = waggle; waggle->sector = sec; waggle->originalHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT); waggle->accumulator = offset; waggle->accDelta = FIX2FLT(speed << 10); waggle->scale = 0; waggle->targetScale = FIX2FLT(height << 10); waggle->scaleDelta = FIX2FLT(FLT2FIX(waggle->targetScale) / (TICSPERSEC + ((3 * TICSPERSEC) * height) / 255)); waggle->ticker = timer ? timer * 35 : -1; waggle->state = WS_EXPAND; } return retCode; }
int waggle_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); if(mapVersion >= 4) { /*int ver =*/ Reader_ReadByte(reader); // version byte. // Start of used data members. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); originalHeight = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accumulator = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); targetScale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scaleDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ticker = Reader_ReadInt32(reader); state = wagglestate_e(Reader_ReadInt32(reader)); } else { // Its in the old pre V4 format which serialized waggle_t // Padding at the start (an old thinker_t struct) byte junk[16]; // sizeof thinker_t Reader_Read(reader, junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); originalHeight = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accumulator = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); accDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); targetScale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scale = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); scaleDelta = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ticker = Reader_ReadInt32(reader); state = wagglestate_e(Reader_ReadInt32(reader)); } thinker.function = (thinkfunc_t) T_FloorWaggle; P_ToXSector(sector)->specialData = this; return true; // Add this thinker. }
void P_SpawnLightSequence(Sector* sector, int indexStep) { int count; { findlightsequencesectorparams_t params; params.seqSpecial = LIGHT_SEQUENCE; // Look for Light_Sequence, first. params.count = 1; params.sec = sector; do { // Make sure that the search doesn't back up. P_ToXSector(params.sec)->special = LIGHT_SEQUENCE_START; params.nextSec = NULL; P_Iteratep(params.sec, DMU_LINE, ¶ms, findLightSequenceSector); params.sec = params.nextSec; } while(params.sec); count = params.count; } { findlightsequencestartsectorparams_t params; float base; fixed_t index, indexDelta; params.sec = sector; count *= indexStep; index = 0; indexDelta = FixedDiv(64 * FRACUNIT, count * FRACUNIT); base = P_SectorLight(sector); do { if(P_SectorLight(params.sec)) { base = P_SectorLight(params.sec); } P_SpawnPhasedLight(params.sec, base, index >> FRACBITS); index += indexDelta; params.nextSec = NULL; P_Iteratep(params.sec, DMU_LINE, ¶ms, findLightSequenceStartSector); params.sec = params.nextSec; } while(params.sec); } }
static int findLightSequenceStartSector(void *p, void *context) { Line *li = (Line *) p; findlightsequencestartsectorparams_t *params = (findlightsequencestartsectorparams_t *) context; if(Sector *sector = P_GetNextSector(li, params->sec)) { if(P_ToXSector(sector)->special == LIGHT_SEQUENCE_START) { params->nextSec = sector; } } return false; // Continue iteration. }
void P_BuildSectorTagLists() { P_DestroySectorTagLists(); for(int i = 0; i < numsectors; ++i) { Sector *sec = (Sector *)P_ToPtr(DMU_SECTOR, i); xsector_t *xsec = P_ToXSector(sec); if(xsec->tag) { iterlist_t *list = P_GetSectorIterListForTag(xsec->tag, true); IterList_PushBack(list, sec); } } }
int pillar_s::read(MapStateReader *msr) { Reader1 *reader = msr->reader(); int mapVersion = msr->mapVersion(); if(mapVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ Reader_ReadByte(reader); // version byte. // Start of used data members. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); ceilingSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ceilingDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); direction = Reader_ReadInt32(reader); crush = Reader_ReadInt32(reader); } else { // Its in the old pre V4 format which serialized pillar_t // Padding at the start (an old thinker_t struct) byte junk[16]; // sizeof thinker_t Reader_Read(reader, junk, 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = (Sector *)P_ToPtr(DMU_SECTOR, (int) Reader_ReadInt32(reader)); DENG_ASSERT(sector != 0); ceilingSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorSpeed = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); floorDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); ceilingDest = FIX2FLT((fixed_t) Reader_ReadInt32(reader)); direction = Reader_ReadInt32(reader); crush = Reader_ReadInt32(reader); } thinker.function = (thinkfunc_t) T_BuildPillar; P_ToXSector(sector)->specialData = this; return true; // Add this thinker. }
static int SV_ReadPlat(plat_t *plat) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes Sector *sector; fixed_t speed; fixed_t low; fixed_t high; int wait; int count; platstate_e status; // was 32bit int platstate_e oldStatus; // was 32bit int boolean crush; int tag; plattype_e type; // was 32bit int } v13_plat_t; */ byte temp[SIZEOF_V13_THINKER_T]; // Padding at the start (an old thinker_t struct) Reader_Read(svReader, &temp, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. plat->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!plat->sector) Con_Error("tc_plat: bad sector number\n"); plat->speed = FIX2FLT(Reader_ReadInt32(svReader)); plat->low = FIX2FLT(Reader_ReadInt32(svReader)); plat->high = FIX2FLT(Reader_ReadInt32(svReader)); plat->wait = Reader_ReadInt32(svReader); plat->count = Reader_ReadInt32(svReader); plat->state = Reader_ReadInt32(svReader); plat->oldState = Reader_ReadInt32(svReader); plat->crush = Reader_ReadInt32(svReader); plat->tag = Reader_ReadInt32(svReader); plat->type = Reader_ReadInt32(svReader); plat->thinker.function = T_PlatRaise; if(!(temp + V13_THINKER_T_FUNC_OFFSET)) Thinker_SetStasis(&plat->thinker, true); P_ToXSector(plat->sector)->specialData = T_PlatRaise; return true; // Add this thinker. }
/** * Start strobing lights (usually from a trigger) */ void EV_StartLightStrobing(Line *line) { iterlist_t *list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { if(P_ToXSector(sec)->specialData) continue; P_SpawnStrobeFlash(sec, SLOWDARK, 0); } }
void P_SpawnGlowingLight(sector_t *sector) { float lightlevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); glow_t *g; g = Z_Malloc(sizeof(*g), PU_MAPSPEC, 0); P_ThinkerAdd(&g->thinker); g->sector = sector; g->minLight = P_FindMinSurroundingLight(sector, lightlevel); g->maxLight = lightlevel; g->thinker.function = T_Glow; g->direction = -1; P_ToXSector(sector)->special = 0; }
/** * Start strobing lights (usually from a trigger). */ void EV_StartLightStrobing(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; P_SpawnStrobeFlash(sec, SLOWDARK, 0); } }
void P_RecursiveSound(struct mobj_s* soundTarget, Sector* sec, int soundBlocks) { spreadsoundtoneighborsparams_t params; xsector_t* xsec = P_ToXSector(sec); // Wake up all monsters in this sector. if(P_GetIntp(sec, DMU_VALID_COUNT) == VALIDCOUNT && xsec->soundTraversed <= soundBlocks + 1) return; // Already flooded. P_SetIntp(sec, DMU_VALID_COUNT, VALIDCOUNT); xsec->soundTraversed = soundBlocks + 1; xsec->soundTarget = soundTarget; params.baseSec = sec; params.soundBlocks = soundBlocks; params.soundTarget = soundTarget; P_Iteratep(sec, DMU_LINE, ¶ms, spreadSoundToNeighbors); }
static int SV_ReadFloor(floor_t *floor) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes floortype_e type; // was 32bit int boolean crush; Sector *sector; int direction; int newspecial; short texture; fixed_t floordestheight; fixed_t speed; } v13_floormove_t; */ Uri *newTextureUrn; // Padding at the start (an old thinker_t struct) Reader_Read(svReader, NULL, SIZEOF_V13_THINKER_T); // Start of used data members. floor->type = Reader_ReadInt32(svReader); floor->crush = Reader_ReadInt32(svReader); // A 32bit pointer to sector, serialized. floor->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!floor->sector) Con_Error("tc_floor: bad sector number\n"); floor->state = (int) Reader_ReadInt32(svReader); floor->newSpecial = Reader_ReadInt32(svReader); newTextureUrn = readTextureUrn(svReader, "Flats"); floor->material = DD_MaterialForTextureUri(newTextureUrn); Uri_Delete(newTextureUrn); floor->floorDestHeight = FIX2FLT(Reader_ReadInt32(svReader)); floor->speed = FIX2FLT(Reader_ReadInt32(svReader)); floor->thinker.function = T_MoveFloor; P_ToXSector(floor->sector)->specialData = T_MoveFloor; return true; // Add this thinker. }
static int SV_ReadCeiling(ceiling_t *ceiling) { /* Original Heretic format: typedef struct { thinker_t thinker; ///< 12 bytes ceilingtype_e type; ///< 32bit int Sector* sector; fixed_t bottomheight, topheight; fixed_t speed; boolean crush; int direction; /// 1= up, 0= waiting, -1= down int tag' int olddirection; } v13_ceiling_t; */ byte temp[SIZEOF_V13_THINKER_T]; // Padding at the start (an old thinker_t struct) Reader_Read(svReader, &temp, SIZEOF_V13_THINKER_T); // Start of used data members. ceiling->type = Reader_ReadInt32(svReader); // A 32bit pointer to sector, serialized. ceiling->sector = P_ToPtr(DMU_SECTOR, Reader_ReadInt32(svReader)); if(!ceiling->sector) Con_Error("tc_ceiling: bad sector number\n"); ceiling->bottomHeight = FIX2FLT(Reader_ReadInt32(svReader)); ceiling->topHeight = FIX2FLT(Reader_ReadInt32(svReader)); ceiling->speed = FIX2FLT(Reader_ReadInt32(svReader)); ceiling->crush = Reader_ReadInt32(svReader); ceiling->state = (Reader_ReadInt32(svReader) == -1? CS_DOWN : CS_UP); ceiling->tag = Reader_ReadInt32(svReader); ceiling->oldState = (Reader_ReadInt32(svReader) == -1? CS_DOWN : CS_UP); ceiling->thinker.function = T_MoveCeiling; if(!(temp + V13_THINKER_T_FUNC_OFFSET)) Thinker_SetStasis(&ceiling->thinker, true); P_ToXSector(ceiling->sector)->specialData = T_MoveCeiling; return true; // Add this thinker. }
void P_SpawnFireFlicker(sector_t *sector) { float lightlevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); fireflicker_t *flick; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; flick = Z_Malloc(sizeof(*flick), PU_MAPSPEC, 0); P_ThinkerAdd(&flick->thinker); flick->thinker.function = T_FireFlicker; flick->sector = sector; flick->maxLight = lightlevel; flick->minLight = P_FindMinSurroundingLight(sector, lightlevel) + (16.0f/255.0f); flick->count = 4; }
/** * After the map has been loaded, scan each sector * for specials that spawn thinkers */ void P_SpawnLightFlash(sector_t *sector) { float lightlevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); lightflash_t *flash; // nothing special about it during gameplay P_ToXSector(sector)->special = 0; flash = Z_Malloc(sizeof(*flash), PU_MAPSPEC, 0); P_ThinkerAdd(&flash->thinker); flash->thinker.function = T_LightFlash; flash->sector = sector; flash->maxLight = lightlevel; flash->minLight = P_FindMinSurroundingLight(sector, lightlevel); flash->maxTime = 64; flash->minTime = 7; flash->count = (P_Random() & flash->maxTime) + 1; }
void P_SpawnGlowingLight(Sector *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; glow_t *g = (glow_t *)Z_Calloc(sizeof(*g), PU_MAP, 0); g->thinker.function = (thinkfunc_t) T_Glow; Thinker_Add(&g->thinker); g->sector = sector; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) g->minLight = otherLevel; else g->minLight = lightLevel; g->maxLight = lightLevel; g->direction = -1; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; }
static int findLightSequenceSector(void *p, void *context) { Line *li = (Line *) p; findlightsequencesectorparams_t *params = (findlightsequencesectorparams_t *) context; Sector *tempSec = P_GetNextSector(li, params->sec); if(tempSec) { if(P_ToXSector(tempSec)->special == params->seqSpecial) { if(params->seqSpecial == LIGHT_SEQUENCE) params->seqSpecial = LIGHT_SEQUENCE_ALT; else params->seqSpecial = LIGHT_SEQUENCE; params->nextSec = tempSec; params->count++; } } return false; // Continue iteration. }
void P_SpawnPhasedLight(Sector *sector, float base, int index) { phase_t *phase = (phase_t *)Z_Calloc(sizeof(*phase), PU_MAP, 0); phase->thinker.function = (thinkfunc_t) T_Phase; Thinker_Add(&phase->thinker); phase->sector = sector; if(index == -1) { // Sector->lightLevel as the index. phase->index = (int) (255.0f * P_SectorLight(sector)) & 63; } else { phase->index = index & 63; } phase->baseValue = base; P_SectorSetLight(phase->sector, phase->baseValue + phaseTable[phase->index]); P_ToXSector(sector)->special = 0; }