// [RH] Modified to support different source and destination ids. // [RH] Modified some more to be accurate. bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse) { int i; line_t *l; if (side || thing->flags2 & MF2_NOTELEPORT || !line || line->sidedef[1] == NULL) return false; FLineIdIterator itr(id); while ((i = itr.Next()) >= 0) { if (line->Index() == i) continue; if ((l=&level.lines[i]) != line && l->backsector) { // Get the thing's position along the source linedef double pos; DVector2 npos; // offsets from line double den; den = line->Delta().LengthSquared(); if (den == 0) { pos = 0; npos.Zero(); } else { double num = (thing->Pos().XY() - line->v1->fPos()) | line->Delta(); if (num <= 0) { pos = 0; } else if (num >= den) { pos = 1; } else { pos = num / den; } npos = thing->Pos().XY() - line->v1->fPos() - line->Delta() * pos; } // Get the angle between the two linedefs, for rotating // orientation and velocity. Rotate 180 degrees, and flip // the position across the exit linedef, if reversed. DAngle angle = l->Delta().Angle() - line->Delta().Angle(); if (!reverse) { angle += 180.; pos = 1 - pos; } // Sine, cosine of angle adjustment double s = angle.Sin(); double c = angle.Cos(); DVector2 p; // Rotate position along normal to match exit linedef p.X = npos.X*c - npos.Y*s; p.Y = npos.Y*c + npos.X*s; // Interpolate position across the exit linedef p += l->v1->fPos() + pos*l->Delta(); // Whether this is a player, and if so, a pointer to its player_t. // Voodoo dolls are excluded by making sure thing->player->mo==thing. player_t *player = thing->player && thing->player->mo == thing ? thing->player : NULL; // Whether walking towards first side of exit linedef steps down bool stepdown = l->frontsector->floorplane.ZatPoint(p) < l->backsector->floorplane.ZatPoint(p); // Height of thing above ground double z = thing->Z() - thing->floorz; // Side to exit the linedef on positionally. // // Notes: // // This flag concerns exit position, not momentum. Due to // roundoff error, the thing can land on either the left or // the right side of the exit linedef, and steps must be // taken to make sure it does not end up on the wrong side. // // Exit momentum is always towards side 1 in a reversed // teleporter, and always towards side 0 otherwise. // // Exiting positionally on side 1 is always safe, as far // as avoiding oscillations and stuck-in-wall problems, // but may not be optimum for non-reversed teleporters. // // Exiting on side 0 can cause oscillations if momentum // is towards side 1, as it is with reversed teleporters. // // Exiting on side 1 slightly improves player viewing // when going down a step on a non-reversed teleporter. // Is this really still necessary with real math instead of imprecise trig tables? #if 1 int side = reverse || (player && stepdown); int fudge = FUDGEFACTOR; double dx = line->Delta().X; double dy = line->Delta().Y; // Make sure we are on correct side of exit linedef. while (P_PointOnLineSidePrecise(p, l) != side && --fudge >= 0) { if (fabs(dx) > fabs(dy)) p.Y -= (dx < 0) != side ? -1 : 1; else p.X += (dy < 0) != side ? -1 : 1; } #endif // Adjust z position to be same height above ground as before. // Ground level at the exit is measured as the higher of the // two floor heights at the exit linedef. z = z + l->sidedef[stepdown]->sector->floorplane.ZatPoint(p); // Attempt to teleport, aborting if blocked if (!P_TeleportMove (thing, DVector3(p, z), false)) { return false; } if (thing == players[consoleplayer].camera) { R_ResetViewInterpolation (); } // Rotate thing's orientation according to difference in linedef angles thing->Angles.Yaw += angle; // Rotate thing's velocity to come out of exit just like it entered p = thing->Vel.XY(); thing->Vel.X = p.X*c - p.Y*s; thing->Vel.Y = p.Y*c + p.X*s; // Adjust a player's view, in case there has been a height change if (player && player->mo == thing) { // Adjust player's local copy of velocity p = player->Vel; player->Vel.X = p.X*c - p.Y*s; player->Vel.Y = p.Y*c + p.X*s; // Save the current deltaviewheight, used in stepping double deltaviewheight = player->deltaviewheight; // Clear deltaviewheight, since we don't want any changes now player->deltaviewheight = 0; // Set player's view according to the newly set parameters P_CalcHeight(player); // Reset the delta to have the same dynamics as before player->deltaviewheight = deltaviewheight; } return true; } } return false; }
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight) { fixed_t oldx; fixed_t oldy; fixed_t oldz; fixed_t aboveFloor; player_t *player; angle_t an; sector_t *destsect; bool resetpitch = false; fixed_t floorheight, ceilingheight; fixed_t missilespeed; oldx = thing->x; oldy = thing->y; oldz = thing->z; aboveFloor = thing->z - thing->floorz; destsect = P_PointInSector (x, y); // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; floorheight = destsect->floorplane.ZatPoint (x, y); ceilingheight = destsect->ceilingplane.ZatPoint (x, y); if (thing->flags & MF_MISSILE) { // We don't measure z velocity, because it doesn't change. missilespeed = xs_CRoundToInt(TVector2<double>(thing->velx, thing->vely).Length()); } if (keepHeight) { z = floorheight + aboveFloor; } else if (z == ONFLOORZ) { if (player) { if (thing->flags & MF_NOGRAVITY && aboveFloor) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; if (!keepOrientation) { resetpitch = false; } } } else if (thing->flags & MF_MISSILE) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; } } if (!P_TeleportMove (thing, x, y, z, false)) { return false; } if (player) { player->viewz = thing->z + player->viewheight; if (resetpitch) { player->mo->pitch = 0; } } if (!keepOrientation) { thing->angle = angle; } else { angle = thing->angle; } // Spawn teleport fog at source and destination if (sourceFog) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE); fog->target = thing; } if (useFog) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; an = angle >> ANGLETOFINESHIFT; AActor *fog = Spawn<ATeleportFog> (x + 20*finecosine[an], y + 20*finesine[an], thing->z + fogDelta, ALLOW_REPLACE); fog->target = thing; if (thing->player) { // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && bHaltVelocity) thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); } } // [BC] && bHaltVelocity. if (thing->player && (useFog || !keepOrientation) && bHaltVelocity) { // Freeze player for about .5 sec if (thing->Inventory == NULL || thing->Inventory->GetSpeedFactor() <= FRACUNIT) thing->reactiontime = 18; } if (thing->flags & MF_MISSILE) { angle >>= ANGLETOFINESHIFT; thing->velx = FixedMul (missilespeed, finecosine[angle]); thing->vely = FixedMul (missilespeed, finesine[angle]); }
// // P_SpawnPlayer // Called when a player is spawned on the level. // Most of the player structure stays unchanged // between levels. // void P_SpawnPlayer (player_t &player, mapthing2_t *mthing) { // denis - clients should not control spawning if(!serverside) return; // [RH] Things 4001-? are also multiplayer starts. Just like 1-4. // To make things simpler, figure out which player is being // spawned here. player_t *p = &player; // not playing? if(!p->ingame()) return; if (p->playerstate == PST_REBORN || p->playerstate == PST_ENTER) G_PlayerReborn (*p); AActor *mobj = new AActor (mthing->x << FRACBITS, mthing->y << FRACBITS, ONFLOORZ, MT_PLAYER); // set color translations for player sprites // [RH] Different now: MF_TRANSLATION is not used. // mobj->translation = translationtables + 256*playernum; mobj->angle = ANG45 * (mthing->angle/45); mobj->pitch = mobj->roll = 0; mobj->player = p; mobj->health = p->health; // [RH] Set player sprite based on skin if(p->userinfo.skin >= numskins) p->userinfo.skin = 0; mobj->sprite = skins[p->userinfo.skin].sprite; p->fov = 90.0f; p->mo = p->camera = mobj->ptr(); p->playerstate = PST_LIVE; p->refire = 0; p->damagecount = 0; p->bonuscount = 0; p->extralight = 0; p->fixedcolormap = 0; p->viewheight = VIEWHEIGHT; p->xviewshift = 0; p->attacker = AActor::AActorPtr(); // Set up some special spectator stuff if (p->spectator) { mobj->translucency = 0; p->mo->flags |= MF_SPECTATOR; p->mo->flags2 |= MF2_FLY; } // [RH] Allow chasecam for demo watching //if ((demoplayback || demonew) && chasedemo) // p->cheats = CF_CHASECAM; // setup gun psprite P_SetupPsprites (p); // give all cards in death match mode if (sv_gametype != GM_COOP) { for (int i = 0; i < NUMCARDS; i++) p->cards[i] = true; } if(serverside) { // [RH] If someone is in the way, kill them P_TeleportMove (mobj, mobj->x, mobj->y, mobj->z, true); // [BC] Do script stuff if (level.behavior != NULL) { if (p->playerstate == PST_ENTER) { level.behavior->StartTypedScripts (SCRIPT_Enter, p->mo); } else if (p->playerstate == PST_REBORN) { level.behavior->StartTypedScripts (SCRIPT_Respawn, p->mo); } } // send new objects SV_SpawnMobj(mobj); } }
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight) { bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING)); fixedvec3 old; fixed_t aboveFloor; player_t *player; angle_t an; sector_t *destsect; bool resetpitch = false; fixed_t floorheight, ceilingheight; fixed_t missilespeed = 0; old = thing->Pos(); aboveFloor = thing->Z() - thing->floorz; destsect = P_PointInSector (x, y); // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; floorheight = destsect->floorplane.ZatPoint (x, y); ceilingheight = destsect->ceilingplane.ZatPoint (x, y); if (thing->flags & MF_MISSILE) { // We don't measure z velocity, because it doesn't change. missilespeed = xs_CRoundToInt(TVector2<double>(thing->velx, thing->vely).Length()); } if (keepHeight) { z = floorheight + aboveFloor; } else if (z == ONFLOORZ) { if (player) { if (thing->flags & MF_NOGRAVITY && aboveFloor) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; if (!keepOrientation) { resetpitch = false; } } } else if (thing->flags & MF_MISSILE) { z = floorheight + aboveFloor; if (z + thing->height > ceilingheight) { z = ceilingheight - thing->height; } } else { z = floorheight; } } if (!P_TeleportMove (thing, x, y, z, false)) { return false; } if (player) { player->viewz = thing->Z() + player->viewheight; if (resetpitch) { player->mo->pitch = 0; } } if (!keepOrientation) { thing->angle = angle; } else { angle = thing->angle; } // Spawn teleport fog at source and destination if (sourceFog && !predicting) { P_SpawnTeleportFog(thing, old, true, true); //Passes the actor through which then pulls the TeleFog metadata types based on properties. } if (useFog) { if (!predicting) { fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; an = angle >> ANGLETOFINESHIFT; P_SpawnTeleportFog(thing, x + 20 * finecosine[an], y + 20 * finesine[an], thing->Z() + fogDelta, false, true); } if (thing->player) { // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && bHaltVelocity) thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); } }
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; }
// // TELEPORTATION // dboolean EV_Teleport(line_t *line, int side, mobj_t *thing) { thinker_t *thinker; int i; // Don't teleport missiles. // Don't teleport if hit back of line, so you can get out of teleporter. if (side || (thing->flags & MF_MISSILE)) return false; // [BH] Don't teleport corpses once kill ccmd used if (thing->flags2 & MF2_MASSACRE) return false; // killough 1/31/98: improve performance by using // P_FindSectorFromLineTag instead of simple linear search. for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) for (thinker = thinkerclasscap[th_mobj].cnext; thinker != &thinkerclasscap[th_mobj]; thinker = thinker->cnext) { mobj_t *m; if ((m = (mobj_t *)thinker)->type == MT_TELEPORTMAN && m->subsector->sector - sectors == i) { fixed_t oldx = thing->x; fixed_t oldy = thing->y; fixed_t oldz = thing->z; player_t *player = thing->player; // killough 5/12/98: exclude voodoo dolls: if (player && player->mo != thing) player = NULL; if (P_TeleportMove(thing, m->x, m->y, m->z, false)) // killough 8/9/98 { mobj_t *fog; fixed_t newx = m->x; fixed_t newy = m->y; // spawn teleport fog at source fog = P_SpawnMobj(oldx, oldy, oldz, MT_TFOG); fog->angle = thing->angle; S_StartSound(fog, sfx_telept); // spawn teleport fog at destination thing->z = thing->floorz; if (player) { unsigned int an = m->angle >> ANGLETOFINESHIFT; newx += 20 * finecosine[an]; newy += 20 * finesine[an]; player->viewz = thing->z + player->viewheight; } fog = P_SpawnMobj(newx, newy, thing->z, MT_TFOG); fog->angle = m->angle; S_StartSound(fog, sfx_telept); if (player) { // [BH] teleport can be drawn on automap if (line->backsector) { int j; for (j = 0; j < line->backsector->linecount; j++) line->backsector->lines[j]->flags |= ML_TELEPORTTRIGGERED; } // don't move for a bit thing->reactiontime = 18; player->psprites[ps_weapon].sx = 0; player->psprites[ps_weapon].sy = WEAPONTOP; player->momx = player->momy = 0; } thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return true; } }
// // TELEPORTATION // int EV_Teleport ( line_t* line, int side, mobj_t* thing ) { int i; int tag; mobj_t* m; mobj_t* fog; unsigned an; thinker_t* thinker; sector_t* sector; int oldx; int oldy; int oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < numsectors; i++) { if (sectors[ i ].tag == tag ) { thinker = thinkercap.next; for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { // not a mobj if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; m = (mobj_t *)thinker; // not a teleportman if (m->type != MT_TELEPORTMAN ) continue; sector = m->subsector->sector; // wrong sector if (sector-sectors != i ) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; thing->z = thing->floorz; //fixme: not needed? if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); I_Sound::getInstance()->startSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); // emit sound, where? I_Sound::getInstance()->startSound (fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } }
// // TELEPORTATION // int EV_Teleport(line_t * line, int side, mobj_t * thing) { int i; int tag; mobj_t *m; mobj_t *fog; unsigned an; thinker_t *thinker; sector_t *sector; fixed_t oldx; fixed_t oldy; fixed_t oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < numsectors; i++) { if (sectors[i].tag == tag) { thinker = thinkercap.next; for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { // not a mobj if (thinker->function.acp1 != (actionf_p1) P_MobjThinker) continue; m = (mobj_t *) thinker; // not a teleportman if (m->type != MT_TELEPORTMAN) continue; sector = m->subsector->sector; // wrong sector if (sector - sectors != i) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove(thing, m->x, m->y)) return 0; // fraggle: this was changed in final doom, // problem between normal doom2 1.9 and final doom // // Note that although chex.exe is based on Final Doom, // it does not have this quirk. if (gameversion < exe_final || gameversion == exe_chex) thing->z = thing->floorz; if (thing->player) { thing->player->viewz = thing->z + thing->player->viewheight; } // spawn teleport fog at source and destination fog = P_SpawnMobj(oldx, oldy, oldz, MT_TFOG); S_StartSound(fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj(m->x + 20 * finecosine[an], m->y + 20 * finesine[an] , thing->z, MT_TFOG); // emit sound, where? S_StartSound(fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; if (thing->player) { thing->player->prevx = m->x; thing->player->prevy = m->y; thing->player->prevan = m->angle; } return 1; } } }
// // TELEPORTATION // int EV_Teleport ( line_t* line, int side, mobj_t* thing ) { int i; int tag; mobj_t* m; mobj_t* fog; unsigned an; thinker_t* thinker; sector_t* sector; fixed_t oldx; fixed_t oldy; fixed_t oldz; // don't teleport missiles if (thing->flags & MF_MISSILE) return 0; // Don't teleport if hit back of line, // so you can get out of teleporter. if (side == 1) return 0; tag = line->tag; for (i = 0; i < numsectors; i++) { if (sectors[ i ].tag == tag ) { thinker = thinkercap.next; for (thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) { // not a mobj if (thinker->function.acp1 != (actionf_p1)P_MobjThinker) continue; m = (mobj_t *)thinker; // not a teleportman if (m->type != MT_TELEPORTMAN ) continue; sector = m->subsector->sector; // wrong sector if (sector-sectors != i ) continue; oldx = thing->x; oldy = thing->y; oldz = thing->z; if (!P_TeleportMove (thing, m->x, m->y)) return 0; // The first Final Doom executable does not set thing->z // when teleporting. This quirk is unique to this // particular version; the later version included in // some versions of the Id Anthology fixed this. if (gameversion != exe_final) thing->z = thing->floorz; if (thing->player) thing->player->viewz = thing->z+thing->player->viewheight; // spawn teleport fog at source and destination fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG); S_StartSound (fog, sfx_telept); an = m->angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] , thing->z, MT_TFOG); // emit sound, where? S_StartSound (fog, sfx_telept); // don't move for a bit if (thing->player) thing->reactiontime = 18; thing->angle = m->angle; thing->momx = thing->momy = thing->momz = 0; return 1; } } }
bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) { bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING)); DVector3 old; double aboveFloor; player_t *player; sector_t *destsect; bool resetpitch = false; double floorheight, ceilingheight; double missilespeed = 0; old = thing->Pos(); aboveFloor = thing->Z() - thing->floorz; destsect = P_PointInSector (pos); // killough 5/12/98: exclude voodoo dolls: player = thing->player; if (player && player->mo != thing) player = NULL; floorheight = destsect->floorplane.ZatPoint (pos); ceilingheight = destsect->ceilingplane.ZatPoint (pos); if (thing->flags & MF_MISSILE) { // We don't measure z velocity, because it doesn't change. missilespeed = thing->VelXYToSpeed(); } if (flags & TELF_KEEPHEIGHT) { pos.Z = floorheight + aboveFloor; } else if (pos.Z == ONFLOORZ) { if (player) { if (thing->flags & MF_NOGRAVITY && aboveFloor) { pos.Z = floorheight + aboveFloor; if (pos.Z + thing->Height > ceilingheight) { pos.Z = ceilingheight - thing->Height; } } else { pos.Z = floorheight; if (!(flags & TELF_KEEPORIENTATION)) { resetpitch = false; } } } else if (thing->flags & MF_MISSILE) { pos.Z = floorheight + aboveFloor; if (pos.Z + thing->Height > ceilingheight) { pos.Z = ceilingheight - thing->Height; } } else { pos.Z = floorheight; } } if (!P_TeleportMove (thing, pos, false)) { return false; } if (player) { player->viewz = thing->Z() + player->viewheight; if (resetpitch) { player->mo->Angles.Pitch = 0.; } } if (!(flags & TELF_KEEPORIENTATION)) { thing->Angles.Yaw = angle; } else { angle = thing->Angles.Yaw; } // Spawn teleport fog at source and destination if ((flags & TELF_SOURCEFOG) && !predicting) { P_SpawnTeleportFog(thing, old, true, true); //Passes the actor through which then pulls the TeleFog metadata types based on properties. } if (flags & TELF_DESTFOG) { if (!predicting) { DVector2 vector = angle.ToVector(20); DVector2 fogpos = P_GetOffsetPosition(pos.X, pos.Y, vector.X, vector.Y); P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true); } if (thing->player) { // [RH] Zoom player's field of vision // [BC] && bHaltVelocity. if (telezoom && thing->player->mo == thing && !(flags & TELF_KEEPVELOCITY)) thing->player->FOV = MIN (175.f, thing->player->DesiredFOV + 45.f); } } // [BC] && bHaltVelocity. if (thing->player && ((flags & TELF_DESTFOG) || !(flags & TELF_KEEPORIENTATION)) && !(flags & TELF_KEEPVELOCITY)) { // Freeze player for about .5 sec if (thing->Inventory == NULL || !thing->Inventory->GetNoTeleportFreeze()) thing->reactiontime = 18; } if (thing->flags & MF_MISSILE) { thing->VelFromAngle(missilespeed); } // [BC] && bHaltVelocity. else if (!(flags & TELF_KEEPORIENTATION) && !(flags & TELF_KEEPVELOCITY)) { // no fog doesn't alter the player's momentum thing->Vel.Zero(); // killough 10/98: kill all bobbing velocity too if (player) player->Vel.Zero(); } return true; }
static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound) { AActor *newmobj; AActor *fog; AActor *eye = self->master; // The eye is the spawnshot's master, not the target! AActor *targ = self->target; // Unlike other projectiles, the target is the intended destination. int r; // [GZ] Should be more viable than a countdown... if (self->special2 != 0) { if (self->special2 > level.maptime) return; // still flying } else { if (self->reactiontime == 0 || --self->reactiontime != 0) return; // still flying } if (spawntype != NULL) { fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE); if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM); } FName SpawnName; FDropItem *di; // di will be our drop item list iterator FDropItem *drop; // while drop stays as the reference point. int n = 0; // First see if this cube has its own actor list drop = self->GetDropItems(); // If not, then default back to its master's list if (drop == NULL && eye != NULL) drop = eye->GetDropItems(); if (drop != NULL) { for (di = drop; di != NULL; di = di->Next) { if (di->Name != NAME_None) { if (di->amount < 0) { di->amount = 1; // default value is -1, we need a positive value. } n += di->amount; // this is how we can weight the list. } } di = drop; n = pr_spawnfly(n); while (n >= 0) { if (di->Name != NAME_None) { n -= di->amount; // logically, none of the -1 values have survived by now. } if ((di->Next != NULL) && (n >= 0)) { di = di->Next; } else { n = -1; } } SpawnName = di->Name; } if (SpawnName == NAME_None) { // Randomly select monster to spawn. r = pr_spawnfly (); // Probability distribution (kind of :), // decreasing likelihood. if (r < 50) SpawnName = "DoomImp"; else if (r < 90) SpawnName = "Demon"; else if (r < 120) SpawnName = "Spectre"; else if (r < 130) SpawnName = "PainElemental"; else if (r < 160) SpawnName = "Cacodemon"; else if (r < 162) SpawnName = "Archvile"; else if (r < 172) SpawnName = "Revenant"; else if (r < 192) SpawnName = "Arachnotron"; else if (r < 222) SpawnName = "Fatso"; else if (r < 246) SpawnName = "HellKnight"; else SpawnName = "BaronOfHell"; } spawntype = PClass::FindClass(SpawnName); if (spawntype != NULL) { newmobj = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE); if (newmobj != NULL) { // Make the new monster hate what the boss eye hates if (eye != NULL) { newmobj->CopyFriendliness (eye, false); } // Make it act as if it was around when the player first made noise // (if the player has made noise). newmobj->LastHeard = newmobj->Sector->SoundTarget; if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL)) { newmobj->SetState (newmobj->SeeState); } if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) { // telefrag anything in this spot P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true); } newmobj->flags4 |= MF4_BOSSSPAWNED; } } // remove self (i.e., cube). self->Destroy (); }
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, angle_t angle, boolean useFog) { fixed_t oldx; fixed_t oldy; fixed_t oldz; fixed_t aboveFloor; fixed_t fogDelta; player_t *player; unsigned an; mobj_t *fog; oldx = thing->x; oldy = thing->y; oldz = thing->z; aboveFloor = thing->z - thing->floorz; if(!P_TeleportMove(thing, x, y)) { return false; } if(thing->player) { player = thing->player; player->plr->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; if(player->powers[pw_flight] && aboveFloor) { thing->z = thing->floorz + aboveFloor; if(thing->z + thing->height > thing->ceilingz) { thing->z = thing->ceilingz - thing->height; } player->plr->viewz = thing->z + player->plr->viewheight; } else { thing->z = thing->floorz; player->plr->viewz = thing->z + player->plr->viewheight; if(useFog) { player->plr->lookdir = 0; } } } else if(thing->flags & MF_MISSILE) { thing->z = thing->floorz + aboveFloor; if(thing->z + thing->height > thing->ceilingz) { thing->z = thing->ceilingz - thing->height; } } else { thing->z = thing->floorz; } // Spawn teleport fog at source and destination if(useFog) { fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT; fog = P_SpawnMobj(oldx, oldy, oldz + fogDelta, MT_TFOG); S_StartSound(SFX_TELEPORT, fog); an = angle >> ANGLETOFINESHIFT; fog = P_SpawnMobj(x + 20 * finecosine[an], y + 20 * finesine[an], thing->z + fogDelta, MT_TFOG); S_StartSound(SFX_TELEPORT, fog); if(thing->player && !thing->player->powers[pw_speed]) { // Freeze player for about .5 sec thing->reactiontime = 18; } thing->angle = angle; } if(thing->flags2 & MF2_FLOORCLIP) { if(thing->z == thing->subsector->sector->floorheight && P_GetThingFloorType(thing) > FLOOR_SOLID) { thing->floorclip = 10 * FRACUNIT; } else { thing->floorclip = 0; } } if(thing->flags & MF_MISSILE) { angle >>= ANGLETOFINESHIFT; thing->momx = FixedMul(thing->info->speed, finecosine[angle]); thing->momy = FixedMul(thing->info->speed, finesine[angle]); }