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 }
int findNextPlaneHeight(void* ptr, void* context) { findnextplaneheightparams_t* params = (findnextplaneheightparams_t*) context; Sector* other = P_GetNextSector((Line*) ptr, params->baseSec); coord_t otherHeight; if(!other) return false; // Continue iteration. otherHeight = P_GetDoublep(other, ((params->flags & FNPHF_FLOOR)? DMU_FLOOR_HEIGHT : DMU_CEILING_HEIGHT)); if(params->flags & FNPHF_ABOVE) { if(otherHeight < params->val && otherHeight > params->baseHeight) { params->val = otherHeight; params->foundSec = other; } } else if(otherHeight > params->val && otherHeight < params->baseHeight) { params->val = otherHeight; params->foundSec = other; } return false; // Continue iteration. }
int findExtremalPlaneHeight(void* ptr, void* context) { findextremalplaneheightparams_t* params = (findextremalplaneheightparams_t*) context; Sector* other = P_GetNextSector((Line*) ptr, params->baseSec); coord_t height; if(!other) return false; // Continue iteration. height = P_GetDoublep(other, ((params->flags & FEPHF_FLOOR)? DMU_FLOOR_HEIGHT : DMU_CEILING_HEIGHT)); if(params->flags & FEPHF_MIN) { if(height < params->val) { params->val = height; params->foundSec = other; } } else if(height > params->val) { params->val = height; params->foundSec = other; } return false; // Continue iteration. }
/** * 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; } }
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 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; }
static void SV_v13_ReadMobj(void) { coord_t pos[3], mom[3], floorz, ceilingz, radius, height; int frame, valid, type, ddflags = 0; spritenum_t sprite; mobjinfo_t* info; angle_t angle; mobj_t* mo; // The thinker was 3 ints long. Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); pos[VX] = FIX2FLT(Reader_ReadInt32(svReader)); pos[VY] = FIX2FLT(Reader_ReadInt32(svReader)); pos[VZ] = FIX2FLT(Reader_ReadInt32(svReader)); // Sector links. Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); angle = (angle_t) (ANG45 * (Reader_ReadInt32(svReader) / 45)); sprite = Reader_ReadInt32(svReader); frame = Reader_ReadInt32(svReader); frame &= ~FF_FRAMEMASK; // not used anymore. // Block links. Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // BspLeaf. Reader_ReadInt32(svReader); floorz = FIX2FLT(Reader_ReadInt32(svReader)); ceilingz = FIX2FLT(Reader_ReadInt32(svReader)); radius = FIX2FLT(Reader_ReadInt32(svReader)); height = FIX2FLT(Reader_ReadInt32(svReader)); mom[MX] = FIX2FLT(Reader_ReadInt32(svReader)); mom[MY] = FIX2FLT(Reader_ReadInt32(svReader)); mom[MZ] = FIX2FLT(Reader_ReadInt32(svReader)); valid = Reader_ReadInt32(svReader); type = Reader_ReadInt32(svReader); info = &MOBJINFO[type]; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; /** * We now have all the information we need to create the mobj. */ mo = P_MobjCreateXYZ(P_MobjThinker, pos[VX], pos[VY], pos[VZ], angle, radius, height, ddflags); mo->sprite = sprite; mo->frame = frame; mo->floorZ = floorz; mo->ceilingZ = ceilingz; mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; mo->mom[MZ] = mom[MZ]; mo->valid = valid; mo->type = type; mo->moveDir = DI_NODIR; /** * Continue reading the mobj data. */ Reader_ReadInt32(svReader); // info mo->tics = Reader_ReadInt32(svReader); mo->state = INT2PTR(state_t, Reader_ReadInt32(svReader)); mo->damage = Reader_ReadInt32(svReader); mo->flags = Reader_ReadInt32(svReader); mo->flags2 = Reader_ReadInt32(svReader); mo->special1 = Reader_ReadInt32(svReader); mo->special2 = Reader_ReadInt32(svReader); mo->health = Reader_ReadInt32(svReader); // Fix a bunch of kludges in the original Heretic. switch(mo->type) { case MT_MACEFX1: case MT_MACEFX2: case MT_MACEFX3: case MT_HORNRODFX2: case MT_HEADFX3: case MT_WHIRLWIND: case MT_TELEGLITTER: case MT_TELEGLITTER2: mo->special3 = mo->health; mo->health = info->spawnHealth; break; default: break; } mo->moveDir = Reader_ReadInt32(svReader); mo->moveCount = Reader_ReadInt32(svReader); Reader_ReadInt32(svReader); // target mo->reactionTime = Reader_ReadInt32(svReader); mo->threshold = Reader_ReadInt32(svReader); mo->player = INT2PTR(player_t, Reader_ReadInt32(svReader)); mo->lastLook = Reader_ReadInt32(svReader); mo->spawnSpot.origin[VX] = (coord_t) Reader_ReadInt32(svReader); mo->spawnSpot.origin[VY] = (coord_t) Reader_ReadInt32(svReader); mo->spawnSpot.origin[VZ] = 0; // Initialize with "something". mo->spawnSpot.angle = (angle_t) (ANG45 * (Reader_ReadInt32(svReader) / 45)); /*mo->spawnSpot.type = (int)*/ Reader_ReadInt32(svReader); { int spawnFlags = ((int) Reader_ReadInt32(svReader)) & ~MASK_UNKNOWN_MSF_FLAGS; // Spawn on the floor by default unless the mobjtype flags override. spawnFlags |= MSF_Z_FLOOR; mo->spawnSpot.flags = spawnFlags; } mo->info = info; SV_TranslateLegacyMobjFlags(mo, 0); mo->state = &STATES[PTR2INT(mo->state)]; mo->target = NULL; if(mo->player) { mo->player = &players[PTR2INT(mo->player) - 1]; mo->player->plr->mo = mo; mo->player->plr->mo->dPlayer = mo->player->plr; } P_MobjSetOrigin(mo); mo->floorZ = P_GetDoublep(mo->bspLeaf, DMU_FLOOR_HEIGHT); mo->ceilingZ = P_GetDoublep(mo->bspLeaf, DMU_CEILING_HEIGHT); }
void T_PlatRaise(void *platThinkerPtr) { plat_t *plat = (plat_t *)platThinkerPtr; result_e res; switch(plat->state) { case PS_UP: res = T_MovePlane(plat->sector, plat->speed, plat->high, plat->crush, 0, 1); // Play a "while-moving" sound? #if __JHERETIC__ if(!(mapTime & 31)) S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); #endif #if __JDOOM__ || __JDOOM64__ if(plat->type == PT_RAISEANDCHANGE || plat->type == PT_RAISETONEARESTANDCHANGE) { if(!(mapTime & 7)) S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); } #endif if(res == crushed && (!plat->crush)) { plat->count = plat->wait; plat->state = PS_DOWN; #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #else # if __JDOOM64__ if(plat->type != PT_DOWNWAITUPDOOR) // jd64 added test # endif S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); #endif } else { if(res == pastdest) { plat->count = plat->wait; plat->state = PS_WAIT; #if __JHEXEN__ SN_StopSequenceInSec(plat->sector); #else S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTOP); #endif switch(plat->type) { case PT_DOWNWAITUPSTAY: #if __JHEXEN__ case PT_DOWNBYVALUEWAITUPSTAY: #else # if !__JHERETIC__ case PT_DOWNWAITUPSTAYBLAZE: case PT_RAISETONEARESTANDCHANGE: # endif # if __JDOOM64__ case PT_DOWNWAITUPPLUS16STAYBLAZE: // jd64 case PT_DOWNWAITUPDOOR: // jd64 # endif case PT_RAISEANDCHANGE: #endif stopPlat(plat); break; default: break; } } } break; case PS_DOWN: res = T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, -1); if(res == pastdest) { plat->count = plat->wait; plat->state = PS_WAIT; #if __JHEXEN__ || __JDOOM64__ switch(plat->type) { # if __JHEXEN__ case PT_UPBYVALUEWAITDOWNSTAY: # endif case PT_UPWAITDOWNSTAY: stopPlat(plat); break; default: break; } #endif #if __JHEXEN__ SN_StopSequenceInSec(plat->sector); #else S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTOP); #endif } else { // Play a "while-moving" sound? #if __JHERETIC__ if(!(mapTime & 31)) S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMMOVE); #endif } break; case PS_WAIT: if(!--plat->count) { if(FEQUAL(P_GetDoublep(plat->sector, DMU_FLOOR_HEIGHT), plat->low)) plat->state = PS_UP; else plat->state = PS_DOWN; #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #else S_PlaneSound((Plane *)P_GetPtrp(plat->sector, DMU_FLOOR_PLANE), SFX_PLATFORMSTART); #endif } break; default: break; } }
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; }
int EV_Teleport(Line* line, int side, mobj_t* mo, dd_bool spawnFog) { mobj_t* dest; // Clients cannot teleport on their own. if(IS_CLIENT) return 0; if(mo->flags2 & MF2_NOTELEPORT) return 0; // Don't teleport if hit back of line, so you can get out of teleporter. if(side == 1) return 0; if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL) { // A suitable destination has been found. coord_t oldPos[3], aboveFloor; angle_t oldAngle; mobj_t* fog; uint an; memcpy(oldPos, mo->origin, sizeof(mo->origin)); oldAngle = mo->angle; aboveFloor = mo->origin[VZ] - mo->floorZ; if(!P_TeleportMove(mo, dest->origin[VX], dest->origin[VY], false)) return 0; mo->origin[VZ] = mo->floorZ; if(spawnFog) { // Spawn teleport fog at source and destination. if((fog = P_SpawnMobj(MT_TFOG, oldPos, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); an = dest->angle >> ANGLETOFINESHIFT; if((fog = P_SpawnMobjXYZ(MT_TFOG, dest->origin[VX] + 20 * FIX2FLT(finecosine[an]), dest->origin[VY] + 20 * FIX2FLT(finesine[an]), mo->origin[VZ], dest->angle + ANG180, 0))) { // Emit sound, where? S_StartSound(SFX_TELEPT, fog); } } mo->angle = dest->angle; if(mo->flags2 & MF2_FLOORCLIP) { mo->floorClip = 0; if(FEQUAL(mo->origin[VZ], P_GetDoublep(Mobj_Sector(mo), DMU_FLOOR_HEIGHT))) { terraintype_t const *tt = P_MobjFloorTerrain(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; // $voodoodolls Must be the real player. if(mo->player && mo->player->plr->mo == mo) { mo->reactionTime = 18; // Don't move for a bit. if(mo->player->powers[PT_FLIGHT] && aboveFloor > 0) { mo->origin[VZ] = mo->floorZ + aboveFloor; if(mo->origin[VZ] + mo->height > mo->ceilingZ) { mo->origin[VZ] = mo->ceilingZ - mo->height; } } else { //mo->dPlayer->clLookDir = 0; /* $unifiedangles */ mo->dPlayer->lookDir = 0; } mo->player->viewHeight = (coord_t) cfg.common.plrViewHeight; mo->player->viewHeightDelta = 0; mo->player->viewZ = mo->origin[VZ] + mo->player->viewHeight; mo->player->viewOffset[VX] = mo->player->viewOffset[VY] = mo->player->viewOffset[VZ] = 0; mo->player->bob = 0; //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */ mo->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXORIGIN | DDPF_FIXMOM; } return 1; }
int mobj_s::read(MapStateReader *msr) { #define FF_FULLBRIGHT 0x8000 ///< Used to be a flag in thing->frame. #define FF_FRAMEMASK 0x7fff Reader1 *reader = msr->reader(); int ver = Reader_ReadByte(reader); #if !__JHEXEN__ if(ver >= 2) // Version 2 has mobj archive numbers. { msr->addMobjToThingArchive(this, Reader_ReadInt16(reader)); } #endif #if !__JHEXEN__ target = 0; if(ver >= 2) { target = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } #endif #if __JDOOM__ || __JDOOM64__ tracer = 0; if(ver >= 5) { tracer = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } #endif onMobj = 0; #if __JHEXEN__ if(ver >= 8) #else if(ver >= 5) #endif { onMobj = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } origin[VX] = FIX2FLT(Reader_ReadInt32(reader)); origin[VY] = FIX2FLT(Reader_ReadInt32(reader)); origin[VZ] = FIX2FLT(Reader_ReadInt32(reader)); angle = Reader_ReadInt32(reader); sprite = Reader_ReadInt32(reader); frame = Reader_ReadInt32(reader); // might be ORed with FF_FULLBRIGHT if(frame & FF_FULLBRIGHT) frame &= FF_FRAMEMASK; // not used anymore. #if __JHEXEN__ if(ver < 6) { /*floorflat =*/ Reader_ReadInt32(reader); } #else floorZ = FIX2FLT(Reader_ReadInt32(reader)); ceilingZ = FIX2FLT(Reader_ReadInt32(reader)); #endif radius = FIX2FLT(Reader_ReadInt32(reader)); height = FIX2FLT(Reader_ReadInt32(reader)); mom[MX] = FIX2FLT(Reader_ReadInt32(reader)); mom[MY] = FIX2FLT(Reader_ReadInt32(reader)); mom[MZ] = FIX2FLT(Reader_ReadInt32(reader)); valid = Reader_ReadInt32(reader); type = Reader_ReadInt32(reader); #if __JHEXEN__ if(ver < 7) { /*info = (mobjinfo_t *)*/ Reader_ReadInt32(reader); } #endif info = &MOBJINFO[type]; if(info->flags2 & MF2_FLOATBOB) mom[MZ] = 0; if(info->flags & MF_SOLID) ddFlags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddFlags |= DDMF_DONTDRAW; tics = Reader_ReadInt32(reader); state = INT2PTR(state_t, Reader_ReadInt32(reader)); #if __JHEXEN__ damage = Reader_ReadInt32(reader); #endif flags = Reader_ReadInt32(reader); #if __JHEXEN__ flags2 = Reader_ReadInt32(reader); if(ver >= 5) { flags3 = Reader_ReadInt32(reader); } special1 = Reader_ReadInt32(reader); special2 = Reader_ReadInt32(reader); #endif health = Reader_ReadInt32(reader); #if __JHERETIC__ if(ver < 8) { // Fix a bunch of kludges in the original Heretic. switch(type) { case MT_MACEFX1: case MT_MACEFX2: case MT_MACEFX3: case MT_HORNRODFX2: case MT_HEADFX3: case MT_WHIRLWIND: case MT_TELEGLITTER: case MT_TELEGLITTER2: special3 = health; if(type == MT_HORNRODFX2 && special3 > 16) special3 = 16; health = MOBJINFO[type].spawnHealth; break; default: break; } } #endif moveDir = Reader_ReadInt32(reader); moveCount = Reader_ReadInt32(reader); #if __JHEXEN__ target = INT2PTR(mobj_t, Reader_ReadInt32(reader)); #endif reactionTime = Reader_ReadInt32(reader); threshold = Reader_ReadInt32(reader); player = INT2PTR(player_t, Reader_ReadInt32(reader)); lastLook = Reader_ReadInt32(reader); #if __JHEXEN__ floorClip = FIX2FLT(Reader_ReadInt32(reader)); msr->addMobjToThingArchive(this, Reader_ReadInt32(reader)); tid = Reader_ReadInt32(reader); #else // For nightmare respawn. if(ver >= 6) { spawnSpot.origin[VX] = FIX2FLT(Reader_ReadInt32(reader)); spawnSpot.origin[VY] = FIX2FLT(Reader_ReadInt32(reader)); spawnSpot.origin[VZ] = FIX2FLT(Reader_ReadInt32(reader)); spawnSpot.angle = Reader_ReadInt32(reader); if(ver < 10) { /*spawnSpot.type =*/ Reader_ReadInt32(reader); } spawnSpot.flags = Reader_ReadInt32(reader); } else { spawnSpot.origin[VX] = (float) Reader_ReadInt16(reader); spawnSpot.origin[VY] = (float) Reader_ReadInt16(reader); spawnSpot.origin[VZ] = 0; // Initialize with "something". spawnSpot.angle = (angle_t) (ANG45 * (Reader_ReadInt16(reader) / 45)); /*spawnSpot.type = (int)*/ Reader_ReadInt16(reader); spawnSpot.flags = (int) Reader_ReadInt16(reader); } # if __JDOOM__ || __JDOOM64__ if(ver >= 3) # elif __JHERETIC__ if(ver >= 5) # endif { intFlags = Reader_ReadInt32(reader); dropOffZ = FIX2FLT(Reader_ReadInt32(reader)); gear = Reader_ReadInt32(reader); } # if __JDOOM__ || __JDOOM64__ if(ver >= 6) { damage = Reader_ReadInt32(reader); flags2 = Reader_ReadInt32(reader); } else // flags2 will be applied from the defs. { damage = DDMAXINT; // Use the value set in mo->info->damage } # elif __JHERETIC__ damage = Reader_ReadInt32(reader); flags2 = Reader_ReadInt32(reader); # endif if(ver >= 7) { flags3 = Reader_ReadInt32(reader); } // Else flags3 will be applied from the defs. #endif #if __JHEXEN__ special = Reader_ReadInt32(reader); Reader_Read(reader, args, 1 * 5); #elif __JHERETIC__ special1 = Reader_ReadInt32(reader); special2 = Reader_ReadInt32(reader); if(ver >= 8) { special3 = Reader_ReadInt32(reader); } #endif #if __JHEXEN__ if(ver >= 2) #else if(ver >= 4) #endif { translucency = Reader_ReadByte(reader); } #if __JHEXEN__ if(ver >= 3) #else if(ver >= 5) #endif { visTarget = (short) (Reader_ReadByte(reader)) -1; } #if __JHEXEN__ if(ver >= 4) { tracer = INT2PTR(mobj_t, Reader_ReadInt32(reader)); } if(ver >= 4) { lastEnemy = INT2PTR(mobj_t, Reader_ReadInt32(reader)); } #else if(ver >= 5) { floorClip = FIX2FLT(Reader_ReadInt32(reader)); } #endif #if __JHERETIC__ if(ver >= 7) { generator = INT2PTR(mobj_t, Reader_ReadInt16(reader)); } else { generator = 0; } #endif /* * Restore! (unmangle) */ info = &MOBJINFO[type]; Mobj_SetState(this, PTR2INT(state)); #if __JHEXEN__ if(flags2 & MF2_DORMANT) { tics = -1; } #endif if(player) { // The player number translation table is used to find out the // *current* (actual) player number of the referenced player. player = msr->player(PTR2INT(player)); #if __JHEXEN__ if(!player) { // This saved player does not exist in the current game! // Destroy this mobj. Mobj_Destroy(this); return false; } #endif dPlayer = player->plr; dPlayer->mo = this; //dPlayer->clAngle = angle; /* $unifiedangles */ dPlayer->lookDir = 0; /* $unifiedangles */ } visAngle = angle >> 16; #if !__JHEXEN__ if(dPlayer && !dPlayer->inGame) { dPlayer->mo = 0; Mobj_Destroy(this); return false; } #endif #if !__JDOOM64__ // Do we need to update this mobj's flag values? if(ver < MOBJ_SAVEVERSION) { SV_TranslateLegacyMobjFlags(this, ver); } #endif P_MobjLink(this); floorZ = P_GetDoublep(Mobj_Sector(this), DMU_FLOOR_HEIGHT); ceilingZ = P_GetDoublep(Mobj_Sector(this), DMU_CEILING_HEIGHT); return false; #undef FF_FRAMEMASK #undef FF_FULLBRIGHT }
void Mobj_XYMoveStopping(mobj_t *mo) { DENG_ASSERT(mo != 0); player_t *player = mo->player; if(player && (P_GetPlayerCheats(player) & CF_NOMOMENTUM)) { // Debug option for no sliding at all. mo->mom[MX] = mo->mom[MY] = 0; return; } if(mo->flags & (MF_MISSILE | MF_SKULLFLY)) { // No friction for missiles. return; } if(mo->origin[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY)) { // No friction when falling. return; } #ifndef __JHEXEN__ if(cfg.slidingCorpses) { // $dropoff_fix: Add objects falling off ledges. Does not apply to players! if(((mo->flags & MF_CORPSE) || (mo->intFlags & MIF_FALLING)) && !mo->player) { // Do not stop sliding if halfway off a step with some momentum. if(!INRANGE_OF(mo->mom[MX], 0, DROPOFFMOMENTUM_THRESHOLD) || !INRANGE_OF(mo->mom[MY], 0, DROPOFFMOMENTUM_THRESHOLD)) { if(!FEQUAL(mo->floorZ, P_GetDoublep(Mobj_Sector(mo), DMU_FLOOR_HEIGHT))) return; } } } #endif bool isVoodooDoll = Mobj_IsVoodooDoll(mo); bool belowWalkStop = (INRANGE_OF(mo->mom[MX], 0, WALKSTOP_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, WALKSTOP_THRESHOLD)); bool belowStandSpeed = false; bool isMovingPlayer = false; if(player) { belowStandSpeed = (INRANGE_OF(mo->mom[MX], 0, STANDSPEED) && INRANGE_OF(mo->mom[MY], 0, STANDSPEED)); isMovingPlayer = (!FEQUAL(player->plr->forwardMove, 0) || !FEQUAL(player->plr->sideMove, 0)); } // Stop player walking animation (only real players). if(!isVoodooDoll && player && belowStandSpeed && !isMovingPlayer && !IS_NETWORK_SERVER) // Netgame servers use logic elsewhere for player animation. { // If in a walking frame, stop moving. if(P_PlayerInWalkState(player)) { P_MobjChangeState(player->plr->mo, statenum_t(PCLASS_INFO(player->class_)->normalState)); } } // Apply friction. if(belowWalkStop && !isMovingPlayer) { // $voodoodolls: Do not zero mom for voodoo dolls! if(!isVoodooDoll) { // Momentum is below the walkstop threshold; stop it completely. mo->mom[MX] = mo->mom[MY] = 0; // $voodoodolls: Stop view bobbing if this isn't a voodoo doll. if(player) player->bob = 0; } } else { coord_t friction = Mobj_Friction(mo); mo->mom[MX] *= friction; mo->mom[MY] *= friction; } }