/** * 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; }
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; }
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; }
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; }
void P_SpawnFireFlicker(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; fireflicker_t *flick = (fireflicker_t *)Z_Calloc(sizeof(*flick), PU_MAP, 0); flick->thinker.function = T_FireFlicker; Thinker_Add(&flick->thinker); flick->sector = sector; flick->count = 4; flick->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flick->minLight = otherLevel; else flick->minLight = lightLevel; flick->minLight += (16.0f/255.0f); }
int EV_OpenPillar(Line * /*line*/, byte *args) { iterlist_t *list = P_GetSectorIterListForTag((int) args[0], false); if(!list) return 0; int rtn = 0; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { // If already moving keep going... if(P_ToXSector(sec)->specialData) continue; if(!FEQUAL(P_GetDoublep(sec, DMU_FLOOR_HEIGHT), P_GetDoublep(sec, DMU_CEILING_HEIGHT))) continue; // Pillar isn't closed. rtn = 1; pillar_t *pillar = (pillar_t *)Z_Calloc(sizeof(*pillar), PU_MAP, 0); pillar->thinker.function = (thinkfunc_t) T_BuildPillar; Thinker_Add(&pillar->thinker); P_ToXSector(sec)->specialData = pillar; pillar->sector = sec; if(!args[2]) { P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &pillar->floorDest); } else { pillar->floorDest = P_GetDoublep(sec, DMU_FLOOR_HEIGHT) - (coord_t) args[2]; } if(!args[3]) { P_FindSectorSurroundingHighestCeiling(sec, 0, &pillar->ceilingDest); } else { pillar->ceilingDest = P_GetDoublep(sec, DMU_CEILING_HEIGHT) + (coord_t) args[3]; } if(P_GetDoublep(sec, DMU_FLOOR_HEIGHT) - pillar->floorDest >= pillar->ceilingDest - P_GetDoublep(sec, DMU_CEILING_HEIGHT)) { pillar->floorSpeed = (float) args[1] * (1.0f / 8); pillar->ceilingSpeed = (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - pillar->ceilingDest) * (pillar->floorSpeed / (pillar->floorDest - P_GetDoublep(sec, DMU_FLOOR_HEIGHT))); } else { pillar->ceilingSpeed = (float) args[1] * (1.0f / 8); pillar->floorSpeed = (pillar->floorDest - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)) * (pillar->ceilingSpeed / (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - pillar->ceilingDest)); } pillar->direction = -1; // Open the pillar. SN_StartSequence((mobj_t *)P_GetPtrp(pillar->sector, DMU_EMITTER), SEQ_PLATFORM + P_ToXSector(pillar->sector)->seqType); } return rtn; }
int EV_BuildPillar(Line * /*line*/, byte *args, dd_bool crush) { iterlist_t *list = P_GetSectorIterListForTag((int) args[0], false); if(!list) return 0; int rtn = 0; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { // If already moving keep going... if(P_ToXSector(sec)->specialData) continue; if(FEQUAL(P_GetDoublep(sec, DMU_FLOOR_HEIGHT), P_GetDoublep(sec, DMU_CEILING_HEIGHT))) continue; // Pillar is already closed. rtn = 1; coord_t newHeight = 0; if(!args[2]) { newHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT) + ((P_GetDoublep(sec, DMU_CEILING_HEIGHT) - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)) * .5f); } else { newHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT) + (coord_t) args[2]; } pillar_t *pillar = (pillar_t *)Z_Calloc(sizeof(*pillar), PU_MAP, 0); pillar->thinker.function = (thinkfunc_t) T_BuildPillar; Thinker_Add(&pillar->thinker); P_ToXSector(sec)->specialData = pillar; pillar->sector = sec; if(!args[2]) { pillar->ceilingSpeed = pillar->floorSpeed = (float) args[1] * (1.0f / 8); } else if(newHeight - P_GetDoublep(sec, DMU_FLOOR_HEIGHT) > P_GetDoublep(sec, DMU_CEILING_HEIGHT) - newHeight) { pillar->floorSpeed = (float) args[1] * (1.0f / 8); pillar->ceilingSpeed = (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - newHeight) * (pillar->floorSpeed / (newHeight - P_GetDoublep(sec, DMU_FLOOR_HEIGHT))); } else { pillar->ceilingSpeed = (float) args[1] * (1.0f / 8); pillar->floorSpeed = (newHeight - P_GetDoublep(sec, DMU_FLOOR_HEIGHT)) * (pillar->ceilingSpeed / (P_GetDoublep(sec, DMU_CEILING_HEIGHT) - newHeight)); } pillar->floorDest = newHeight; pillar->ceilingDest = newHeight; pillar->direction = 1; pillar->crush = crush * (int) args[3]; SN_StartSequence((mobj_t *)P_GetPtrp(pillar->sector, DMU_EMITTER), SEQ_PLATFORM + P_ToXSector(pillar->sector)->seqType); } return rtn; }
/** * Things to handle: * * T_MoveCeiling, (ceiling_t: Sector * swizzle), - active list * T_Door, (door_t: Sector * swizzle), * T_MoveFloor, (floor_t: Sector * swizzle), * T_LightFlash, (lightflash_t: Sector * swizzle), * T_StrobeFlash, (strobe_t: Sector *), * T_Glow, (glow_t: Sector *), * T_PlatRaise, (plat_t: Sector *), - active list */ static void P_v13_UnArchiveSpecials(void) { enum { tc_ceiling, tc_door, tc_floor, tc_plat, tc_flash, tc_strobe, tc_glow, tc_endspecials }; byte tclass; ceiling_t* ceiling; door_t* door; floor_t* floor; plat_t* plat; lightflash_t* flash; strobe_t* strobe; glow_t* glow; // Read in saved thinkers. for(;;) { tclass = Reader_ReadByte(svReader); switch(tclass) { case tc_endspecials: return; // End of list. case tc_ceiling: ceiling = Z_Calloc(sizeof(*ceiling), PU_MAP, NULL); SV_ReadCeiling(ceiling); Thinker_Add(&ceiling->thinker); break; case tc_door: door = Z_Calloc(sizeof(*door), PU_MAP, NULL); SV_ReadDoor(door); Thinker_Add(&door->thinker); break; case tc_floor: floor = Z_Calloc(sizeof(*floor), PU_MAP, NULL); SV_ReadFloor(floor); Thinker_Add(&floor->thinker); break; case tc_plat: plat = Z_Calloc(sizeof(*plat), PU_MAP, NULL); SV_ReadPlat(plat); Thinker_Add(&plat->thinker); break; case tc_flash: flash = Z_Calloc(sizeof(*flash), PU_MAP, NULL); SV_ReadFlash(flash); Thinker_Add(&flash->thinker); break; case tc_strobe: strobe = Z_Calloc(sizeof(*strobe), PU_MAP, NULL); SV_ReadStrobe(strobe); Thinker_Add(&strobe->thinker); break; case tc_glow: glow = Z_Calloc(sizeof(*glow), PU_MAP, NULL); SV_ReadGlow(glow); Thinker_Add(&glow->thinker); break; default: Con_Error("P_UnarchiveSpecials:Unknown tclass %i " "in savegame", tclass); } } }
static int doPlat(Line *line, int tag, plattype_e type, int amount) #endif { #if !__JHEXEN__ Sector *frontSector = (Sector *)P_GetPtrp(line, DMU_FRONT_SECTOR); #endif iterlist_t *list = P_GetSectorIterListForTag(tag, false); if(!list) return 0; int rtn = 0; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { xsector_t *xsec = P_ToXSector(sec); if(xsec->specialData) continue; // Find lowest & highest floors around sector rtn = 1; plat_t *plat = (plat_t *) Z_Calloc(sizeof(*plat), PU_MAP, 0); plat->thinker.function = T_PlatRaise; Thinker_Add(&plat->thinker); xsec->specialData = plat; plat->type = type; plat->sector = sec; plat->crush = false; plat->tag = tag; #if __JHEXEN__ plat->speed = (float) args[1] * (1.0 / 8); #endif coord_t floorHeight = P_GetDoublep(sec, DMU_FLOOR_HEIGHT); switch(type) { #if !__JHEXEN__ case PT_RAISETONEARESTANDCHANGE: plat->speed = PLATSPEED * .5; P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL)); { coord_t nextFloor; if(P_FindSectorSurroundingNextHighestFloor(sec, floorHeight, &nextFloor)) plat->high = nextFloor; else plat->high = floorHeight; } plat->wait = 0; plat->state = PS_UP; // No more damage if applicable. xsec->special = 0; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); break; case PT_RAISEANDCHANGE: plat->speed = PLATSPEED * .5; P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL)); plat->high = floorHeight + amount; plat->wait = 0; plat->state = PS_UP; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); break; #endif case PT_DOWNWAITUPSTAY: P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); #if __JHEXEN__ plat->low += 8; #else plat->speed = PLATSPEED * 4; #endif if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->state = PS_DOWN; #if __JHEXEN__ plat->wait = (int) args[2]; #else plat->wait = PLATWAIT * TICSPERSEC; #endif #if !__JHEXEN__ S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); #endif break; #if __JDOOM64__ || __JHEXEN__ case PT_UPWAITDOWNSTAY: P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high); if(plat->high < floorHeight) plat->high = floorHeight; plat->low = floorHeight; plat->state = PS_UP; # if __JHEXEN__ plat->wait = (int) args[2]; # else plat->wait = PLATWAIT * TICSPERSEC; # endif # if __JDOOM64__ plat->speed = PLATSPEED * 8; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); # endif break; #endif #if __JDOOM64__ case PT_DOWNWAITUPDOOR: // jd64 plat->speed = PLATSPEED * 8; P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); if(plat->low > floorHeight) plat->low = floorHeight; if(plat->low != floorHeight) plat->low += 6; plat->high = floorHeight; plat->wait = 50 * PLATWAIT; plat->state = PS_DOWN; break; #endif #if __JHEXEN__ case PT_DOWNBYVALUEWAITUPSTAY: plat->low = floorHeight - (coord_t) args[3] * 8; if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->wait = (int) args[2]; plat->state = PS_DOWN; break; case PT_UPBYVALUEWAITDOWNSTAY: plat->high = floorHeight + (coord_t) args[3] * 8; if(plat->high < floorHeight) plat->high = floorHeight; plat->low = floorHeight; plat->wait = (int) args[2]; plat->state = PS_UP; break; #endif #if __JDOOM__ || __JDOOM64__ case PT_DOWNWAITUPSTAYBLAZE: plat->speed = PLATSPEED * 8; P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->wait = PLATWAIT * TICSPERSEC; plat->state = PS_DOWN; S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); break; #endif case PT_PERPETUALRAISE: P_FindSectorSurroundingLowestFloor(sec, P_GetDoublep(sec, DMU_FLOOR_HEIGHT), &plat->low); #if __JHEXEN__ plat->low += 8; #else plat->speed = PLATSPEED; #endif if(plat->low > floorHeight) plat->low = floorHeight; P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high); if(plat->high < floorHeight) plat->high = floorHeight; plat->state = platstate_e(P_Random() & 1); #if __JHEXEN__ plat->wait = (int) args[2]; #else plat->wait = PLATWAIT * TICSPERSEC; #endif #if !__JHEXEN__ S_PlaneSound((Plane *)P_GetPtrp(sec, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); #endif break; default: break; } #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #endif } return rtn; }
dd_bool EV_SpawnLight(Line * /*line*/, byte *arg, lighttype_t type) { int arg1, arg2, arg3, arg4; arg1 = (int) arg[1]; arg2 = (int) arg[2]; arg3 = (int) arg[3]; arg4 = (int) arg[4]; iterlist_t *list = P_GetSectorIterListForTag((int) arg[0], false); if(!list) return false; dd_bool rtn = false; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); IterList_RewindIterator(list); Sector *sec; while((sec = (Sector *)IterList_MoveIterator(list))) { rtn = true; dd_bool think = false; light_t *light = (light_t *)Z_Calloc(sizeof(*light), PU_MAP, 0); light->type = type; light->sector = sec; light->count = 0; switch(type) { case LITE_RAISEBYVALUE: P_SectorModifyLight(light->sector, (float) arg1 / 255.0f); break; case LITE_LOWERBYVALUE: P_SectorModifyLight(light->sector, -((float) arg1 / 255.0f)); break; case LITE_CHANGETOVALUE: P_SectorSetLight(light->sector, (float) arg1 / 255.0f); break; case LITE_FADE: think = true; light->value1 = (float) arg1 / 255.0f; // Destination lightlevel. light->value2 = FIX2FLT(FixedDiv((arg1 - (int) (255.0f * P_SectorLight(light->sector))) << FRACBITS, arg2 << FRACBITS)) / 255.0f; // Delta lightlevel. if(P_SectorLight(light->sector) <= (float) arg1 / 255.0f) { light->tics2 = 1; // Get brighter. } else { light->tics2 = -1; } break; case LITE_GLOW: think = true; light->value1 = (float) arg1 / 255.0f; // Upper lightlevel. light->value2 = (float) arg2 / 255.0f; // Lower lightlevel. light->tics1 = FixedDiv((arg1 - (int) (255.0f * P_SectorLight(light->sector))) << FRACBITS, arg3 << FRACBITS); // Lightlevel delta. if(P_SectorLight(light->sector) <= (float) arg1 / 255.0f) { light->tics2 = 1; // Get brighter. } else { light->tics2 = -1; } break; case LITE_FLICKER: think = true; light->value1 = (float) arg1 / 255.0f; // Upper lightlevel. light->value2 = (float) arg2 / 255.0f; // Lower lightlevel. P_SectorSetLight(light->sector, light->value1); light->count = (P_Random() & 64) + 1; break; case LITE_STROBE: think = true; light->value1 = (float) arg1 / 255.0f; // Upper lightlevel. light->value2 = (float) arg2 / 255.0f; // Lower lightlevel. light->tics1 = arg3; // Upper tics. light->tics2 = arg4; // Lower tics. light->count = arg3; P_SectorSetLight(light->sector, light->value1); break; default: rtn = false; break; } if(think) { light->thinker.function = (thinkfunc_t) T_Light; Thinker_Add(&light->thinker); } else { Z_Free(light); } } return rtn; }