Merge branch 'SRB2-CHAT' into '2122-version'

Chat and other multiplayer quality of life improvements.

See merge request STJr/SRB2!398
This commit is contained in:
Digiku 2018-12-23 17:53:54 -05:00
commit 7a64e3d1a8
30 changed files with 1984 additions and 262 deletions

View File

@ -128,11 +128,16 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}
// whether to use console background picture, or translucent mode
static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"},
{3, "Red"}, {4, "Orange"}, {5, "Yellow"},
{6, "Green"}, {7, "Blue"}, {8, "Cyan"},
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"},
{3, "Brown"}, {4, "Pink"}, {5, "Raspberry"},
{6, "Red"}, {7, "Creamsicle"}, {8, "Orange"},
{9, "Gold"}, {10,"Yellow"}, {11,"Emerald"},
{12,"Green"}, {13,"Cyan"}, {14,"Steel"},
{15,"Periwinkle"}, {16,"Blue"}, {17,"Purple"},
{18,"Lavender"},
{0, NULL}};
consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
consvar_t cons_backcolor = {"con_backcolor", "Black", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
static void CON_Print(char *msg);
@ -238,29 +243,41 @@ void CON_SetupBackColormap(void)
UINT16 i, palsum;
UINT8 j, palindex;
UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE);
INT32 shift = 6;
if (!consolebgmap)
consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL);
switch (cons_backcolor.value)
{
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 63; break; // Brown
case 3: palindex = 143; break; // Red
case 4: palindex = 95; break; // Orange
case 5: palindex = 111; break; // Yellow
case 6: palindex = 175; break; // Green
case 7: palindex = 239; break; // Blue
case 8: palindex = 219; break; // Cyan
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 47; break; // Sepia
case 3: palindex = 63; break; // Brown
case 4: palindex = 150; shift = 7; break; // Pink
case 5: palindex = 127; shift = 7; break; // Raspberry
case 6: palindex = 143; break; // Red
case 7: palindex = 86; shift = 7; break; // Creamsicle
case 8: palindex = 95; break; // Orange
case 9: palindex = 119; shift = 7; break; // Gold
case 10: palindex = 111; break; // Yellow
case 11: palindex = 191; shift = 7; break; // Emerald
case 12: palindex = 175; break; // Green
case 13: palindex = 219; break; // Cyan
case 14: palindex = 207; shift = 7; break; // Steel
case 15: palindex = 230; shift = 7; break; // Periwinkle
case 16: palindex = 239; break; // Blue
case 17: palindex = 199; shift = 7; break; // Purple
case 18: palindex = 255; shift = 7; break; // Lavender
// Default green
default: palindex = 175; break;
}
// setup background colormap
for (i = 0, j = 0; i < 768; i += 3, j++)
{
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> 6;
palsum = (pal[i] + pal[i+1] + pal[i+2]) >> shift;
consolebgmap[j] = (UINT8)(palindex - palsum);
}
}
@ -839,7 +856,7 @@ boolean CON_Responder(event_t *ev)
// ...why shouldn't it eat the key? if it doesn't, it just means you
// can control Sonic from the console, which is silly
return true; //return false;
return true;//return false;
}
// command completion forward (tab) and backward (shift-tab)
@ -1033,15 +1050,30 @@ boolean CON_Responder(event_t *ev)
else if (key == KEY_KPADSLASH)
key = '/';
if (shiftdown)
// capslock
if (key == KEY_CAPSLOCK) // it's a toggle.
{
if (capslock)
capslock = false;
else
capslock = true;
return true;
}
if (key >= 'a' && key <= 'z')
{
if (capslock ^ shiftdown)
key = shiftxform[key];
}
else if (shiftdown)
key = shiftxform[key];
// enter a char into the command prompt
if (key < 32 || key > 127)
return true; // even if key can't be printed, eat it anyway
return true;
// add key to cmd line here
if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers
if (key >= 'A' && key <= 'Z' && !(shiftdown ^ capslock)) //this is only really necessary for dedicated servers
key = key + 'a' - 'A';
if (input_sel != input_cur)
@ -1419,8 +1451,8 @@ static void CON_DrawHudlines(void)
if (con_hudlines <= 0)
return;
if (chat_on)
y = charheight; // leave place for chat input in the first row of text
if (chat_on && OLDCHAT)
y = charheight; // leave place for chat input in the first row of text (only do it if consolechat is on.)
else
y = 0;

View File

@ -2762,7 +2762,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
msg = KICK_MSG_CON_FAIL;
}
CONS_Printf("\x82%s ", player_names[pnum]);
//CONS_Printf("\x82%s ", player_names[pnum]);
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
@ -2779,17 +2779,17 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
switch (msg)
{
case KICK_MSG_GO_AWAY:
CONS_Printf(M_GetText("has been kicked (Go away)\n"));
HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
kickreason = KR_KICK;
break;
#ifdef NEWPING
case KICK_MSG_PING_HIGH:
CONS_Printf(M_GetText("left the game (Broke ping limit)\n"));
HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
kickreason = KR_PINGLIMIT;
break;
#endif
case KICK_MSG_CON_FAIL:
CONS_Printf(M_GetText("left the game (Synch failure)\n"));
HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
kickreason = KR_SYNCH;
if (M_CheckParm("-consisdump")) // Helps debugging some problems
@ -2826,26 +2826,26 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
}
break;
case KICK_MSG_TIMEOUT:
CONS_Printf(M_GetText("left the game (Connection timeout)\n"));
HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false);
kickreason = KR_TIMEOUT;
break;
case KICK_MSG_PLAYER_QUIT:
if (netgame) // not splitscreen/bots
CONS_Printf(M_GetText("left the game\n"));
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
kickreason = KR_LEAVE;
break;
case KICK_MSG_BANNED:
CONS_Printf(M_GetText("has been banned (Don't come back)\n"));
HU_AddChatText(va("\x82*%s has been banned (Don't come back)", player_names[pnum]), false);
kickreason = KR_BAN;
break;
case KICK_MSG_CUSTOM_KICK:
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
CONS_Printf(M_GetText("has been kicked (%s)\n"), reason);
HU_AddChatText(va("\x82*%s has been kicked (%s)", player_names[pnum], reason), false);
kickreason = KR_KICK;
break;
case KICK_MSG_CUSTOM_BAN:
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
CONS_Printf(M_GetText("has been banned (%s)\n"), reason);
HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false);
kickreason = KR_BAN;
break;
}
@ -3119,9 +3119,6 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (newplayernum+1 > doomcom->numslots)
doomcom->numslots = (INT16)(newplayernum+1);
if (netgame)
CONS_Printf(M_GetText("Player %d has joined the game (node %d)\n"), newplayernum+1, node);
// the server is creating my player
if (node == mynode)
{
@ -3143,11 +3140,17 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
D_SendPlayerConfig();
addedtogame = true;
}
else if (server && netgame && cv_showjoinaddress.value)
if (netgame)
{
const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
CONS_Printf(M_GetText("Player Address is %s\n"), address);
if (server && cv_showjoinaddress.value)
{
const char *address;
if (I_GetNodeAddress && (address = I_GetNodeAddress(node)) != NULL)
HU_AddChatText(va("\x82*Player %d has joined the game (node %d) (%s)", newplayernum+1, node, address), false); // merge join notification + IP to avoid clogging console/chat.
}
else
HU_AddChatText(va("\x82*Player %d has joined the game (node %d)", newplayernum+1, node), false); // if you don't wanna see the join address.
}
if (server && multiplayer && motd[0] != '\0')

View File

@ -178,6 +178,7 @@ void D_PostEvent_end(void) {};
UINT8 shiftdown = 0; // 0x1 left, 0x2 right
UINT8 ctrldown = 0; // 0x1 left, 0x2 right
UINT8 altdown = 0; // 0x1 left, 0x2 right
boolean capslock = 0; // gee i wonder what this does.
//
// D_ModifierKeyResponder
// Sets global shift/ctrl/alt variables, never actually eats events

View File

@ -22,6 +22,7 @@
#define MAXNETNODES 32
#define BROADCASTADDR MAXNETNODES
#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer
//#define NETSPLITSCREEN // Kart's splitscreen netgame feature
#define STATLENGTH (TICRATE*2)

View File

@ -673,6 +673,14 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_usegamma);
// m_menu.c
CV_RegisterVar(&cv_compactscoreboard);
CV_RegisterVar(&cv_chatheight);
CV_RegisterVar(&cv_chatwidth);
CV_RegisterVar(&cv_chattime);
CV_RegisterVar(&cv_chatspamprotection);
CV_RegisterVar(&cv_chatbacktint);
CV_RegisterVar(&cv_consolechat);
CV_RegisterVar(&cv_chatnotifications);
CV_RegisterVar(&cv_crosshair);
CV_RegisterVar(&cv_crosshair2);
CV_RegisterVar(&cv_alwaysfreelook);
@ -988,8 +996,8 @@ static void SetPlayerName(INT32 playernum, char *newname)
if (strcasecmp(newname, player_names[playernum]) != 0)
{
if (netgame)
CONS_Printf(M_GetText("%s renamed to %s\n"),
player_names[playernum], newname);
HU_AddChatText(va("\x82*%s renamed to %s", player_names[playernum], newname), false);
strcpy(player_names[playernum], newname);
}
}

View File

@ -8338,7 +8338,6 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, token);
return 1;
}
return 0;
}

View File

@ -410,6 +410,7 @@ extern INT32 cv_debug;
// Modifier key variables, accessible anywhere
extern UINT8 shiftdown, ctrldown, altdown;
extern boolean capslock;
// if we ever make our alloc stuff...
#define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL)

View File

@ -347,6 +347,37 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
#endif
#endif
// don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler.
// it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on!
consvar_t cv_compactscoreboard= {"compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// chat timer thingy
static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}};
consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// chatwidth
static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}};
consvar_t cv_chatwidth = {"chatwidth", "128", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// chatheight
static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
consvar_t cv_chatheight= {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// chat notifications (do you want to hear beeps? I'd understand if you didn't.)
consvar_t cv_chatnotifications= {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// chat spam protection (why would you want to disable that???)
consvar_t cv_chatspamprotection= {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// minichat text background
consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.)
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -3646,7 +3677,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
unlocktriggers = 0;
// clear itemfinder, just in case
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
CV_StealthSetValue(&cv_itemfinder, 0);
}

View File

@ -54,6 +54,7 @@ extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard di
extern INT16 rw_maximums[NUM_WEAPONS];
// used in game menu
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
extern consvar_t cv_crosshair, cv_crosshair2;
extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove;
extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2;

View File

@ -790,6 +790,110 @@ void HWR_drawAMline(const fline_t *fl, INT32 color)
HWD.pfnDraw2DLine(&v1, &v2, color_rgba);
}
// -------------------+
// HWR_DrawConsoleFill : draw flat coloured transparent rectangle because that's cool, and hw sucks less than sw for that.
// -------------------+
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options)
{
FOutVector v[4];
FSurfaceInfo Surf;
float fx, fy, fw, fh;
if (w < 0 || h < 0)
return; // consistency w/ software
// 3--2
// | /|
// |/ |
// 0--1
fx = (float)x;
fy = (float)y;
fw = (float)w;
fh = (float)h;
if (!(options & V_NOSCALESTART))
{
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{
RGBA_t rgbaColour = V_GetColor(color);
FRGBAFloat clearColour;
clearColour.red = (float)rgbaColour.s.red / 255;
clearColour.green = (float)rgbaColour.s.green / 255;
clearColour.blue = (float)rgbaColour.s.blue / 255;
clearColour.alpha = 1;
HWD.pfnClearBuffer(true, false, &clearColour);
return;
}
fx *= dupx;
fy *= dupy;
fw *= dupx;
fh *= dupy;
if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f)
{
if (options & V_SNAPTORIGHT)
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
else if (!(options & V_SNAPTOLEFT))
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
}
if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f)
{
// same thing here
if (options & V_SNAPTOBOTTOM)
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
else if (!(options & V_SNAPTOTOP))
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
}
}
if (fx >= vid.width || fy >= vid.height)
return;
if (fx < 0)
{
fw += fx;
fx = 0;
}
if (fy < 0)
{
fh += fy;
fy = 0;
}
if (fw <= 0 || fh <= 0)
return;
if (fx + fw > vid.width)
fw = (float)vid.width - fx;
if (fy + fh > vid.height)
fh = (float)vid.height - fy;
fx = -1 + fx / (vid.width / 2);
fy = 1 - fy / (vid.height / 2);
fw = fw / (vid.width / 2);
fh = fh / (vid.height / 2);
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
v[0].y = v[1].y = fy;
v[2].y = v[3].y = fy - fh;
//Hurdler: do we still use this argb color? if not, we should remove it
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].sow = v[3].sow = 0.0f;
v[2].sow = v[1].sow = 1.0f;
v[0].tow = v[1].tow = 0.0f;
v[2].tow = v[3].tow = 1.0f;
Surf.FlatColor.rgba = UINT2RGBA(color);
Surf.FlatColor.s.alpha = 0x80;
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
}
// -----------------+
// HWR_DrawFill : draw flat coloured rectangle, with no texture

View File

@ -51,6 +51,7 @@ void HWR_CreatePlanePolygons(INT32 bspnum);
void HWR_CreateStaticLightmaps(INT32 bspnum);
void HWR_PrepLevelCache(size_t pnumtextures);
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right.
void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum);
void HWR_AddCommands(void);

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,20 @@ typedef struct
// chat stuff
//------------------------------------
#define HU_MAXMSGLEN 224
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
#ifdef NETSPLITSCREEN
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640)
#else
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640 || splitscreen)
#endif
#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot.
#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted.
// some functions
void HU_AddChatText(const char *text, boolean playsound);
// set true when entering a chat message
extern boolean chat_on;
extern patch_t *hu_font[HU_FONTSIZE], *tny_font[HU_FONTSIZE];
extern patch_t *tallnum[10];
@ -72,9 +86,6 @@ extern patch_t *bmatcico;
extern patch_t *tagico;
extern patch_t *tallminus;
// set true when entering a chat message
extern boolean chat_on;
// set true whenever the tab rankings are being shown for any reason
extern boolean hu_showscores;
@ -87,12 +98,12 @@ void HU_LoadGraphics(void);
void HU_Start(void);
boolean HU_Responder(event_t *ev);
void HU_Ticker(void);
void HU_Drawer(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);
void HU_clearChatChars(void);
void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // Lat': Ping drawer for scoreboard.
void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer);
void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);

View File

@ -23,7 +23,7 @@
#include "m_random.h"
#include "s_sound.h"
#include "g_game.h"
#include "hu_stuff.h"
#include "hu_stuff.h" // HU_AddChatText
#include "console.h"
#include "d_netcmd.h" // IsPlayerAdmin
@ -91,6 +91,51 @@ static int lib_print(lua_State *L)
return 0;
}
// Print stuff in the chat, or in the console if we can't.
static int lib_chatprint(lua_State *L)
{
const char *str = luaL_checkstring(L, 1); // retrieve string
boolean sound = lua_optboolean(L, 2); // retrieve sound boolean
int len = strlen(str);
if (str == NULL) // error if we don't have a string!
return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprint"));
if (len > 255) // string is too long!!!
return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
HU_AddChatText(str, sound);
return 0;
}
// Same as above, but do it for only one player.
static int lib_chatprintf(lua_State *L)
{
int n = lua_gettop(L); /* number of arguments */
const char *str = luaL_checkstring(L, 2); // retrieve string
boolean sound = lua_optboolean(L, 3); // sound?
int len = strlen(str);
player_t *plr;
if (n < 2)
return luaL_error(L, "chatprintf requires at least two arguments: player and text.");
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player
if (!plr)
return LUA_ErrInvalid(L, "player_t");
if (plr != &players[consoleplayer])
return 0;
if (str == NULL) // error if we don't have a string!
return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("chatprintf"));
if (len > 255) // string is too long!!!
return luaL_error(L, "String exceeds the 255 characters limit of the chat buffer.");
HU_AddChatText(str, sound);
return 0;
}
static int lib_evalMath(lua_State *L)
{
const char *word = luaL_checkstring(L, 1);
@ -1709,7 +1754,7 @@ static int lib_sStartSound(lua_State *L)
const void *origin = NULL;
sfxenum_t sound_id = luaL_checkinteger(L, 2);
player_t *player = NULL;
NOHUD
//NOHUD // kys @whoever did this.
if (sound_id >= NUMSFX)
return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
if (!lua_isnil(L, 1))
@ -1725,7 +1770,12 @@ static int lib_sStartSound(lua_State *L)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
if (hud_running)
origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error.
S_StartSound(origin, sound_id);
}
return 0;
}
@ -2052,6 +2102,8 @@ static int lib_gTicsToMilliseconds(lua_State *L)
static luaL_Reg lib[] = {
{"print", lib_print},
{"chatprint", lib_chatprint},
{"chatprintf", lib_chatprintf},
{"EvalMath", lib_evalMath},
{"IsPlayerAdmin", lib_isPlayerAdmin},

View File

@ -952,7 +952,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
return hooked;
}
// Hook for player chat
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
{
hook_p hookp;
@ -1005,6 +1005,7 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
return hooked;
}
// Hook for hurt messages
boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
{

View File

@ -292,7 +292,7 @@ menu_t OP_SoundOptionsDef;
//Misc
menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef;
menu_t OP_GameOptionsDef, OP_ServerOptionsDef;
menu_t OP_GameOptionsDef, OP_ChatOptionsDef, OP_ServerOptionsDef;
menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef;
menu_t OP_MonitorToggleDef;
static void M_ScreenshotOptions(INT32 choice);
@ -1299,22 +1299,36 @@ static menuitem_t OP_GameOptionsMenu[] =
{IT_STRING | IT_CVAR | IT_CV_STRING,
NULL, "Master server", &cv_masterserver, 10},
#endif
{IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40},
{IT_STRING | IT_SUBMENU, NULL, "Chat Options...", &OP_ChatOptionsDef, 40},
{IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 50},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
NULL, "HUD Visibility", &cv_translucenthud, 50},
{IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 60},
NULL, "HUD Visibility", &cv_translucenthud, 60},
{IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 70},
{IT_STRING | IT_CVAR, NULL, "Always Compact Rankings", &cv_compactscoreboard, 80},
#ifdef SEENAMES
{IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 80},
{IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 90},
#endif
{IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 90},
{IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 100},
{IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 100},
{IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,110},
{IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 120},
{IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 110},
{IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,120},
{IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 130},
{IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 140},
};
static menuitem_t OP_ChatOptionsMenu[] =
{
{IT_STRING | IT_CVAR, NULL, "Chat Mode", &cv_consolechat, 10},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Width", &cv_chatwidth, 30},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Chat Box Height", &cv_chatheight, 40},
{IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 50},
{IT_STRING | IT_CVAR, NULL, "Chat Notifications", &cv_chatnotifications, 60},
{IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70},
{IT_STRING | IT_CVAR, NULL, "Chat background tint", &cv_chatbacktint, 80},
};
static menuitem_t OP_ServerOptionsMenu[] =
{
{IT_STRING | IT_SUBMENU, NULL, "General netgame options...", &OP_NetgameOptionsDef, 10},
@ -1709,6 +1723,7 @@ menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu,
menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30);
menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30);
menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 30, 30);
menu_t OP_MonitorToggleDef =
{
"M_SERVER",

View File

@ -1531,6 +1531,10 @@ boolean M_ScreenshotResponder(event_t *ev)
return false;
ch = ev->data1;
if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus!
return false;
if (ch == KEY_F8 || ch == gamecontrol[gc_screenshot][0] || ch == gamecontrol[gc_screenshot][1]) // remappable F8
M_ScreenShot();
else if (ch == KEY_F9 || ch == gamecontrol[gc_recordgif][0] || ch == gamecontrol[gc_recordgif][1]) // remappable F9

View File

@ -382,30 +382,26 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum)
Z_Free(data);
}
//
// Computes the line length in fracunits, the OpenGL render needs this
//
/** Computes the length of a seg in fracunits.
* This is needed for splats.
*
* \param seg Seg to compute length for.
* \return Length in fracunits.
*/
fixed_t P_SegLength(seg_t *seg)
{
fixed_t dx, dy;
// make a vector (start at origin)
dx = seg->v2->x - seg->v1->x;
dy = seg->v2->y - seg->v1->y;
return FixedHypot(dx, dy);
INT64 dx = (seg->v2->x - seg->v1->x)>>1;
INT64 dy = (seg->v2->y - seg->v1->y)>>1;
return FixedHypot(dx, dy)<<1;
}
#ifdef HWRENDER
static inline float P_SegLengthf(seg_t *seg)
/** Computes the length of a seg as a float.
* This is needed for OpenGL.
*
* \param seg Seg to compute length for.
* \return Length as a float.
*/
static inline float P_SegLengthFloat(seg_t *seg)
{
float dx, dy;
@ -441,11 +437,11 @@ static void P_LoadRawSegs(UINT8 *data, size_t i)
li->v1 = &vertexes[SHORT(ml->v1)];
li->v2 = &vertexes[SHORT(ml->v2)];
#ifdef HWRENDER // not win32 only 19990829 by Kin
// used for the hardware render
if (rendermode != render_soft && rendermode != render_none)
li->length = P_SegLength(li);
#ifdef HWRENDER
if (rendermode == render_opengl)
{
li->flength = P_SegLengthf(li);
li->flength = P_SegLengthFloat(li);
//Hurdler: 04/12/2000: for now, only used in hardware mode
li->lightmaps = NULL; // list of static lightmap for this seg
}
@ -2632,7 +2628,7 @@ static boolean P_CanSave(void)
{
// Saving is completely ignored under these conditions:
if ((cursaveslot < 0) // Playing without saving
|| (!modifiedgame || savemoddata) // Game is modified
|| (!modifiedgame || savemoddata) // Game is modified
|| (netgame || multiplayer) // Not in single-player
|| (demoplayback || demorecording || metalrecording) // Currently in demo
|| (players[consoleplayer].lives <= 0) // Completely dead
@ -2643,7 +2639,7 @@ static boolean P_CanSave(void)
return true; // Saving should ALWAYS happen!
else if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_NEVER)
return false; // Saving should NEVER happen!
// Default condition: In a non-hidden map, at the beginning of a zone or on a completed save-file, and not on save reload.
return (!(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)
&& (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete)

View File

@ -403,17 +403,17 @@ static void R_AddLine(seg_t *line)
{
INT32 x1, x2;
angle_t angle1, angle2, span, tspan;
static sector_t tempsec; // ceiling/water hack
static sector_t tempsec;
portalline = false;
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
// big room fix
angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y);
angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y);
curline = line;
portalline = false;
// OPTIMIZE: quickly reject orthogonal back sides.
angle1 = R_PointToAngle(line->v1->x, line->v1->y);
angle2 = R_PointToAngle(line->v2->x, line->v2->y);
// Clip to view edges.
span = angle1 - angle2;
@ -592,69 +592,35 @@ INT32 checkcoord[12][4] =
{2, 1, 3, 0}
};
static boolean R_CheckBBox(fixed_t *bspcoord)
static boolean R_CheckBBox(const fixed_t *bspcoord)
{
INT32 boxpos, sx1, sx2;
fixed_t px1, py1, px2, py2;
angle_t angle1, angle2, span, tspan;
angle_t angle1, angle2;
INT32 sx1, sx2, boxpos;
const INT32* check;
cliprange_t *start;
// Find the corners of the box that define the edges from current viewpoint.
if (viewx <= bspcoord[BOXLEFT])
boxpos = 0;
else if (viewx < bspcoord[BOXRIGHT])
boxpos = 1;
else
boxpos = 2;
if (viewy >= bspcoord[BOXTOP])
boxpos |= 0;
else if (viewy > bspcoord[BOXBOTTOM])
boxpos |= 1<<2;
else
boxpos |= 2<<2;
if (boxpos == 5)
if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
return true;
px1 = bspcoord[checkcoord[boxpos][0]];
py1 = bspcoord[checkcoord[boxpos][1]];
px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]];
check = checkcoord[boxpos];
// check clip list for an open space
angle1 = R_PointToAngle2(viewx>>1, viewy>>1, px1>>1, py1>>1) - viewangle;
angle2 = R_PointToAngle2(viewx>>1, viewy>>1, px2>>1, py2>>1) - viewangle;
// big room fix
angle1 = R_PointToAngleEx(viewx, viewy, bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
angle2 = R_PointToAngleEx(viewx, viewy, bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
span = angle1 - angle2;
// Sitting on a line?
if (span >= ANGLE_180)
return true;
tspan = angle1 + clipangle;
if (tspan > doubleclipangle)
if ((signed)angle1 < (signed)angle2)
{
tspan -= doubleclipangle;
// Totally off the left edge?
if (tspan >= span)
return false;
angle1 = clipangle;
if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270))
angle1 = ANGLE_180-1;
else
angle2 = -ANGLE_180;
}
tspan = clipangle - angle2;
if (tspan > doubleclipangle)
{
tspan -= doubleclipangle;
// Totally off the left edge?
if (tspan >= span)
return false;
angle2 = -(signed)clipangle;
}
if ((signed)angle2 >= (signed)clipangle) return false;
if ((signed)angle1 <= -(signed)clipangle) return false;
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle;
if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle;
// Find the first clippost that touches the source post (adjacent pixels are touching).
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
@ -663,9 +629,7 @@ static boolean R_CheckBBox(fixed_t *bspcoord)
sx2 = viewangletox[angle2];
// Does not cross a pixel.
if (sx1 == sx2)
return false;
sx2--;
if (sx1 >= sx2) return false;
start = solidsegs;
while (start->last < sx2)

View File

@ -573,6 +573,7 @@ typedef struct seg_s
sector_t *frontsector;
sector_t *backsector;
fixed_t length; // precalculated seg length
#ifdef HWRENDER
// new pointers so that AdjustSegs doesn't mess with v1/v2
void *pv1; // polyvertex_t

View File

@ -355,6 +355,29 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y)
return R_PointToDist2(viewx, viewy, x, y);
}
angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1)
{
INT64 dx = x1-x2;
INT64 dy = y1-y2;
if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX)
{
x1 = (int)(dx / 2 + x2);
y1 = (int)(dy / 2 + y2);
}
return (y1 -= y2, (x1 -= x2) || y1) ?
x1 >= 0 ?
y1 >= 0 ?
(x1 > y1) ? tantoangle[SlopeDivEx(y1,x1)] : // octant 0
ANGLE_90-tantoangle[SlopeDivEx(x1,y1)] : // octant 1
x1 > (y1 = -y1) ? 0-tantoangle[SlopeDivEx(y1,x1)] : // octant 8
ANGLE_270+tantoangle[SlopeDivEx(x1,y1)] : // octant 7
y1 >= 0 ? (x1 = -x1) > y1 ? ANGLE_180-tantoangle[SlopeDivEx(y1,x1)] : // octant 3
ANGLE_90 + tantoangle[SlopeDivEx(x1,y1)] : // octant 2
(x1 = -x1) > (y1 = -y1) ? ANGLE_180+tantoangle[SlopeDivEx(y1,x1)] : // octant 4
ANGLE_270-tantoangle[SlopeDivEx(x1,y1)] : // octant 5
0;
}
//
// R_ScaleFromGlobalAngle
// Returns the texture mapping scale for the current line (horizontal span)

View File

@ -58,6 +58,7 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
angle_t R_PointToAngle(fixed_t x, fixed_t y);
angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1);
fixed_t R_PointToDist(fixed_t x, fixed_t y);
fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);

View File

@ -1647,6 +1647,23 @@ static void R_RenderSegLoop (void)
}
}
// Uses precalculated seg->length
static INT64 R_CalcSegDist(seg_t* seg, INT64 x2, INT64 y2)
{
if (!seg->linedef->dy)
return llabs(y2 - seg->v1->y);
else if (!seg->linedef->dx)
return llabs(x2 - seg->v1->x);
else
{
INT64 dx = (seg->v2->x)-(seg->v1->x);
INT64 dy = (seg->v2->y)-(seg->v1->y);
INT64 vdx = x2-(seg->v1->x);
INT64 vdy = y2-(seg->v1->y);
return ((dy*vdx)-(dx*vdy))/(seg->length);
}
}
//
// R_StoreWallRange
// A wall segment will be drawn
@ -1657,6 +1674,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
fixed_t hyp;
fixed_t sineval;
angle_t distangle, offsetangle;
boolean longboi;
#ifndef ESLOPE
fixed_t vtop;
#endif
@ -1702,10 +1720,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
offsetangle = ANGLE_90;
distangle = ANGLE_90 - offsetangle;
hyp = R_PointToDist (curline->v1->x, curline->v1->y);
sineval = FINESINE(distangle>>ANGLETOFINESHIFT);
rw_distance = FixedMul (hyp, sineval);
hyp = R_PointToDist(curline->v1->x, curline->v1->y);
rw_distance = FixedMul(hyp, sineval);
longboi = (hyp >= INT32_MAX);
// big room fix
if (longboi)
rw_distance = (fixed_t)R_CalcSegDist(curline,viewx,viewy);
ds_p->x1 = rw_x = start;
ds_p->x2 = stop;
@ -2562,8 +2585,18 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (offsetangle > ANGLE_90)
offsetangle = ANGLE_90;
sineval = FINESINE(offsetangle >>ANGLETOFINESHIFT);
rw_offset = FixedMul (hyp, sineval);
sineval = FINESINE(offsetangle>>ANGLETOFINESHIFT);
rw_offset = FixedMul(hyp, sineval);
// big room fix
if (longboi)
{
INT64 dx = (curline->v2->x)-(curline->v1->x);
INT64 dy = (curline->v2->y)-(curline->v1->y);
INT64 vdx = viewx-(curline->v1->x);
INT64 vdy = viewy-(curline->v1->y);
rw_offset = ((dx*vdx-dy*vdy))/(curline->length);
}
if (rw_normalangle-rw_angle1 < ANGLE_180)
rw_offset = -rw_offset;

View File

@ -297,7 +297,7 @@
</ClCompile>
<ClCompile Include="..\i_tcp.c" />
<ClCompile Include="..\lua_baselib.c" />
<ClCompile Include="..\lua_blockmaplib.c" />
<ClCompile Include="..\lua_blockmaplib.c" />
<ClCompile Include="..\lua_consolelib.c" />
<ClCompile Include="..\lua_hooklib.c" />
<ClCompile Include="..\lua_hudlib.c" />

View File

@ -200,7 +200,10 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
}
// Reposition window only in windowed mode
SDL_SetWindowSize(window, width, height);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_SetWindowPosition(window,
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
);
}
}
else

View File

@ -37,6 +37,15 @@ unsigned SlopeDiv(unsigned num, unsigned den)
return ans <= SLOPERANGE ? ans : SLOPERANGE;
}
UINT64 SlopeDivEx(unsigned int num, unsigned int den)
{
UINT64 ans;
if (den < 512)
return SLOPERANGE;
ans = ((UINT64)num<<3)/(den>>8);
return ans <= SLOPERANGE ? ans : SLOPERANGE;
}
fixed_t AngleFixed(angle_t af)
{
angle_t wa = ANGLE_180;

View File

@ -83,6 +83,8 @@ extern angle_t tantoangle[SLOPERANGE+1];
// Utility function, called by R_PointToAngle.
FUNCMATH unsigned SlopeDiv(unsigned num, unsigned den);
// Only called by R_PointToAngleEx
UINT64 SlopeDivEx(unsigned int num, unsigned int den);
// 360 - angle_t(ANGLE_45) = ANGLE_315
FUNCMATH FUNCINLINE static ATTRINLINE angle_t InvAngle(angle_t a)

View File

@ -841,6 +841,145 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
memset(dest, c, w * vid.bpp);
}
#ifdef HWRENDER
// This is now a function since it's otherwise repeated 2 times and honestly looks retarded:
static UINT32 V_GetHWConsBackColor(void)
{
UINT32 hwcolor;
switch (cons_backcolor.value)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x80808000; break; // Gray
case 2: hwcolor = 0xdeb88700; break; // Sepia
case 3: hwcolor = 0x40201000; break; // Brown
case 4: hwcolor = 0xfa807200; break; // Pink
case 5: hwcolor = 0xff69b400; break; // Raspberry
case 6: hwcolor = 0xff000000; break; // Red
case 7: hwcolor = 0xffd68300; break; // Creamsicle
case 8: hwcolor = 0xff800000; break; // Orange
case 9: hwcolor = 0xdaa52000; break; // Gold
case 10: hwcolor = 0x80800000; break; // Yellow
case 11: hwcolor = 0x00ff0000; break; // Emerald
case 12: hwcolor = 0x00800000; break; // Green
case 13: hwcolor = 0x4080ff00; break; // Cyan
case 14: hwcolor = 0x4682b400; break; // Steel
case 15: hwcolor = 0x1e90ff00; break; // Periwinkle
case 16: hwcolor = 0x0000ff00; break; // Blue
case 17: hwcolor = 0xff00ff00; break; // Purple
case 18: hwcolor = 0xee82ee00; break; // Lavender
// Default green
default: hwcolor = 0x00800000; break;
}
return hwcolor;
}
#endif
// THANK YOU MPC!!!
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
{
UINT8 *dest;
INT32 u, v;
UINT8 *fadetable;
UINT32 alphalevel = 0;
if (rendermode == render_none)
return;
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
{
UINT32 hwcolor = V_GetHWConsBackColor();
HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this.
return;
}
#endif
if (!(c & V_NOSCALESTART))
{
INT32 dupx = vid.dupx, dupy = vid.dupy;
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp);
return;
}
x *= dupx;
y *= dupy;
w *= dupx;
h *= dupy;
// Center it if necessary
if (vid.width != BASEVIDWIDTH * dupx)
{
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if (c & V_SNAPTORIGHT)
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(c & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if (c & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(c & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
}
}
if (x >= vid.width || y >= vid.height)
return; // off the screen
if (x < 0) {
w += x;
x = 0;
}
if (y < 0) {
h += y;
y = 0;
}
if (w <= 0 || h <= 0)
return; // zero width/height wouldn't draw anything
if (x + w > vid.width)
w = vid.width-x;
if (y + h > vid.height)
h = vid.height-y;
dest = screens[0] + y*vid.width + x;
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
{
if (alphalevel == 13)
alphalevel = hudminusalpha[cv_translucenthud.value];
else if (alphalevel == 14)
alphalevel = 10 - cv_translucenthud.value;
else if (alphalevel == 15)
alphalevel = hudplusalpha[cv_translucenthud.value];
if (alphalevel >= 10)
return; // invis
}
c &= 255;
// Jimita (12-04-2018)
w = min(w, vid.width);
h = min(h, vid.height);
fadetable = ((UINT8 *)transtables + ((alphalevel-1)<<FF_TRANSSHIFT) + (c*256));
for (v = 0; v < h; v++, dest += vid.width)
for (u = 0; u < w; u++)
{
if (!alphalevel)
dest[u] = consolebgmap[dest[u]];
else
dest[u] = fadetable[consolebgmap[dest[u]]];
}
}
//
// Fills a box of pixels using a flat texture as a pattern, scaled to screen size.
//
@ -983,21 +1122,7 @@ void V_DrawFadeConsBack(INT32 plines)
#ifdef HWRENDER // not win32 only 19990829 by Kin
if (rendermode != render_soft && rendermode != render_none)
{
UINT32 hwcolor;
switch (cons_backcolor.value)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x80808000; break; // Gray
case 2: hwcolor = 0x40201000; break; // Brown
case 3: hwcolor = 0xff000000; break; // Red
case 4: hwcolor = 0xff800000; break; // Orange
case 5: hwcolor = 0x80800000; break; // Yellow
case 6: hwcolor = 0x00800000; break; // Green
case 7: hwcolor = 0x0000ff00; break; // Blue
case 8: hwcolor = 0x4080ff00; break; // Cyan
// Default green
default: hwcolor = 0x00800000; break;
}
UINT32 hwcolor = V_GetHWConsBackColor();
HWR_DrawConsoleBack(hwcolor, plines);
return;
}
@ -1012,7 +1137,7 @@ void V_DrawFadeConsBack(INT32 plines)
// Gets string colormap, used for 0x80 color codes
//
static const UINT8 *V_GetStringColormap(INT32 colorflags)
UINT8 *V_GetStringColormap(INT32 colorflags)
{
switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT)
{
@ -1061,6 +1186,32 @@ void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed)
V_DrawScaledPatch(x, y, flags, hu_font[c]);
}
// Writes a single character for the chat. (draw WHITE if bit 7 set)
// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge..
//
void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap)
{
INT32 w, flags;
//const UINT8 *colormap = V_GetStringColormap(c);
flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
c &= 0x7f;
if (lowercaseallowed)
c -= HU_FONTSTART;
else
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
return;
w = (vid.width < 640 ) ? (SHORT(hu_font[c]->width)/2) : (SHORT(hu_font[c]->width)); // use normal sized characters if we're using a terribly low resolution.
if (x + w > vid.width)
return;
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap);
}
// Precompile a wordwrapped string to any given width.
// This is a muuuch better method than V_WORDWRAP.
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)

View File

@ -139,6 +139,7 @@ void V_DrawScaledPic (INT32 px1, INT32 py1, INT32 scrn, INT32 lumpnum);
// fill a box with a single color
void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c);
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c);
// fill a box with a flat as a pattern
void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
@ -149,11 +150,14 @@ void V_DrawFadeConsBack(INT32 plines);
// draw a single character
void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
// draw a single character, but for the chat
void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap);
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string);
// wordwrap a string using the hu_font
char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string);
UINT8 *V_GetStringColormap(INT32 colorflags);
// draw a string using the hu_font
void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string);

View File

@ -132,7 +132,7 @@
</ClCompile>
<ClCompile Include="..\i_tcp.c" />
<ClCompile Include="..\lua_baselib.c" />
<ClCompile Include="..\lua_blockmaplib.c" />
<ClCompile Include="..\lua_blockmaplib.c" />
<ClCompile Include="..\lua_consolelib.c" />
<ClCompile Include="..\lua_hooklib.c" />
<ClCompile Include="..\lua_hudlib.c" />