SRB2/src/p_telept.c
2023-12-23 13:45:16 +01:00

180 lines
5 KiB
C

// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file p_telept.c
/// \brief Teleportation
#include "doomdef.h"
#include "g_game.h"
#include "p_local.h"
#include "r_state.h"
#include "s_sound.h"
#include "r_main.h"
/** \brief The P_MixUp function
\param thing mobj_t to mix up
\param x new x pos
\param y new y pos
\param z new y pos
\param angle new angle to look at
\return void
*/
void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
INT16 starpostx, INT16 starposty, INT16 starpostz,
INT32 starpostnum, tic_t starposttime, angle_t starpostangle,
fixed_t starpostscale, angle_t drawangle, INT32 flags2)
{
const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
// the move is ok,
// so link the thing into its new position
P_UnsetThingPosition(thing);
// Remove touching_sectorlist from mobj.
if (sector_list)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
thing->x = x;
thing->y = y;
thing->z = z;
if (thing->player)
{
if (thing->eflags & MFE_VERTICALFLIP)
thing->player->viewz = thing->z + thing->height - thing->player->viewheight;
else
thing->player->viewz = thing->z + thing->player->viewheight;
if (!thing->tracer)
thing->reactiontime = TICRATE/2; // don't move for about half a second
// absolute angle position
P_SetPlayerAngle(thing->player, angle);
// move chasecam at new player location
if (splitscreen && camera2.chase
&& thing->player == &players[secondarydisplayplayer])
{
P_ResetCamera(thing->player, &camera2);
}
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
// don't run in place after a teleport
thing->player->cmomx = thing->player->cmomy = 0;
thing->player->rmomx = thing->player->rmomy = 0;
if (!thing->tracer)
thing->player->speed = 0;
// Starpost information
thing->player->starpostx = starpostx;
thing->player->starposty = starposty;
thing->player->starpostz = starpostz;
thing->player->starposttime = starposttime;
thing->player->starpostangle = starpostangle;
thing->player->starpostscale = starpostscale;
thing->player->starpostnum = starpostnum;
thing->player->drawangle = drawangle;
// Reset map starposts for the player's new info.
P_ResetStarposts();
P_ClearStarPost(starpostnum);
P_ResetPlayer(thing->player);
P_SetMobjState(thing, S_PLAY_STND);
P_FlashPal(thing->player, PAL_MIXUP, 10);
}
thing->angle = angle;
thing->momx = thing->momy = thing->momz = 0;
thing->flags2 = (thing->flags2 & ~takeflags2) | (flags2 & takeflags2);
}
/** \brief The P_Teleport function
\param thing mobj_t to teleport
\param x new x pos
\param y new y pos
\param z new y pos
\param angle new angle to look at
\return if true, the thing "teleported"
*/
boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove)
{
if (!P_SetOrigin(thing, x, y, z))
return false;
if (!dontstopmove)
thing->momx = thing->momy = thing->momz = 0;
else // Change speed to match direction
P_InstaThrust(thing, angle, FixedHypot(thing->momx, thing->momy));
if (thing->player)
{
if (thing->eflags & MFE_VERTICALFLIP)
thing->player->viewz = thing->z + thing->height - thing->player->viewheight;
else
thing->player->viewz = thing->z + thing->player->viewheight;
// don't run in place after a teleport
if (!dontstopmove)
{
INT32 p;
// Search for any players you might be carrying, so you can get them off before they end up being taken with you!
for (p = 0; p < MAXPLAYERS; p++)
if (playeringame[p] && players[p].mo && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == thing)
{
players[p].powers[pw_carry] = CR_NONE;
P_SetTarget(&players[p].mo->tracer, NULL);
break;
}
thing->player->cmomx = thing->player->cmomy = 0;
thing->player->rmomx = thing->player->rmomy = 0;
thing->player->speed = 0;
P_ResetPlayer(thing->player);
P_SetMobjState(thing, S_PLAY_STND);
thing->reactiontime = TICRATE/2; // don't move for about half a second
thing->player->drawangle = angle;
}
else
thing->player->drawangle += (angle - thing->angle);
// absolute angle position
P_SetPlayerAngle(thing->player, angle);
// move chasecam at new player location
if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])
P_ResetCamera(thing->player, &camera2);
else if (camera.chase && thing->player == &players[displayplayer])
P_ResetCamera(thing->player, &camera);
if (flash)
P_FlashPal(thing->player, PAL_MIXUP, 10);
}
thing->angle = angle;
return true;
}