2015-05-19 21:54:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
|
|
|
|
Shadow Warrior is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-10-09 16:09:05 +00:00
|
|
|
#include "ns.h"
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#define QUIET
|
|
|
|
#include "build.h"
|
2020-09-06 10:44:58 +00:00
|
|
|
#include "automap.h"
|
2019-12-17 22:25:07 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#include "names2.h"
|
|
|
|
#include "panel.h"
|
|
|
|
#include "game.h"
|
|
|
|
|
|
|
|
#include "jsector.h"
|
|
|
|
|
2019-10-25 22:32:49 +00:00
|
|
|
#include "gamecontrol.h"
|
2021-02-16 10:36:08 +00:00
|
|
|
#include "gamefuncs.h"
|
2019-03-21 02:24:19 +00:00
|
|
|
#include "network.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "pal.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "jtags.h"
|
|
|
|
#include "parent.h"
|
|
|
|
|
2020-08-05 15:07:19 +00:00
|
|
|
#include "misc.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#include "menus.h"
|
2020-11-26 17:05:49 +00:00
|
|
|
#include "interpolate.h"
|
2020-05-01 11:29:12 +00:00
|
|
|
#include "interpso.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "sector.h"
|
2020-10-04 16:31:48 +00:00
|
|
|
#include "razemenu.h"
|
2019-12-31 18:25:49 +00:00
|
|
|
#include "v_2ddrawer.h"
|
2020-01-12 19:28:07 +00:00
|
|
|
#include "v_video.h"
|
2020-10-04 16:31:48 +00:00
|
|
|
#include "v_draw.h"
|
2021-03-21 11:22:50 +00:00
|
|
|
#include "render.h"
|
2021-05-31 09:51:02 +00:00
|
|
|
#include "razefont.h"
|
2022-01-07 11:49:41 +00:00
|
|
|
EXTERN_CVAR(Bool, vid_renderer)
|
2021-03-21 11:22:50 +00:00
|
|
|
|
2021-12-03 23:34:20 +00:00
|
|
|
extern DCoreActor* wall_to_sprite_actors[8];
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
|
|
|
|
2021-03-29 19:48:23 +00:00
|
|
|
int display_mirror;
|
2020-09-09 17:52:52 +00:00
|
|
|
static int OverlapDraw = false;
|
2020-09-09 18:32:24 +00:00
|
|
|
extern bool QuitFlag, SpriteInfo;
|
|
|
|
extern bool Voxel;
|
|
|
|
bool DrawScreen;
|
2021-11-21 20:47:37 +00:00
|
|
|
extern int f_c;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-31 12:37:57 +00:00
|
|
|
extern TILE_INFO_TYPE aVoxelArray[MAXTILES];
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
void PreDrawStackedWater(void);
|
|
|
|
|
2020-08-16 16:18:56 +00:00
|
|
|
void SW_InitMultiPsky(void)
|
|
|
|
{
|
|
|
|
// default
|
|
|
|
psky_t* const defaultsky = tileSetupSky(DEFAULTPSKY);
|
|
|
|
defaultsky->lognumtiles = 1;
|
|
|
|
defaultsky->horizfrac = 8192;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#if 1
|
2021-12-30 10:48:10 +00:00
|
|
|
void ShadeSprite(tspritetype* tsp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// set shade of sprite
|
2021-12-30 15:58:48 +00:00
|
|
|
tsp->shade = tsp->sectp->floorshade - 25;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (tsp->shade > -3)
|
|
|
|
tsp->shade = -3;
|
|
|
|
|
|
|
|
if (tsp->shade < -30)
|
|
|
|
tsp->shade = -30;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2021-12-04 18:08:50 +00:00
|
|
|
int GetRotation(tspritetype* tsprite, int& spritesortcnt, int tSpriteNum, int viewx, int viewy)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-16 17:58:43 +00:00
|
|
|
static const uint8_t RotTable8[] = {0, 7, 6, 5, 4, 3, 2, 1};
|
|
|
|
static const uint8_t RotTable5[] = {0, 1, 2, 3, 4, 3, 2, 1};
|
2021-11-21 20:50:26 +00:00
|
|
|
int rotation;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* tsp = &tsprite[tSpriteNum];
|
2021-12-25 18:28:40 +00:00
|
|
|
auto ownerActor = static_cast<DSWActor*>(tsp->ownerActor);
|
2021-11-21 20:50:26 +00:00
|
|
|
int angle2;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (!ownerActor->hasU() || ownerActor->user.RotNum == 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Get which of the 8 angles of the sprite to draw (0-7)
|
|
|
|
// rotation ranges from 0-7
|
2021-12-22 11:17:17 +00:00
|
|
|
angle2 = getangle(tsp->pos.X - viewx, tsp->pos.Y - viewy);
|
2015-05-19 21:54:34 +00:00
|
|
|
rotation = ((tsp->ang + 3072 + 128 - angle2) & 2047);
|
|
|
|
rotation = (rotation >> 8) & 7;
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (ownerActor->user.RotNum == 5)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((ownerActor->user.Flags & SPR_XFLIP_TOGGLE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (rotation <= 4)
|
|
|
|
{
|
|
|
|
// leave rotation alone
|
2021-12-27 17:58:15 +00:00
|
|
|
tsp->cstat &= ~(CSTAT_SPRITE_XFLIP);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rotation = (8 - rotation);
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_XFLIP); // clear x-flipping bit
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (rotation > 3 || rotation == 0)
|
|
|
|
{
|
|
|
|
// leave rotation alone
|
2021-12-27 17:58:15 +00:00
|
|
|
tsp->cstat &= ~(CSTAT_SPRITE_XFLIP); // clear x-flipping bit
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rotation = (8 - rotation);
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_XFLIP); // set
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special case bunk
|
2021-12-25 18:28:40 +00:00
|
|
|
int ID = ownerActor->user.ID;
|
|
|
|
if (ID == TOILETGIRL_R0 || ID == WASHGIRL_R0 || ID == TRASHCAN ||
|
|
|
|
ID == CARGIRL_R0 || ID == MECHANICGIRL_R0 || ID == PRUNEGIRL_R0 ||
|
|
|
|
ID == SAILORGIRL_R0)
|
2021-12-27 17:58:15 +00:00
|
|
|
tsp->cstat &= ~(CSTAT_SPRITE_XFLIP); // clear x-flipping bit
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
return RotTable5[rotation];
|
|
|
|
}
|
|
|
|
|
|
|
|
return RotTable8[rotation];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
|
|
!AIC - At draw time this is called for actor rotation. GetRotation() is more
|
|
|
|
complex than needs to be in part because importing of actor rotations and x-flip
|
|
|
|
directions was not standardized.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2021-12-04 18:08:50 +00:00
|
|
|
int SetActorRotation(tspritetype* tsprite, int& spritesortcnt, int tSpriteNum, int viewx, int viewy)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* tsp = &tsprite[tSpriteNum];
|
2021-12-25 18:28:40 +00:00
|
|
|
auto ownerActor = static_cast<DSWActor*>(tsp->ownerActor);
|
2021-11-21 20:50:26 +00:00
|
|
|
int StateOffset, Rotation;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (!ownerActor->hasU()) return 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
// don't modify ANY tu vars - back them up!
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* State = ownerActor->user.State;
|
|
|
|
STATE* StateStart = ownerActor->user.StateStart;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (ownerActor->user.RotNum == 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Get the offset into the State animation
|
2021-11-21 20:50:26 +00:00
|
|
|
StateOffset = int(State - StateStart);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Get the rotation angle
|
2021-04-02 08:28:40 +00:00
|
|
|
Rotation = GetRotation(tsprite, spritesortcnt, tSpriteNum, viewx, viewy);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
ASSERT(Rotation < 5);
|
|
|
|
|
|
|
|
// Reset the State animation start based on the Rotation
|
2021-12-25 18:28:40 +00:00
|
|
|
StateStart = ownerActor->user.Rot[Rotation];
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Set the sprites state
|
|
|
|
State = StateStart + StateOffset;
|
|
|
|
|
|
|
|
// set the picnum here - may be redundant, but we just changed states and
|
|
|
|
// thats a big deal
|
|
|
|
tsp->picnum = State->Pic;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-12-30 10:48:10 +00:00
|
|
|
int DoShadowFindGroundPoint(tspritetype* tspr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// USES TSPRITE !!!!!
|
2021-12-25 20:02:31 +00:00
|
|
|
auto ownerActor = static_cast<DSWActor*>(tspr->ownerActor);
|
2021-11-06 11:19:08 +00:00
|
|
|
Collision ceilhit, florhit;
|
2021-12-25 20:02:31 +00:00
|
|
|
int hiz, loz = ownerActor->user.loz;
|
2021-12-18 19:41:15 +00:00
|
|
|
ESpriteFlags save_cstat, bak_cstat;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// recursive routine to find the ground - either sector or floor sprite
|
|
|
|
// skips over enemy and other types of sprites
|
|
|
|
|
|
|
|
// IMPORTANT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
// This will return invalid FAF ceiling and floor heights inside of analyzesprite
|
|
|
|
// because the ceiling and floors get moved out of the way for drawing.
|
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
save_cstat = tspr->cstat;
|
2021-12-27 18:07:39 +00:00
|
|
|
tspr->cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
2021-12-30 15:58:48 +00:00
|
|
|
FAFgetzrangepoint(tspr->pos.X, tspr->pos.Y, tspr->pos.Z, tspr->sectp, &hiz, &ceilhit, &loz, &florhit);
|
2021-12-24 20:49:44 +00:00
|
|
|
tspr->cstat = save_cstat;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-06 11:19:08 +00:00
|
|
|
switch (florhit.type)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-06 11:19:08 +00:00
|
|
|
case kHitSprite:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:54:43 +00:00
|
|
|
auto hitactor = florhit.actor();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((hitactor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_FLOOR))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// found a sprite floor
|
|
|
|
return loz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// reset the blocking bit of what you hit and try again -
|
|
|
|
// recursive
|
2021-12-24 20:54:43 +00:00
|
|
|
bak_cstat = hitactor->spr.cstat;
|
2021-12-27 18:07:39 +00:00
|
|
|
hitactor->spr.cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
2021-12-24 20:49:44 +00:00
|
|
|
loz = DoShadowFindGroundPoint(tspr);
|
2021-12-24 20:54:43 +00:00
|
|
|
hitactor->spr.cstat = bak_cstat;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2019-04-08 06:28:26 +00:00
|
|
|
break;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-06 11:19:08 +00:00
|
|
|
case kHitSector:
|
2019-04-08 06:28:26 +00:00
|
|
|
break;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
default:
|
2020-09-09 17:52:52 +00:00
|
|
|
ASSERT(true == false);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return loz;
|
|
|
|
}
|
|
|
|
|
2021-12-30 10:48:10 +00:00
|
|
|
void DoShadows(tspritetype* tsprite, int& spritesortcnt, tspritetype* tsp, int viewz, int camang)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* tSpr = &tsprite[spritesortcnt];
|
2021-12-25 18:28:40 +00:00
|
|
|
auto ownerActor = static_cast<DSWActor*>(tsp->ownerActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
int ground_dist = 0;
|
|
|
|
int view_dist = 0;
|
|
|
|
int loz;
|
2021-11-21 20:50:26 +00:00
|
|
|
int xrepeat;
|
|
|
|
int yrepeat;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (!ownerActor->hasU()) return;
|
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
auto sect = tsp->sectp;
|
2015-05-19 21:54:34 +00:00
|
|
|
// make sure its the correct sector
|
|
|
|
// DoShadowFindGroundPoint calls FAFgetzrangepoint and this is sensitive
|
2021-12-22 11:17:17 +00:00
|
|
|
updatesector(tsp->pos.X, tsp->pos.Y, §);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-25 17:52:10 +00:00
|
|
|
if (sect == nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-30 15:36:04 +00:00
|
|
|
tsp->sectp = sect;
|
2021-10-31 21:14:06 +00:00
|
|
|
*tSpr = *tsp;
|
2015-05-19 21:54:34 +00:00
|
|
|
// shadow is ALWAYS draw last - status is priority
|
2021-10-31 21:14:06 +00:00
|
|
|
tSpr->statnum = MAXSTATUS;
|
2021-12-30 15:36:04 +00:00
|
|
|
tSpr->sectp = sect;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if ((tsp->yrepeat >> 2) > 4)
|
|
|
|
{
|
2021-12-23 19:20:29 +00:00
|
|
|
yrepeat = (tsp->yrepeat >> 2) - (GetSpriteSizeY(tsp) / 64) * 2;
|
2021-10-31 21:14:06 +00:00
|
|
|
xrepeat = tSpr->xrepeat;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-31 21:14:06 +00:00
|
|
|
yrepeat = tSpr->yrepeat;
|
|
|
|
xrepeat = tSpr->xrepeat;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-31 21:14:06 +00:00
|
|
|
tSpr->shade = 127;
|
2021-12-27 17:07:45 +00:00
|
|
|
tSpr->cstat |= CSTAT_SPRITE_TRANSLUCENT;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
loz = ownerActor->user.loz;
|
|
|
|
if (ownerActor->user.lowActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-29 05:18:25 +00:00
|
|
|
if (!(ownerActor->user.lowActor->spr.cstat & (CSTAT_SPRITE_ALIGNMENT_WALL | CSTAT_SPRITE_ALIGNMENT_FLOOR)))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
loz = DoShadowFindGroundPoint(tsp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// need to find the ground here
|
2021-12-22 11:29:00 +00:00
|
|
|
tSpr->pos.Z = loz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// if below or close to sprites z don't bother to draw it
|
|
|
|
if ((viewz - loz) > -Z(8))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// if close to shadows z shrink it
|
|
|
|
view_dist = labs(loz - viewz) >> 8;
|
|
|
|
if (view_dist < 32)
|
|
|
|
view_dist = 256/view_dist;
|
|
|
|
else
|
|
|
|
view_dist = 0;
|
|
|
|
|
|
|
|
// make shadow smaller depending on height from ground
|
2021-12-23 19:20:29 +00:00
|
|
|
ground_dist = labs(loz - GetSpriteZOfBottom(tsp)) >> 12;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
xrepeat = max(xrepeat - ground_dist - view_dist, 4);
|
|
|
|
yrepeat = max(yrepeat - ground_dist - view_dist, 4);
|
2021-11-21 20:50:26 +00:00
|
|
|
xrepeat = min(xrepeat, 255);
|
|
|
|
yrepeat = min(yrepeat, 255);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 21:14:06 +00:00
|
|
|
tSpr->xrepeat = uint8_t(xrepeat);
|
|
|
|
tSpr->yrepeat = uint8_t(yrepeat);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-08-12 22:45:50 +00:00
|
|
|
if (tilehasmodelorvoxel(tsp->picnum,tsp->pal))
|
2020-04-19 18:15:57 +00:00
|
|
|
{
|
2021-10-31 21:14:06 +00:00
|
|
|
tSpr->yrepeat = 0;
|
2020-08-12 22:45:50 +00:00
|
|
|
// cstat: trans reverse
|
|
|
|
// clipdist: tell mdsprite.cpp to use Z-buffer hacks to hide overdraw issues
|
2021-10-31 21:14:06 +00:00
|
|
|
tSpr->clipdist |= TSPR_FLAGS_MDHACK;
|
2021-12-18 16:00:22 +00:00
|
|
|
tSpr->cstat |= CSTAT_SPRITE_TRANS_FLIP;
|
2020-08-12 22:45:50 +00:00
|
|
|
}
|
2022-01-07 11:49:41 +00:00
|
|
|
else if (!vid_renderer)
|
2020-08-12 22:45:50 +00:00
|
|
|
{
|
2021-05-29 12:04:57 +00:00
|
|
|
// Alter the shadow's position so that it appears behind the sprite itself.
|
2021-12-30 12:29:01 +00:00
|
|
|
int look = getangle(tSpr->pos.X - Player[screenpeek].si.X, tSpr->pos.Y - Player[screenpeek].si.Y);
|
2021-12-22 10:57:10 +00:00
|
|
|
tSpr->pos.X += bcos(look, -9);
|
2021-12-22 11:17:17 +00:00
|
|
|
tSpr->pos.Y += bsin(look, -9);
|
2020-04-19 18:15:57 +00:00
|
|
|
}
|
2021-10-31 21:14:06 +00:00
|
|
|
else tSpr->time = 1;
|
2020-04-19 18:15:57 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
// Check for voxel items and use a round generic pic if so
|
2017-01-23 11:21:32 +00:00
|
|
|
//DoVoxelShadow(New);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
spritesortcnt++;
|
|
|
|
}
|
|
|
|
|
2021-12-11 02:49:58 +00:00
|
|
|
void DoMotionBlur(tspritetype* tsprite, int& spritesortcnt, tspritetype const * const tsp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
auto ownerActor = static_cast<DSWActor*>(tsp->ownerActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
int nx,ny,nz = 0,dx,dy,dz;
|
2021-11-21 20:50:26 +00:00
|
|
|
int i, ang;
|
|
|
|
int xrepeat, yrepeat, repeat_adj = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
int z_amt_per_pixel;
|
|
|
|
|
|
|
|
ang = NORM_ANGLE(tsp->ang + 1024);
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (!ownerActor->hasU() || tsp->xvel == 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((tsp->extra & SPRX_PLAYER_OR_ENEMY))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
z_amt_per_pixel = IntToFixed((int)-ownerActor->user.jump_speed * ACTORMOVETICS)/tsp->xvel;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-09-01 13:00:35 +00:00
|
|
|
z_amt_per_pixel = IntToFixed((int)-tsp->zvel)/tsp->xvel;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
switch (ownerActor->user.motion_blur_dist)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
case 64:
|
|
|
|
case 128:
|
|
|
|
case 256:
|
|
|
|
case 512:
|
2021-12-25 18:28:40 +00:00
|
|
|
nz = FixedToInt(z_amt_per_pixel * ownerActor->user.motion_blur_dist);
|
2020-09-26 16:07:07 +00:00
|
|
|
[[fallthrough]];
|
2015-05-19 21:54:34 +00:00
|
|
|
default:
|
2021-12-25 18:28:40 +00:00
|
|
|
dx = nx = MOVEx(ownerActor->user.motion_blur_dist, ang);
|
|
|
|
dy = ny = MOVEy(ownerActor->user.motion_blur_dist, ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
dz = nz;
|
|
|
|
|
|
|
|
xrepeat = tsp->xrepeat;
|
|
|
|
yrepeat = tsp->yrepeat;
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
switch ((ownerActor->user.Flags2 & SPR2_BLUR_TAPER))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
repeat_adj = 0;
|
|
|
|
break;
|
|
|
|
case SPR2_BLUR_TAPER_SLOW:
|
2021-12-25 18:28:40 +00:00
|
|
|
repeat_adj = xrepeat / (ownerActor->user.motion_blur_num*2);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case SPR2_BLUR_TAPER_FAST:
|
2021-12-25 18:28:40 +00:00
|
|
|
repeat_adj = xrepeat / ownerActor->user.motion_blur_num;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
for (i = 0; i < ownerActor->user.motion_blur_num; i++)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* tSpr = &tsprite[spritesortcnt];
|
2021-10-31 21:14:06 +00:00
|
|
|
*tSpr = *tsp;
|
2021-12-27 17:07:45 +00:00
|
|
|
tSpr->cstat |= CSTAT_SPRITE_TRANSLUCENT|CSTAT_SPRITE_TRANS_FLIP;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-22 10:57:10 +00:00
|
|
|
tSpr->pos.X += dx;
|
2021-12-22 11:17:17 +00:00
|
|
|
tSpr->pos.Y += dy;
|
2015-05-19 21:54:34 +00:00
|
|
|
dx += nx;
|
|
|
|
dy += ny;
|
|
|
|
|
2021-12-22 11:29:00 +00:00
|
|
|
tSpr->pos.Z += dz;
|
2015-05-19 21:54:34 +00:00
|
|
|
dz += nz;
|
|
|
|
|
2021-10-31 21:14:06 +00:00
|
|
|
tSpr->xrepeat = uint8_t(xrepeat);
|
|
|
|
tSpr->yrepeat = uint8_t(yrepeat);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
xrepeat -= repeat_adj;
|
|
|
|
yrepeat -= repeat_adj;
|
|
|
|
|
|
|
|
spritesortcnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-12-04 18:08:50 +00:00
|
|
|
void WarpCopySprite(tspritetype* tsprite, int& spritesortcnt)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-10-15 16:07:35 +00:00
|
|
|
int spnum;
|
2015-05-19 21:54:34 +00:00
|
|
|
int xoff,yoff,zoff;
|
2021-11-21 20:50:26 +00:00
|
|
|
int match;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// look for the first one
|
2021-10-31 21:14:06 +00:00
|
|
|
SWStatIterator it(STAT_WARP_COPY_SPRITE1);
|
|
|
|
while (auto itActor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:36:36 +00:00
|
|
|
match = itActor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// look for the second one
|
2021-10-31 21:14:06 +00:00
|
|
|
SWStatIterator it1(STAT_WARP_COPY_SPRITE2);
|
|
|
|
while (auto itActor1 = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:36:36 +00:00
|
|
|
if (itActor1->spr.lotag == match)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
auto sect1 = itActor->sector();
|
|
|
|
auto sect2 = itActor1->sector();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 21:14:06 +00:00
|
|
|
SWSectIterator it2(sect1);
|
|
|
|
while (auto itActor2 = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:36:36 +00:00
|
|
|
if (itActor2 == itActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-12-24 20:36:36 +00:00
|
|
|
if (itActor2->spr.picnum == ST1)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* newTSpr = renderAddTsprite(tsprite, spritesortcnt, itActor2);
|
2021-10-31 21:14:06 +00:00
|
|
|
newTSpr->statnum = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:36:36 +00:00
|
|
|
xoff = itActor->spr.pos.X - newTSpr->pos.X;
|
|
|
|
yoff = itActor->spr.pos.Y - newTSpr->pos.Y;
|
|
|
|
zoff = itActor->spr.pos.Z - newTSpr->pos.Z;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:36:36 +00:00
|
|
|
newTSpr->pos.X = itActor1->spr.pos.X - xoff;
|
|
|
|
newTSpr->pos.Y = itActor1->spr.pos.Y - yoff;
|
|
|
|
newTSpr->pos.Z = itActor1->spr.pos.Z - zoff;
|
2021-12-30 15:51:56 +00:00
|
|
|
newTSpr->sectp = itActor1->sector();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 17:52:10 +00:00
|
|
|
it2.Reset(sect2);
|
|
|
|
while (auto itActor2 = it2.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:36:36 +00:00
|
|
|
if (itActor2 == itActor1)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-12-24 20:36:36 +00:00
|
|
|
if (itActor2->spr.picnum == ST1)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* newTSpr = renderAddTsprite(tsprite, spritesortcnt, itActor2);
|
2021-10-31 21:14:06 +00:00
|
|
|
newTSpr->statnum = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:36:36 +00:00
|
|
|
auto off = itActor1->spr.pos - newTSpr->pos;
|
|
|
|
newTSpr->pos = itActor->spr.pos - off;
|
2021-12-30 15:51:56 +00:00
|
|
|
newTSpr->sectp = itActor->sector();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-30 10:48:10 +00:00
|
|
|
void DoStarView(tspritetype* tsp, DSWActor* tActor, int viewz)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
extern STATE s_Star[], s_StarDown[];
|
|
|
|
extern STATE s_StarStuck[], s_StarDownStuck[];
|
2021-12-22 11:29:00 +00:00
|
|
|
int zdiff = viewz - tsp->pos.Z;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (labs(zdiff) > Z(24))
|
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->user.StateStart == s_StarStuck)
|
|
|
|
tsp->picnum = s_StarDownStuck[tActor->user.State - s_StarStuck].Pic;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-12-25 18:28:40 +00:00
|
|
|
tsp->picnum = s_StarDown[tActor->user.State - s_Star].Pic;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (zdiff > 0)
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_YFLIP);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (zdiff > 0)
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_YFLIP);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-04 18:08:50 +00:00
|
|
|
template<class sprt>
|
|
|
|
DSWActor* CopySprite(sprt const* tsp, sectortype* newsector)
|
|
|
|
{
|
|
|
|
|
2021-12-04 21:04:16 +00:00
|
|
|
auto actorNew = insertActor(newsector, STAT_FAF_COPY);
|
2021-12-04 18:08:50 +00:00
|
|
|
|
2021-12-24 20:44:57 +00:00
|
|
|
actorNew->spr.pos = tsp->pos;
|
|
|
|
actorNew->spr.cstat = tsp->cstat;
|
|
|
|
actorNew->spr.picnum = tsp->picnum;
|
|
|
|
actorNew->spr.pal = tsp->pal;
|
|
|
|
actorNew->spr.xrepeat = tsp->xrepeat;
|
|
|
|
actorNew->spr.yrepeat = tsp->yrepeat;
|
|
|
|
actorNew->spr.xoffset = tsp->xoffset;
|
|
|
|
actorNew->spr.yoffset = tsp->yoffset;
|
|
|
|
actorNew->spr.ang = tsp->ang;
|
|
|
|
actorNew->spr.xvel = tsp->xvel;
|
|
|
|
actorNew->spr.yvel = tsp->yvel;
|
|
|
|
actorNew->spr.zvel = tsp->zvel;
|
|
|
|
actorNew->spr.shade = tsp->shade;
|
|
|
|
|
2021-12-27 17:58:15 +00:00
|
|
|
actorNew->spr.cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
2021-12-04 18:08:50 +00:00
|
|
|
|
|
|
|
return actorNew;
|
|
|
|
}
|
|
|
|
|
2021-12-24 20:44:57 +00:00
|
|
|
DSWActor* ConnectCopySprite(spritetypebase const* tsp)
|
2021-12-04 18:08:50 +00:00
|
|
|
{
|
|
|
|
sectortype* newsector;
|
|
|
|
int testz;
|
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (FAF_ConnectCeiling(tsp->sectp))
|
2021-12-04 18:08:50 +00:00
|
|
|
{
|
2021-12-30 15:58:48 +00:00
|
|
|
newsector = tsp->sectp;
|
2021-12-23 19:20:29 +00:00
|
|
|
testz = GetSpriteZOfTop(tsp) - Z(10);
|
2021-12-04 18:08:50 +00:00
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (testz < tsp->sectp->ceilingz)
|
2021-12-22 11:17:17 +00:00
|
|
|
updatesectorz(tsp->pos.X, tsp->pos.Y, testz, &newsector);
|
2021-12-04 18:08:50 +00:00
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (newsector != nullptr && newsector != tsp->sectp)
|
2021-12-04 18:08:50 +00:00
|
|
|
{
|
|
|
|
return CopySprite(tsp, newsector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (FAF_ConnectFloor(tsp->sectp))
|
2021-12-04 18:08:50 +00:00
|
|
|
{
|
2021-12-30 15:58:48 +00:00
|
|
|
newsector = tsp->sectp;
|
2021-12-23 19:20:29 +00:00
|
|
|
testz = GetSpriteZOfBottom(tsp) + Z(10);
|
2021-12-04 18:08:50 +00:00
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (testz > tsp->sectp->floorz)
|
2021-12-22 11:17:17 +00:00
|
|
|
updatesectorz(tsp->pos.X, tsp->pos.Y, testz, &newsector);
|
2021-12-04 18:08:50 +00:00
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (newsector != nullptr && newsector != tsp->sectp)
|
2021-12-04 18:08:50 +00:00
|
|
|
{
|
|
|
|
return CopySprite(tsp, newsector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void analyzesprites(tspritetype* tsprite, int& spritesortcnt, int viewx, int viewy, int viewz, int camang)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
int tSpriteNum;
|
2015-05-19 21:54:34 +00:00
|
|
|
int smr4, smr2;
|
|
|
|
static int ang = 0;
|
2021-12-31 14:59:11 +00:00
|
|
|
PLAYER* pp = Player + screenpeek;
|
2021-11-21 20:50:26 +00:00
|
|
|
int newshade=0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-08-16 07:04:24 +00:00
|
|
|
const int DART_PIC = 2526;
|
|
|
|
const int DART_REPEAT = 16;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
ang = NORM_ANGLE(ang + 12);
|
|
|
|
|
2021-05-12 00:02:26 +00:00
|
|
|
smr4 = int(smoothratio) + IntToFixed(MoveSkip4);
|
|
|
|
smr2 = int(smoothratio) + IntToFixed(MoveSkip2);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--)
|
|
|
|
{
|
2022-01-09 23:38:26 +00:00
|
|
|
validateTSpriteSize(tsprite, spritesortcnt);
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* tsp = &tsprite[tSpriteNum];
|
2021-12-04 18:08:50 +00:00
|
|
|
auto tActor = static_cast<DSWActor*>(tsp->ownerActor);
|
2021-12-30 15:58:48 +00:00
|
|
|
auto tsectp = tsp->sectp;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
// Brighten up the sprite if set somewhere else to do so
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tu && tActor->user.Vis > 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-21 20:50:26 +00:00
|
|
|
int tmpshade; // Having this prevent overflow
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
tmpshade = tsp->shade - tActor->user.Vis;
|
2015-05-19 21:54:34 +00:00
|
|
|
if (tmpshade < -128) tmpshade = -128;
|
|
|
|
|
|
|
|
tsp->shade = tmpshade;
|
2021-12-25 18:28:40 +00:00
|
|
|
tActor->user.Vis -= 8;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// don't draw these
|
|
|
|
if (tsp->statnum >= STAT_DONT_DRAW)
|
|
|
|
{
|
2021-12-04 18:08:50 +00:00
|
|
|
tsp->ownerActor = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->hasU())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (tsp->statnum != STAT_DEFAULT)
|
|
|
|
{
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((tActor->user.Flags & SPR_SKIP4))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (tsp->statnum <= STAT_SKIP4_INTERP_END)
|
|
|
|
{
|
2021-12-30 16:32:31 +00:00
|
|
|
tsp->pos = tActor->interpolatedvec3(smr4, 18);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((tActor->user.Flags & SPR_SKIP2))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (tsp->statnum <= STAT_SKIP2_INTERP_END)
|
|
|
|
{
|
2021-12-30 16:32:31 +00:00
|
|
|
tsp->pos = tActor->interpolatedvec3(smr2, 17);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-02 06:41:29 +00:00
|
|
|
// workaround for mines and floor decals beneath the floor
|
|
|
|
if (tsp->picnum == BETTY_R0 || tsp->picnum == FLOORBLOOD1)
|
2020-02-02 06:41:25 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
int32_t const floorz = getflorzofslopeptr(tActor->sector(), tActor->spr.pos.X, tActor->spr.pos.Y);
|
2021-12-24 20:44:57 +00:00
|
|
|
if (tActor->spr.pos.Z > floorz)
|
2021-12-22 11:29:00 +00:00
|
|
|
tsp->pos.Z = floorz;
|
2020-02-02 06:41:25 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if (r_shadows && (tActor->user.Flags & SPR_SHADOW))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-04-02 08:28:40 +00:00
|
|
|
DoShadows(tsprite, spritesortcnt, tsp, viewz, camang);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//#define UK_VERSION 1
|
|
|
|
|
|
|
|
//#define DART_REPEAT 6
|
|
|
|
//#define DART_PIC 2233
|
2019-12-07 19:48:16 +00:00
|
|
|
if (sw_darts)
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->user.ID == 1793 || tsp->picnum == 1793)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
tsp->picnum = 2519;
|
|
|
|
tsp->xrepeat = 27;
|
|
|
|
tsp->yrepeat = 29;
|
|
|
|
}
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->user.ID == STAR1)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2019-12-07 19:48:16 +00:00
|
|
|
if (sw_darts)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-08-16 07:04:24 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
tsp->picnum = DART_PIC;
|
|
|
|
tsp->ang = NORM_ANGLE(tsp->ang - 512 - 24);
|
|
|
|
tsp->xrepeat = tsp->yrepeat = DART_REPEAT;
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_ALIGNMENT_WALL);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
2021-12-25 18:28:40 +00:00
|
|
|
DoStarView(tsp, tActor, viewz);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// rotation
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->user.RotNum > 0)
|
2021-04-02 08:28:40 +00:00
|
|
|
SetActorRotation(tsprite, spritesortcnt, tSpriteNum, viewx, viewy);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->user.motion_blur_num)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-04-02 08:28:40 +00:00
|
|
|
DoMotionBlur(tsprite, spritesortcnt, tsp);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// set palette lookup correctly
|
2021-11-20 22:20:43 +00:00
|
|
|
if (tsp->pal != tsectp->floorpal)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-20 22:20:43 +00:00
|
|
|
if (tsectp->floorpal == PALETTE_DEFAULT)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
// default pal for sprite is stored in tActor->user.spal
|
2015-05-19 21:54:34 +00:00
|
|
|
// mostly for players and other monster types
|
2021-12-25 18:28:40 +00:00
|
|
|
tsp->pal = tActor->user.spal;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// if sector pal is something other than default
|
2021-11-20 22:20:43 +00:00
|
|
|
uint8_t pal = tsectp->floorpal;
|
2020-09-09 18:32:24 +00:00
|
|
|
bool nosectpal=false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// sprite does not take on the new pal if sector flag is set
|
2021-12-29 05:53:36 +00:00
|
|
|
if (tsectp->hasU() && (tsectp->flags & SECTFU_DONT_COPY_PALETTE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
pal = PALETTE_DEFAULT;
|
2020-09-09 17:52:52 +00:00
|
|
|
nosectpal = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
//if(tActor->user.spal == PALETTE_DEFAULT)
|
2015-05-19 21:54:34 +00:00
|
|
|
if (tsp->hitag != SECTFU_DONT_COPY_PALETTE && tsp->hitag != LUMINOUS
|
|
|
|
&& !nosectpal
|
|
|
|
&& pal != PALETTE_FOG && pal != PALETTE_DIVE &&
|
|
|
|
pal != PALETTE_DIVE_LAVA)
|
|
|
|
tsp->pal = pal;
|
|
|
|
else
|
2021-12-25 18:28:40 +00:00
|
|
|
tsp->pal = tActor->user.spal;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sprite debug information mode
|
|
|
|
if (tsp->hitag == 9997)
|
|
|
|
{
|
|
|
|
tsp->pal = PALETTE_RED_LIGHTING;
|
|
|
|
// Turn it off, it gets reset by PrintSpriteInfo
|
2021-12-21 22:18:23 +00:00
|
|
|
tActor->spr.hitag = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-07 19:48:16 +00:00
|
|
|
if (sw_darts)
|
2015-05-19 21:54:34 +00:00
|
|
|
if (tsp->statnum == STAT_STAR_QUEUE)
|
|
|
|
{
|
|
|
|
tsp->picnum = DART_PIC;
|
|
|
|
tsp->ang = NORM_ANGLE(tsp->ang - 512);
|
|
|
|
tsp->xrepeat = tsp->yrepeat = DART_REPEAT;
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_ALIGNMENT_WALL);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call my sprite handler
|
|
|
|
// Does autosizing and voxel handling
|
|
|
|
JAnalyzeSprites(tsp);
|
|
|
|
|
|
|
|
// only do this of you are a player sprite
|
|
|
|
//if (tsp->statnum >= STAT_PLAYER0 && tsp->statnum < STAT_PLAYER0 + MAX_SW_PLAYERS)
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->hasU() && tActor->user.PlayerP)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// Shadow spell
|
2021-12-29 05:13:28 +00:00
|
|
|
if (!(tsp->cstat & CSTAT_SPRITE_TRANSLUCENT))
|
2015-05-19 21:54:34 +00:00
|
|
|
ShadeSprite(tsp);
|
|
|
|
|
|
|
|
// sw if its your playersprite
|
2021-12-26 07:44:18 +00:00
|
|
|
if (Player[screenpeek].actor == tActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 09:24:30 +00:00
|
|
|
pp = Player + screenpeek;
|
2021-12-29 05:25:37 +00:00
|
|
|
if (display_mirror || (pp->Flags & (PF_VIEW_FROM_OUTSIDE|PF_VIEW_FROM_CAMERA)))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-27 18:34:06 +00:00
|
|
|
if (pp->Flags & (PF_VIEW_FROM_OUTSIDE))
|
2021-12-27 16:43:00 +00:00
|
|
|
tsp->cstat |= (CSTAT_SPRITE_TRANSLUCENT);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-27 18:34:06 +00:00
|
|
|
if (pp->Flags & (PF_CLIMBING))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// move sprite forward some so he looks like he's
|
|
|
|
// climbing
|
2021-12-30 12:29:01 +00:00
|
|
|
tsp->pos.X = pp->si.X + MOVEx(128 + 80, tsp->ang);
|
|
|
|
tsp->pos.Y = pp->si.Y + MOVEy(128 + 80, tsp->ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-30 12:29:01 +00:00
|
|
|
tsp->pos.X = pp->si.X;
|
|
|
|
tsp->pos.Y = pp->si.Y;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 12:29:01 +00:00
|
|
|
tsp->pos.Z = tsp->pos.Z + pp->si.Z;
|
2020-04-03 21:51:51 +00:00
|
|
|
tsp->ang = pp->siang;
|
2015-05-19 21:54:34 +00:00
|
|
|
//continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// dont draw your sprite
|
2021-12-04 18:08:50 +00:00
|
|
|
tsp->ownerActor = nullptr;
|
2021-12-27 16:43:00 +00:00
|
|
|
//tsp->cstat |= (CSTAT_SPRITE_INVISIBLE);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-01 13:08:07 +00:00
|
|
|
else // Otherwise just interpolate the player sprite
|
2020-04-18 14:38:31 +00:00
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
pp = tActor->user.PlayerP;
|
2021-05-12 00:02:26 +00:00
|
|
|
int sr = 65536 - int(smoothratio);
|
2021-12-22 11:52:02 +00:00
|
|
|
tsp->pos.X -= MulScale(pp->pos.X - pp->opos.X, sr, 16);
|
2021-12-22 11:52:32 +00:00
|
|
|
tsp->pos.Y -= MulScale(pp->pos.Y - pp->opos.Y, sr, 16);
|
2021-12-22 11:53:07 +00:00
|
|
|
tsp->pos.Z -= MulScale(pp->pos.Z - pp->opos.Z, sr, 16);
|
2021-05-12 00:02:26 +00:00
|
|
|
tsp->ang -= MulScale(pp->angle.ang.asbuild() - pp->angle.oang.asbuild(), sr, 16);
|
2020-04-18 14:38:31 +00:00
|
|
|
}
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 15:58:48 +00:00
|
|
|
if (OverlapDraw && FAF_ConnectArea(tsp->sectp) && tsp->ownerActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-03-24 19:28:58 +00:00
|
|
|
ConnectCopySprite(tsp);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// kens original sprite shade code he moved out of the engine
|
|
|
|
//
|
|
|
|
|
|
|
|
switch (tsp->statnum)
|
|
|
|
{
|
|
|
|
case STAT_ENEMY:
|
|
|
|
case STAT_DEAD_ACTOR:
|
|
|
|
case STAT_FAF_COPY:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
newshade = tsp->shade;
|
|
|
|
newshade += 6;
|
|
|
|
if (newshade > 127) newshade = 127;
|
2021-05-12 00:02:26 +00:00
|
|
|
tsp->shade = int8_t(newshade);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((tsectp->ceilingstat & CSTAT_SECTOR_SKY))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
newshade = tsp->shade;
|
2021-11-20 22:20:43 +00:00
|
|
|
newshade += tsectp->ceilingshade;
|
2015-05-19 21:54:34 +00:00
|
|
|
if (newshade > 127) newshade = 127;
|
|
|
|
if (newshade < -128) newshade = -128;
|
2021-05-12 00:02:26 +00:00
|
|
|
tsp->shade = int8_t(newshade);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newshade = tsp->shade;
|
2021-11-20 22:20:43 +00:00
|
|
|
newshade += tsectp->floorshade;
|
2015-05-19 21:54:34 +00:00
|
|
|
if (newshade > 127) newshade = 127;
|
|
|
|
if (newshade < -128) newshade = -128;
|
2021-05-12 00:02:26 +00:00
|
|
|
tsp->shade = int8_t(newshade);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tsp->hitag == 9998)
|
|
|
|
tsp->shade = 127; // Invisible enemy ninjas
|
|
|
|
|
|
|
|
// Correct shades for luminous sprites
|
|
|
|
if (tsp->hitag == LUMINOUS)
|
|
|
|
{
|
|
|
|
tsp->shade = -128;
|
|
|
|
}
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if (pp->NightVision && (tsp->extra & SPRX_PLAYER_OR_ENEMY))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->hasU() && tActor->user.ID == TRASHCAN) continue; // Don't light up trashcan
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
tsp->pal = PALETTE_ILLUMINATE; // Make sprites REALLY bright green.
|
|
|
|
tsp->shade = -128;
|
|
|
|
}
|
|
|
|
|
2021-12-25 18:28:40 +00:00
|
|
|
if (tActor->hasU() && tActor->user.PlayerP)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((tActor->user.Flags2 & SPR2_VIS_SHADING))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-26 07:44:18 +00:00
|
|
|
if (Player[screenpeek].actor != tActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-29 05:13:28 +00:00
|
|
|
if (!(tActor->user.PlayerP->Flags & PF_VIEW_FROM_OUTSIDE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-27 17:58:15 +00:00
|
|
|
tsp->cstat &= ~(CSTAT_SPRITE_TRANSLUCENT);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-25 15:30:22 +00:00
|
|
|
tsp->shade = 12 - StdRandomRange(30);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-02 08:28:40 +00:00
|
|
|
WarpCopySprite(tsprite, spritesortcnt);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-03-29 19:48:23 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#if 1
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* get_tsprite(tspritetype* tsprite, int& spritesortcnt, DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int tSpriteNum;
|
|
|
|
|
|
|
|
for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--)
|
|
|
|
{
|
2021-12-04 18:08:50 +00:00
|
|
|
if (tsprite[tSpriteNum].ownerActor == actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
return &tsprite[tSpriteNum];
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:25:18 +00:00
|
|
|
return nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-11 02:49:58 +00:00
|
|
|
void post_analyzesprites(tspritetype* tsprite, int& spritesortcnt)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int tSpriteNum;
|
|
|
|
|
|
|
|
for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--)
|
|
|
|
{
|
2021-12-04 18:08:50 +00:00
|
|
|
auto actor = static_cast<DSWActor*>(tsprite[tSpriteNum].ownerActor);
|
|
|
|
if (!actor) continue; // JBF: verify this is safe
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* tsp = &tsprite[tSpriteNum];
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-04 18:08:50 +00:00
|
|
|
if (actor->hasU())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 18:28:40 +00:00
|
|
|
if (actor->user.ID == FIREBALL_FLAMES && actor->user.attachActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 10:48:10 +00:00
|
|
|
tspritetype* const atsp = get_tsprite(tsprite, spritesortcnt, actor->user.attachActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (!atsp)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-12-22 10:57:10 +00:00
|
|
|
tsp->pos.X = atsp->pos.X;
|
2021-12-22 11:17:17 +00:00
|
|
|
tsp->pos.Y = atsp->pos.Y;
|
2015-05-19 21:54:34 +00:00
|
|
|
// statnum is priority - draw this ALWAYS first at 0
|
|
|
|
// statnum is priority - draw this ALWAYS last at MAXSTATUS
|
2021-12-29 05:53:36 +00:00
|
|
|
if ((atsp->extra & SPRX_BURNABLE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
atsp->statnum = 1;
|
|
|
|
tsp->statnum = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tsp->statnum = MAXSTATUS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-12-11 02:49:58 +00:00
|
|
|
void CircleCamera(int *nx, int *ny, int *nz, sectortype** vsect, binangle *nang, fixed_t q16horiz)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-06 11:24:22 +00:00
|
|
|
HitInfo hit{};
|
2020-03-06 15:49:49 +00:00
|
|
|
int i, vx, vy, vz, hx, hy;
|
2021-12-18 19:41:15 +00:00
|
|
|
int daang;
|
2021-12-31 14:59:11 +00:00
|
|
|
PLAYER* pp = &Player[screenpeek];
|
2020-10-08 03:23:29 +00:00
|
|
|
binangle ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-10-08 03:23:29 +00:00
|
|
|
ang = *nang + buildang(pp->circle_camera_ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Calculate the vector (nx,ny,nz) to shoot backwards
|
2020-11-15 09:41:01 +00:00
|
|
|
vx = -ang.bcos(-4);
|
|
|
|
vy = -ang.bsin(-4);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// lengthen the vector some
|
2021-12-27 17:19:30 +00:00
|
|
|
vx += vx >> 1;
|
|
|
|
vy += vy >> 1;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-10-07 02:28:38 +00:00
|
|
|
vz = q16horiz >> 8;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Player sprite of current view
|
2021-12-24 20:44:57 +00:00
|
|
|
DSWActor* actor = pp->actor;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
auto bakcstat = actor->spr.cstat;
|
2021-12-27 17:58:15 +00:00
|
|
|
actor->spr.cstat &= ~(CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Make sure sector passed to hitscan is correct
|
2021-11-07 17:55:55 +00:00
|
|
|
//updatesector(*nx, *ny, vsect);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 00:01:16 +00:00
|
|
|
hitscan({ *nx, *ny, *nz }, *vsect, { vx, vy, vz }, hit, CLIPMASK_MISSILE);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
actor->spr.cstat = bakcstat; // Restore cstat
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-22 09:36:09 +00:00
|
|
|
hx = hit.hitpos.X - (*nx);
|
2021-12-22 09:40:26 +00:00
|
|
|
hy = hit.hitpos.Y - (*ny);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// If something is in the way, make pp->circle_camera_dist lower if necessary
|
2021-01-04 12:02:00 +00:00
|
|
|
if (abs(vx) + abs(vy) > abs(hx) + abs(hy))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-26 00:01:16 +00:00
|
|
|
if (hit.hitWall) // Push you a little bit off the wall
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-26 00:01:16 +00:00
|
|
|
*vsect = hit.hitSector;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 00:01:16 +00:00
|
|
|
daang = getangle(hit.hitWall->delta());
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-11-15 09:41:01 +00:00
|
|
|
i = vx * bsin(daang) + vy * -bcos(daang);
|
2021-01-04 12:02:00 +00:00
|
|
|
if (abs(vx) > abs(vy))
|
2021-01-04 11:36:54 +00:00
|
|
|
hx -= MulScale(vx, i, 28);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-01-04 11:36:54 +00:00
|
|
|
hy -= MulScale(vy, i, 28);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-11-26 00:01:16 +00:00
|
|
|
else if (hit.actor() == nullptr) // Push you off the ceiling/floor
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-26 00:01:16 +00:00
|
|
|
*vsect = hit.hitSector;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-01-04 12:02:00 +00:00
|
|
|
if (abs(vx) > abs(vy))
|
2015-05-19 21:54:34 +00:00
|
|
|
hx -= (vx >> 5);
|
|
|
|
else
|
|
|
|
hy -= (vy >> 5);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-24 20:54:43 +00:00
|
|
|
auto hitactor = hit.actor();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// if you hit a sprite that's not a wall sprite - try again
|
2021-12-29 05:13:28 +00:00
|
|
|
if (!(hitactor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_WALL))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:54:43 +00:00
|
|
|
auto flag_backup = hitactor->spr.cstat;
|
2021-12-27 18:07:39 +00:00
|
|
|
hitactor->spr.cstat &= ~(CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-10-08 03:23:29 +00:00
|
|
|
CircleCamera(nx, ny, nz, vsect, nang, q16horiz);
|
2021-12-24 20:54:43 +00:00
|
|
|
hitactor->spr.cstat = flag_backup;
|
2015-05-19 21:54:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-04 12:02:00 +00:00
|
|
|
if (abs(vx) > abs(vy))
|
2020-09-01 13:00:35 +00:00
|
|
|
i = IntToFixed(hx) / vx;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2020-09-01 13:00:35 +00:00
|
|
|
i = IntToFixed(hy) / vy;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (i < pp->circle_camera_dist)
|
|
|
|
pp->circle_camera_dist = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Actually move you! (Camerdist is 65536 if nothing is in the way)
|
2020-09-01 13:00:35 +00:00
|
|
|
*nx = (*nx) + FixedToInt(vx * pp->circle_camera_dist);
|
|
|
|
*ny = (*ny) + FixedToInt(vy * pp->circle_camera_dist);
|
|
|
|
*nz = (*nz) + FixedToInt(vz * pp->circle_camera_dist);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Slowly increase pp->circle_camera_dist until it reaches 65536
|
|
|
|
// Synctics is a timer variable so it increases the same rate
|
|
|
|
// on all speed computers
|
|
|
|
pp->circle_camera_dist = min(pp->circle_camera_dist + (3 << 8), 65536);
|
|
|
|
//pp->circle_camera_dist = min(pp->circle_camera_dist + (synctics << 10), 65536);
|
|
|
|
|
|
|
|
// Make sure vsect is correct
|
|
|
|
updatesectorz(*nx, *ny, *nz, vsect);
|
|
|
|
|
2020-10-08 03:23:29 +00:00
|
|
|
*nang = ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2019-12-23 19:55:12 +00:00
|
|
|
FString GameInterface::GetCoordString()
|
|
|
|
{
|
2021-12-31 14:59:11 +00:00
|
|
|
PLAYER* pp = Player + myconnectindex;
|
2019-12-23 19:55:12 +00:00
|
|
|
FString out;
|
2021-12-11 06:22:44 +00:00
|
|
|
out.AppendFormat("POSX:%d ", pp->pos.X);
|
2021-12-11 06:24:41 +00:00
|
|
|
out.AppendFormat("POSY:%d ", pp->pos.Y);
|
2021-12-11 06:26:10 +00:00
|
|
|
out.AppendFormat("POSZ:%d ", pp->pos.Z);
|
2020-10-08 03:23:29 +00:00
|
|
|
out.AppendFormat("ANG:%d\n", pp->angle.ang.asbuild());
|
2019-12-23 19:55:12 +00:00
|
|
|
|
|
|
|
return out;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-31 14:59:11 +00:00
|
|
|
void PrintSpriteInfo(PLAYER* pp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-08-16 07:04:24 +00:00
|
|
|
const int Y_STEP = 7;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-12-23 19:55:12 +00:00
|
|
|
//if (SpriteInfo && !LocationInfo)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-26 07:44:18 +00:00
|
|
|
auto actor = DoPickTarget(pp->actor, 32, 2);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
actor->spr.hitag = 9997; // Special tag to make the actor glow red for one frame
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 16:54:18 +00:00
|
|
|
if (actor == nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2019-12-23 19:55:12 +00:00
|
|
|
Printf("SPRITENUM: NONE TARGETED\n");
|
2015-05-19 21:54:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
2021-11-01 16:54:18 +00:00
|
|
|
Printf("SPRITENUM:%d\n", actor->GetIndex());
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
if (actor->hasU())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 20:02:31 +00:00
|
|
|
Printf("ID:%d, ", actor->user.ID);
|
|
|
|
Printf("PALETTE:%d, ", actor->user.spal);
|
|
|
|
Printf("HEALTH:%d, ", actor->user.Health);
|
|
|
|
Printf("WAITTICS:%d, ", actor->user.WaitTics);
|
|
|
|
Printf("COUNTER:%d, ", actor->user.Counter);
|
|
|
|
Printf("COUNTER2:%d\n", actor->user.Counter);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:49:44 +00:00
|
|
|
Printf("POSX:%d, ", actor->spr.pos.X);
|
|
|
|
Printf("POSY:%d, ", actor->spr.pos.Y);
|
|
|
|
Printf("POSZ:%d,", actor->spr.pos.Z);
|
|
|
|
Printf("ANG:%d\n", actor->spr.ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-31 14:59:11 +00:00
|
|
|
void DrawCrosshair(PLAYER* pp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-25 07:52:00 +00:00
|
|
|
if (!(CameraTestMode))
|
2020-08-15 20:04:37 +00:00
|
|
|
{
|
2021-12-29 05:53:36 +00:00
|
|
|
::DrawCrosshair(2326, pp->actor->user.Health, -pp->angle.look_anghalf(smoothratio), (pp->Flags & PF_VIEW_FROM_OUTSIDE) ? 5 : 0, 2, shadeToLight(10));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-31 14:59:11 +00:00
|
|
|
void CameraView(PLAYER* pp, int *tx, int *ty, int *tz, sectortype** tsect, binangle *tang, fixedhoriz *thoriz)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-10-08 03:23:29 +00:00
|
|
|
binangle ang;
|
2020-09-09 18:32:24 +00:00
|
|
|
bool found_camera = false;
|
|
|
|
bool player_in_camera = false;
|
|
|
|
bool FAFcansee_test;
|
|
|
|
bool ang_test;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (pp == &Player[screenpeek])
|
|
|
|
{
|
2021-10-31 21:14:06 +00:00
|
|
|
SWStatIterator it(STAT_DEMO_CAMERA);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:49:44 +00:00
|
|
|
ang = bvectangbam(*tx - actor->spr.pos.X, *ty - actor->spr.pos.Y);
|
|
|
|
ang_test = getincangle(ang.asbuild(), actor->spr.ang) < actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
FAFcansee_test =
|
2021-12-30 15:51:56 +00:00
|
|
|
(FAFcansee(actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, actor->sector(), *tx, *ty, *tz, pp->cursector) ||
|
|
|
|
FAFcansee(actor->spr.pos.X, actor->spr.pos.Y, actor->spr.pos.Z, actor->sector(), *tx, *ty, *tz + ActorSizeZ(pp->actor), pp->cursector));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
player_in_camera = ang_test && FAFcansee_test;
|
|
|
|
|
|
|
|
if (player_in_camera || pp->camera_check_time_delay > 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
// if your not in the camera but are still looking
|
|
|
|
// make sure that only the last camera shows you
|
|
|
|
|
|
|
|
if (!player_in_camera && pp->camera_check_time_delay > 0)
|
|
|
|
{
|
2021-12-05 08:34:30 +00:00
|
|
|
if (pp->last_camera_act != actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
switch (actor->spr.clipdist)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
case 1:
|
2021-12-05 08:34:30 +00:00
|
|
|
pp->last_camera_act = actor;
|
2021-11-24 22:54:37 +00:00
|
|
|
CircleCamera(tx, ty, tz, tsect, tang, 0);
|
2020-09-09 17:52:52 +00:00
|
|
|
found_camera = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
int xvect,yvect,zvect,zdiff;
|
|
|
|
|
2021-12-05 08:34:30 +00:00
|
|
|
pp->last_camera_act = actor;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-11-15 09:41:01 +00:00
|
|
|
xvect = ang.bcos(-3);
|
|
|
|
yvect = ang.bsin(-3);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-24 20:49:44 +00:00
|
|
|
zdiff = actor->spr.pos.Z - *tz;
|
|
|
|
if (labs(actor->spr.pos.X - *tx) > 1000)
|
|
|
|
zvect = Scale(xvect, zdiff, actor->spr.pos.X - *tx);
|
|
|
|
else if (labs(actor->spr.pos.Y - *ty) > 1000)
|
|
|
|
zvect = Scale(yvect, zdiff, actor->spr.pos.Y - *ty);
|
|
|
|
else if (actor->spr.pos.X - *tx != 0)
|
|
|
|
zvect = Scale(xvect, zdiff, actor->spr.pos.X - *tx);
|
|
|
|
else if (actor->spr.pos.Y - *ty != 0)
|
|
|
|
zvect = Scale(yvect, zdiff, actor->spr.pos.Y - *ty);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
zvect = 0;
|
|
|
|
|
|
|
|
// new horiz to player
|
2020-10-07 07:08:57 +00:00
|
|
|
*thoriz = q16horiz(clamp(-(zvect << 8), gi->playerHorizMin(), gi->playerHorizMax()));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-10-08 03:23:29 +00:00
|
|
|
*tang = ang;
|
2021-12-24 20:49:44 +00:00
|
|
|
*tx = actor->spr.pos.X;
|
|
|
|
*ty = actor->spr.pos.Y;
|
|
|
|
*tz = actor->spr.pos.Z;
|
2021-12-30 15:51:56 +00:00
|
|
|
*tsect = actor->sector();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
found_camera = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_camera)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if you player_in_camera you definately have a camera
|
|
|
|
if (player_in_camera)
|
|
|
|
{
|
|
|
|
pp->camera_check_time_delay = 120/2;
|
2021-12-27 16:22:41 +00:00
|
|
|
pp->Flags |= (PF_VIEW_FROM_CAMERA);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
ASSERT(found_camera);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// if you !player_in_camera you still might have a camera
|
|
|
|
// for a split second
|
|
|
|
{
|
|
|
|
if (found_camera)
|
|
|
|
{
|
2021-12-27 16:22:41 +00:00
|
|
|
pp->Flags |= (PF_VIEW_FROM_CAMERA);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pp->circle_camera_ang = 0;
|
|
|
|
pp->circle_camera_dist = CIRCLE_CAMERA_DIST_MIN;
|
2021-12-27 17:58:15 +00:00
|
|
|
pp->Flags &= ~(PF_VIEW_FROM_CAMERA);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-11 02:49:58 +00:00
|
|
|
void PreDraw(void)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2015-05-19 21:54:34 +00:00
|
|
|
PreDrawStackedWater();
|
|
|
|
|
2021-10-31 21:14:06 +00:00
|
|
|
SWStatIterator it(STAT_FLOOR_SLOPE_DONT_DRAW);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
actor->sector()->floorstat &= ~(CSTAT_SECTOR_SLOPE);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-11 02:49:58 +00:00
|
|
|
void PostDraw(void)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2021-10-31 21:14:06 +00:00
|
|
|
SWStatIterator it(STAT_FLOOR_SLOPE_DONT_DRAW);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
actor->sector()->floorstat |= (CSTAT_SECTOR_SLOPE);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-10-15 15:30:55 +00:00
|
|
|
it.Reset(STAT_FAF_COPY);
|
2021-10-31 21:14:06 +00:00
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-17 16:01:10 +00:00
|
|
|
actor->clearUser();
|
2021-12-06 16:00:15 +00:00
|
|
|
actor->Destroy();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PreDrawStackedWater(void)
|
|
|
|
{
|
2021-10-31 22:01:00 +00:00
|
|
|
SWStatIterator it(STAT_CEILING_FLOOR_PIC_OVERRIDE);
|
|
|
|
while (auto itActor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
SWSectIterator it2(itActor->sector());
|
2021-10-31 22:01:00 +00:00
|
|
|
while (auto itActor2 = it2.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 22:01:00 +00:00
|
|
|
if (itActor2->hasU())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 20:44:57 +00:00
|
|
|
if (itActor2->spr.statnum == STAT_ITEM)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-12-24 20:44:57 +00:00
|
|
|
if (itActor2->spr.statnum <= STAT_DEFAULT || itActor2->spr.statnum > STAT_PLAYER0 + MAX_SW_PLAYERS)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// code so that a copied sprite will not make another copy
|
2021-12-30 13:21:41 +00:00
|
|
|
if (itActor2->user.change.X == -989898)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-12-24 20:44:57 +00:00
|
|
|
auto actorNew = ConnectCopySprite(&itActor2->spr);
|
2021-10-31 22:01:00 +00:00
|
|
|
if (actorNew != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// spawn a user
|
2021-12-25 18:53:06 +00:00
|
|
|
actorNew->allocUser();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-30 13:21:41 +00:00
|
|
|
actorNew->user.change.X = -989898;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// copy everything reasonable from the user that
|
|
|
|
// analyzesprites() needs to draw the image
|
2021-12-25 20:02:31 +00:00
|
|
|
actorNew->user.State = itActor2->user.State;
|
|
|
|
actorNew->user.Rot = itActor2->user.Rot;
|
|
|
|
actorNew->user.StateStart = itActor2->user.StateStart;
|
|
|
|
actorNew->user.StateEnd = itActor2->user.StateEnd;
|
|
|
|
actorNew->user.Flags = itActor2->user.Flags;
|
|
|
|
actorNew->user.Flags2 = itActor2->user.Flags2;
|
|
|
|
actorNew->user.RotNum = itActor2->user.RotNum;
|
|
|
|
actorNew->user.ID = itActor2->user.ID;
|
|
|
|
|
|
|
|
actorNew->user.PlayerP = itActor2->user.PlayerP;
|
|
|
|
actorNew->user.spal = itActor2->user.spal;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-12-31 14:59:11 +00:00
|
|
|
void DoPlayerDiveMeter(PLAYER* pp);
|
2019-10-09 17:58:09 +00:00
|
|
|
|
2021-12-31 14:59:11 +00:00
|
|
|
void polymost_drawscreen(PLAYER* pp, int tx, int ty, int tz, binangle tang, fixedhoriz thoriz, sectortype* tsect);
|
2021-03-21 11:22:50 +00:00
|
|
|
|
|
|
|
|
2021-03-21 16:04:06 +00:00
|
|
|
void UpdateWallPortalState()
|
|
|
|
{
|
|
|
|
// This is too obtuse to be maintained statically, but with 8 mirrors at most easy to be kept up to date.
|
2021-05-08 13:23:45 +00:00
|
|
|
for (int i = 0; i < mirrorcnt; i++)
|
2021-03-21 16:04:06 +00:00
|
|
|
{
|
2021-11-24 17:18:23 +00:00
|
|
|
if (mirror[i].mirrorWall == nullptr) {
|
2021-05-08 11:13:47 +00:00
|
|
|
continue;
|
|
|
|
}
|
2021-11-24 17:18:23 +00:00
|
|
|
walltype* wal = mirror[i].mirrorWall;
|
2021-11-13 10:49:40 +00:00
|
|
|
if (wal->picnum != MIRRORLABEL + i)
|
|
|
|
{
|
|
|
|
wal->portalflags = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2021-03-21 16:04:06 +00:00
|
|
|
wal->portalflags = 0;
|
|
|
|
wal->portalnum = 0;
|
|
|
|
|
|
|
|
if (!mirror[i].ismagic)
|
|
|
|
{
|
|
|
|
// a simple mirror
|
|
|
|
wal->portalflags = PORTAL_WALL_MIRROR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-07 18:22:30 +00:00
|
|
|
DSWActor* cam = mirror[i].cameraActor;
|
|
|
|
if (cam)
|
2021-03-21 16:04:06 +00:00
|
|
|
{
|
2021-12-24 20:44:57 +00:00
|
|
|
if (!TEST_BOOL1(cam))
|
2021-12-07 18:22:30 +00:00
|
|
|
{
|
|
|
|
wal->portalflags = PORTAL_WALL_TO_SPRITE;
|
|
|
|
wal->portalnum = i;
|
|
|
|
wall_to_sprite_actors[i] = cam;
|
|
|
|
}
|
2021-03-21 16:04:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-30 21:27:11 +00:00
|
|
|
|
2021-10-31 22:01:00 +00:00
|
|
|
SWStatIterator it(STAT_CEILING_FLOOR_PIC_OVERRIDE);
|
|
|
|
while (auto actor = it.Next())
|
2021-03-30 21:27:11 +00:00
|
|
|
{
|
2021-12-24 14:21:44 +00:00
|
|
|
if (SP_TAG3(actor) == 0)
|
2021-03-30 21:27:11 +00:00
|
|
|
{
|
|
|
|
// back up ceilingpicnum and ceilingstat
|
2021-12-30 15:51:56 +00:00
|
|
|
SP_TAG5(actor) = actor->sector()->ceilingpicnum;
|
|
|
|
actor->sector()->ceilingpicnum = SP_TAG2(actor);
|
|
|
|
SP_TAG4(actor) = actor->sector()->ceilingstat;
|
|
|
|
actor->sector()->ceilingstat |= (ESectorFlags::FromInt(SP_TAG6(actor)));
|
|
|
|
actor->sector()->ceilingstat &= ~(CSTAT_SECTOR_SKY);
|
2021-03-30 21:27:11 +00:00
|
|
|
}
|
2021-12-24 14:21:44 +00:00
|
|
|
else if (SP_TAG3(actor) == 1)
|
2021-03-30 21:27:11 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
SP_TAG5(actor) = actor->sector()->floorpicnum;
|
|
|
|
actor->sector()->floorpicnum = SP_TAG2(actor);
|
|
|
|
SP_TAG4(actor) = actor->sector()->floorstat;
|
|
|
|
actor->sector()->floorstat |= (ESectorFlags::FromInt(SP_TAG6(actor)));
|
|
|
|
actor->sector()->floorstat &= ~(CSTAT_SECTOR_SKY);
|
2021-03-30 21:27:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-21 16:04:06 +00:00
|
|
|
}
|
|
|
|
|
2021-03-30 21:27:11 +00:00
|
|
|
void RestorePortalState()
|
|
|
|
{
|
2021-10-31 22:01:00 +00:00
|
|
|
SWStatIterator it(STAT_CEILING_FLOOR_PIC_OVERRIDE);
|
|
|
|
while (auto actor = it.Next())
|
2021-03-30 21:27:11 +00:00
|
|
|
{
|
2021-12-24 14:21:44 +00:00
|
|
|
if (SP_TAG3(actor) == 0)
|
2021-03-30 21:27:11 +00:00
|
|
|
{
|
|
|
|
// restore ceilingpicnum and ceilingstat
|
2021-12-30 15:51:56 +00:00
|
|
|
actor->sector()->ceilingpicnum = SP_TAG5(actor);
|
|
|
|
actor->sector()->ceilingstat = ESectorFlags::FromInt(SP_TAG4(actor));
|
|
|
|
actor->sector()->ceilingstat &= ~(CSTAT_SECTOR_SKY);
|
2021-03-30 21:27:11 +00:00
|
|
|
}
|
2021-12-24 14:21:44 +00:00
|
|
|
else if (SP_TAG3(actor) == 1)
|
2021-03-30 21:27:11 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
actor->sector()->floorpicnum = SP_TAG5(actor);
|
|
|
|
actor->sector()->floorstat = ESectorFlags::FromInt(SP_TAG4(actor));
|
|
|
|
actor->sector()->floorstat &= ~(CSTAT_SECTOR_SKY);
|
2021-03-30 21:27:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-21 16:04:06 +00:00
|
|
|
|
2022-01-08 11:09:04 +00:00
|
|
|
void drawscreen(PLAYER* pp, double smoothratio, bool sceneonly)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-09 18:32:24 +00:00
|
|
|
extern bool CameraTestMode;
|
2020-05-20 08:10:27 +00:00
|
|
|
int tx, ty, tz;
|
2021-04-11 05:43:11 +00:00
|
|
|
binangle tang, trotscrnang;
|
2020-10-07 07:08:57 +00:00
|
|
|
fixedhoriz thoriz;
|
2021-11-26 16:50:49 +00:00
|
|
|
sectortype* tsect;
|
2015-05-19 21:54:34 +00:00
|
|
|
short i,j;
|
|
|
|
int bob_amt = 0;
|
|
|
|
int quake_z, quake_x, quake_y;
|
|
|
|
short quake_ang;
|
2020-09-09 18:32:24 +00:00
|
|
|
extern bool FAF_DebugView;
|
2021-12-31 14:59:11 +00:00
|
|
|
PLAYER* camerapp; // prediction player if prediction is on, else regular player
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-12-03 09:44:42 +00:00
|
|
|
int const viewingRange = viewingrange;
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
DrawScreen = true;
|
2015-05-19 21:54:34 +00:00
|
|
|
PreDraw();
|
|
|
|
|
2020-08-18 06:25:12 +00:00
|
|
|
PreUpdatePanel(smoothratio);
|
2021-05-12 00:02:26 +00:00
|
|
|
int sr = (int)smoothratio;
|
|
|
|
pm_smoothratio = sr;
|
2020-08-18 06:25:12 +00:00
|
|
|
|
2022-01-08 11:09:04 +00:00
|
|
|
if (!sceneonly)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-11-26 17:05:49 +00:00
|
|
|
DoInterpolations(smoothratio / 65536.); // Stick at beginning of drawscreen
|
2020-05-22 23:26:51 +00:00
|
|
|
if (cl_sointerpolation)
|
2021-05-12 00:02:26 +00:00
|
|
|
so_dointerpolations(sr); // Stick at beginning of drawscreen
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TENSW: when rendering with prediction, the only thing that counts should
|
|
|
|
// be the predicted player.
|
|
|
|
if (PredictionOn && CommEnabled && pp == Player+myconnectindex)
|
|
|
|
camerapp = ppp;
|
|
|
|
else
|
|
|
|
camerapp = pp;
|
|
|
|
|
2021-12-22 11:52:02 +00:00
|
|
|
tx = interpolatedvalue(camerapp->opos.X, camerapp->pos.X, sr);
|
2021-12-22 11:52:32 +00:00
|
|
|
ty = interpolatedvalue(camerapp->opos.Y, camerapp->pos.Y, sr);
|
2021-12-22 11:53:07 +00:00
|
|
|
tz = interpolatedvalue(camerapp->opos.Z, camerapp->pos.Z, sr);
|
2020-09-10 10:47:41 +00:00
|
|
|
|
|
|
|
// Interpolate the player's angle while on a sector object, just like VoidSW.
|
|
|
|
// This isn't needed for the turret as it was fixable, but moving sector objects are problematic.
|
2020-11-30 22:40:16 +00:00
|
|
|
if (SyncInput() || pp != Player+myconnectindex)
|
2020-04-11 07:17:59 +00:00
|
|
|
{
|
2020-10-08 03:23:29 +00:00
|
|
|
tang = camerapp->angle.interpolatedsum(smoothratio);
|
2020-10-07 07:08:57 +00:00
|
|
|
thoriz = camerapp->horizon.interpolatedsum(smoothratio);
|
2020-10-08 03:23:29 +00:00
|
|
|
trotscrnang = camerapp->angle.interpolatedrotscrn(smoothratio);
|
2020-04-11 07:17:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-08 03:23:29 +00:00
|
|
|
tang = pp->angle.sum();
|
2020-10-07 07:08:57 +00:00
|
|
|
thoriz = pp->horizon.sum();
|
2020-10-08 03:23:29 +00:00
|
|
|
trotscrnang = pp->angle.rotscrnang;
|
2020-04-11 07:17:59 +00:00
|
|
|
}
|
2021-11-26 16:50:49 +00:00
|
|
|
tsect = camerapp->cursector;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-26 16:50:49 +00:00
|
|
|
updatesector(tx, ty, &tsect);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (pp->sop_riding || pp->sop_control)
|
|
|
|
{
|
2020-05-01 15:10:48 +00:00
|
|
|
if (pp->sop_control &&
|
2020-05-22 23:26:51 +00:00
|
|
|
(!cl_sointerpolation || (CommEnabled && !pp->sop_remote)))
|
2020-04-13 19:47:19 +00:00
|
|
|
{
|
2021-12-11 06:22:44 +00:00
|
|
|
tx = pp->pos.X;
|
2021-12-11 06:24:41 +00:00
|
|
|
ty = pp->pos.Y;
|
2021-12-11 06:26:10 +00:00
|
|
|
tz = pp->pos.Z;
|
2020-10-08 03:23:29 +00:00
|
|
|
tang = pp->angle.ang;
|
2020-04-13 19:47:19 +00:00
|
|
|
}
|
2021-11-26 16:50:49 +00:00
|
|
|
tsect = pp->cursector;
|
|
|
|
updatesectorz(tx, ty, tz, &tsect);
|
2020-05-19 11:44:52 +00:00
|
|
|
}
|
2020-04-03 21:49:57 +00:00
|
|
|
|
2021-12-30 12:29:01 +00:00
|
|
|
pp->si.X = tx;
|
|
|
|
pp->si.Y = ty;
|
|
|
|
pp->si.Z = tz - pp->pos.Z;
|
2020-10-08 03:23:29 +00:00
|
|
|
pp->siang = tang.asbuild();
|
2020-04-03 21:49:57 +00:00
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
QuakeViewChange(camerapp, &quake_z, &quake_x, &quake_y, &quake_ang);
|
2022-01-08 11:23:05 +00:00
|
|
|
int vis = g_visibility;
|
|
|
|
VisViewChange(camerapp, &vis);
|
|
|
|
g_relvisibility = vis - g_visibility;
|
2015-05-19 21:54:34 +00:00
|
|
|
tz = tz + quake_z;
|
|
|
|
tx = tx + quake_x;
|
|
|
|
ty = ty + quake_y;
|
2020-10-07 07:08:57 +00:00
|
|
|
//thoriz += buildhoriz(quake_x);
|
2020-10-08 03:23:29 +00:00
|
|
|
tang += buildang(quake_ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (pp->sop_remote)
|
|
|
|
{
|
2021-12-24 20:54:43 +00:00
|
|
|
DSWActor* ractor = pp->remoteActor;
|
|
|
|
if (TEST_BOOL1(ractor))
|
|
|
|
tang = buildang(ractor->spr.ang);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-12-31 22:33:30 +00:00
|
|
|
tang = bvectangbam(pp->sop_remote->pmid.X - tx, pp->sop_remote->pmid.Y - ty);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-27 18:34:06 +00:00
|
|
|
if (pp->Flags & (PF_VIEW_FROM_OUTSIDE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-25 07:52:00 +00:00
|
|
|
tz -= 8448;
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2021-12-26 07:44:18 +00:00
|
|
|
if (!calcChaseCamPos(&tx, &ty, &tz, pp->actor, &tsect, tang, thoriz, smoothratio))
|
2020-09-25 07:52:00 +00:00
|
|
|
{
|
|
|
|
tz += 8448;
|
2021-12-26 07:44:18 +00:00
|
|
|
calcChaseCamPos(&tx, &ty, &tz, pp->actor, &tsect, tang, thoriz, smoothratio);
|
2020-09-25 07:52:00 +00:00
|
|
|
}
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bob_amt = camerapp->bob_amt;
|
|
|
|
|
2020-08-15 20:31:44 +00:00
|
|
|
if (CameraTestMode)
|
2020-03-28 11:31:02 +00:00
|
|
|
{
|
2021-11-26 16:50:49 +00:00
|
|
|
CameraView(camerapp, &tx, &ty, &tz, &tsect, &tang, &thoriz);
|
2020-03-28 11:31:02 +00:00
|
|
|
}
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 05:18:25 +00:00
|
|
|
if (!(pp->Flags & (PF_VIEW_FROM_CAMERA|PF_VIEW_FROM_OUTSIDE)))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-20 08:25:16 +00:00
|
|
|
if (cl_viewbob)
|
|
|
|
{
|
|
|
|
tz += bob_amt;
|
2021-04-11 06:45:19 +00:00
|
|
|
tz += interpolatedvalue(pp->obob_z, pp->bob_z, smoothratio);
|
2020-09-20 08:25:16 +00:00
|
|
|
}
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// recoil only when not in camera
|
2021-10-30 21:53:26 +00:00
|
|
|
thoriz = q16horiz(clamp(thoriz.asq16() + interpolatedvalue(pp->recoil_ohorizoff, pp->recoil_horizoff, smoothratio), gi->playerHorizMin(), gi->playerHorizMax()));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 11:09:04 +00:00
|
|
|
if (automapMode != am_full)
|
2020-03-29 12:01:46 +00:00
|
|
|
{
|
|
|
|
// Cameras must be done before the main loop.
|
2022-01-07 11:49:41 +00:00
|
|
|
if (!vid_renderer) JS_DrawCameras(pp, tx, ty, tz, smoothratio);
|
2021-03-28 17:22:51 +00:00
|
|
|
else JS_CameraParms(pp, tx, ty, tz);
|
2020-03-29 12:01:46 +00:00
|
|
|
}
|
|
|
|
|
2022-01-07 11:49:41 +00:00
|
|
|
if (!vid_renderer)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-05-12 00:02:26 +00:00
|
|
|
renderSetRollAngle((float)trotscrnang.asbuildf());
|
2021-11-26 16:50:49 +00:00
|
|
|
polymost_drawscreen(pp, tx, ty, tz, tang, thoriz, tsect);
|
2022-01-08 11:09:04 +00:00
|
|
|
if (!sceneonly) UpdatePanel(smoothratio);
|
2021-03-21 11:22:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-01-08 11:09:04 +00:00
|
|
|
if (!sceneonly) UpdatePanel(smoothratio);
|
2021-03-21 16:04:06 +00:00
|
|
|
UpdateWallPortalState();
|
2021-12-26 07:44:18 +00:00
|
|
|
render_drawrooms(pp->actor, { tx, ty, tz }, sectnum(tsect), tang, thoriz, trotscrnang, smoothratio);
|
2021-03-30 21:27:11 +00:00
|
|
|
RestorePortalState();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 11:09:04 +00:00
|
|
|
if (sceneonly)
|
2020-09-19 19:31:35 +00:00
|
|
|
{
|
|
|
|
DrawScreen = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-08 11:09:04 +00:00
|
|
|
// if doing a screen save don't need to process the rest
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-02 00:05:07 +00:00
|
|
|
MarkSectorSeen(pp->cursector);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-08-24 17:36:17 +00:00
|
|
|
if ((automapMode != am_off) && pp == Player+myconnectindex)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 22:01:00 +00:00
|
|
|
SWSpriteIterator it;
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// Don't show sprites tagged with 257
|
2021-12-24 20:49:44 +00:00
|
|
|
if (actor->spr.lotag == 257)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-27 18:34:06 +00:00
|
|
|
if (actor->spr.cstat & (CSTAT_SPRITE_ALIGNMENT_FLOOR))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-27 17:58:15 +00:00
|
|
|
actor->spr.cstat &= ~(CSTAT_SPRITE_ALIGNMENT_FLOOR);
|
2021-12-24 20:49:44 +00:00
|
|
|
actor->spr.owner = -2;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-02 07:23:01 +00:00
|
|
|
DrawOverheadMap(tx, ty, tang.asbuild(), smoothratio);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-31 22:01:00 +00:00
|
|
|
SWSpriteIterator it;
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// Don't show sprites tagged with 257
|
2021-12-24 20:49:44 +00:00
|
|
|
if (actor->spr.lotag == 257 && actor->spr.owner == -2)
|
2021-10-31 22:01:00 +00:00
|
|
|
{
|
2021-12-27 16:13:47 +00:00
|
|
|
actor->spr.cstat |= (CSTAT_SPRITE_ALIGNMENT_FLOOR);
|
2021-12-24 20:49:44 +00:00
|
|
|
actor->spr.owner = -1;
|
2021-10-31 22:01:00 +00:00
|
|
|
}
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if SYNC_TEST
|
|
|
|
SyncStatMessage();
|
|
|
|
#endif
|
|
|
|
|
2020-09-02 16:59:56 +00:00
|
|
|
UpdateStatusBar();
|
2015-05-19 21:54:34 +00:00
|
|
|
DrawCrosshair(pp);
|
|
|
|
DoPlayerDiveMeter(pp); // Do the underwater breathing bar
|
|
|
|
|
|
|
|
// Boss Health Meter, if Boss present
|
|
|
|
BossHealthMeter();
|
|
|
|
|
|
|
|
#if SYNC_TEST
|
|
|
|
SyncStatMessage();
|
|
|
|
#endif
|
|
|
|
|
2020-11-26 17:05:49 +00:00
|
|
|
RestoreInterpolations(); // Stick at end of drawscreen
|
2020-05-22 23:26:51 +00:00
|
|
|
if (cl_sointerpolation)
|
2020-05-01 11:29:12 +00:00
|
|
|
so_restoreinterpolations(); // Stick at end of drawscreen
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-05-29 00:32:53 +00:00
|
|
|
if (paused && !M_Active())
|
|
|
|
{
|
2021-04-28 22:56:36 +00:00
|
|
|
auto str = GStrings("Game Paused");
|
2021-05-31 09:51:02 +00:00
|
|
|
auto font = PickSmallFont(str);
|
|
|
|
int w = font->StringWidth(str);
|
|
|
|
DrawText(twod, font, CR_UNTRANSLATED, 160-w, 100, str, DTA_FullscreenScale, FSMode_Fit320x200, TAG_DONE);
|
2020-05-29 00:32:53 +00:00
|
|
|
}
|
|
|
|
|
2021-12-29 05:53:36 +00:00
|
|
|
if (!CommEnabled && (pp->Flags & PF_DEAD))
|
2020-05-29 00:32:53 +00:00
|
|
|
{
|
|
|
|
if (ReloadPrompt)
|
|
|
|
{
|
2020-09-09 17:52:52 +00:00
|
|
|
ReloadPrompt = false;
|
2020-05-29 00:32:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
PostDraw();
|
2020-09-09 17:52:52 +00:00
|
|
|
DrawScreen = false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 19:44:20 +00:00
|
|
|
bool GameInterface::GenerateSavePic()
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2022-01-08 11:09:04 +00:00
|
|
|
drawscreen(Player + myconnectindex, 65536, true);
|
2020-01-14 19:44:20 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
|
2021-11-26 22:11:59 +00:00
|
|
|
bool GameInterface::DrawAutomapPlayer(int mx, int my, int cposx, int cposy, int czoom, int cang, double const smoothratio)
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
2021-12-24 09:24:30 +00:00
|
|
|
int k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff;
|
2020-09-06 19:50:02 +00:00
|
|
|
int dax, day, cosang, sinang, xspan, yspan, sprx, spry;
|
|
|
|
int xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
|
2021-03-24 19:28:58 +00:00
|
|
|
int xvect, yvect;
|
2020-09-06 19:50:02 +00:00
|
|
|
walltype* wal, * wal2;
|
|
|
|
short p;
|
|
|
|
static int pspr_ndx[8] = { 0,0,0,0,0,0,0,0 };
|
|
|
|
bool sprisplayer = false;
|
|
|
|
short txt_x, txt_y;
|
|
|
|
|
2020-11-15 09:41:01 +00:00
|
|
|
xvect = -bsin(cang) * czoom;
|
|
|
|
yvect = -bcos(cang) * czoom;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Draw sprites
|
2021-12-26 07:44:18 +00:00
|
|
|
auto peekActor = Player[screenpeek].actor;
|
2021-12-21 09:51:41 +00:00
|
|
|
for (unsigned i = 0; i < sector.Size(); i++)
|
2020-10-15 16:07:35 +00:00
|
|
|
{
|
2021-10-31 22:01:00 +00:00
|
|
|
SWSectIterator it(i);
|
|
|
|
while (auto actor = it.Next())
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
|
|
|
for (p = connecthead; p >= 0; p = connectpoint2[p])
|
|
|
|
{
|
2021-12-26 07:44:18 +00:00
|
|
|
if (Player[p].actor == actor)
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
2021-12-24 20:54:43 +00:00
|
|
|
if (actor->spr.xvel > 16)
|
2020-09-06 19:50:02 +00:00
|
|
|
pspr_ndx[myconnectindex] = ((PlayClock >> 4) & 3);
|
2020-09-09 17:52:52 +00:00
|
|
|
sprisplayer = true;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
goto SHOWSPRITE;
|
|
|
|
}
|
|
|
|
}
|
2021-12-24 20:54:43 +00:00
|
|
|
if (gFullMap || (actor->spr.cstat2 & CSTAT2_SPRITE_MAPPED))
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
|
|
|
SHOWSPRITE:
|
|
|
|
|
|
|
|
PalEntry col = GPalette.BaseColors[56]; // 1=white / 31=black / 44=green / 56=pink / 128=yellow / 210=blue / 248=orange / 255=purple
|
2021-12-24 20:54:43 +00:00
|
|
|
if ((actor->spr.cstat & CSTAT_SPRITE_BLOCK) > 0)
|
2020-09-06 19:50:02 +00:00
|
|
|
col = GPalette.BaseColors[248];
|
2021-10-31 22:01:00 +00:00
|
|
|
if (actor == peekActor)
|
2020-09-06 19:50:02 +00:00
|
|
|
col = GPalette.BaseColors[31];
|
|
|
|
|
2021-12-24 20:54:43 +00:00
|
|
|
sprx = actor->spr.pos.X;
|
|
|
|
spry = actor->spr.pos.Y;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
2021-12-24 20:54:43 +00:00
|
|
|
k = actor->spr.statnum;
|
2020-09-06 19:50:02 +00:00
|
|
|
if ((k >= 1) && (k <= 8) && (k != 2)) // Interpolate moving
|
|
|
|
{
|
2021-12-30 16:32:31 +00:00
|
|
|
sprx = actor->interpolatedx(smoothratio);
|
|
|
|
spry = actor->interpolatedy(smoothratio);
|
2020-09-06 19:50:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-24 20:54:43 +00:00
|
|
|
switch (actor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK)
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
|
|
|
case 0: // Regular sprite
|
2021-12-26 07:44:18 +00:00
|
|
|
if (Player[p].actor == actor)
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
2021-11-26 22:11:59 +00:00
|
|
|
ox = mx - cposx;
|
|
|
|
oy = my - cposy;
|
|
|
|
x1 = DMulScale(ox, xvect, -oy, yvect, 16);
|
|
|
|
y1 = DMulScale(oy, xvect, ox, yvect, 16);
|
|
|
|
int xx = xdim / 2. + x1 / 4096.;
|
|
|
|
int yy = ydim / 2. + y1 / 4096.;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
2021-04-01 18:47:05 +00:00
|
|
|
if (czoom > 192)
|
2020-09-06 19:50:02 +00:00
|
|
|
{
|
2021-12-30 16:32:31 +00:00
|
|
|
daang = ((!SyncInput() ? actor->spr.ang : actor->interpolatedang(smoothratio)) - cang) & 2047;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
// Special case tiles
|
2021-12-24 20:54:43 +00:00
|
|
|
if (actor->spr.picnum == 3123) break;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
int spnum = -1;
|
|
|
|
if (sprisplayer)
|
|
|
|
{
|
2021-12-26 07:44:18 +00:00
|
|
|
if (gNet.MultiGameType != MULTI_GAME_COMMBAT || actor == Player[screenpeek].actor)
|
2020-09-06 19:50:02 +00:00
|
|
|
spnum = 1196 + pspr_ndx[myconnectindex];
|
|
|
|
}
|
2021-12-24 20:54:43 +00:00
|
|
|
else spnum = actor->spr.picnum;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
2021-12-24 20:54:43 +00:00
|
|
|
double sc = czoom * (actor->spr.yrepeat) / 32768.;
|
2020-09-06 19:50:02 +00:00
|
|
|
if (spnum >= 0)
|
|
|
|
{
|
2021-11-26 22:11:59 +00:00
|
|
|
DrawTexture(twod, tileGetTexture(1196 + pspr_ndx[myconnectindex], true), xx, yy, DTA_ScaleX, sc, DTA_ScaleY, sc, DTA_Rotate, daang * -BAngToDegree,
|
2021-12-24 20:54:43 +00:00
|
|
|
DTA_CenterOffsetRel, 2, DTA_TranslationIndex, TRANSLATION(Translation_Remap, actor->spr.pal), DTA_Color, shadeToLight(actor->spr.shade),
|
|
|
|
DTA_Alpha, (actor->spr.cstat & CSTAT_SPRITE_TRANSLUCENT) ? 0.33 : 1., TAG_DONE);
|
2020-09-06 19:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 16: // Rotated sprite
|
|
|
|
x1 = sprx;
|
|
|
|
y1 = spry;
|
2021-12-24 20:54:43 +00:00
|
|
|
tilenum = actor->spr.picnum;
|
|
|
|
xoff = (int)tileLeftOffset(tilenum) + (int)actor->spr.xoffset;
|
|
|
|
if ((actor->spr.cstat & CSTAT_SPRITE_XFLIP) > 0)
|
2020-09-06 19:50:02 +00:00
|
|
|
xoff = -xoff;
|
2021-12-24 20:54:43 +00:00
|
|
|
k = actor->spr.ang;
|
|
|
|
l = actor->spr.xrepeat;
|
2020-11-15 09:41:01 +00:00
|
|
|
dax = bsin(k) * l;
|
|
|
|
day = -bcos(k) * l;
|
2020-11-20 07:18:26 +00:00
|
|
|
l = tileWidth(tilenum);
|
2020-09-06 19:50:02 +00:00
|
|
|
k = (l >> 1) + xoff;
|
2021-01-04 11:36:54 +00:00
|
|
|
x1 -= MulScale(dax, k, 16);
|
|
|
|
x2 = x1 + MulScale(dax, l, 16);
|
|
|
|
y1 -= MulScale(day, k, 16);
|
|
|
|
y2 = y1 + MulScale(day, l, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
ox = x1 - cposx;
|
|
|
|
oy = y1 - cposy;
|
2021-01-04 11:36:54 +00:00
|
|
|
x1 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
|
2021-03-24 19:28:58 +00:00
|
|
|
y1 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
ox = x2 - cposx;
|
|
|
|
oy = y2 - cposy;
|
2021-01-04 11:36:54 +00:00
|
|
|
x2 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
|
2021-03-24 19:28:58 +00:00
|
|
|
y2 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
drawlinergb(x1 + (xdim << 11), y1 + (ydim << 11),
|
|
|
|
x2 + (xdim << 11), y2 + (ydim << 11), col);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 32: // Floor sprite
|
|
|
|
if (automapMode == am_overlay)
|
|
|
|
{
|
2021-12-24 20:54:43 +00:00
|
|
|
tilenum = actor->spr.picnum;
|
|
|
|
xoff = (int)tileLeftOffset(tilenum) + (int)actor->spr.xoffset;
|
|
|
|
yoff = (int)tileTopOffset(tilenum) + (int)actor->spr.yoffset;
|
|
|
|
if ((actor->spr.cstat & CSTAT_SPRITE_XFLIP) > 0)
|
2020-09-06 19:50:02 +00:00
|
|
|
xoff = -xoff;
|
2021-12-24 20:54:43 +00:00
|
|
|
if ((actor->spr.cstat & CSTAT_SPRITE_YFLIP) > 0)
|
2020-09-06 19:50:02 +00:00
|
|
|
yoff = -yoff;
|
|
|
|
|
2021-12-24 20:54:43 +00:00
|
|
|
k = actor->spr.ang;
|
2020-11-15 09:41:01 +00:00
|
|
|
cosang = bcos(k);
|
|
|
|
sinang = bsin(k);
|
2020-11-20 07:18:26 +00:00
|
|
|
xspan = tileWidth(tilenum);
|
2021-12-24 20:54:43 +00:00
|
|
|
xrepeat = actor->spr.xrepeat;
|
2020-11-20 07:18:26 +00:00
|
|
|
yspan = tileHeight(tilenum);
|
2021-12-24 20:54:43 +00:00
|
|
|
yrepeat = actor->spr.yrepeat;
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
dax = ((xspan >> 1) + xoff) * xrepeat;
|
|
|
|
day = ((yspan >> 1) + yoff) * yrepeat;
|
2021-01-04 11:36:54 +00:00
|
|
|
x1 = sprx + MulScale(sinang, dax, 16) + MulScale(cosang, day, 16);
|
|
|
|
y1 = spry + MulScale(sinang, day, 16) - MulScale(cosang, dax, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
l = xspan * xrepeat;
|
2021-01-04 11:36:54 +00:00
|
|
|
x2 = x1 - MulScale(sinang, l, 16);
|
|
|
|
y2 = y1 + MulScale(cosang, l, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
l = yspan * yrepeat;
|
2021-01-04 11:36:54 +00:00
|
|
|
k = -MulScale(cosang, l, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
x3 = x2 + k;
|
|
|
|
x4 = x1 + k;
|
2021-01-04 11:36:54 +00:00
|
|
|
k = -MulScale(sinang, l, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
y3 = y2 + k;
|
|
|
|
y4 = y1 + k;
|
|
|
|
|
|
|
|
ox = x1 - cposx;
|
|
|
|
oy = y1 - cposy;
|
2021-01-04 11:36:54 +00:00
|
|
|
x1 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
|
2021-03-24 19:28:58 +00:00
|
|
|
y1 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
ox = x2 - cposx;
|
|
|
|
oy = y2 - cposy;
|
2021-01-04 11:36:54 +00:00
|
|
|
x2 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
|
2021-03-24 19:28:58 +00:00
|
|
|
y2 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
ox = x3 - cposx;
|
|
|
|
oy = y3 - cposy;
|
2021-01-04 11:36:54 +00:00
|
|
|
x3 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
|
2021-03-24 19:28:58 +00:00
|
|
|
y3 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
ox = x4 - cposx;
|
|
|
|
oy = y4 - cposy;
|
2021-01-04 11:36:54 +00:00
|
|
|
x4 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
|
2021-03-24 19:28:58 +00:00
|
|
|
y4 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
drawlinergb(x1 + (xdim << 11), y1 + (ydim << 11),
|
|
|
|
x2 + (xdim << 11), y2 + (ydim << 11), col);
|
|
|
|
|
|
|
|
drawlinergb(x2 + (xdim << 11), y2 + (ydim << 11),
|
|
|
|
x3 + (xdim << 11), y3 + (ydim << 11), col);
|
|
|
|
|
|
|
|
drawlinergb(x3 + (xdim << 11), y3 + (ydim << 11),
|
|
|
|
x4 + (xdim << 11), y4 + (ydim << 11), col);
|
|
|
|
|
|
|
|
drawlinergb(x4 + (xdim << 11), y4 + (ydim << 11),
|
|
|
|
x1 + (xdim << 11), y1 + (ydim << 11), col);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-15 16:07:35 +00:00
|
|
|
}
|
|
|
|
return true;
|
2020-09-06 19:50:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 18:08:50 +00:00
|
|
|
void GameInterface::processSprites(tspritetype* tsprite, int& spritesortcnt, int viewx, int viewy, int viewz, binangle viewang, double smoothRatio)
|
2021-03-26 00:35:23 +00:00
|
|
|
{
|
2021-04-02 08:28:40 +00:00
|
|
|
analyzesprites(tsprite, spritesortcnt, viewx, viewy, viewz, viewang.asbuild());
|
|
|
|
post_analyzesprites(tsprite, spritesortcnt);
|
2021-03-26 00:35:23 +00:00
|
|
|
}
|
|
|
|
|
2020-09-06 19:50:02 +00:00
|
|
|
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|